Compare commits
76
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
078e754a82 | ||
|
|
a776c14cf8 | ||
|
|
bd296a27f8 | ||
|
|
2e9619ff67 | ||
|
|
67a0d18ce7 | ||
|
|
c5428a8726 | ||
|
|
8db2132856 | ||
|
|
2e28df3dc6 | ||
|
|
b362abf4b2 | ||
|
|
da1cd9eb11 | ||
|
|
82628cfc5a | ||
|
|
690b3c5a28 | ||
|
|
865fa37ed9 | ||
|
|
6fae1811d9 | ||
|
|
7b476e4532 | ||
|
|
ba7fedca6e | ||
|
|
b2b29cb33f | ||
|
|
c5efe48aa3 | ||
|
|
c2d4643204 | ||
|
|
328fbf3f19 | ||
|
|
b5119201ff | ||
|
|
fe2a488f30 | ||
|
|
2bfc349952 | ||
|
|
eb6a39ecde | ||
|
|
266532f18c | ||
|
|
95027e0ae8 | ||
|
|
b5a0332181 | ||
|
|
ff935b4707 | ||
|
|
793c603826 | ||
|
|
03b270cf18 | ||
|
|
3c1c6f6c79 | ||
|
|
81766d31f7 | ||
|
|
cb886d4524 | ||
|
|
31836d2667 | ||
|
|
5dcd01801c | ||
|
|
5215abe5c5 | ||
|
|
d34d232682 | ||
|
|
a084b3295e | ||
|
|
48f7e6bcd5 | ||
|
|
74195870e2 | ||
|
|
e27e75b197 | ||
|
|
0cdc3616f2 | ||
|
|
92e9ca7153 | ||
|
|
ff727d537a | ||
|
|
8803219dd5 | ||
|
|
ada56b06bb | ||
|
|
14eaa097cb | ||
|
|
98be188cbe | ||
|
|
3a61446626 | ||
|
|
dd456dcb19 | ||
|
|
c6303d1ec3 | ||
|
|
ece57df986 | ||
|
|
3803fbfe20 | ||
|
|
50b5bb1970 | ||
|
|
047e0280ca | ||
|
|
afc493394d | ||
|
|
54a32e979f | ||
|
|
07f8043bce | ||
|
|
0a7a01e617 | ||
|
|
a68b21369c | ||
|
|
9a53fc4425 | ||
|
|
ab68d046c8 | ||
|
|
cdb9851da6 | ||
|
|
93e9a29353 | ||
|
|
fba6997c67 | ||
|
|
880f8869a6 | ||
|
|
e71497eaa6 | ||
|
|
256b33f75a | ||
|
|
c316d8fccd | ||
|
|
bc09b06166 | ||
|
|
208299f703 | ||
|
|
523befc238 | ||
|
|
2098a36d4b | ||
|
|
083ab81035 | ||
|
|
847261b6c9 | ||
|
|
309e6ae959 |
@@ -1,12 +0,0 @@
|
||||
# GitHub views all .h files as C, let's assume it's C++
|
||||
*.h linguist-language=c++
|
||||
|
||||
# Internal tools overriding
|
||||
tools/* linguist-vendored
|
||||
editor/* linguist-vendored
|
||||
|
||||
# Third-party overriding
|
||||
extensions/curl/curl-src/* linguist-vendored
|
||||
extensions/geoip/GeoIP.c linguist-vendored
|
||||
extensions/geoip/GeoIP.h linguist-vendored
|
||||
extensions/sqlite/sqlite-source/* linguist-vendored
|
||||
@@ -7,17 +7,17 @@ Please consider the following guidelines when reporting an issue.
|
||||
#### Not for general support
|
||||
This is not the right place to get help with using or installing SourceMod, or for issues with specific, third-party SourceMod plugins or extensions.
|
||||
|
||||
For help with SourceMod, please consult the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52). Similarly, for assistance with, or to report issues with, third-party SourceMod plugins or extensions, you should post in the existing thread for that plugin or extension on the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52).
|
||||
For help with SourceMod, please consult the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52). Similary, for assistance with, or to report issues with third-party SourceMod plugins or extension, you should post in the existing thread for the plugin or extension at the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52).
|
||||
|
||||
#### Details, details, details
|
||||
Provide as much detail as possible when reporting an issue.
|
||||
|
||||
For bugs or other undesired behavior, answers to the following questions are a great start:
|
||||
For bugs or other undesired behavior, answers to the follow questions are a great start.
|
||||
* What is the issue?
|
||||
* What behavior are you expecting instead?
|
||||
* On what operating system is the game server running?
|
||||
* What game is the game server running?
|
||||
* What exact version (full x.y.z.a version number) of Metamod:Source and SourceMod are installed on the game server?
|
||||
* What exact (full x.y.z.a version number) version of Metamod:Source and SourceMod are installed on the game server?
|
||||
* What is the specific, shortest path to reproducing this issue? If this issue can be reproduced with plugin code, please try to shorten it to the minimum required to trigger the problem.
|
||||
|
||||
If this is a feature request, the following are helpful. Generally, not all will apply, but whatever you can answer ahead of time will shorten back and forth conversation.
|
||||
@@ -29,18 +29,18 @@ If this is a feature request, the following are helpful. Generally, not all will
|
||||
Please report any security bugs to [[email protected]](mailto:[email protected]) rather than to this public issue tracker.
|
||||
|
||||
#### We're only human
|
||||
Please keep in mind that we maintain this project in our spare time, at no cost. There is no SLA, and you are not owed a response or a fix.
|
||||
Please keep in mind that we maintain the project in our spare time, at no cost. There is no SLA, and you are not owed a response or fix.
|
||||
|
||||
#### Conduct
|
||||
Please refer to the [AlliedModders forum rules.](https://forums.alliedmods.net/misc.php?do=showrules)
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Firstly, thank you for considering contributing changes to the project!
|
||||
Firstly, thank you for considering to contribute changes to the project!
|
||||
|
||||
However, if this is anything more than a small fix such as a gamedata update, a glaring code flaw, or a simple typo in a file like this one, please file an issue first so that it can be discussed, unless you have already spoken to multiple members of the development team about it on IRC or the AlliedModders forums.
|
||||
However, if this is anything more than a small fix such an a gamedata update, a glaring code flaw, or a simple typo in a file like this one, please file an issue first so that it can be discussed, unless you have already spoken to multiple members of the development team about it on IRC or the AlliedModders forums.
|
||||
|
||||
We don't like to have to reject pull requests, so we want to avoid those scenarios. We wouldn't want you to feel like you wasted your time writing something only for us to shoot it down.
|
||||
We don't like to have to reject pull requests, so we want to avoid those scenarios. We wouldn't want you to feel that you wasted your time writing something only for us to have it then be shot down.
|
||||
|
||||
#### Rejection
|
||||
*Copied from Phabricator's [Contributing Code guidelines](https://secure.phabricator.com/book/phabcontrib/article/contributing_code/#rejecting-patches), as we largely feel the same way about this.*
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: https://www.sourcemod.net/donate.php
|
||||
@@ -1,26 +0,0 @@
|
||||
# Help us help you
|
||||
- [ ] I have checked that my issue [doesn't exist yet](https://github.com/alliedmodders/sourcemod/issues).
|
||||
- [ ] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
|
||||
- [ ] I can always reproduce the issue with the provided description below.
|
||||
|
||||
# Environment
|
||||
* Operating System version:
|
||||
* Game/AppID (with version if applicable):
|
||||
* Current SourceMod version:
|
||||
* Current SourceMod snapshot:
|
||||
* Current Metamod: Source snapshot:
|
||||
- [ ] I have updated SourceMod to the [latest version](https://www.sourcemod.net/downloads.php) and it still happens.
|
||||
- [ ] I have updated SourceMod to the [latest snapshot](https://www.sourcemod.net/downloads.php?branch=dev) and it still happens.
|
||||
- [ ] I have updated SourceMM to the [latest snapshot](https://sourcemm.net/downloads.php?branch=dev) and it still happens.
|
||||
|
||||
# Description
|
||||
|
||||
|
||||
# Problematic Code (or Steps to Reproduce)
|
||||
```
|
||||
// TODO(you): code here to reproduce the problem
|
||||
```
|
||||
|
||||
# Logs
|
||||
* Please attach in separate files: game output, library logs, kernel logs, and any other supporting information.
|
||||
* In case of a crash, please attach minidump or dump analyze output.
|
||||
@@ -1,98 +0,0 @@
|
||||
name: Continuous Integration
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- '[0-9]+.[0-9]+-dev'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- '[0-9]+.[0-9]+-dev'
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-latest, windows-latest]
|
||||
include:
|
||||
- os: windows-latest
|
||||
os_short: win
|
||||
compiler_cc: msvc
|
||||
- os: ubuntu-latest
|
||||
os_short: linux
|
||||
compiler_cc: clang
|
||||
compiler_cxx: clang++
|
||||
- os: ubuntu-18.04
|
||||
os_short: linux
|
||||
compiler_cc: clang-8
|
||||
compiler_cxx: clang++-8
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os_short }}-${{ matrix.compiler_cc }}
|
||||
env:
|
||||
SDKS: '["episode1","css","tf2","l4d2","csgo"]'
|
||||
ARCH: x86,x86_64
|
||||
DEPENDENCIES_FOLDER: dependencies
|
||||
DEPENDENCIES_ROOT: ${{ github.workspace }}/dependencies
|
||||
MYSQL_VERSION: '5.5'
|
||||
MMSOURCE_VERSION: '1.10'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
path: sourcemod
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: hl2sdk-mysql-mmsource
|
||||
with:
|
||||
path: ${{ env.DEPENDENCIES_ROOT }}
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-mysql${{ env.MYSQL_VERSION }}-mmsource${{ env.MMSOURCE_VERSION }}-${{ join(fromJSON(env.SDKS), '') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-mysql${{ env.MYSQL_VERSION }}-mmsource${{ env.MMSOURCE_VERSION }}-
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-mysql${{ env.MYSQL_VERSION }}-
|
||||
|
||||
# Setup Python for AMBuild
|
||||
- uses: actions/setup-python@v2
|
||||
name: Setup Python 3.8
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip setuptools wheel
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ${{ env.DEPENDENCIES_FOLDER }}
|
||||
cd ${{ env.DEPENDENCIES_FOLDER }}
|
||||
|
||||
# Satisfy checkout-deps requirement for a "sourcemod" folder.
|
||||
mkdir -p sourcemod
|
||||
../sourcemod/tools/checkout-deps.sh -s ${{ join(fromJSON(env.SDKS)) }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
gcc-multilib g++-multilib libstdc++6 lib32stdc++6 \
|
||||
libc6-dev libc6-dev-i386 linux-libc-dev \
|
||||
linux-libc-dev:i386 lib32z1-dev ${{ matrix.compiler_cc }}
|
||||
|
||||
- name: Select clang compiler
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
run: |
|
||||
echo "CC=${{ matrix.compiler_cc }}" >> $GITHUB_ENV
|
||||
echo "CXX=${{ matrix.compiler_cxx }}" >> $GITHUB_ENV
|
||||
${{ matrix.compiler_cc }} --version
|
||||
${{ matrix.compiler_cxx }} --version
|
||||
|
||||
- name: Build
|
||||
working-directory: sourcemod
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
python ../configure.py --enable-optimize --sdks=${{ join(fromJSON(env.SDKS)) }} --targets=${{ env.ARCH }} --mms-path=${{ env.DEPENDENCIES_ROOT }}/mmsource-${{ env.MMSOURCE_VERSION }} --hl2sdk-root=${{ env.DEPENDENCIES_ROOT }} --mysql-path=${{ env.DEPENDENCIES_ROOT }}/mysql-${{ env.MYSQL_VERSION }} --mysql64-path=${{ env.DEPENDENCIES_ROOT }}/mysql-${{ env.MYSQL_VERSION }}-x86_64
|
||||
ambuild
|
||||
@@ -1,79 +0,0 @@
|
||||
name: SourcePawn scripting
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- '[0-9]+.[0-9]+-dev'
|
||||
paths:
|
||||
- 'plugins/include/*'
|
||||
- 'sourcepawn/**'
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '53 05 01 */3 *' # Artifacts expire every 3 months
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
os_short: linux
|
||||
- os: windows-latest
|
||||
os_short: win
|
||||
- os: macos-latest
|
||||
os_short: mac
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
ARCH: x86,x86_64
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# Setup Python for AMBuild
|
||||
- uses: actions/setup-python@v2
|
||||
name: Setup Python 3.8
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install AMBuild
|
||||
run: |
|
||||
python -m pip install --upgrade pip setuptools wheel
|
||||
pip install git+https://github.com/alliedmodders/ambuild
|
||||
|
||||
- name: Build only for x64 on macOS
|
||||
if: startsWith(runner.os, 'macOS')
|
||||
run: echo "ARCH=x86_64" >> $GITHUB_ENV
|
||||
|
||||
- name: Install Linux dependencies
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
gcc-multilib g++-multilib libstdc++6 lib32stdc++6 \
|
||||
libc6-dev libc6-dev-i386 linux-libc-dev \
|
||||
linux-libc-dev:i386 lib32z1-dev ${{ matrix.compiler_cc }}
|
||||
|
||||
- name: Select clang compiler
|
||||
if: startsWith(runner.os, 'Linux') || startsWith(runner.os, 'macOS')
|
||||
run: |
|
||||
echo "CC=clang" >> $GITHUB_ENV
|
||||
echo "CXX=clang++" >> $GITHUB_ENV
|
||||
clang --version
|
||||
clang++ --version
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
python ../configure.py --enable-optimize --scripting-only --targets=${{ env.ARCH }}
|
||||
ambuild
|
||||
echo "SM_VERSION=$(cat ../product.version)" >> $GITHUB_ENV
|
||||
|
||||
- name: Archive tooling
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: sourcemod-tooling-${{ env.SM_VERSION }}-${{ matrix.os_short }}
|
||||
path: build/package
|
||||
+1
-5
@@ -28,7 +28,7 @@ LIB-Debug/
|
||||
[Tt]humbs.db
|
||||
|
||||
# AMBuild build directories
|
||||
build*/
|
||||
build/
|
||||
obj-*/
|
||||
*~
|
||||
*.rej
|
||||
@@ -36,7 +36,3 @@ obj-*/
|
||||
*.smx
|
||||
*.swp
|
||||
*.gdb_history
|
||||
objdir
|
||||
|
||||
.vs/*
|
||||
.vscode/*
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
[submodule "public/amtl"]
|
||||
path = public/amtl
|
||||
url = https://github.com/alliedmodders/amtl
|
||||
shallow = true
|
||||
[submodule "sourcepawn"]
|
||||
path = sourcepawn
|
||||
url = https://github.com/alliedmodders/sourcepawn
|
||||
shallow = true
|
||||
url = https://github.com/BotoX/sourcepawn.git
|
||||
|
||||
+87
-57
@@ -1,86 +1,116 @@
|
||||
git:
|
||||
depth: 3
|
||||
|
||||
sudo: false
|
||||
language: cpp
|
||||
os: linux
|
||||
dist: xenial
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- llvm-toolchain-trusty-5.0
|
||||
packages:
|
||||
- lib32stdc++6
|
||||
- lib32z1-dev
|
||||
- libc6-dev-i386
|
||||
- linux-libc-dev
|
||||
- g++-multilib
|
||||
# - clang-3.6
|
||||
# - clang-3.8
|
||||
# - clang-4.0
|
||||
# - clang-5.0
|
||||
# - g++-6
|
||||
# - g++-6-multilib
|
||||
- g++-4.8-multilib
|
||||
- g++-4.8
|
||||
- g++-4.9-multilib
|
||||
- g++-4.9
|
||||
- g++-5-multilib
|
||||
- g++-5
|
||||
- g++-7-multilib
|
||||
- g++-7
|
||||
cache:
|
||||
directories:
|
||||
- ../mysql-5.0
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
|
||||
- MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
|
||||
- MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
|
||||
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: false
|
||||
language: cpp
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-4.9-multilib', 'python3-pip']
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
|
||||
- SDKS=episode1,css,tf2,l4d2,csgo
|
||||
- MODE=optimize
|
||||
- ARCH=x86,x86_64
|
||||
packages: ['clang-3.6', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||
cache:
|
||||
directories: ['../mysql-5.0']
|
||||
env: ['MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6"']
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: false
|
||||
language: cpp
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages: ['clang-3.4', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-4.9-multilib', 'python3-pip']
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang && CXX=clang++"
|
||||
- SDKS=episode1,css,tf2,l4d2,csgo
|
||||
- MODE=optimize
|
||||
- ARCH=x86,x86_64
|
||||
packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||
cache:
|
||||
directories: ['../mysql-5.0']
|
||||
env: ['MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"']
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.2
|
||||
language: cpp
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang && CXX=clang++"
|
||||
- SDKS=episode1,css,tf2,l4d2,csgo
|
||||
- MODE=optimize
|
||||
- ARCH=x86_64,x86
|
||||
|
||||
# # This is a faster test for the latest g++.
|
||||
# - os: linux
|
||||
# dist: bionic
|
||||
# sudo: false
|
||||
# language: cpp
|
||||
# addons:
|
||||
# apt:
|
||||
# packages: ['lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-multilib', 'g++']
|
||||
# cache:
|
||||
# directories: ['../mysql-5.0']
|
||||
# env:
|
||||
# - MATRIX_EVAL="CC=gcc && CXX=g++"
|
||||
# - SDKS=csgo
|
||||
# # GCC currently fails in opt builds trying to inline stuff in sqlite3.c.
|
||||
# - MODE=debug
|
||||
|
||||
# This is a faster test for the latest clang.
|
||||
- os: linux
|
||||
dist: bionic
|
||||
sudo: false
|
||||
language: cpp
|
||||
addons:
|
||||
apt:
|
||||
packages: ['lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-multilib', 'clang']
|
||||
env:
|
||||
- MATRIX_EVAL="CC=clang && CXX=clang++"
|
||||
- SDKS=csgo
|
||||
- MODE=optimize
|
||||
- ARCH=x86
|
||||
sources: ['llvm-toolchain-trusty-4.0']
|
||||
packages: ['clang-4.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||
cache:
|
||||
directories: ['../mysql-5.0']
|
||||
env: ['MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"']
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
language: cpp
|
||||
addons:
|
||||
apt:
|
||||
sources: ['llvm-toolchain-trusty-5.0']
|
||||
packages: ['clang-5.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||
cache:
|
||||
directories: ['../mysql-5.0']
|
||||
env: ['MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"']
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
language: cpp
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6', 'g++-6-multilib', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
|
||||
cache:
|
||||
directories: ['../mysql-5.0']
|
||||
env: ['MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"']
|
||||
|
||||
allow_failures:
|
||||
- env: MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7"
|
||||
- env: MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
|
||||
- env: MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
|
||||
- env: MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
|
||||
- env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||
- env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||
|
||||
|
||||
before_script:
|
||||
- CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh -s ${SDKS} && cd $CHECKOUT_DIR
|
||||
- CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
- PATH="~/.local/bin:$PATH"
|
||||
- eval "${MATRIX_EVAL}"
|
||||
- eval "${CC} --version"
|
||||
- eval "${CXX} --version"
|
||||
- python3 ../configure.py --enable-${MODE} --sdks=${SDKS} --targets=${ARCH}
|
||||
- python ../configure.py --enable-optimize --sdks=episode1,tf2,l4d2,csgo,dota
|
||||
- ambuild
|
||||
|
||||
+121
-385
@@ -1,8 +1,5 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import collections
|
||||
import os, sys
|
||||
import subprocess
|
||||
import traceback
|
||||
|
||||
class SDK(object):
|
||||
def __init__(self, sdk, ext, aDef, name, platform, dir):
|
||||
@@ -14,41 +11,12 @@ class SDK(object):
|
||||
self.platform = platform
|
||||
self.name = dir
|
||||
self.path = None # Actual path
|
||||
self.platformSpec = platform
|
||||
|
||||
# By default, nothing supports x64.
|
||||
if type(platform) is list:
|
||||
self.platformSpec = {p: ['x86'] for p in platform}
|
||||
else:
|
||||
self.platformSpec = platform
|
||||
|
||||
def shouldBuild(self, targets):
|
||||
for cxx in targets:
|
||||
if cxx.target.platform in self.platformSpec:
|
||||
if cxx.target.arch in self.platformSpec[cxx.target.platform]:
|
||||
return True
|
||||
return False
|
||||
|
||||
WinOnly = ['windows']
|
||||
WinLinux = ['windows', 'linux']
|
||||
WinLinuxMac = ['windows', 'linux', 'mac']
|
||||
Blade = {
|
||||
'windows': ['x86', 'x86_64'],
|
||||
'linux': ['x86_64'],
|
||||
'mac': ['x86_64']
|
||||
}
|
||||
CSGO = {
|
||||
'windows': ['x86'],
|
||||
'linux': ['x86', 'x86_64'],
|
||||
'mac': ['x86_64']
|
||||
}
|
||||
Mock = {
|
||||
'windows': ['x86', 'x86_64'],
|
||||
'linux': ['x86', 'x86_64'],
|
||||
'mac': ['x86_64']
|
||||
}
|
||||
|
||||
SDKMap = {
|
||||
PossibleSDKs = {
|
||||
'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
|
||||
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'),
|
||||
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
|
||||
@@ -63,21 +31,15 @@ SDKMap = {
|
||||
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'),
|
||||
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
|
||||
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
|
||||
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, 'csgo'),
|
||||
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', WinLinux, 'csgo'),
|
||||
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'),
|
||||
'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', Blade, 'blade'),
|
||||
'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'),
|
||||
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
|
||||
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '14', 'CONTAGION', WinOnly, 'contagion'),
|
||||
'bms': SDK('HL2SDKBMS', '2.bms', '10', 'BMS', WinLinux, 'bms'),
|
||||
'doi': SDK('HL2SDKDOI', '2.doi', '20', 'DOI', WinLinuxMac, 'doi'),
|
||||
'mock': SDK('HL2SDK-MOCK', '2.mock', '999', 'MOCK', Mock, 'mock'),
|
||||
}
|
||||
|
||||
# Stable sorting for command equivalence in AMBuild.
|
||||
PossibleSDKs = collections.OrderedDict()
|
||||
for key in sorted(SDKMap.keys()):
|
||||
PossibleSDKs[key] = SDKMap[key]
|
||||
|
||||
def ResolveEnvPath(env, folder):
|
||||
if env in os.environ:
|
||||
path = os.environ[env]
|
||||
@@ -98,54 +60,18 @@ def ResolveEnvPath(env, folder):
|
||||
|
||||
def Normalize(path):
|
||||
return os.path.abspath(os.path.normpath(path))
|
||||
|
||||
def SetArchFlags(compiler):
|
||||
if compiler.behavior == 'gcc':
|
||||
if compiler.target.arch == 'x86_64':
|
||||
compiler.cflags += ['-fPIC']
|
||||
elif compiler.like('msvc'):
|
||||
if compiler.target.arch == 'x86_64':
|
||||
compiler.defines += ['WIN64']
|
||||
|
||||
class SMConfig(object):
|
||||
def __init__(self):
|
||||
self.sdks = {}
|
||||
self.binaries = []
|
||||
self.spvm = []
|
||||
self.extensions = []
|
||||
self.generated_headers = None
|
||||
self.mms_root = None
|
||||
self.mysql_root = {}
|
||||
self.mysql_root = None
|
||||
self.spcomp = None
|
||||
self.spcomp_bins = None
|
||||
self.smx_files = {}
|
||||
self.versionlib = None
|
||||
self.all_targets = []
|
||||
self.target_archs = set()
|
||||
self.enable_asan = getattr(builder.options, 'enable_asan', False)
|
||||
self.asan_libs = {}
|
||||
|
||||
if builder.options.targets:
|
||||
target_archs = builder.options.targets.split(',')
|
||||
else:
|
||||
target_archs = ['x86']
|
||||
if builder.backend != 'amb2':
|
||||
target_archs.append('x86_64')
|
||||
|
||||
for arch in target_archs:
|
||||
try:
|
||||
cxx = builder.DetectCxx(target_arch = arch)
|
||||
self.target_archs.add(cxx.target.arch)
|
||||
except Exception as e:
|
||||
# Error if archs were manually overridden.
|
||||
if builder.options.targets:
|
||||
raise
|
||||
print('Skipping target {}: {}'.format(arch, e))
|
||||
continue
|
||||
self.all_targets.append(cxx)
|
||||
|
||||
if not self.all_targets:
|
||||
raise Exception('No suitable C/C++ compiler was found.')
|
||||
|
||||
def use_auto_versioning(self):
|
||||
if builder.backend != 'amb2':
|
||||
@@ -174,34 +100,31 @@ class SMConfig(object):
|
||||
|
||||
def detectSDKs(self):
|
||||
sdk_list = builder.options.sdks.split(',')
|
||||
use_none = sdk_list[0] == 'none'
|
||||
use_all = sdk_list[0] == 'all'
|
||||
use_present = sdk_list[0] == 'present'
|
||||
|
||||
for sdk_name in PossibleSDKs:
|
||||
sdk = PossibleSDKs[sdk_name]
|
||||
if sdk.shouldBuild(self.all_targets):
|
||||
if builder.target.platform in sdk.platform:
|
||||
if builder.options.hl2sdk_root:
|
||||
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
|
||||
else:
|
||||
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
|
||||
if sdk_path is None or not os.path.isdir(sdk_path):
|
||||
if (use_all and sdk_name != 'mock') or sdk_name in sdk_list:
|
||||
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 len(self.sdks) < 1:
|
||||
raise Exception('At least one SDK must be available.')
|
||||
|
||||
if builder.options.mms_path:
|
||||
self.mms_root = builder.options.mms_path
|
||||
else:
|
||||
self.mms_root = ResolveEnvPath('MMSOURCE111', 'mmsource-1.11')
|
||||
if not self.mms_root:
|
||||
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
|
||||
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
|
||||
if not self.mms_root:
|
||||
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
|
||||
if not self.mms_root:
|
||||
@@ -212,49 +135,21 @@ class SMConfig(object):
|
||||
self.mms_root = Normalize(self.mms_root)
|
||||
|
||||
if builder.options.hasMySql:
|
||||
if 'x86' in self.target_archs:
|
||||
if builder.options.mysql_path:
|
||||
self.mysql_root['x86'] = builder.options.mysql_path
|
||||
else:
|
||||
for i in range(10):
|
||||
self.mysql_root['x86'] = ResolveEnvPath('MYSQL55', 'mysql-5.' + str(i))
|
||||
if self.mysql_root['x86']:
|
||||
break
|
||||
if not self.mysql_root['x86'] or not os.path.isdir(self.mysql_root['x86']):
|
||||
raise Exception('Could not find a path to MySQL. Configure with --no-mysql to disable it.')
|
||||
self.mysql_root['x86'] = Normalize(self.mysql_root['x86'])
|
||||
|
||||
if 'x86_64' in self.target_archs:
|
||||
if builder.options.mysql64_path:
|
||||
self.mysql_root['x86_64'] = builder.options.mysql64_path
|
||||
else:
|
||||
for i in range(10):
|
||||
self.mysql_root['x86_64'] = ResolveEnvPath('MYSQL55_64', 'mysql-5.' + str(i) + '-x86_64')
|
||||
if self.mysql_root['x86_64']:
|
||||
break
|
||||
if not self.mysql_root['x86_64'] or not os.path.isdir(self.mysql_root['x86_64']):
|
||||
raise Exception('Could not find a path to 64-bit MySQL!')
|
||||
self.mysql_root['x86_64'] = Normalize(self.mysql_root['x86_64'])
|
||||
if builder.options.mysql_path:
|
||||
self.mysql_root = builder.options.mysql_path
|
||||
else:
|
||||
for i in range(7):
|
||||
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
|
||||
if self.mysql_root:
|
||||
break
|
||||
if not self.mysql_root or not os.path.isdir(self.mysql_root):
|
||||
raise Exception('Could not find a path to MySQL!')
|
||||
self.mysql_root = Normalize(self.mysql_root)
|
||||
|
||||
def configure(self):
|
||||
builder.AddConfigureFile('pushbuild.txt')
|
||||
|
||||
if not set(self.target_archs).issubset(['x86', 'x86_64']):
|
||||
raise Exception('Unknown target architecture: {0}'.format(self.target_archs))
|
||||
|
||||
for cxx in self.all_targets:
|
||||
self.configure_cxx(cxx)
|
||||
|
||||
def configure_cxx(self, cxx):
|
||||
if cxx.family == 'msvc':
|
||||
if cxx.version < 1900:
|
||||
raise Exception('Only MSVC 2015 and later are supported, c++14 support is required.')
|
||||
if cxx.family == 'gcc':
|
||||
if cxx.version < 'gcc-4.9':
|
||||
raise Exception('Only GCC versions 4.9 or greater are supported, c++14 support is required.')
|
||||
if cxx.family == 'clang':
|
||||
if cxx.version < 'clang-3.4':
|
||||
raise Exception('Only clang versions 3.4 or greater are supported, c++14 support is required.')
|
||||
cxx = builder.DetectCxx()
|
||||
|
||||
if cxx.like('gcc'):
|
||||
self.configure_gcc(cxx)
|
||||
@@ -270,11 +165,11 @@ class SMConfig(object):
|
||||
cxx.defines += ['DEBUG', '_DEBUG']
|
||||
|
||||
# Platform-specifics
|
||||
if cxx.target.platform == 'linux':
|
||||
if builder.target.platform == 'linux':
|
||||
self.configure_linux(cxx)
|
||||
elif cxx.target.platform == 'mac':
|
||||
elif builder.target.platform == 'mac':
|
||||
self.configure_mac(cxx)
|
||||
elif cxx.target.platform == 'windows':
|
||||
elif builder.target.platform == 'windows':
|
||||
self.configure_windows(cxx)
|
||||
|
||||
# Finish up.
|
||||
@@ -305,33 +200,31 @@ class SMConfig(object):
|
||||
'-pipe',
|
||||
'-fno-strict-aliasing',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
# '-Werror',
|
||||
'-Wno-unused',
|
||||
'-Wno-switch',
|
||||
'-Wno-array-bounds',
|
||||
'-msse',
|
||||
'-m32',
|
||||
'-fvisibility=hidden',
|
||||
]
|
||||
|
||||
if cxx.version == 'apple-clang-6.0' or cxx.version == 'clang-3.4':
|
||||
cxx.cxxflags += ['-std=c++1y']
|
||||
else:
|
||||
cxx.cxxflags += ['-std=c++14']
|
||||
|
||||
cxx.cxxflags += [
|
||||
'-std=c++11',
|
||||
'-fno-exceptions',
|
||||
'-fno-threadsafe-statics',
|
||||
'-Wno-non-virtual-dtor',
|
||||
'-Wno-overloaded-virtual',
|
||||
'-fvisibility-inlines-hidden',
|
||||
]
|
||||
cxx.linkflags += ['-m32']
|
||||
|
||||
have_gcc = cxx.family == 'gcc'
|
||||
have_clang = cxx.family == 'clang'
|
||||
if cxx.version >= 'clang-3.9' or cxx.version == 'clang-3.4' or cxx.version > 'apple-clang-6.0':
|
||||
if cxx.version >= 'clang-3.9':
|
||||
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':
|
||||
if cxx.version >= 'clang-3.6' 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']
|
||||
@@ -341,8 +234,7 @@ class SMConfig(object):
|
||||
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
|
||||
if cxx.version >= 'gcc-4.8':
|
||||
cxx.cflags += ['-Wno-unused-result']
|
||||
if cxx.version >= 'gcc-9.0':
|
||||
cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned']
|
||||
|
||||
if have_clang:
|
||||
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
|
||||
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
|
||||
@@ -351,35 +243,14 @@ class SMConfig(object):
|
||||
cxx.cxxflags += ['-Wno-deprecated']
|
||||
cxx.cflags += ['-Wno-sometimes-uninitialized']
|
||||
|
||||
if self.enable_asan:
|
||||
if not have_clang:
|
||||
raise Exception('--enable-asan only supported when using Clang')
|
||||
self.configure_asan(cxx)
|
||||
|
||||
# Work around SDK warnings.
|
||||
if cxx.version >= 'clang-10.0' or cxx.version >= 'apple-clang-12.0':
|
||||
cxx.cflags += [
|
||||
'-Wno-implicit-int-float-conversion',
|
||||
'-Wno-tautological-overlap-compare',
|
||||
]
|
||||
|
||||
if have_gcc:
|
||||
cxx.cflags += ['-mfpmath=sse']
|
||||
cxx.cflags += ['-Wno-maybe-uninitialized']
|
||||
|
||||
if builder.options.opt == '1':
|
||||
if self.enable_asan:
|
||||
cxx.cflags += ['-O1']
|
||||
else:
|
||||
cxx.cflags += ['-O3']
|
||||
|
||||
# Don't omit the frame pointer.
|
||||
cxx.cflags += ['-fno-omit-frame-pointer']
|
||||
cxx.cflags += ['-O3']
|
||||
|
||||
def configure_msvc(self, cxx):
|
||||
if self.enable_asan:
|
||||
raise Exception('--enable-asan only supported when using Clang')
|
||||
|
||||
if builder.options.debug == '1':
|
||||
cxx.cflags += ['/MTd']
|
||||
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
|
||||
@@ -400,6 +271,7 @@ class SMConfig(object):
|
||||
'/TP',
|
||||
]
|
||||
cxx.linkflags += [
|
||||
'/MACHINE:X86',
|
||||
'kernel32.lib',
|
||||
'user32.lib',
|
||||
'gdi32.lib',
|
||||
@@ -425,29 +297,6 @@ class SMConfig(object):
|
||||
# Don't omit the frame pointer.
|
||||
cxx.cflags += ['/Oy-']
|
||||
|
||||
def configure_asan(self, cxx):
|
||||
if cxx.target.platform != 'linux':
|
||||
raise Exception('--enable-asan only supported on Linux')
|
||||
cxx.cflags += ['-fsanitize=address']
|
||||
cxx.linkflags += ['-fsanitize=address']
|
||||
if cxx.target.arch == 'x86':
|
||||
libclang_rt = 'libclang_rt.asan-i386.so'
|
||||
else:
|
||||
libclang_rt = 'libclang_rt.asan-x86_64.so'
|
||||
|
||||
try:
|
||||
argv = cxx.cxx_argv + ['--print-file-name', libclang_rt]
|
||||
output = subprocess.check_output(argv)
|
||||
output = output.decode('utf-8')
|
||||
output = output.strip()
|
||||
except:
|
||||
raise Exception('Could not find {}'.format(libclang_rt))
|
||||
|
||||
print('ASAN library for {}: {}'.format(cxx.target.arch, output))
|
||||
print('You will need to LD_PRELOAD this into srcds.')
|
||||
|
||||
self.asan_libs[cxx.target.arch] = os.path.dirname(output)
|
||||
|
||||
def configure_linux(self, cxx):
|
||||
cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
|
||||
cxx.linkflags += ['-lm']
|
||||
@@ -455,33 +304,23 @@ class SMConfig(object):
|
||||
cxx.linkflags += ['-static-libgcc']
|
||||
elif cxx.family == 'clang':
|
||||
cxx.linkflags += ['-lgcc_eh']
|
||||
cxx.linkflags += ['-static-libstdc++']
|
||||
|
||||
def configure_mac(self, cxx):
|
||||
cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
|
||||
cxx.cflags += ['-mmacosx-version-min=10.7']
|
||||
cxx.cflags += ['-mmacosx-version-min=10.5']
|
||||
cxx.linkflags += [
|
||||
'-mmacosx-version-min=10.7',
|
||||
'-stdlib=libc++',
|
||||
'-lc++',
|
||||
'-mmacosx-version-min=10.5',
|
||||
'-arch', 'i386',
|
||||
'-lstdc++',
|
||||
'-stdlib=libstdc++',
|
||||
]
|
||||
cxx.cxxflags += ['-stdlib=libc++']
|
||||
cxx.cxxflags += ['-stdlib=libstdc++']
|
||||
|
||||
def configure_windows(self, cxx):
|
||||
cxx.defines += ['WIN32', '_WINDOWS']
|
||||
|
||||
def add_libamtl(self):
|
||||
# Add libamtl.
|
||||
self.libamtl = {}
|
||||
for cxx in self.all_targets:
|
||||
def get_configure_fn(cxx):
|
||||
return lambda builder, name: self.StaticLibrary(builder, cxx, name)
|
||||
extra_vars = {'Configure': get_configure_fn(cxx)}
|
||||
libamtl = builder.Build('public/amtl/amtl/AMBuilder', extra_vars)
|
||||
self.libamtl[cxx.target.arch] = libamtl.binary
|
||||
|
||||
def AddVersioning(self, binary):
|
||||
if binary.compiler.target.platform == 'windows':
|
||||
if builder.target.platform == 'windows':
|
||||
binary.sources += ['version.rc']
|
||||
binary.compiler.rcdefines += [
|
||||
'BINARY_NAME="{0}"'.format(binary.outputFile),
|
||||
@@ -489,14 +328,14 @@ class SMConfig(object):
|
||||
]
|
||||
if self.use_auto_versioning():
|
||||
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
|
||||
elif binary.compiler.target.platform == 'mac':
|
||||
elif builder.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.postlink += [self.versionlib[binary.compiler.target.arch]]
|
||||
binary.compiler.linkflags += [self.versionlib]
|
||||
binary.compiler.sourcedeps += SM.generated_headers
|
||||
return binary
|
||||
|
||||
@@ -505,13 +344,6 @@ class SMConfig(object):
|
||||
self.AddVersioning(binary)
|
||||
if binary.compiler.like('msvc'):
|
||||
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
|
||||
|
||||
# Dumb clang behavior means we have to manually find libclang_rt.
|
||||
if self.enable_asan:
|
||||
binary.compiler.linkflags += [
|
||||
'-shared-libsan',
|
||||
'-Wl,-rpath={}'.format(self.asan_libs[binary.compiler.target.arch]),
|
||||
]
|
||||
return binary
|
||||
|
||||
def ProgramBuilder(self, compiler, name):
|
||||
@@ -519,32 +351,28 @@ class SMConfig(object):
|
||||
self.AddVersioning(binary)
|
||||
if '-static-libgcc' in binary.compiler.linkflags:
|
||||
binary.compiler.linkflags.remove('-static-libgcc')
|
||||
if self.enable_asan:
|
||||
binary.compiler.linkflags.append('-static-libsan')
|
||||
if '-lgcc_eh' in binary.compiler.linkflags:
|
||||
binary.compiler.linkflags.remove('-lgcc_eh')
|
||||
if binary.compiler.like('gcc'):
|
||||
binary.compiler.linkflags += ['-lstdc++', '-lpthread']
|
||||
binary.compiler.linkflags += ['-lstdc++']
|
||||
if binary.compiler.like('msvc'):
|
||||
binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE']
|
||||
return binary
|
||||
|
||||
def StaticLibraryBuilder(self, compiler, name):
|
||||
return compiler.StaticLibrary(name)
|
||||
binary = compiler.StaticLibrary(name)
|
||||
return binary;
|
||||
|
||||
def Library(self, context, compiler, name):
|
||||
compiler = compiler.clone()
|
||||
SetArchFlags(compiler)
|
||||
def Library(self, context, name):
|
||||
compiler = context.cxx.clone()
|
||||
return self.LibraryBuilder(compiler, name)
|
||||
|
||||
def Program(self, context, compiler, name):
|
||||
compiler = compiler.clone()
|
||||
SetArchFlags(compiler)
|
||||
def Program(self, context, name):
|
||||
compiler = context.cxx.clone()
|
||||
return self.ProgramBuilder(compiler, name)
|
||||
|
||||
def StaticLibrary(self, context, compiler, name):
|
||||
compiler = compiler.clone()
|
||||
SetArchFlags(compiler)
|
||||
def StaticLibrary(self, context, name):
|
||||
compiler = context.cxx.clone()
|
||||
return self.StaticLibraryBuilder(compiler, name)
|
||||
|
||||
def ConfigureForExtension(self, context, compiler):
|
||||
@@ -558,15 +386,13 @@ class SMConfig(object):
|
||||
]
|
||||
return compiler
|
||||
|
||||
def ExtLibrary(self, context, compiler, name):
|
||||
binary = self.Library(context, compiler, name)
|
||||
SetArchFlags(compiler)
|
||||
def ExtLibrary(self, context, name):
|
||||
binary = self.Library(context, name)
|
||||
self.ConfigureForExtension(context, binary.compiler)
|
||||
return binary
|
||||
|
||||
def ConfigureForHL2(self, context, binary, sdk):
|
||||
def ConfigureForHL2(self, binary, sdk):
|
||||
compiler = binary.compiler
|
||||
SetArchFlags(compiler)
|
||||
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(self.mms_root, 'core'),
|
||||
@@ -603,160 +429,108 @@ class SMConfig(object):
|
||||
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']
|
||||
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
|
||||
if compiler.version >= 1900:
|
||||
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']:
|
||||
if builder.target.platform in ['linux', 'mac']:
|
||||
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
|
||||
|
||||
if compiler.target.platform == 'linux':
|
||||
if sdk.name in ['csgo', 'blade']:
|
||||
compiler.linkflags.remove('-static-libstdc++')
|
||||
compiler.linkflags += ['-lstdc++']
|
||||
compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
|
||||
elif compiler.target.platform == 'mac':
|
||||
if sdk.name in ['csgo']:
|
||||
# Switch libc++ to libstdc++ for protobuf linkage.
|
||||
compiler.cxxflags.remove('-stdlib=libc++')
|
||||
compiler.linkflags.remove('-stdlib=libc++')
|
||||
compiler.linkflags.remove('-lc++')
|
||||
|
||||
compiler.cxxflags += ['-stdlib=libstdc++']
|
||||
compiler.linkflags += ['-stdlib=libstdc++']
|
||||
compiler.linkflags += ['-lstdc++']
|
||||
|
||||
if 'c++1y' in compiler.cxxflags:
|
||||
compiler.cxxflags.remove('-std=c++1y')
|
||||
compiler.cxxflags += ['-std=c++11']
|
||||
elif 'c++14' in compiler.cxxflags:
|
||||
compiler.cxxflags.remove('-std=c++14')
|
||||
compiler.cxxflags += ['-std=c++11']
|
||||
if sdk.name == 'csgo' and builder.target.platform == 'linux':
|
||||
compiler.linkflags += ['-lstdc++']
|
||||
|
||||
for path in paths:
|
||||
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
|
||||
|
||||
if compiler.target.platform == 'linux':
|
||||
if builder.target.platform == 'linux':
|
||||
if sdk.name == 'episode1':
|
||||
lib_folder = os.path.join(sdk.path, 'linux_sdk')
|
||||
elif sdk.name in ['sdk2013', 'bms']:
|
||||
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
|
||||
elif compiler.target.arch == 'x86_64':
|
||||
lib_folder = os.path.join(sdk.path, 'lib', 'linux64')
|
||||
else:
|
||||
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
|
||||
elif compiler.target.platform == 'mac':
|
||||
elif builder.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':
|
||||
if builder.target.platform in ['linux', 'mac']:
|
||||
if sdk.name in ['sdk2013', 'bms']:
|
||||
compiler.postlink += [
|
||||
os.path.join(lib_folder, 'tier1.a'),
|
||||
os.path.join(lib_folder, 'mathlib.a')
|
||||
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
|
||||
compiler.Dep(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')
|
||||
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')),
|
||||
compiler.Dep(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')]
|
||||
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
|
||||
|
||||
dynamic_libs = []
|
||||
if compiler.target.platform == 'linux':
|
||||
if builder.target.platform == 'linux':
|
||||
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']:
|
||||
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
|
||||
elif compiler.target.arch == 'x86_64' and sdk.name in ['csgo', 'mock']:
|
||||
dynamic_libs = ['libtier0_client.so', 'libvstdlib_client.so']
|
||||
elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo']:
|
||||
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
|
||||
else:
|
||||
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
|
||||
elif compiler.target.platform == 'mac':
|
||||
elif builder.target.platform == 'mac':
|
||||
compiler.linkflags.append('-liconv')
|
||||
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
|
||||
elif compiler.target.platform == 'windows':
|
||||
elif builder.target.platform == 'windows':
|
||||
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
|
||||
if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo']:
|
||||
libs.append('interfaces')
|
||||
for lib in libs:
|
||||
if compiler.target.arch == 'x86':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
|
||||
elif compiler.target.arch == 'x86_64':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'public', 'win64', lib) + '.lib'
|
||||
compiler.linkflags.append(lib_path)
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
|
||||
compiler.linkflags.append(compiler.Dep(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)
|
||||
def make_linker(source_path, output_path):
|
||||
def link(context, binary):
|
||||
cmd_node, (output,) = context.AddSymlink(source_path, output_path)
|
||||
return output
|
||||
return link
|
||||
|
||||
compiler.weaklinkdeps += [output]
|
||||
compiler.linkflags[0:0] = [library]
|
||||
linker = make_linker(source_path, output_path)
|
||||
compiler.linkflags[0:0] = [compiler.Dep(library, linker)]
|
||||
|
||||
return binary
|
||||
|
||||
def HL2Library(self, context, compiler, name, sdk):
|
||||
binary = self.Library(context, compiler, name)
|
||||
def HL2Library(self, context, name, sdk):
|
||||
binary = self.Library(context, name)
|
||||
self.ConfigureForExtension(context, binary.compiler)
|
||||
return self.ConfigureForHL2(context, binary, sdk)
|
||||
return self.ConfigureForHL2(binary, sdk)
|
||||
|
||||
def HL2Config(self, project, context, compiler, name, sdk):
|
||||
binary = project.Configure(compiler, name,
|
||||
'{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch))
|
||||
def HL2Project(self, context, name):
|
||||
project = context.cxx.LibraryProject(name)
|
||||
self.ConfigureForExtension(context, project.compiler)
|
||||
return project
|
||||
|
||||
def HL2Config(self, project, name, sdk):
|
||||
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
|
||||
self.AddVersioning(binary)
|
||||
return self.ConfigureForHL2(context, binary, sdk)
|
||||
|
||||
def HL2ExtConfig(self, project, context, compiler, name, sdk):
|
||||
binary = project.Configure(compiler, name,
|
||||
'{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch))
|
||||
self.AddVersioning(binary)
|
||||
self.ConfigureForHL2(context, binary, sdk)
|
||||
self.ConfigureForExtension(context, binary.compiler)
|
||||
return binary
|
||||
|
||||
if getattr(builder, 'target', None) is not None:
|
||||
sys.stderr.write("Your output folder was configured for AMBuild 2.1, and SourceMod is now\n")
|
||||
sys.stderr.write("configured to use AMBuild 2.2. Please remove your output folder and\n")
|
||||
sys.stderr.write("reconfigure to continue.\n")
|
||||
os._exit(1)
|
||||
return self.ConfigureForHL2(binary, sdk)
|
||||
|
||||
SM = SMConfig()
|
||||
SM.detectProductVersion()
|
||||
if not getattr(builder.options, 'scripting_only', False):
|
||||
SM.detectSDKs()
|
||||
SM.detectSDKs()
|
||||
SM.configure()
|
||||
SM.add_libamtl()
|
||||
|
||||
# This will clone the list and each cxx object as we recurse, preventing child
|
||||
# scripts from messing up global state.
|
||||
builder.targets = builder.CloneableList(SM.all_targets)
|
||||
|
||||
if SM.use_auto_versioning():
|
||||
SM.generated_headers = builder.Build(
|
||||
@@ -768,79 +542,41 @@ if SM.use_auto_versioning():
|
||||
{ 'SM': SM }
|
||||
)
|
||||
|
||||
class SPRoot(object):
|
||||
# SourcePawn's build scripts are always one-offs, and attach the current target
|
||||
# to the builder, so we have to provide a shim to our StaticLibrary() method.
|
||||
def StaticLibrary(self, builder, name):
|
||||
return SM.StaticLibrary(builder, builder.cxx, name)
|
||||
def Program(self, builder, name):
|
||||
return SM.Program(builder, builder.cxx, name)
|
||||
def Library(self, builder, name):
|
||||
return SM.Library(builder, builder.cxx, name)
|
||||
|
||||
@property
|
||||
def targets(self):
|
||||
return SM.all_targets
|
||||
|
||||
@property
|
||||
def libamtl(self):
|
||||
return SM.libamtl
|
||||
|
||||
SP_build_parts = ['core']
|
||||
if getattr(builder.options, 'scripting_only', False):
|
||||
SP_build_parts = ['spcomp']
|
||||
|
||||
# Build SourcePawn externally.
|
||||
SP = builder.Build('sourcepawn/AMBuildScript', {
|
||||
'external_root': SPRoot(),
|
||||
'external_root': SM,
|
||||
'external_amtl': os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||
'external_build': SP_build_parts,
|
||||
'external_build': ['core'],
|
||||
})
|
||||
if len(SP.spcomp) > 1:
|
||||
SM.spcomp = SP.spcomp['x86']
|
||||
else:
|
||||
SM.spcomp = SP.spcomp[list(SP.spcomp.keys())[0]]
|
||||
SM.spcomp_bins = list(SP.spcomp.values())
|
||||
SM.spcomp = SP.spcomp
|
||||
SM.binaries += [
|
||||
SP.libsourcepawn
|
||||
]
|
||||
|
||||
if not getattr(builder.options, 'scripting_only', False):
|
||||
for cxx in SM.all_targets:
|
||||
SM.spvm += [
|
||||
SP.libsourcepawn[cxx.target.arch]
|
||||
]
|
||||
BuildScripts = [
|
||||
'loader/AMBuilder',
|
||||
'core/AMBuilder',
|
||||
'core/logic/AMBuilder',
|
||||
'extensions/bintools/AMBuilder',
|
||||
'extensions/clientprefs/AMBuilder',
|
||||
'extensions/curl/AMBuilder',
|
||||
'extensions/cstrike/AMBuilder',
|
||||
'extensions/geoip/AMBuilder',
|
||||
'extensions/mysql/AMBuilder',
|
||||
'extensions/regex/AMBuilder',
|
||||
'extensions/sdkhooks/AMBuilder',
|
||||
'extensions/sdktools/AMBuilder',
|
||||
'extensions/sqlite/AMBuilder',
|
||||
'extensions/tf2/AMBuilder',
|
||||
'extensions/topmenus/AMBuilder',
|
||||
'extensions/updater/AMBuilder',
|
||||
]
|
||||
|
||||
if getattr(builder.options, 'scripting_only', False):
|
||||
BuildScripts = [
|
||||
'tools/buildbot/PackageHelpers',
|
||||
'tools/buildbot/ToolsPackageScript',
|
||||
if builder.backend == 'amb2':
|
||||
BuildScripts += [
|
||||
'plugins/AMBuilder',
|
||||
'tools/buildbot/PackageScript',
|
||||
]
|
||||
else:
|
||||
BuildScripts = [
|
||||
'loader/AMBuilder',
|
||||
'core/AMBuilder',
|
||||
'core/logic/AMBuilder',
|
||||
'extensions/bintools/AMBuilder',
|
||||
'extensions/clientprefs/AMBuilder',
|
||||
'extensions/curl/AMBuilder',
|
||||
'extensions/cstrike/AMBuilder',
|
||||
'extensions/dhooks/AMBuilder',
|
||||
'extensions/geoip/AMBuilder',
|
||||
'extensions/mysql/AMBuilder',
|
||||
'extensions/pgsql/AMBuilder',
|
||||
'extensions/regex/AMBuilder',
|
||||
'extensions/sdkhooks/AMBuilder',
|
||||
'extensions/sdktools/AMBuilder',
|
||||
'extensions/sqlite/AMBuilder',
|
||||
'extensions/tf2/AMBuilder',
|
||||
'extensions/topmenus/AMBuilder',
|
||||
'extensions/updater/AMBuilder',
|
||||
]
|
||||
|
||||
if builder.backend == 'amb2':
|
||||
BuildScripts += [
|
||||
'plugins/AMBuilder',
|
||||
'tools/buildbot/PackageHelpers',
|
||||
'tools/buildbot/PackageScript',
|
||||
]
|
||||
|
||||
builder.Build(BuildScripts, { 'SM': SM })
|
||||
|
||||
|
||||
@@ -14,14 +14,4 @@ Development
|
||||
- [Issue tracker](https://github.com/alliedmodders/sourcemod/issues): Issues that require back and forth communication
|
||||
- [Building SourceMod](https://wiki.alliedmods.net/Building_SourceMod): Instructions on how to build SourceMod itself using [AMBuild](https://github.com/alliedmodders/ambuild)
|
||||
- [SourcePawn scripting](https://wiki.alliedmods.net/Category:SourceMod_Scripting): SourcePawn examples and introduction to the language
|
||||
- [SourceMod plugin API](https://sm.alliedmods.net/new-api): Online SourceMod plugin API reference generated from the include files
|
||||
- [SourceMod extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces
|
||||
|
||||
Contact
|
||||
-------
|
||||
- Connect with us on [GameSurge](https://gamesurge.net) IRC in #sourcemod
|
||||
- Alternatively feel free to join our [Discord](https://discord.gg/HgZctSS) server
|
||||
|
||||
License
|
||||
-------
|
||||
SourceMod is licensed under the GNU General Public License version 3. Special exceptions are outlined in the LICENSE.txt file inside of the licenses folder.
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
version: 1.0.{build}
|
||||
image: Visual Studio 2015
|
||||
clone_folder: c:/projects/sourcemod
|
||||
clone_depth: 1
|
||||
install:
|
||||
- cmd: set PATH=C:\Python38;C:\Python38\Scripts;%PATH%
|
||||
- cmd: git submodule update --init --recursive
|
||||
- cmd: git pull --recurse-submodules
|
||||
- cmd: cd ..
|
||||
- ps: sourcemod/tools/checkout-deps.ps1 -SDKs episode1,css,tf2,l4d2,csgo
|
||||
- cmd: cd sourcemod
|
||||
build_script:
|
||||
- cmd: call "%VS140COMNTOOLS%/vsvars32.bat"
|
||||
- cmd: mkdir build
|
||||
- cmd: cd build
|
||||
- cmd: python.exe ../configure.py --enable-optimize --no-mysql --sdks=episode1,css,tf2,l4d2,csgo
|
||||
- cmd: ambuild
|
||||
@@ -35,7 +35,7 @@ namespace SourceMod {
|
||||
|
||||
// Add 1 to the RHS of this expression to bump the intercom file
|
||||
// This is to prevent mismatching core/logic binaries
|
||||
static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 57;
|
||||
static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 55;
|
||||
|
||||
} // namespace SourceMod
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ struct DatabaseInfo;
|
||||
class IPlayerInfoBridge;
|
||||
class ICommandArgs;
|
||||
|
||||
typedef ke::Function<bool(int client, const ICommandArgs*)> CommandFunc;
|
||||
typedef ke::Lambda<bool(int client, const ICommandArgs*)> CommandFunc;
|
||||
|
||||
class CoreProvider
|
||||
{
|
||||
@@ -115,8 +115,6 @@ public:
|
||||
virtual void ConsolePrint(const char *fmt, ...) = 0;
|
||||
virtual void ConsolePrintVa(const char *fmt, va_list ap) = 0;
|
||||
|
||||
virtual void FormatSourceBinaryName(const char *basename, char *buffer, size_t maxlength) = 0;
|
||||
|
||||
// Game engine helper functions.
|
||||
virtual bool IsClientConVarQueryingSupported() = 0;
|
||||
virtual int QueryClientConVar(int client, const char *cvar) = 0;
|
||||
|
||||
@@ -50,6 +50,7 @@ class IProviderCallbacks;
|
||||
class IExtensionSys;
|
||||
class ITextParsers;
|
||||
class ILogger;
|
||||
class IDataPack;
|
||||
class ICellArray;
|
||||
|
||||
struct sm_logic_t
|
||||
@@ -69,13 +70,10 @@ struct sm_logic_t
|
||||
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
|
||||
void (*AddNatives)(sp_nativeinfo_t *natives);
|
||||
void (*RegisterProfiler)(IProfilingTool *tool);
|
||||
IDataPack * (*CreateDataPack)();
|
||||
void (*FreeDataPack)(IDataPack *pack);
|
||||
ICellArray * (*CreateCellArray)(size_t blocksize);
|
||||
void (*FreeCellArray)(ICellArray *arr);
|
||||
void * (*FromPseudoAddress)(uint32_t pseudoAddr);
|
||||
uint32_t (*ToPseudoAddress)(void *addr);
|
||||
void (*SetEntityLumpWritable)(bool writable);
|
||||
bool (*ParseEntityLumpString)(const char *entityString, int &status, size_t &position);
|
||||
const char * (*GetEntityLumpString)();
|
||||
IScriptManager *scripts;
|
||||
IShareSys *sharesys;
|
||||
IExtensionSys *extsys;
|
||||
|
||||
+1
-11
@@ -145,15 +145,5 @@
|
||||
* Disable this option at your own risk.
|
||||
*/
|
||||
"FollowCSGOServerGuidelines" "yes"
|
||||
|
||||
/**
|
||||
* Controls whether the SourcePawn runtime will generate additional metadata about
|
||||
* JIT-compiled functions for performance profiling or debugging purposes.
|
||||
*
|
||||
* "none" - Don't generate any additional JIT metadata
|
||||
* "default" - Generate basic perf metadata (on Linux) and delete it automatically on quit
|
||||
* "perf" - Generate basic perf metadata (Linux only - function names)
|
||||
* "jitdump" - Generate extended perf metadata (Linux only - function names, bytecode, and source information)
|
||||
*/
|
||||
"JITMetadata" "default"
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,41 +0,0 @@
|
||||
CREATE TABLE IF NOT EXISTS sm_cookies
|
||||
(
|
||||
id serial,
|
||||
name varchar(30) NOT NULL UNIQUE,
|
||||
description varchar(255),
|
||||
access INTEGER,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sm_cookie_cache
|
||||
(
|
||||
player varchar(65) NOT NULL,
|
||||
cookie_id int NOT NULL,
|
||||
value varchar(100),
|
||||
timestamp int NOT NULL,
|
||||
PRIMARY KEY (player, cookie_id)
|
||||
);
|
||||
|
||||
CREATE LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION add_or_update_cookie(in_player VARCHAR(65), in_cookie INT, in_value VARCHAR(100), in_time INT) RETURNS VOID AS
|
||||
$$
|
||||
BEGIN
|
||||
LOOP
|
||||
-- first try to update the it.
|
||||
UPDATE sm_cookie_cache SET value = in_value, timestamp = in_time WHERE player = in_player AND cookie_id = in_cookie;
|
||||
IF found THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
-- not there, so try to insert.
|
||||
-- if someone else inserts the same key concurrently, we could get a unique-key failure.
|
||||
BEGIN
|
||||
INSERT INTO sm_cookie_cache (player, cookie_id, value, timestamp) VALUES (in_player, in_cookie, in_value, in_time);
|
||||
RETURN;
|
||||
EXCEPTION WHEN unique_violation THEN
|
||||
-- do nothing... loop again, and we'll update.
|
||||
END;
|
||||
END LOOP;
|
||||
END;
|
||||
$$
|
||||
LANGUAGE plpgsql;
|
||||
@@ -1,65 +0,0 @@
|
||||
CREATE TABLE sm_admins (
|
||||
id serial,
|
||||
authtype varchar(6) NOT NULL,
|
||||
CHECK (authtype in ('steam', 'name', 'ip')),
|
||||
identity varchar(65) NOT NULL,
|
||||
password varchar(65),
|
||||
flags varchar(30) NOT NULL,
|
||||
name varchar(65) NOT NULL,
|
||||
immunity int NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE sm_groups (
|
||||
id serial,
|
||||
flags varchar(30) NOT NULL,
|
||||
name varchar(120) NOT NULL,
|
||||
immunity_level int NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE sm_group_immunity (
|
||||
group_id int NOT NULL,
|
||||
other_id int NOT NULL,
|
||||
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (other_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (group_id, other_id)
|
||||
);
|
||||
|
||||
CREATE TABLE sm_group_overrides (
|
||||
group_id int NOT NULL,
|
||||
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
||||
type varchar(10) NOT NULL,
|
||||
CHECK (type in ('command', 'group')),
|
||||
name varchar(32) NOT NULL,
|
||||
access varchar(5) NOT NULL,
|
||||
CHECK (access in ('allow', 'deny')),
|
||||
PRIMARY KEY (group_id, type, name)
|
||||
);
|
||||
|
||||
CREATE TABLE sm_overrides (
|
||||
type varchar(10) NOT NULL,
|
||||
CHECK (type in ('command', 'group')),
|
||||
name varchar(32) NOT NULL,
|
||||
flags varchar(30) NOT NULL,
|
||||
PRIMARY KEY (type,name)
|
||||
);
|
||||
|
||||
CREATE TABLE sm_admins_groups (
|
||||
admin_id int NOT NULL,
|
||||
group_id int NOT NULL,
|
||||
FOREIGN KEY (admin_id) REFERENCES sm_admins(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
|
||||
inherit_order int NOT NULL,
|
||||
PRIMARY KEY (admin_id, group_id)
|
||||
);
|
||||
|
||||
-- side note, this is pgsql module, sm_config will not exist if the above stuff exists... and it's being left to the admin
|
||||
-- to figure out if it exists.
|
||||
CREATE TABLE sm_config (
|
||||
cfg_key varchar(32) NOT NULL,
|
||||
cfg_value varchar(255) NOT NULL,
|
||||
PRIMARY KEY (cfg_key)
|
||||
);
|
||||
|
||||
INSERT INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409');
|
||||
+28
-37
@@ -1,49 +1,40 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet:
|
||||
import sys
|
||||
try:
|
||||
from ambuild2 import run, util
|
||||
from ambuild2 import run, util
|
||||
except:
|
||||
try:
|
||||
import ambuild
|
||||
sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n')
|
||||
sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n')
|
||||
except:
|
||||
sys.stderr.write('AMBuild must be installed to build this project.\n')
|
||||
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
|
||||
sys.exit(1)
|
||||
try:
|
||||
import ambuild
|
||||
sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n')
|
||||
sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n')
|
||||
except:
|
||||
sys.stderr.write('AMBuild must be installed to build this project.\n')
|
||||
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
|
||||
sys.exit(1)
|
||||
|
||||
# Hack to show a decent upgrade message, which wasn't done until 2.2.
|
||||
ambuild_version = getattr(run, 'CURRENT_API', '2.1')
|
||||
if ambuild_version.startswith('2.1'):
|
||||
sys.stderr.write("AMBuild 2.2 or higher is required; please update\n")
|
||||
sys.exit(1)
|
||||
def make_objdir_name(p):
|
||||
return 'obj-' + util.Platform() + '-' + p.target_arch
|
||||
|
||||
parser = run.BuildParser(sourcePath=sys.path[0], api='2.2')
|
||||
parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
|
||||
help='Root search folder for HL2SDKs')
|
||||
parser.options.add_argument('--mysql-path', type=str, dest='mysql_path', default=None,
|
||||
help='Path to MySQL 5')
|
||||
parser.options.add_argument('--mysql64-path', type=str, dest='mysql64_path', default=None,
|
||||
help='Path to 64-bit MySQL 5')
|
||||
parser.options.add_argument('--mms-path', type=str, dest='mms_path', default=None,
|
||||
parser = run.BuildParser(sourcePath=sys.path[0], api='2.1')
|
||||
parser.default_arch = 'x86'
|
||||
parser.default_build_folder = make_objdir_name
|
||||
parser.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
|
||||
help='Root search folder for HL2SDKs')
|
||||
parser.options.add_option('--mysql-path', type=str, dest='mysql_path', default=None,
|
||||
help='Path to MySQL 5')
|
||||
parser.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
|
||||
help='Path to Metamod:Source')
|
||||
parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug',
|
||||
parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
|
||||
help='Enable debugging symbols')
|
||||
parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt',
|
||||
parser.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
||||
help='Enable optimization')
|
||||
parser.options.add_argument('--no-mysql', action='store_false', default=True, dest='hasMySql',
|
||||
parser.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
|
||||
help='Disable building MySQL extension')
|
||||
parser.options.add_argument('-s', '--sdks', default='present', dest='sdks',
|
||||
help='Build against specified SDKs; valid args are "none", "all", "present",'
|
||||
' or comma-delimited list of engine names')
|
||||
parser.options.add_argument('--breakpad-dump', action='store_true', dest='breakpad_dump',
|
||||
default=False, help='Dump and upload breakpad symbols')
|
||||
parser.options.add_argument('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
|
||||
parser.options.add_option('-s', '--sdks', default='all', dest='sdks',
|
||||
help='Build against specified SDKs; valid args are "all", "present", or '
|
||||
'comma-delimited list of engine names (default: %default)')
|
||||
parser.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
|
||||
default=False, help='Dump and upload breakpad symbols')
|
||||
parser.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
|
||||
default=False, help='Disable the auto versioning script')
|
||||
parser.options.add_argument('--targets', type=str, dest='targets', default=None,
|
||||
help="Override the target architecture (use commas to separate multiple targets).")
|
||||
parser.options.add_argument('--scripting-only', action='store_true', dest='scripting_only', default=False,
|
||||
help="Only build and package the files required for scripting in SourcePawn.")
|
||||
parser.options.add_argument('--enable-asan', action='store_true', dest='enable_asan',
|
||||
default=False, help='Enable ASAN (clang only)')
|
||||
parser.Configure()
|
||||
|
||||
+47
-78
@@ -1,8 +1,7 @@
|
||||
# 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
|
||||
|
||||
project = builder.LibraryProject('sourcemod')
|
||||
|
||||
project = SM.HL2Project(builder, 'sourcemod')
|
||||
project.sources += [
|
||||
'MenuStyle_Valve.cpp',
|
||||
'logic_bridge.cpp',
|
||||
@@ -38,98 +37,68 @@ project.sources += [
|
||||
'MenuStyle_Radio.cpp',
|
||||
'sm_autonatives.cpp',
|
||||
'ConsoleDetours.cpp',
|
||||
'vprof_tool.cpp',
|
||||
'smn_commandline.cpp',
|
||||
'GameHooks.cpp',
|
||||
]
|
||||
|
||||
for sdk_name in SM.sdks:
|
||||
sdk = SM.sdks[sdk_name]
|
||||
for cxx in builder.targets:
|
||||
if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]:
|
||||
continue
|
||||
binary_name = 'sourcemod.' + sdk.ext
|
||||
|
||||
binary_name = 'sourcemod.' + sdk.ext
|
||||
binary = SM.HL2Config(project, binary_name, sdk)
|
||||
compiler = binary.compiler
|
||||
|
||||
binary = SM.HL2Config(project, builder, cxx, binary_name, sdk)
|
||||
SM.ConfigureForExtension(builder, binary.compiler)
|
||||
compiler.cxxincludes += [
|
||||
builder.sourcePath
|
||||
]
|
||||
|
||||
compiler = binary.compiler
|
||||
if sdk.name == 'csgo':
|
||||
compiler.cxxincludes += [
|
||||
builder.sourcePath
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||
]
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||
]
|
||||
elif sdk.name == 'blade':
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf')
|
||||
]
|
||||
if compiler.like('msvc'):
|
||||
compiler.defines += ['_XKEYCHECK_H']
|
||||
|
||||
if compiler.like('msvc'):
|
||||
compiler.defines += ['_ALLOW_KEYWORD_MACROS']
|
||||
if cxx.target.platform == 'linux':
|
||||
compiler.postlink += ['-lpthread', '-lrt']
|
||||
if builder.target.platform == 'linux':
|
||||
compiler.postlink += ['-lpthread', '-lrt']
|
||||
|
||||
if sdk.name in ['csgo', 'blade']:
|
||||
if compiler.target.platform == 'linux':
|
||||
if compiler.target.arch == 'x86':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||
elif compiler.target.arch == 'x86_64':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'linux64', 'release', 'libprotobuf.a')
|
||||
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
|
||||
elif compiler.target.platform == 'mac':
|
||||
if compiler.target.arch == 'x86':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
||||
elif compiler.target.arch == 'x86_64':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
|
||||
elif compiler.target.platform == 'windows':
|
||||
msvc_ver = compiler.version
|
||||
vs_year = ''
|
||||
platform = ''
|
||||
if compiler.target.arch == 'x86':
|
||||
platform = 'win32'
|
||||
elif compiler.target.arch == 'x86_64':
|
||||
platform = 'win64'
|
||||
|
||||
if 1900 <= msvc_ver < 2000:
|
||||
vs_year = '2015'
|
||||
else:
|
||||
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
|
||||
if sdk.name == 'csgo':
|
||||
if builder.target.platform == 'linux':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
|
||||
elif builder.target.platform == 'mac':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
||||
elif builder.target.platform == 'windows':
|
||||
msvc_ver = compiler.version
|
||||
vs_year = ''
|
||||
if msvc_ver == 1800:
|
||||
vs_year = '2013'
|
||||
elif 1900 <= msvc_ver < 2000:
|
||||
vs_year = '2015'
|
||||
else:
|
||||
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
|
||||
|
||||
if 'DEBUG' in compiler.defines:
|
||||
lib_path = os.path.join(sdk.path, 'lib', platform, 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
else:
|
||||
lib_path = os.path.join(sdk.path, 'lib', platform, 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
compiler.linkflags.insert(0, lib_path)
|
||||
if 'DEBUG' in compiler.defines:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
else:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
||||
|
||||
if sdk.name in ['csgo', 'blade']:
|
||||
binary.sources += ['smn_protobuf.cpp']
|
||||
else:
|
||||
binary.sources += ['smn_bitbuffer.cpp']
|
||||
if sdk.name == 'csgo':
|
||||
binary.sources += ['smn_protobuf.cpp']
|
||||
else:
|
||||
binary.sources += ['smn_bitbuffer.cpp']
|
||||
|
||||
if sdk.name != 'blade':
|
||||
binary.sources += [
|
||||
'vprof_tool.cpp',
|
||||
]
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||
]
|
||||
elif sdk.name == 'blade':
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf', 'berimbau_usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf', 'berimbau_usermessage_helpers.cpp'),
|
||||
]
|
||||
if sdk.name == 'csgo':
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||
]
|
||||
|
||||
SM.binaries += builder.Add(project)
|
||||
|
||||
|
||||
+21
-15
@@ -29,8 +29,6 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <ITextParsers.h>
|
||||
#include "ChatTriggers.h"
|
||||
#include "sm_stringutil.h"
|
||||
@@ -66,7 +64,7 @@ ChatTriggers::~ChatTriggers()
|
||||
|
||||
void ChatTriggers::SetChatTrigger(ChatTriggerType type, const char *value)
|
||||
{
|
||||
std::unique_ptr<char[]> filtered(new char[strlen(value) + 1]);
|
||||
ke::AutoPtr<char[]> filtered(new char[strlen(value) + 1]);
|
||||
|
||||
const char *src = value;
|
||||
char *dest = filtered.get();
|
||||
@@ -137,26 +135,26 @@ void ChatTriggers::OnSourceModGameInitialized()
|
||||
};
|
||||
|
||||
if (ConCommand *say = FindCommand("say")) {
|
||||
hooks_.push_back(sCoreProviderImpl.AddCommandHook(say, pre_hook));
|
||||
hooks_.push_back(sCoreProviderImpl.AddPostCommandHook(say, post_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddCommandHook(say, pre_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say, post_hook));
|
||||
}
|
||||
if (ConCommand *say_team = FindCommand("say_team")) {
|
||||
hooks_.push_back(sCoreProviderImpl.AddCommandHook(say_team, pre_hook));
|
||||
hooks_.push_back(sCoreProviderImpl.AddPostCommandHook(say_team, post_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddCommandHook(say_team, pre_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_team, post_hook));
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
|
||||
if (m_bIsINS) {
|
||||
if (ConCommand *say2 = FindCommand("say2")) {
|
||||
hooks_.push_back(sCoreProviderImpl.AddCommandHook(say2, pre_hook));
|
||||
hooks_.push_back(sCoreProviderImpl.AddPostCommandHook(say2, post_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddCommandHook(say2, pre_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say2, post_hook));
|
||||
}
|
||||
}
|
||||
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
if (ConCommand *say_squad = FindCommand("say_squad")) {
|
||||
hooks_.push_back(sCoreProviderImpl.AddCommandHook(say_squad, pre_hook));
|
||||
hooks_.push_back(sCoreProviderImpl.AddPostCommandHook(say_squad, post_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddCommandHook(say_squad, pre_hook));
|
||||
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_squad, post_hook));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -277,10 +275,10 @@ bool ChatTriggers::OnSayCommand_Pre(int client, const ICommandArgs *command)
|
||||
bool is_silent = false;
|
||||
|
||||
// Prefer the silent trigger in case of clashes.
|
||||
if (strchr(m_PrivTrigger.c_str(), m_ArgSBackup[0])) {
|
||||
if (strchr(m_PrivTrigger.chars(), m_ArgSBackup[0])) {
|
||||
is_trigger = true;
|
||||
is_silent = true;
|
||||
} else if (strchr(m_PubTrigger.c_str(), m_ArgSBackup[0])) {
|
||||
} else if (strchr(m_PubTrigger.chars(), m_ArgSBackup[0])) {
|
||||
is_trigger = true;
|
||||
}
|
||||
|
||||
@@ -363,7 +361,7 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
||||
if (!g_ConCmds.LookForSourceModCommand(cmd_buf))
|
||||
{
|
||||
/* Check if we had an "sm_" prefix */
|
||||
if (strncasecmp(cmd_buf, "sm_", 3) == 0)
|
||||
if (strncmp(cmd_buf, "sm_", 3) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -387,7 +385,15 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
|
||||
/* See if we need to do extra string manipulation */
|
||||
if (prepended)
|
||||
{
|
||||
ke::SafeSprintf(m_ToExecute, sizeof(m_ToExecute), "sm_%s", args);
|
||||
size_t len;
|
||||
|
||||
/* Check if we need to prepend sm_ */
|
||||
if (prepended)
|
||||
{
|
||||
len = ke::SafeSprintf(m_ToExecute, sizeof(m_ToExecute), "sm_%s", args);
|
||||
} else {
|
||||
len = ke::SafeStrcpy(m_ToExecute, sizeof(m_ToExecute), args);
|
||||
}
|
||||
} else {
|
||||
ke::SafeStrcpy(m_ToExecute, sizeof(m_ToExecute), args);
|
||||
}
|
||||
|
||||
+3
-3
@@ -73,9 +73,9 @@ private:
|
||||
bool ClientIsFlooding(int client);
|
||||
cell_t CallOnClientSayCommand(int client);
|
||||
private:
|
||||
std::vector<ke::RefPtr<CommandHook>> hooks_;
|
||||
std::string m_PubTrigger;
|
||||
std::string m_PrivTrigger;
|
||||
ke::Vector<ke::RefPtr<CommandHook>> hooks_;
|
||||
ke::AString m_PubTrigger;
|
||||
ke::AString m_PrivTrigger;
|
||||
bool m_bWillProcessInPost;
|
||||
bool m_bIsChatTrigger;
|
||||
bool m_bWasFloodedMessage;
|
||||
|
||||
+60
-38
@@ -30,22 +30,21 @@
|
||||
*/
|
||||
|
||||
#include "ConCmdManager.h"
|
||||
|
||||
#include <bridge/include/IScriptManager.h>
|
||||
#include "ChatTriggers.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "command_args.h"
|
||||
#include "logic_bridge.h"
|
||||
#include "provider.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "HalfLife2.h"
|
||||
#include "ChatTriggers.h"
|
||||
#include "logic_bridge.h"
|
||||
#include "sourcemod.h"
|
||||
#include "provider.h"
|
||||
#include "command_args.h"
|
||||
#include <bridge/include/IScriptManager.h>
|
||||
|
||||
using namespace ke;
|
||||
|
||||
ConCmdManager g_ConCmds;
|
||||
|
||||
typedef std::list<CmdHook *> PluginHookList;
|
||||
typedef ke::LinkedList<CmdHook *> PluginHookList;
|
||||
void RegisterInPlugin(CmdHook *hook);
|
||||
|
||||
ConCmdManager::ConCmdManager()
|
||||
@@ -121,13 +120,8 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
||||
if (hook->admin)
|
||||
hook->admin->group->hooks.remove(hook);
|
||||
|
||||
if (hook->info->hooks.empty()) {
|
||||
if (hook->info->hooks.empty())
|
||||
RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true);
|
||||
}
|
||||
else { // update plugin reference to next hook in line
|
||||
auto next = *hook->info->hooks.begin();
|
||||
next->info->pPlugin = next->plugin;
|
||||
}
|
||||
|
||||
iter = pList->erase(iter);
|
||||
delete hook;
|
||||
@@ -153,13 +147,30 @@ ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
ConCmdList::iterator ConCmdManager::FindInList(const char *cmd)
|
||||
{
|
||||
List<ConCmdInfo *>::iterator iter = m_CmdList.begin();
|
||||
|
||||
while (iter != m_CmdList.end())
|
||||
{
|
||||
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
|
||||
break;
|
||||
iter++;
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int args, ResultType type)
|
||||
{
|
||||
ConCmdInfo *pInfo = FindInTrie(cmd);
|
||||
ConCmdInfo *pInfo;
|
||||
|
||||
if (pInfo == NULL)
|
||||
if ((pInfo = FindInTrie(cmd)) == NULL)
|
||||
{
|
||||
return type;
|
||||
ConCmdList::iterator item = FindInList(cmd);
|
||||
if (item == m_CmdList.end())
|
||||
return type;
|
||||
pInfo = *item;
|
||||
}
|
||||
|
||||
cell_t result = type;
|
||||
@@ -170,7 +181,7 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
|
||||
if (hook->type == CmdHook::Server || !hook->pf->IsRunnable())
|
||||
continue;
|
||||
|
||||
if (hook->admin && !CheckAccess(client, cmd, hook->admin.get()))
|
||||
if (hook->admin && !CheckAccess(client, cmd, hook->admin))
|
||||
{
|
||||
if (result < Pl_Handled)
|
||||
result = Pl_Handled;
|
||||
@@ -214,7 +225,17 @@ bool ConCmdManager::InternalDispatch(int client, const ICommandArgs *args)
|
||||
ConCmdInfo *pInfo = FindInTrie(cmd);
|
||||
if (pInfo == NULL)
|
||||
{
|
||||
return false;
|
||||
/* Unfortunately, we now have to do a slow lookup because Valve made client commands
|
||||
* case-insensitive. We can't even use our sortedness.
|
||||
*/
|
||||
if (client == 0 && !engine->IsDedicatedServer())
|
||||
return false;
|
||||
|
||||
ConCmdList::iterator item = FindInList(cmd);
|
||||
if (item == m_CmdList.end())
|
||||
return false;
|
||||
|
||||
pInfo = *item;
|
||||
}
|
||||
|
||||
/* This is a hack to prevent say triggers from firing on messages that were
|
||||
@@ -250,7 +271,7 @@ bool ConCmdManager::InternalDispatch(int client, const ICommandArgs *args)
|
||||
} else {
|
||||
// Check admin rights if needed. realClient isn't needed since we
|
||||
// should bypass admin checks if client == 0 anyway.
|
||||
if (client && hook->admin && !CheckAccess(client, cmd, hook->admin.get()))
|
||||
if (client && hook->admin && !CheckAccess(client, cmd, hook->admin))
|
||||
{
|
||||
if (result < Pl_Handled)
|
||||
result = Pl_Handled;
|
||||
@@ -296,7 +317,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
|
||||
char buffer[128];
|
||||
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
|
||||
{
|
||||
ke::SafeStrcpy(buffer, sizeof(buffer), "You do not have access to this command");
|
||||
ke::SafeSprintf(buffer, sizeof(buffer), "You do not have access to this command");
|
||||
}
|
||||
|
||||
unsigned int replyto = g_ChatTriggers.GetReplyTo();
|
||||
@@ -321,10 +342,9 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *group,
|
||||
int adminflags,
|
||||
const char *description,
|
||||
int flags,
|
||||
IPlugin *pPlugin)
|
||||
int flags)
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
|
||||
if (!pInfo)
|
||||
return false;
|
||||
@@ -338,8 +358,8 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
}
|
||||
RefPtr<CommandGroup> cmdgroup = i->value;
|
||||
|
||||
CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description, pPlugin);
|
||||
pHook->admin = std::make_unique<AdminCmdInfo>(cmdgroup, adminflags);
|
||||
CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description);
|
||||
pHook->admin = new AdminCmdInfo(cmdgroup, adminflags);
|
||||
|
||||
/* First get the command group override, if any */
|
||||
bool override = adminsys->GetCommandOverride(group,
|
||||
@@ -359,7 +379,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
pHook->admin->eflags = pHook->admin->flags;
|
||||
pInfo->eflags = pHook->admin->eflags;
|
||||
|
||||
cmdgroup->hooks.push_back(pHook);
|
||||
cmdgroup->hooks.append(pHook);
|
||||
pInfo->hooks.append(pHook);
|
||||
RegisterInPlugin(pHook);
|
||||
return true;
|
||||
@@ -368,16 +388,15 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *description,
|
||||
int flags,
|
||||
IPlugin *pPlugin)
|
||||
int flags)
|
||||
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
|
||||
if (!pInfo)
|
||||
return false;
|
||||
|
||||
CmdHook *pHook = new CmdHook(CmdHook::Server, pInfo, pFunction, description, pPlugin);
|
||||
CmdHook *pHook = new CmdHook(CmdHook::Server, pInfo, pFunction, description);
|
||||
|
||||
pInfo->hooks.append(pHook);
|
||||
RegisterInPlugin(pHook);
|
||||
@@ -404,13 +423,13 @@ void RegisterInPlugin(CmdHook *hook)
|
||||
const char *cmd = (*iter)->info->pCmd->GetName();
|
||||
if (strcmp(orig, cmd) < 0)
|
||||
{
|
||||
pList->emplace(iter, hook);
|
||||
pList->insertBefore(iter, hook);
|
||||
return;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
pList->emplace_back(hook);
|
||||
pList->append(hook);
|
||||
}
|
||||
|
||||
void ConCmdManager::AddToCmdList(ConCmdInfo *info)
|
||||
@@ -474,7 +493,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
|
||||
for (PluginHookList::iterator iter = group->hooks.begin(); iter != group->hooks.end(); iter++)
|
||||
{
|
||||
CmdHook *hook = *iter;
|
||||
if (!remove)
|
||||
if (remove)
|
||||
hook->admin->eflags = bits;
|
||||
else
|
||||
hook->admin->eflags = hook->admin->flags;
|
||||
@@ -536,11 +555,15 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
|
||||
return true;
|
||||
}
|
||||
|
||||
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin)
|
||||
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
|
||||
{
|
||||
ConCmdInfo *pInfo;
|
||||
if (!m_Cmds.retrieve(name, &pInfo))
|
||||
{
|
||||
ConCmdList::iterator item = FindInList(name);
|
||||
if (item != m_CmdList.end())
|
||||
return *item;
|
||||
|
||||
pInfo = new ConCmdInfo();
|
||||
/* Find the commandopan */
|
||||
ConCommand *pCmd = FindCommand(name);
|
||||
@@ -557,7 +580,6 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
|
||||
char *new_name = sm_strdup(name);
|
||||
char *new_help = sm_strdup(description);
|
||||
pCmd = new ConCommand(new_name, CommandCallback, new_help, flags);
|
||||
pInfo->pPlugin = pPlugin;
|
||||
pInfo->sourceMod = true;
|
||||
}
|
||||
else
|
||||
@@ -623,7 +645,7 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs
|
||||
|
||||
name = hook->info->pCmd->GetName();
|
||||
if (hook->helptext.length())
|
||||
help = hook->helptext.c_str();
|
||||
help = hook->helptext.chars();
|
||||
else
|
||||
help = hook->info->pCmd->GetHelpText();
|
||||
UTIL_ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
|
||||
|
||||
+19
-43
@@ -32,14 +32,6 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
||||
#define _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include <am-inlinelist.h>
|
||||
#include <am-refcounting.h>
|
||||
#include <am-utility.h>
|
||||
#include <sm_stringhashmap.h>
|
||||
|
||||
#include "sm_globals.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include <IForwardSys.h>
|
||||
@@ -49,7 +41,11 @@
|
||||
#include <IAdminSystem.h>
|
||||
#include "concmd_cleaner.h"
|
||||
#include "GameHooks.h"
|
||||
#include <sm_namehashset.h>
|
||||
#include <sm_stringhashmap.h>
|
||||
#include <am-utility.h>
|
||||
#include <am-inlinelist.h>
|
||||
#include <am-linkedlist.h>
|
||||
#include <am-refcounting.h>
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
@@ -58,7 +54,7 @@ struct ConCmdInfo;
|
||||
|
||||
struct CommandGroup : public ke::Refcounted<CommandGroup>
|
||||
{
|
||||
std::list<CmdHook *> hooks;
|
||||
ke::LinkedList<CmdHook *> hooks;
|
||||
};
|
||||
|
||||
struct AdminCmdInfo
|
||||
@@ -81,11 +77,10 @@ struct CmdHook : public ke::InlineListNode<CmdHook>
|
||||
Client
|
||||
};
|
||||
|
||||
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description, IPlugin *plugin)
|
||||
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description)
|
||||
: type(type),
|
||||
info(cmd),
|
||||
pf(fun),
|
||||
plugin(plugin),
|
||||
helptext(description)
|
||||
{
|
||||
}
|
||||
@@ -93,9 +88,8 @@ struct CmdHook : public ke::InlineListNode<CmdHook>
|
||||
Type type;
|
||||
ConCmdInfo *info;
|
||||
IPluginFunction *pf; /* function hook */
|
||||
IPlugin *plugin; /* owning plugin */
|
||||
std::string helptext; /* help text */
|
||||
std::unique_ptr<AdminCmdInfo> admin; /* admin requirements, if any */
|
||||
ke::AString helptext; /* help text */
|
||||
ke::AutoPtr<AdminCmdInfo> admin; /* admin requirements, if any */
|
||||
};
|
||||
|
||||
typedef ke::InlineList<CmdHook> CmdHookList;
|
||||
@@ -104,37 +98,15 @@ struct ConCmdInfo
|
||||
{
|
||||
ConCmdInfo()
|
||||
{
|
||||
pPlugin = nullptr;
|
||||
sourceMod = false;
|
||||
pCmd = nullptr;
|
||||
pCmd = NULL;
|
||||
eflags = 0;
|
||||
}
|
||||
|
||||
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
|
||||
ConCommand *pCmd; /**< Pointer to the command itself */
|
||||
CmdHookList hooks; /**< Hook list */
|
||||
FlagBits eflags; /**< Effective admin flags */
|
||||
ke::RefPtr<CommandHook> sh_hook; /**< SourceHook hook, if any. */
|
||||
IPlugin *pPlugin; /**< Owning plugin handle. */
|
||||
|
||||
struct ConCmdPolicy
|
||||
{
|
||||
static inline bool matches(const char *name, ConCmdInfo *info)
|
||||
{
|
||||
const char *conCmdChars = info->pCmd->GetName();
|
||||
|
||||
std::string concmdName = ke::Lowercase(conCmdChars);
|
||||
std::string input = ke::Lowercase(name);
|
||||
|
||||
return concmdName == input;
|
||||
}
|
||||
|
||||
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||
{
|
||||
std::string lower = ke::Lowercase(key.c_str());
|
||||
return detail::CharsAndLength(lower.c_str()).hash();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
typedef List<ConCmdInfo *> ConCmdList;
|
||||
@@ -159,14 +131,13 @@ public: //IRootConsoleCommand
|
||||
public: //IConCommandTracker
|
||||
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override;
|
||||
public:
|
||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags, IPlugin *pPlugin);
|
||||
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
|
||||
bool AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *group,
|
||||
int adminflags,
|
||||
const char *description,
|
||||
int flags,
|
||||
IPlugin *pPlugin);
|
||||
int flags);
|
||||
ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type);
|
||||
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
|
||||
bool LookForSourceModCommand(const char *cmd);
|
||||
@@ -174,10 +145,15 @@ public:
|
||||
private:
|
||||
bool InternalDispatch(int client, const ICommandArgs *args);
|
||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
||||
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin);
|
||||
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
|
||||
void AddToCmdList(ConCmdInfo *info);
|
||||
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool untrack);
|
||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
||||
|
||||
// Case insensitive
|
||||
ConCmdList::iterator FindInList(const char *name);
|
||||
|
||||
// Case sensitive
|
||||
ConCmdInfo *FindInTrie(const char *name);
|
||||
public:
|
||||
inline const List<ConCmdInfo *> & GetCommandList()
|
||||
@@ -187,7 +163,7 @@ public:
|
||||
private:
|
||||
typedef StringHashMap<ke::RefPtr<CommandGroup> > GroupMap;
|
||||
|
||||
NameHashSet<ConCmdInfo *, ConCmdInfo::ConCmdPolicy> m_Cmds; /* command lookup */
|
||||
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
|
||||
GroupMap m_CmdGrps; /* command group map */
|
||||
ConCmdList m_CmdList; /* command list */
|
||||
};
|
||||
|
||||
+10
-47
@@ -41,11 +41,7 @@ ConVarManager g_ConVarManager;
|
||||
|
||||
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
|
||||
typedef List<const ConVar *> ConVarList;
|
||||
NameHashSet<ConVarInfo *, ConVarInfo::ConVarPolicy> convar_cache;
|
||||
|
||||
enum {
|
||||
eQueryCvarValueStatus_Cancelled = -1,
|
||||
};
|
||||
NameHashSet<ConVarInfo *> convar_cache;
|
||||
|
||||
class ConVarReentrancyGuard
|
||||
{
|
||||
@@ -210,27 +206,18 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
|
||||
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
ConVarList *pConVarList;
|
||||
List<ConVarQuery>::iterator iter;
|
||||
|
||||
/* If plugin has a convar list, free its memory */
|
||||
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
|
||||
{
|
||||
delete pConVarList;
|
||||
}
|
||||
|
||||
/* Clear any references to this plugin as the convar creator */
|
||||
for (List<ConVarInfo *>::iterator iter = m_ConVars.begin(); iter != m_ConVars.end(); ++iter)
|
||||
{
|
||||
ConVarInfo *pInfo = (*iter);
|
||||
|
||||
if (pInfo->pPlugin == plugin)
|
||||
{
|
||||
pInfo->pPlugin = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const IPluginRuntime * pRuntime = plugin->GetRuntime();
|
||||
|
||||
/* Remove convar queries for this plugin that haven't returned results yet */
|
||||
for (List<ConVarQuery>::iterator iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
|
||||
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
|
||||
{
|
||||
ConVarQuery &query = (*iter);
|
||||
if (query.pCallback->GetParentRuntime() == pRuntime)
|
||||
@@ -251,19 +238,6 @@ void ConVarManager::OnClientDisconnected(int client)
|
||||
ConVarQuery &query = (*iter);
|
||||
if (query.client == client)
|
||||
{
|
||||
IPluginFunction *pCallback = query.pCallback;
|
||||
if (pCallback)
|
||||
{
|
||||
cell_t ret;
|
||||
|
||||
pCallback->PushCell(query.cookie);
|
||||
pCallback->PushCell(client);
|
||||
pCallback->PushCell(eQueryCvarValueStatus_Cancelled);
|
||||
pCallback->PushString("");
|
||||
pCallback->PushString("");
|
||||
pCallback->PushCell(query.value);
|
||||
pCallback->Execute(&ret);
|
||||
}
|
||||
iter = m_ConVarQueries.erase(iter);
|
||||
continue;
|
||||
}
|
||||
@@ -356,8 +330,6 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
||||
ConVarInfo *pInfo = NULL;
|
||||
Handle_t hndl = 0;
|
||||
|
||||
IPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
|
||||
/* Find out if the convar exists already */
|
||||
pConVar = icvar->FindVar(name);
|
||||
|
||||
@@ -365,16 +337,11 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
||||
if (pConVar)
|
||||
{
|
||||
/* Add convar to plugin's list */
|
||||
AddConVarToPluginList(plugin, pConVar);
|
||||
AddConVarToPluginList(pContext, pConVar);
|
||||
|
||||
/* First find out if we already have a handle to it */
|
||||
if (convar_cache_lookup(name, &pInfo))
|
||||
{
|
||||
/* If the convar doesn't have an owning plugin, but SM created it, adopt it */
|
||||
if (pInfo->sourceMod && pInfo->pPlugin == nullptr) {
|
||||
pInfo->pPlugin = plugin;
|
||||
}
|
||||
|
||||
return pInfo->handle;
|
||||
}
|
||||
else
|
||||
@@ -415,7 +382,6 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
||||
pInfo->handle = hndl;
|
||||
pInfo->sourceMod = true;
|
||||
pInfo->pChangeForward = NULL;
|
||||
pInfo->pPlugin = plugin;
|
||||
|
||||
/* Create a handle from the new convar */
|
||||
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||
@@ -432,7 +398,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
||||
pInfo->pVar = pConVar;
|
||||
|
||||
/* Add convar to plugin's list */
|
||||
AddConVarToPluginList(plugin, pConVar);
|
||||
AddConVarToPluginList(pContext, pConVar);
|
||||
|
||||
/* Insert struct into caches */
|
||||
m_ConVars.push_back(pInfo);
|
||||
@@ -586,13 +552,15 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
|
||||
return cookie;
|
||||
}
|
||||
|
||||
void ConVarManager::AddConVarToPluginList(IPlugin *plugin, const ConVar *pConVar)
|
||||
void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar)
|
||||
{
|
||||
ConVarList *pConVarList;
|
||||
ConVarList::iterator iter;
|
||||
bool inserted = false;
|
||||
const char *orig = pConVar->GetName();
|
||||
|
||||
IPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext());
|
||||
|
||||
/* Check plugin for an existing convar list */
|
||||
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
|
||||
{
|
||||
@@ -711,7 +679,7 @@ void ConVarManager::OnClientQueryFinished(QueryCvarCookie_t cookie,
|
||||
}
|
||||
#endif
|
||||
|
||||
HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar, IPlugin **ppPlugin)
|
||||
HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
|
||||
{
|
||||
ConVarInfo *pInfo;
|
||||
HandleError error;
|
||||
@@ -726,10 +694,5 @@ HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar, IPlugi
|
||||
*pVar = pInfo->pVar;
|
||||
}
|
||||
|
||||
if (ppPlugin)
|
||||
{
|
||||
*ppPlugin = pInfo->pPlugin;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
+9
-20
@@ -62,27 +62,16 @@ struct ConVarInfo
|
||||
bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */
|
||||
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
||||
ConVar *pVar; /**< The actual convar */
|
||||
IPlugin *pPlugin; /**< Originally owning plugin */
|
||||
List<IConVarChangeListener *> changeListeners;
|
||||
|
||||
struct ConVarPolicy
|
||||
static inline bool matches(const char *name, const ConVarInfo *info)
|
||||
{
|
||||
static inline bool matches(const char *name, ConVarInfo *info)
|
||||
{
|
||||
const char *conVarChars = info->pVar->GetName();
|
||||
|
||||
std::string convarName = ke::Lowercase(conVarChars);
|
||||
std::string input = ke::Lowercase(name);
|
||||
|
||||
return convarName == input;
|
||||
}
|
||||
|
||||
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||
{
|
||||
std::string lower = ke::Lowercase(key.c_str());
|
||||
return detail::CharsAndLength(lower.c_str()).hash();
|
||||
}
|
||||
};
|
||||
return strcmp(name, info->pVar->GetName()) == 0;
|
||||
}
|
||||
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||
{
|
||||
return key.hash();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -155,7 +144,7 @@ public:
|
||||
|
||||
bool IsQueryingSupported();
|
||||
|
||||
HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar, IPlugin **ppPlugin = nullptr);
|
||||
HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar);
|
||||
|
||||
// Called via game hooks.
|
||||
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||
@@ -172,7 +161,7 @@ private:
|
||||
/**
|
||||
* Adds a convar to a plugin's list.
|
||||
*/
|
||||
static void AddConVarToPluginList(IPlugin *plugin, const ConVar *pConVar);
|
||||
static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar);
|
||||
private:
|
||||
HandleType_t m_ConVarType;
|
||||
List<ConVarInfo *> m_ConVars;
|
||||
|
||||
@@ -307,7 +307,7 @@ bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<char[]> str(UTIL_ToLowerCase(command));
|
||||
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
|
||||
IChangeableForward *forward;
|
||||
if (!m_Listeners.retrieve(str.get(), &forward))
|
||||
{
|
||||
@@ -329,7 +329,7 @@ bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<char[]> str(UTIL_ToLowerCase(command));
|
||||
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
|
||||
IChangeableForward *forward;
|
||||
if (!m_Listeners.retrieve(str.get(), &forward))
|
||||
return false;
|
||||
|
||||
+4
-4
@@ -290,18 +290,18 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
std::string vstr(value);
|
||||
m_KeyValues.replace(option, std::move(vstr));
|
||||
ke::AString vstr(value);
|
||||
m_KeyValues.replace(option, ke::Move(vstr));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *CoreConfig::GetCoreConfigValue(const char *key)
|
||||
{
|
||||
StringHashMap<std::string>::Result r = m_KeyValues.find(key);
|
||||
StringHashMap<ke::AString>::Result r = m_KeyValues.find(key);
|
||||
if (!r.found())
|
||||
return NULL;
|
||||
return r->value.c_str();
|
||||
return r->value.chars();
|
||||
}
|
||||
|
||||
bool SM_AreConfigsExecuted()
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ private:
|
||||
*/
|
||||
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
|
||||
private:
|
||||
StringHashMap<std::string> m_KeyValues;
|
||||
StringHashMap<ke::AString> m_KeyValues;
|
||||
};
|
||||
|
||||
extern bool SM_AreConfigsExecuted();
|
||||
|
||||
@@ -364,8 +364,8 @@ void EventManager::FireEvent(EventInfo *pInfo, bool bDontBroadcast)
|
||||
|
||||
void EventManager::FireEventToClient(EventInfo *pInfo, IClient *pClient)
|
||||
{
|
||||
// The IClient vtable is +sizeof(void *) from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
|
||||
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - sizeof(void *));
|
||||
// The IClient vtable is +4 from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
|
||||
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - 4);
|
||||
pGameClient->FireGameEvent(pInfo->pEvent);
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
pForward->PushCell(BAD_HANDLE);
|
||||
}
|
||||
|
||||
pForward->PushString(pHook->name.c_str());
|
||||
pForward->PushString(pHook->name.chars());
|
||||
pForward->PushCell(bDontBroadcast);
|
||||
pForward->Execute(NULL);
|
||||
|
||||
@@ -505,7 +505,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
|
||||
{
|
||||
assert(pHook->pPostHook == NULL);
|
||||
assert(pHook->pPreHook == NULL);
|
||||
m_EventHooks.remove(pHook->name.c_str());
|
||||
m_EventHooks.remove(pHook->name.chars());
|
||||
delete pHook;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -71,11 +71,11 @@ struct EventHook
|
||||
IChangeableForward *pPostHook;
|
||||
bool postCopy;
|
||||
unsigned int refCount;
|
||||
std::string name;
|
||||
ke::AString name;
|
||||
|
||||
static inline bool matches(const char *name, const EventHook *hook)
|
||||
{
|
||||
return strcmp(name, hook->name.c_str()) == 0;
|
||||
return strcmp(name, hook->name.chars()) == 0;
|
||||
}
|
||||
static inline uint32_t hash(const detail::CharsAndLength &key)
|
||||
{
|
||||
|
||||
+2
-2
@@ -91,7 +91,7 @@ void GameHooks::OnVSPReceived()
|
||||
|
||||
void GameHooks::Shutdown()
|
||||
{
|
||||
for (size_t i = 0; i < hooks_.size(); i++)
|
||||
for (size_t i = 0; i < hooks_.length(); i++)
|
||||
SH_REMOVE_HOOK_ID(hooks_[i]);
|
||||
hooks_.clear();
|
||||
|
||||
@@ -115,7 +115,7 @@ void GameHooks::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPla
|
||||
const char *cvarName, const char *cvarValue){
|
||||
int client = IndexOfEdict(pPlayer);
|
||||
|
||||
# if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
# if SOURCE_ENGINE == SE_CSGO
|
||||
if (g_Players.HandleConVarQuery(cookie, client, result, cvarName, cvarValue))
|
||||
return;
|
||||
# endif
|
||||
|
||||
+3
-3
@@ -63,7 +63,7 @@ class CommandHook : public ke::Refcounted<CommandHook>
|
||||
{
|
||||
public:
|
||||
// return false to RETURN_META(MRES_IGNORED), or true to SUPERCEDE.
|
||||
typedef ke::Function<bool(int, const ICommandArgs *)> Callback;
|
||||
typedef ke::Lambda<bool(int, const ICommandArgs *)> Callback;
|
||||
|
||||
public:
|
||||
CommandHook(ConCommand *cmd, const Callback &callback, bool post);
|
||||
@@ -114,11 +114,11 @@ private:
|
||||
void SetCommandClient(int client);
|
||||
|
||||
private:
|
||||
class HookList : public std::vector<int>
|
||||
class HookList : public ke::Vector<int>
|
||||
{
|
||||
public:
|
||||
HookList &operator += (int hook_id) {
|
||||
this->push_back(hook_id);
|
||||
this->append(hook_id);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
+40
-183
@@ -45,14 +45,13 @@
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <cstrike15_usermessages.pb.h>
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
#include <berimbau_usermessages.pb.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef ICommandLine *(*FakeGetCommandLine)();
|
||||
|
||||
#define TIER0_NAME FORMAT_SOURCE_BIN_NAME("tier0")
|
||||
#define VSTDLIB_NAME FORMAT_SOURCE_BIN_NAME("vstdlib")
|
||||
#define TIER0_NAME SOURCE_BIN_PREFIX "tier0" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT
|
||||
#define VSTDLIB_NAME SOURCE_BIN_PREFIX "vstdlib" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT
|
||||
|
||||
CHalfLife2 g_HL2;
|
||||
ConVar *sv_lan = NULL;
|
||||
@@ -60,7 +59,6 @@ ConVar *sv_lan = NULL;
|
||||
static void *g_EntList = NULL;
|
||||
static void **g_pEntInfoList = NULL;
|
||||
static int entInfoOffset = -1;
|
||||
static int utlVecOffsetOffset = -1;
|
||||
|
||||
static CEntInfo *EntInfoArray()
|
||||
{
|
||||
@@ -141,11 +139,9 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
|
||||
m_CSGOBadList.add("m_flFallbackWear");
|
||||
m_CSGOBadList.add("m_nFallbackStatTrak");
|
||||
m_CSGOBadList.add("m_iCompetitiveRanking");
|
||||
m_CSGOBadList.add("m_iCompetitiveRankType");
|
||||
m_CSGOBadList.add("m_nActiveCoinRank");
|
||||
m_CSGOBadList.add("m_nMusicID");
|
||||
#endif
|
||||
g_pGameConf->GetOffset("CSendPropExtra_UtlVector::m_Offset", &utlVecOffsetOffset);
|
||||
}
|
||||
|
||||
ConfigResult CHalfLife2::OnSourceModConfigChanged(const char *key, const char *value,
|
||||
@@ -166,7 +162,7 @@ ConfigResult CHalfLife2::OnSourceModConfigChanged(const char *key, const char *v
|
||||
}
|
||||
else
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
#endif
|
||||
@@ -183,7 +179,6 @@ void CHalfLife2::InitLogicalEntData()
|
||||
|| SOURCE_ENGINE == SE_CSS \
|
||||
|| SOURCE_ENGINE == SE_SDK2013 \
|
||||
|| SOURCE_ENGINE == SE_BMS \
|
||||
|| SOURCE_ENGINE == SE_BLADE \
|
||||
|| SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
|
||||
if (g_SMAPI->GetServerFactory(false)("VSERVERTOOLS003", nullptr))
|
||||
@@ -232,12 +227,7 @@ void CHalfLife2::InitLogicalEntData()
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
g_EntList = *reinterpret_cast<void **>(addr + offset);
|
||||
#elif defined PLATFORM_X64
|
||||
int32_t varOffset = *reinterpret_cast<int32_t *>(addr + offset);
|
||||
g_EntList = reinterpret_cast<void *>(addr + offset + sizeof(int32_t) + varOffset);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
@@ -321,41 +311,23 @@ bool UTIL_FindInSendTable(SendTable *pTable,
|
||||
sm_sendprop_info_t *info,
|
||||
unsigned int offset)
|
||||
{
|
||||
const char *pname;
|
||||
int props = pTable->GetNumProps();
|
||||
for (int i = 0; i < props; i++)
|
||||
SendProp *prop;
|
||||
|
||||
for (int i=0; i<props; i++)
|
||||
{
|
||||
SendProp *prop = pTable->GetProp(i);
|
||||
|
||||
// Skip InsideArray props (SendPropArray / SendPropArray2),
|
||||
// we'll find them later by their containing array.
|
||||
if (prop->IsInsideArray()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *pname = prop->GetName();
|
||||
SendTable *pInnerTable = prop->GetDataTable();
|
||||
|
||||
prop = pTable->GetProp(i);
|
||||
pname = prop->GetName();
|
||||
if (pname && strcmp(name, pname) == 0)
|
||||
{
|
||||
// get true offset of CUtlVector
|
||||
if (utlVecOffsetOffset != -1 && prop->GetOffset() == 0 && pInnerTable && pInnerTable->GetNumProps())
|
||||
{
|
||||
SendProp *pLengthProxy = pInnerTable->GetProp(0);
|
||||
const char *ipname = pLengthProxy->GetName();
|
||||
if (ipname && strcmp(ipname, "lengthproxy") == 0 && pLengthProxy->GetExtraData())
|
||||
{
|
||||
info->prop = prop;
|
||||
info->actual_offset = offset + *reinterpret_cast<size_t *>(reinterpret_cast<intptr_t>(pLengthProxy->GetExtraData()) + utlVecOffsetOffset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
info->prop = prop;
|
||||
info->actual_offset = offset + info->prop->GetOffset();
|
||||
return true;
|
||||
}
|
||||
if (pInnerTable)
|
||||
if (prop->GetDataTable())
|
||||
{
|
||||
if (UTIL_FindInSendTable(pInnerTable,
|
||||
if (UTIL_FindInSendTable(prop->GetDataTable(),
|
||||
name,
|
||||
info,
|
||||
offset + prop->GetOffset())
|
||||
@@ -538,7 +510,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
char buffer[253];
|
||||
ke::SafeSprintf(buffer, sizeof(buffer), "%s\1\n", msg);
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_SayText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
@@ -565,7 +537,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
|
||||
}
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_TextMsg *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
@@ -602,7 +574,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
{
|
||||
cell_t players[] = {client};
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_HintText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
@@ -632,7 +604,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
|
||||
|
||||
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_HintText *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
@@ -667,7 +639,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
||||
int count = 0;
|
||||
cell_t players[] = {client};
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
CCSUsrMsg_VGUIMenu *pMsg;
|
||||
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
|
||||
{
|
||||
@@ -692,7 +664,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
||||
SubKey = data->GetFirstSubKey();
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pMsg->set_name(name);
|
||||
pMsg->set_show(show);
|
||||
|
||||
@@ -855,7 +827,7 @@ void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
|
||||
|
||||
kick.client = client;
|
||||
kick.userid = userid;
|
||||
ke::SafeStrcpy(kick.buffer, sizeof(kick.buffer), msg);
|
||||
ke::SafeSprintf(kick.buffer, sizeof(kick.buffer), "%s", msg);
|
||||
|
||||
m_DelayedKicks.push(kick);
|
||||
}
|
||||
@@ -1222,7 +1194,7 @@ bool IsWindowsReservedDeviceName(const char *pMapname)
|
||||
};
|
||||
|
||||
size_t reservedCount = sizeof(reservedDeviceNames) / sizeof(reservedDeviceNames[0]);
|
||||
for (size_t i = 0; i < reservedCount; ++i)
|
||||
for (int i = 0; i < reservedCount; ++i)
|
||||
{
|
||||
if (CheckReservedFilename(pMapname, reservedDeviceNames[i]))
|
||||
{
|
||||
@@ -1234,45 +1206,6 @@ bool IsWindowsReservedDeviceName(const char *pMapname)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && defined PLATFORM_WINDOWS && SOURCE_ENGINE != SE_MOCK
|
||||
// This frees memory allocated by the game using the game's CRT on Windows,
|
||||
// avoiding a crash due to heap corruption (issue #910).
|
||||
template< class T, class I >
|
||||
class CUtlMemoryGlobalMalloc : public CUtlMemory< T, I >
|
||||
{
|
||||
typedef CUtlMemory< T, I > BaseClass;
|
||||
|
||||
public:
|
||||
using BaseClass::BaseClass;
|
||||
|
||||
void Purge()
|
||||
{
|
||||
if (!IsExternallyAllocated())
|
||||
{
|
||||
if (m_pMemory)
|
||||
{
|
||||
UTLMEMORY_TRACK_FREE();
|
||||
g_pMemAlloc->Free((void*)m_pMemory);
|
||||
m_pMemory = 0;
|
||||
}
|
||||
m_nAllocationCount = 0;
|
||||
}
|
||||
BaseClass::Purge();
|
||||
}
|
||||
};
|
||||
|
||||
void CHalfLife2::FreeUtlVectorUtlString(CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> &vec)
|
||||
{
|
||||
CUtlMemoryGlobalMalloc<unsigned char> *pMemory;
|
||||
FOR_EACH_VEC(vec, i)
|
||||
{
|
||||
pMemory = (CUtlMemoryGlobalMalloc<unsigned char> *) &vec[i].m_Storage.m_Memory;
|
||||
pMemory->Purge();
|
||||
vec[i].m_Storage.SetLength(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_t nMapNameMax)
|
||||
{
|
||||
/* We need to ensure user input does not contain reserved device names on windows */
|
||||
@@ -1306,13 +1239,8 @@ SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_
|
||||
|
||||
static size_t helperCmdLen = strlen(pHelperCmd->GetName());
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> results;
|
||||
pHelperCmd->AutoCompleteSuggest(pMapName, *(CUtlVector<CUtlString, CUtlMemory<CUtlString>>*)&results);
|
||||
#else
|
||||
CUtlVector<CUtlString> results;
|
||||
pHelperCmd->AutoCompleteSuggest(pMapName, results);
|
||||
#endif
|
||||
if (results.Count() == 0)
|
||||
return SMFindMapResult::NotFound;
|
||||
|
||||
@@ -1324,40 +1252,27 @@ SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_
|
||||
bool bExactMatch = Q_strcmp(pMapName, &results[0][helperCmdLen + 1]) == 0;
|
||||
if (bExactMatch)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
FreeUtlVectorUtlString(results);
|
||||
#endif
|
||||
return SMFindMapResult::Found;
|
||||
}
|
||||
else
|
||||
{
|
||||
ke::SafeStrcpy(pFoundMap, nMapNameMax, &results[0][helperCmdLen + 1]);
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
FreeUtlVectorUtlString(results);
|
||||
#endif
|
||||
return SMFindMapResult::FuzzyMatch;
|
||||
}
|
||||
|
||||
#elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM \
|
||||
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS
|
||||
static IVEngineServer *engine23 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer023", nullptr));
|
||||
if (engine23)
|
||||
#elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_BMS
|
||||
static char szTemp[PLATFORM_MAX_PATH];
|
||||
if (pFoundMap == NULL)
|
||||
{
|
||||
static char szTemp[PLATFORM_MAX_PATH];
|
||||
if (pFoundMap == NULL)
|
||||
{
|
||||
ke::SafeStrcpy(szTemp, SM_ARRAYSIZE(szTemp), pMapName);
|
||||
pFoundMap = szTemp;
|
||||
nMapNameMax = 0;
|
||||
}
|
||||
ke::SafeStrcpy(szTemp, SM_ARRAYSIZE(szTemp), pMapName);
|
||||
pFoundMap = szTemp;
|
||||
nMapNameMax = 0;
|
||||
}
|
||||
|
||||
return static_cast<SMFindMapResult>(engine->FindMap(pFoundMap, static_cast<int>(nMapNameMax)));
|
||||
}
|
||||
else
|
||||
{
|
||||
static IVEngineServer *engine21 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer021", nullptr));
|
||||
return engine21->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
|
||||
}
|
||||
return static_cast<SMFindMapResult>(engine->FindMap(pFoundMap, static_cast<int>(nMapNameMax)));
|
||||
#elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_SDK2013
|
||||
static IVEngineServer *engine21 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer021", nullptr));
|
||||
return engine21->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
|
||||
#else
|
||||
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
|
||||
#endif
|
||||
@@ -1385,39 +1300,11 @@ bool CHalfLife2::IsMapValid(const char *map)
|
||||
if (!map || !map[0])
|
||||
return false;
|
||||
|
||||
return FindMap(map) == SMFindMapResult::Found;
|
||||
return FindMap(map) != SMFindMapResult::NotFound;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE < SE_ORANGEBOX
|
||||
class VKeyValuesSS_Helper {};
|
||||
static bool VKeyValuesSS(CBaseEntity* pThisPtr, const char *pszKey, const char *pszValue, int offset)
|
||||
{
|
||||
void** this_ptr = *reinterpret_cast<void***>(&pThisPtr);
|
||||
void** vtable = *reinterpret_cast<void***>(pThisPtr);
|
||||
void* vfunc = vtable[offset];
|
||||
|
||||
union
|
||||
{
|
||||
bool (VKeyValuesSS_Helper::* mfpnew)(const char *, const char *);
|
||||
#ifndef PLATFORM_POSIX
|
||||
void* addr;
|
||||
} u;
|
||||
u.addr = vfunc;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
void* addr;
|
||||
intptr_t adjustor;
|
||||
} s;
|
||||
} u;
|
||||
u.s.addr = vfunc;
|
||||
u.s.adjustor = 0;
|
||||
#endif
|
||||
|
||||
return (bool)(reinterpret_cast<VKeyValuesSS_Helper*>(this_ptr)->*u.mfpnew)(pszKey, pszValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Add ep1 support for this. (No IServerTools available there)
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
string_t CHalfLife2::AllocPooledString(const char *pszValue)
|
||||
{
|
||||
// This is admittedly a giant hack, but it's a relatively safe method for
|
||||
@@ -1427,62 +1314,32 @@ string_t CHalfLife2::AllocPooledString(const char *pszValue)
|
||||
// current targetname string_t, set it to our string to insert via SetKeyValue,
|
||||
// read back the new targetname value, restore the old value, and return the new one.
|
||||
|
||||
#if SOURCE_ENGINE < SE_ORANGEBOX
|
||||
CBaseEntity* pEntity = nullptr;
|
||||
for (int i = 0; i < gpGlobals->maxEntities; ++i)
|
||||
{
|
||||
pEntity = ReferenceToEntity(i);
|
||||
if (pEntity)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pEntity)
|
||||
{
|
||||
logger->LogError("Failed to locate a valid entity for AllocPooledString.");
|
||||
return NULL_STRING;
|
||||
}
|
||||
|
||||
#else
|
||||
CBaseEntity *pEntity = ((IServerUnknown *) servertools->FirstEntity())->GetBaseEntity();
|
||||
#endif
|
||||
auto *pDataMap = GetDataMap(pEntity);
|
||||
assert(pDataMap);
|
||||
|
||||
static int iNameOffset = -1;
|
||||
if (iNameOffset == -1)
|
||||
static int offset = -1;
|
||||
if (offset == -1)
|
||||
{
|
||||
sm_datatable_info_t info;
|
||||
bool found = FindDataMapInfo(pDataMap, "m_iName", &info);
|
||||
assert(found);
|
||||
iNameOffset = info.actual_offset;
|
||||
offset = info.actual_offset;
|
||||
}
|
||||
|
||||
string_t* pProp = (string_t*)((intp)pEntity + iNameOffset);
|
||||
string_t *pProp = (string_t *) ((intp) pEntity + offset);
|
||||
string_t backup = *pProp;
|
||||
|
||||
#if SOURCE_ENGINE < SE_ORANGEBOX
|
||||
static int iFuncOffset;
|
||||
if (!g_pGameConf->GetOffset("DispatchKeyValue", &iFuncOffset) || !iFuncOffset)
|
||||
{
|
||||
logger->LogError("Failed to locate DispatchKeyValue in core gamedata. AllocPooledString unsupported.");
|
||||
return NULL_STRING;
|
||||
}
|
||||
VKeyValuesSS(pEntity, "targetname", pszValue, iFuncOffset);
|
||||
#else
|
||||
servertools->SetKeyValue(pEntity, "targetname", pszValue);
|
||||
#endif
|
||||
|
||||
string_t newString = *pProp;
|
||||
*pProp = backup;
|
||||
|
||||
return newString;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const
|
||||
{
|
||||
CSteamID sid((uint64)GetServerSteamId64());
|
||||
CSteamID sid(GetServerSteamId64());
|
||||
|
||||
switch (sid.GetEAccountType())
|
||||
{
|
||||
|
||||
+5
-15
@@ -70,8 +70,8 @@ using namespace SourceMod;
|
||||
#define SOURCE_BIN_EXT ".dylib"
|
||||
#elif defined __linux__
|
||||
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|
||||
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \
|
||||
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI
|
||||
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \
|
||||
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI
|
||||
#define SOURCE_BIN_PREFIX "lib"
|
||||
#define SOURCE_BIN_SUFFIX "_srv"
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
@@ -84,9 +84,6 @@ using namespace SourceMod;
|
||||
#define SOURCE_BIN_EXT ".so"
|
||||
#endif
|
||||
|
||||
#define FORMAT_SOURCE_BIN_NAME(basename) \
|
||||
(SOURCE_BIN_PREFIX basename SOURCE_BIN_SUFFIX SOURCE_BIN_EXT)
|
||||
|
||||
struct DataTableInfo
|
||||
{
|
||||
struct SendPropPolicy
|
||||
@@ -179,12 +176,6 @@ enum class SMFindMapResult : cell_t {
|
||||
PossiblyAvailable
|
||||
};
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && defined PLATFORM_WINDOWS
|
||||
template< class T, class I = int >
|
||||
class CUtlMemoryGlobalMalloc;
|
||||
class CUtlString;
|
||||
#endif
|
||||
|
||||
class CHalfLife2 :
|
||||
public SMGlobalClass,
|
||||
public IGameHelpers
|
||||
@@ -235,11 +226,10 @@ public: //IGameHelpers
|
||||
bool IsMapValid(const char *map);
|
||||
SMFindMapResult FindMap(char *pMapName, size_t nMapNameMax);
|
||||
SMFindMapResult FindMap(const char *pMapName, char *pFoundMap = NULL, size_t nMapNameMax = 0);
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && defined PLATFORM_WINDOWS && SOURCE_ENGINE != SE_MOCK
|
||||
void FreeUtlVectorUtlString(CUtlVector<CUtlString, CUtlMemoryGlobalMalloc<CUtlString>> &vec);
|
||||
#endif
|
||||
bool GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax);
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
string_t AllocPooledString(const char *pszValue);
|
||||
#endif
|
||||
bool GetServerSteam3Id(char *pszOut, size_t len) const override;
|
||||
uint64_t GetServerSteamId64() const override;
|
||||
public:
|
||||
@@ -278,7 +268,7 @@ public:
|
||||
return !m_bFollowCSGOServerGuidelines || !m_CSGOBadList.has(pszPropName);
|
||||
}
|
||||
private:
|
||||
ke::HashSet<std::string, detail::StringHashMapPolicy> m_CSGOBadList;
|
||||
ke::HashSet<ke::AString, detail::StringHashMapPolicy> m_CSGOBadList;
|
||||
bool m_bFollowCSGOServerGuidelines = true;
|
||||
#endif
|
||||
};
|
||||
|
||||
+45
-45
@@ -36,7 +36,7 @@
|
||||
#include "MenuManager.h"
|
||||
#include "CellRecipientFilter.h"
|
||||
#if defined MENU_DEBUG
|
||||
#include <bridge/include/ILogger.h>
|
||||
#include "Logger.h"
|
||||
#endif
|
||||
#include "logic_bridge.h"
|
||||
#include "AutoHandleRooter.h"
|
||||
@@ -59,7 +59,7 @@ Handle_t BaseMenuStyle::GetHandle()
|
||||
void BaseMenuStyle::AddClientToWatch(int client)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] AddClientToWatch(%d)", client);
|
||||
g_Logger.LogMessage("[SM_MENU] AddClientToWatch(%d)", client);
|
||||
#endif
|
||||
m_WatchList.push_back(client);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ void BaseMenuStyle::AddClientToWatch(int client)
|
||||
void BaseMenuStyle::RemoveClientFromWatch(int client)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] RemoveClientFromWatch(%d)", client);
|
||||
g_Logger.LogMessage("[SM_MENU] RemoveClientFromWatch(%d)", client);
|
||||
#endif
|
||||
m_WatchList.remove(client);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ void BaseMenuStyle::RemoveClientFromWatch(int client)
|
||||
void BaseMenuStyle::_CancelClientMenu(int client, MenuCancelReason reason, bool bAutoIgnore/* =false */)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] _CancelClientMenu() (client %d) (bAutoIgnore %d) (reason %d)", client, bAutoIgnore, reason);
|
||||
g_Logger.LogMessage("[SM_MENU] _CancelClientMenu() (client %d) (bAutoIgnore %d) (reason %d)", client, bAutoIgnore, reason);
|
||||
#endif
|
||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
||||
menu_states_t &states = player->states;
|
||||
@@ -115,7 +115,7 @@ void BaseMenuStyle::_CancelClientMenu(int client, MenuCancelReason reason, bool
|
||||
void BaseMenuStyle::CancelMenu(CBaseMenu *menu)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] CancelMenu() (menu %p)", menu);
|
||||
g_Logger.LogMessage("[SM_MENU] CancelMenu() (menu %p)", menu);
|
||||
#endif
|
||||
int maxClients = g_Players.GetMaxClients();
|
||||
for (int i=1; i<=maxClients; i++)
|
||||
@@ -135,7 +135,7 @@ void BaseMenuStyle::CancelMenu(CBaseMenu *menu)
|
||||
bool BaseMenuStyle::CancelClientMenu(int client, bool autoIgnore)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] CancelClientMenu() (client %d) (bAutoIgnore %d)", client, autoIgnore);
|
||||
g_Logger.LogMessage("[SM_MENU] CancelClientMenu() (client %d) (bAutoIgnore %d)", client, autoIgnore);
|
||||
#endif
|
||||
if (client < 1 || client > g_Players.MaxClients())
|
||||
{
|
||||
@@ -191,7 +191,7 @@ MenuSource BaseMenuStyle::GetClientMenu(int client, void **object)
|
||||
void BaseMenuStyle::OnClientDisconnected(int client)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] OnClientDisconnected(%d)", client);
|
||||
g_Logger.LogMessage("[SM_MENU] OnClientDisconnected(%d)", client);
|
||||
#endif
|
||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
||||
if (!player->bInMenu)
|
||||
@@ -214,7 +214,7 @@ void BaseMenuStyle::ProcessWatchList()
|
||||
}
|
||||
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)",
|
||||
g_Logger.LogMessage("BaseMenuStyle::ProcessWatchList(%d,%d,%d,%d,%d,%p)",
|
||||
m_WatchList.m_Size,
|
||||
m_WatchList.m_FirstLink,
|
||||
m_WatchList.m_FreeNodes,
|
||||
@@ -232,7 +232,7 @@ void BaseMenuStyle::ProcessWatchList()
|
||||
#if defined MENU_DEBUG
|
||||
if (total)
|
||||
{
|
||||
logger->LogMessage("[SM_MENU] ProcessWatchList() found %d clients", total);
|
||||
g_Logger.LogMessage("[SM_MENU] ProcessWatchList() found %d clients", total);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -244,7 +244,7 @@ void BaseMenuStyle::ProcessWatchList()
|
||||
client = do_lookup[i];
|
||||
player = GetMenuPlayer(client);
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] ProcessWatchList() (client %d) (bInMenu %d) (menuHoldTime %d) (curTime %f) (menuStartTime %f)",
|
||||
g_Logger.LogMessage("[SM_MENU] ProcessWatchList() (client %d) (bInMenu %d) (menuHoldTime %d) (curTime %f) (menuStartTime %f)",
|
||||
client,
|
||||
player->bInMenu,
|
||||
player->menuHoldTime,
|
||||
@@ -254,7 +254,7 @@ void BaseMenuStyle::ProcessWatchList()
|
||||
if (!player->bInMenu || !player->menuHoldTime)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] ProcessWatchList() removing client %d", client);
|
||||
g_Logger.LogMessage("[SM_MENU] ProcessWatchList() removing client %d", client);
|
||||
#endif
|
||||
m_WatchList.remove(client);
|
||||
continue;
|
||||
@@ -269,7 +269,7 @@ void BaseMenuStyle::ProcessWatchList()
|
||||
void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] ClientPressedKey() (client %d) (key_press %d)", client, key_press);
|
||||
g_Logger.LogMessage("[SM_MENU] ClientPressedKey() (client %d) (key_press %d)", client, key_press);
|
||||
#endif
|
||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
||||
|
||||
@@ -412,7 +412,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
||||
bool BaseMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] DoClientMenu() (client %d) (panel %p) (mh %p) (time %d)",
|
||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (panel %p) (mh %p) (time %d)",
|
||||
client,
|
||||
menu,
|
||||
mh,
|
||||
@@ -475,7 +475,7 @@ bool BaseMenuStyle::DoClientMenu(int client,
|
||||
unsigned int time)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] DoClientMenu() (client %d) (menu %p) (mh %p) (time %d)",
|
||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu() (client %d) (menu %p) (mh %p) (time %d)",
|
||||
client,
|
||||
menu,
|
||||
mh,
|
||||
@@ -487,7 +487,7 @@ bool BaseMenuStyle::DoClientMenu(int client,
|
||||
if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] DoClientMenu(): Failed to display to client %d", client);
|
||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to display to client %d", client);
|
||||
#endif
|
||||
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
||||
mh->OnMenuEnd(menu, MenuEnd_Cancelled);
|
||||
@@ -498,7 +498,7 @@ bool BaseMenuStyle::DoClientMenu(int client,
|
||||
if (player->bAutoIgnore)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] DoClientMenu(): Client %d is autoIgnoring", client);
|
||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Client %d is autoIgnoring", client);
|
||||
#endif
|
||||
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
||||
mh->OnMenuEnd(menu, MenuEnd_Cancelled);
|
||||
@@ -517,7 +517,7 @@ bool BaseMenuStyle::DoClientMenu(int client,
|
||||
if (player->bInMenu)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] DoClientMenu(): Cancelling old menu to client %d", client);
|
||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Cancelling old menu to client %d", client);
|
||||
#endif
|
||||
_CancelClientMenu(client, MenuCancel_Interrupted, true);
|
||||
}
|
||||
@@ -532,7 +532,7 @@ bool BaseMenuStyle::DoClientMenu(int client,
|
||||
if (!display)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] DoClientMenu(): Failed to render to client %d", client);
|
||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu(): Failed to render to client %d", client);
|
||||
#endif
|
||||
player->bAutoIgnore = false;
|
||||
player->bInMenu = false;
|
||||
@@ -562,7 +562,7 @@ bool BaseMenuStyle::DoClientMenu(int client,
|
||||
player->bAutoIgnore = false;
|
||||
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] DoClientMenu() finished successfully (client %d)", client);
|
||||
g_Logger.LogMessage("[SM_MENU] DoClientMenu() finished successfully (client %d)", client);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -571,7 +571,7 @@ bool BaseMenuStyle::DoClientMenu(int client,
|
||||
bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] RedoClientMenu() (client %d) (order %d)", client, order);
|
||||
g_Logger.LogMessage("[SM_MENU] RedoClientMenu() (client %d) (order %d)", client, order);
|
||||
#endif
|
||||
CBaseMenuPlayer *player = GetMenuPlayer(client);
|
||||
menu_states_t &states = player->states;
|
||||
@@ -581,7 +581,7 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
|
||||
if (!display)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] RedoClientMenu(): Failed to render menu");
|
||||
g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Failed to render menu");
|
||||
#endif
|
||||
if (player->menuHoldTime)
|
||||
{
|
||||
@@ -598,7 +598,7 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
|
||||
player->bAutoIgnore = false;
|
||||
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] RedoClientMenu(): Succeeded to client %d", client);
|
||||
g_Logger.LogMessage("[SM_MENU] RedoClientMenu(): Succeeded to client %d", client);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -628,49 +628,49 @@ Handle_t CBaseMenu::GetHandle()
|
||||
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
||||
{
|
||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
|
||||
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
||||
&& m_items.length() >= m_pStyle->GetMaxPageItems())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CItem item(m_items.size());
|
||||
CItem item(m_items.length());
|
||||
|
||||
item.info = info;
|
||||
if (draw.display)
|
||||
item.display = std::make_unique<std::string>(draw.display);
|
||||
item.display = new ke::AString(draw.display);
|
||||
item.style = draw.style;
|
||||
|
||||
m_items.push_back(std::move(item));
|
||||
m_items.append(ke::Move(item));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
|
||||
{
|
||||
if (m_Pagination == (unsigned)MENU_NO_PAGINATION &&
|
||||
m_items.size() >= m_pStyle->GetMaxPageItems())
|
||||
m_items.length() >= m_pStyle->GetMaxPageItems())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (position >= m_items.size())
|
||||
if (position >= m_items.length())
|
||||
return false;
|
||||
|
||||
CItem item(position);
|
||||
item.info = info;
|
||||
if (draw.display)
|
||||
item.display = std::make_unique<std::string>(draw.display);
|
||||
item.display = new ke::AString(draw.display);
|
||||
item.style = draw.style;
|
||||
|
||||
m_items.emplace(m_items.begin() + position, std::move(item));
|
||||
m_items.insert(position, ke::Move(item));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBaseMenu::RemoveItem(unsigned int position)
|
||||
{
|
||||
if (position >= m_items.size())
|
||||
if (position >= m_items.length())
|
||||
return false;
|
||||
|
||||
m_items.erase(m_items.begin() + position);
|
||||
m_items.remove(position);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -681,21 +681,21 @@ void CBaseMenu::RemoveAllItems()
|
||||
|
||||
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */, int client/* =0 */)
|
||||
{
|
||||
if (position >= m_items.size())
|
||||
if (position >= m_items.length())
|
||||
return NULL;
|
||||
|
||||
if (client > 0 && position < m_RandomMaps[client].size())
|
||||
if (client > 0 && position < m_RandomMaps[client].length())
|
||||
{
|
||||
position = m_RandomMaps[client][position];
|
||||
}
|
||||
|
||||
if (draw)
|
||||
{
|
||||
draw->display = m_items[position].display->c_str();
|
||||
draw->display = m_items[position].display->chars();
|
||||
draw->style = m_items[position].style;
|
||||
}
|
||||
|
||||
return m_items[position].info.c_str();
|
||||
return m_items[position].info.chars();
|
||||
}
|
||||
|
||||
void CBaseMenu::ShufflePerClient(int start, int stop)
|
||||
@@ -705,7 +705,7 @@ void CBaseMenu::ShufflePerClient(int start, int stop)
|
||||
if (stop >= 0)
|
||||
length = MIN(length, stop);
|
||||
|
||||
for (int i = 1; i <= SM_MAXPLAYERS; i++)
|
||||
for (int i = 1; i < SM_MAXPLAYERS + 1; i++)
|
||||
{
|
||||
// populate per-client map ...
|
||||
m_RandomMaps[i].resize(length);
|
||||
@@ -735,9 +735,9 @@ void CBaseMenu::SetClientMapping(int client, int *array, int length)
|
||||
|
||||
bool CBaseMenu::IsPerClientShuffled()
|
||||
{
|
||||
for (int i = 1; i <= SM_MAXPLAYERS; i++)
|
||||
for (int i = 1; i < SM_MAXPLAYERS + 1; i++)
|
||||
{
|
||||
if(m_RandomMaps[i].size() > 0)
|
||||
if(m_RandomMaps[i].length() > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -745,7 +745,7 @@ bool CBaseMenu::IsPerClientShuffled()
|
||||
|
||||
unsigned int CBaseMenu::GetRealItemIndex(int client, unsigned int position)
|
||||
{
|
||||
if (client > 0 && position < m_RandomMaps[client].size())
|
||||
if (client > 0 && position < m_RandomMaps[client].length())
|
||||
{
|
||||
position = m_RandomMaps[client][position];
|
||||
return m_items[position].index;
|
||||
@@ -756,7 +756,7 @@ unsigned int CBaseMenu::GetRealItemIndex(int client, unsigned int position)
|
||||
|
||||
unsigned int CBaseMenu::GetItemCount()
|
||||
{
|
||||
return m_items.size();
|
||||
return m_items.length();
|
||||
}
|
||||
|
||||
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
|
||||
@@ -794,7 +794,7 @@ void CBaseMenu::SetDefaultTitle(const char *message)
|
||||
|
||||
const char *CBaseMenu::GetDefaultTitle()
|
||||
{
|
||||
return m_Title.c_str();
|
||||
return m_Title.chars();
|
||||
}
|
||||
|
||||
void CBaseMenu::Cancel()
|
||||
@@ -805,7 +805,7 @@ void CBaseMenu::Cancel()
|
||||
}
|
||||
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] CBaseMenu::Cancel(%p) (m_bShouldDelete %d)",
|
||||
g_Logger.LogMessage("[SM_MENU] CBaseMenu::Cancel(%p) (m_bShouldDelete %d)",
|
||||
this,
|
||||
m_bShouldDelete);
|
||||
#endif
|
||||
@@ -829,7 +829,7 @@ void CBaseMenu::Destroy(bool releaseHandle)
|
||||
}
|
||||
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] CBaseMenu::Destroy(%p) (release %d) (m_bCancelling %d) (m_bShouldDelete %d)",
|
||||
g_Logger.LogMessage("[SM_MENU] CBaseMenu::Destroy(%p) (release %d) (m_bCancelling %d) (m_bShouldDelete %d)",
|
||||
this,
|
||||
releaseHandle,
|
||||
m_bCancelling,
|
||||
@@ -886,5 +886,5 @@ IMenuHandler *CBaseMenu::GetHandler()
|
||||
|
||||
unsigned int CBaseMenu::GetBaseMemUsage()
|
||||
{
|
||||
return m_Title.size() + (m_items.size() * sizeof(CItem));
|
||||
return m_Title.length() + (m_items.length() * sizeof(CItem));
|
||||
}
|
||||
|
||||
+9
-12
@@ -32,9 +32,6 @@
|
||||
#ifndef _INCLUDE_MENUSTYLE_BASE_H
|
||||
#define _INCLUDE_MENUSTYLE_BASE_H
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include <IMenuManager.h>
|
||||
#include <IPlayerHelpers.h>
|
||||
#include <am-string.h>
|
||||
@@ -53,8 +50,8 @@ public:
|
||||
access = 0;
|
||||
}
|
||||
CItem(CItem &&other)
|
||||
: info(std::move(other.info)),
|
||||
display(std::move(other.display))
|
||||
: info(ke::Move(other.info)),
|
||||
display(ke::Move(other.display))
|
||||
{
|
||||
index = other.index;
|
||||
style = other.style;
|
||||
@@ -63,8 +60,8 @@ public:
|
||||
CItem & operator =(CItem &&other)
|
||||
{
|
||||
index = other.index;
|
||||
info = std::move(other.info);
|
||||
display = std::move(other.display);
|
||||
info = ke::Move(other.info);
|
||||
display = ke::Move(other.display);
|
||||
style = other.style;
|
||||
access = other.access;
|
||||
return *this;
|
||||
@@ -72,8 +69,8 @@ public:
|
||||
|
||||
public:
|
||||
unsigned int index;
|
||||
std::string info;
|
||||
std::unique_ptr<std::string> display;
|
||||
ke::AString info;
|
||||
ke::AutoPtr<ke::AString> display;
|
||||
unsigned int style;
|
||||
unsigned int access;
|
||||
|
||||
@@ -166,10 +163,10 @@ public:
|
||||
private:
|
||||
void InternalDelete();
|
||||
protected:
|
||||
std::string m_Title;
|
||||
ke::AString m_Title;
|
||||
IMenuStyle *m_pStyle;
|
||||
unsigned int m_Pagination;
|
||||
std::vector<CItem> m_items;
|
||||
ke::Vector<CItem> m_items;
|
||||
bool m_bShouldDelete;
|
||||
bool m_bCancelling;
|
||||
IdentityToken_t *m_pOwner;
|
||||
@@ -178,7 +175,7 @@ protected:
|
||||
Handle_t m_hHandle;
|
||||
IMenuHandler *m_pHandler;
|
||||
unsigned int m_nFlags;
|
||||
std::vector<uint8_t> m_RandomMaps[SM_MAXPLAYERS+1];
|
||||
ke::Vector<uint8_t> m_RandomMaps[SM_MAXPLAYERS+1];
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_MENUSTYLE_BASE_H
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <IGameConfigs.h>
|
||||
#include "PlayerManager.h"
|
||||
#if defined MENU_DEBUG
|
||||
#include <bridge/include/ILogger.h>
|
||||
#include "Logger.h"
|
||||
#endif
|
||||
#include "logic_bridge.h"
|
||||
|
||||
@@ -45,8 +45,6 @@
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
#include <game/shared/berimbau/protobuf/berimbau_usermessages.pb.h>
|
||||
#endif
|
||||
|
||||
extern const char *g_RadioNumTable[];
|
||||
@@ -61,7 +59,7 @@ unsigned int g_RadioMenuTimeout = 0;
|
||||
#define MAX_MENUSLOT_KEYS 10
|
||||
|
||||
static unsigned int s_RadioMaxPageItems = MAX_MENUSLOT_KEYS;
|
||||
static bool s_RadioClosesOnInvalidSlot = false;
|
||||
|
||||
|
||||
CRadioStyle::CRadioStyle()
|
||||
{
|
||||
@@ -124,12 +122,6 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
|
||||
}
|
||||
}
|
||||
|
||||
const char *closes = g_pGameConf->GetKeyValue("RadioMenuClosesOnInvalidSlot");
|
||||
if (closes != nullptr && strcmp(closes, "yes") == 0)
|
||||
{
|
||||
s_RadioClosesOnInvalidSlot = true;
|
||||
}
|
||||
|
||||
g_Menus.SetDefaultStyle(this);
|
||||
|
||||
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
|
||||
@@ -182,7 +174,7 @@ void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFil
|
||||
{
|
||||
int count = pFilter->GetRecipientCount();
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
|
||||
#else
|
||||
bf_read br(bf->GetBasePointer(), 3);
|
||||
@@ -205,7 +197,7 @@ void CRadioStyle::OnUserMessageSent(int msg_id)
|
||||
{
|
||||
int client = g_last_clients[i];
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] CRadioStyle got ShowMenu (client %d) (bInMenu %d)",
|
||||
g_Logger.LogMessage("[SM_MENU] CRadioStyle got ShowMenu (client %d) (bInMenu %d)",
|
||||
client,
|
||||
m_players[client].bInExternMenu);
|
||||
#endif
|
||||
@@ -466,20 +458,12 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
|
||||
}
|
||||
else
|
||||
{
|
||||
display_len = ke::SafeStrcpy(display_pkt,
|
||||
display_len = ke::SafeSprintf(display_pkt,
|
||||
sizeof(display_pkt),
|
||||
"%s",
|
||||
text);
|
||||
}
|
||||
|
||||
// Some games have implemented CHudMenu::SelectMenuItem to close the menu
|
||||
// even if an invalid slot has been selected, which causes us a problem as
|
||||
// we'll never get any notification from the client and we'll keep the menu
|
||||
// alive on our end indefinitely. For these games, pretend that every slot
|
||||
// is valid for selection so we're guaranteed to get a menuselect command.
|
||||
// We don't want to do this for every game as the common SelectMenuItem
|
||||
// implementation ignores invalid selections and keeps the menu open, which
|
||||
// is a much nicer user experience.
|
||||
display_keys = s_RadioClosesOnInvalidSlot ? 0x7ff : keys;
|
||||
display_keys = keys;
|
||||
}
|
||||
|
||||
void CRadioMenuPlayer::Radio_Refresh()
|
||||
@@ -500,13 +484,9 @@ void CRadioMenuPlayer::Radio_Refresh()
|
||||
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
// TODO: find what happens past 240 on CS:GO
|
||||
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
|
||||
if (!msg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
msg->set_bits_valid_slots(display_keys);
|
||||
msg->set_display_time(time);
|
||||
msg->set_menu_string(ptr);
|
||||
@@ -597,7 +577,7 @@ bool CRadioMenu::DisplayAtItem(int client,
|
||||
IMenuHandler *alt_handler)
|
||||
{
|
||||
#if defined MENU_DEBUG
|
||||
logger->LogMessage("[SM_MENU] CRadioMenu::Display(%p) (client %d) (time %d)",
|
||||
g_Logger.LogMessage("[SM_MENU] CRadioMenu::Display(%p) (client %d) (time %d)",
|
||||
this,
|
||||
client,
|
||||
time);
|
||||
|
||||
+15
-7
@@ -63,7 +63,11 @@ bool g_forcedChange = false;
|
||||
|
||||
void NextMapManager::OnSourceModAllInitialized_Post()
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||
#else
|
||||
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||
#endif
|
||||
|
||||
ConCommand *pCmd = FindCommand("changelevel");
|
||||
if (pCmd != NULL)
|
||||
@@ -75,7 +79,11 @@ void NextMapManager::OnSourceModAllInitialized_Post()
|
||||
|
||||
void NextMapManager::OnSourceModShutdown()
|
||||
{
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||
#else
|
||||
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
|
||||
#endif
|
||||
|
||||
if (changeLevelCmd != NULL)
|
||||
{
|
||||
@@ -130,8 +138,8 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
|
||||
|
||||
logger->LogMessage("[SM] Changed map to \"%s\"", newmap);
|
||||
|
||||
ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
|
||||
ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
||||
ke::SafeSprintf(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
|
||||
ke::SafeSprintf(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
|
||||
|
||||
#if SOURCE_ENGINE != SE_DARKMESSIAH
|
||||
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
|
||||
@@ -176,14 +184,14 @@ void NextMapManager::OnSourceModLevelChange( const char *mapName )
|
||||
m_tempChangeInfo.m_mapName[0] ='\0';
|
||||
m_tempChangeInfo.m_changeReason[0] = '\0';
|
||||
m_tempChangeInfo.startTime = time(NULL);
|
||||
ke::SafeStrcpy(lastMap, sizeof(lastMap), mapName);
|
||||
ke::SafeSprintf(lastMap, sizeof(lastMap), "%s", mapName);
|
||||
}
|
||||
|
||||
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
|
||||
{
|
||||
/* Store the mapname and reason */
|
||||
ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName);
|
||||
ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), changeReason);
|
||||
ke::SafeSprintf(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), "%s", mapName);
|
||||
ke::SafeSprintf(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "%s", changeReason);
|
||||
|
||||
/* Change level and skip our hook */
|
||||
g_forcedChange = true;
|
||||
@@ -213,7 +221,7 @@ void CmdChangeLevelCallback()
|
||||
|
||||
if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0')
|
||||
{
|
||||
ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
|
||||
ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
|
||||
ke::SafeSprintf(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
|
||||
ke::SafeSprintf(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
|
||||
}
|
||||
}
|
||||
|
||||
+84
-141
@@ -64,7 +64,7 @@ const unsigned int *g_NumPlayersToAuth = NULL;
|
||||
int lifestate_offset = -1;
|
||||
List<ICommandTargetProcessor *> target_processors;
|
||||
|
||||
ConVar sm_debug_connect("sm_debug_connect", "1", 0, "Log Debug information about potential connection issues.");
|
||||
ConVar sm_debug_connect("sm_debug_connect", "0", 0, "Log Debug information about potential connection issues.");
|
||||
|
||||
SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
|
||||
SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
|
||||
@@ -97,7 +97,7 @@ SH_DECL_HOOK2_void(IVEngineServer, ClientPrintf, SH_NOATTRIB, 0, edict_t *, cons
|
||||
|
||||
static void PrintfBuffer_FrameAction(void *data)
|
||||
{
|
||||
g_Players.OnPrintfFrameAction(static_cast<unsigned int>(reinterpret_cast<uintptr_t>(data)));
|
||||
g_Players.OnPrintfFrameAction(reinterpret_cast<unsigned int>(data));
|
||||
}
|
||||
|
||||
ConCommand *maxplayersCmd = NULL;
|
||||
@@ -109,7 +109,7 @@ class KickPlayerTimer : public ITimedEvent
|
||||
public:
|
||||
ResultType OnTimer(ITimer *pTimer, void *pData)
|
||||
{
|
||||
int userid = (int)(intptr_t)pData;
|
||||
int userid = (int)pData;
|
||||
int client = g_Players.GetClientOfUserId(userid);
|
||||
if (client)
|
||||
{
|
||||
@@ -196,7 +196,6 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
m_clcommandkv_post = forwardsys->CreateForward("OnClientCommandKeyValues_Post", ET_Ignore, 2, NULL, Param_Cell, Param_Cell);
|
||||
m_clinfochanged = forwardsys->CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2);
|
||||
m_clauth = forwardsys->CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
|
||||
m_cllang = forwardsys->CreateForward("OnClientLanguageChanged", ET_Ignore, 2, NULL, Param_Cell, Param_Cell);
|
||||
m_onActivate = forwardsys->CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
|
||||
m_onActivate2 = forwardsys->CreateForward("OnMapStart", ET_Ignore, 0, NULL);
|
||||
|
||||
@@ -213,9 +212,6 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdMaxplayersCallback), true);
|
||||
maxplayersCmd = pCmd;
|
||||
}
|
||||
|
||||
gameevents->AddListener(this, "player_connect", true);
|
||||
gameevents->AddListener(this, "player_disconnect", true);
|
||||
}
|
||||
|
||||
void PlayerManager::OnSourceModShutdown()
|
||||
@@ -250,7 +246,6 @@ void PlayerManager::OnSourceModShutdown()
|
||||
forwardsys->ReleaseForward(m_clcommandkv_post);
|
||||
forwardsys->ReleaseForward(m_clinfochanged);
|
||||
forwardsys->ReleaseForward(m_clauth);
|
||||
forwardsys->ReleaseForward(m_cllang);
|
||||
forwardsys->ReleaseForward(m_onActivate);
|
||||
forwardsys->ReleaseForward(m_onActivate2);
|
||||
|
||||
@@ -264,8 +259,6 @@ void PlayerManager::OnSourceModShutdown()
|
||||
{
|
||||
SH_REMOVE_HOOK(ConCommand, Dispatch, maxplayersCmd, SH_STATIC(CmdMaxplayersCallback), true);
|
||||
}
|
||||
|
||||
gameevents->RemoveListener(this);
|
||||
}
|
||||
|
||||
ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
|
||||
@@ -288,7 +281,7 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
|
||||
} else if (strcasecmp(value, "off") == 0) {
|
||||
m_QueryLang = false;
|
||||
} else {
|
||||
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
||||
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
return ConfigResult_Accept;
|
||||
@@ -299,7 +292,7 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
|
||||
} else if ( strcasecmp(value, "no") == 0) {
|
||||
m_bAuthstringValidation = false;
|
||||
} else {
|
||||
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
return ConfigResult_Accept;
|
||||
@@ -412,7 +405,7 @@ void PlayerManager::RunAuthChecks()
|
||||
pPlayer = &m_Players[m_AuthQueue[i]];
|
||||
pPlayer->UpdateAuthIds();
|
||||
|
||||
authstr = pPlayer->m_AuthID.c_str();
|
||||
authstr = pPlayer->m_AuthID.chars();
|
||||
|
||||
if (!pPlayer->IsAuthStringValidated())
|
||||
{
|
||||
@@ -519,7 +512,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
/* Get the client's language */
|
||||
if (m_QueryLang)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||
#else
|
||||
const char *name;
|
||||
@@ -527,8 +520,6 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
|
||||
{
|
||||
unsigned int langid;
|
||||
pPlayer->m_LangId = (translator->GetLanguageByName(name, &langid)) ? langid : translator->GetServerLanguage();
|
||||
|
||||
OnClientLanguageChanged(client, pPlayer->m_LangId);
|
||||
} else {
|
||||
pPlayer->m_LangId = translator->GetServerLanguage();
|
||||
}
|
||||
@@ -675,8 +666,6 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
&& (m_SourceTVUserId == userId
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
|| strcmp(playername, "GOTV") == 0
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
|| strcmp(playername, "BBTV") == 0
|
||||
#elif (SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_SDK2013 \
|
||||
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_NUCLEARDAWN || SOURCE_ENGINE == SE_LEFT4DEAD2)
|
||||
|| (tv_name && strcmp(playername, tv_name->GetString()) == 0) || (tv_name && tv_name->GetString()[0] == 0 && strcmp(playername, "unnamed") == 0)
|
||||
@@ -720,19 +709,19 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
{
|
||||
pListener = (*iter);
|
||||
pListener->OnClientAuthorized(client, steamId ? steamId : pPlayer->m_AuthID.c_str());
|
||||
pListener->OnClientAuthorized(client, steamId ? steamId : pPlayer->m_AuthID.chars());
|
||||
}
|
||||
/* Finally, tell plugins */
|
||||
if (m_clauth->GetFunctionCount())
|
||||
{
|
||||
m_clauth->PushCell(client);
|
||||
/* For legacy reasons, people are expecting the Steam2 id here if using Steam auth */
|
||||
m_clauth->PushString(steamId ? steamId : pPlayer->m_AuthID.c_str());
|
||||
m_clauth->PushString(steamId ? steamId : pPlayer->m_AuthID.chars());
|
||||
m_clauth->Execute(NULL);
|
||||
}
|
||||
pPlayer->Authorize_Post();
|
||||
}
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
else if(m_QueryLang)
|
||||
{
|
||||
// Not a bot
|
||||
@@ -792,7 +781,7 @@ void PlayerManager::OnServerHibernationUpdate(bool bHibernating)
|
||||
CPlayer *pPlayer = &m_Players[i];
|
||||
if (pPlayer->IsConnected() && pPlayer->IsFakeClient())
|
||||
{
|
||||
#if SOURCE_ENGINE < SE_LEFT4DEAD || SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
#if SOURCE_ENGINE < SE_LEFT4DEAD || SOURCE_ENGINE >= SE_CSGO || SOURCE_ENGINE == SE_NUCLEARDAWN
|
||||
// These games have the bug fixed where hltv/replay was getting kicked on hibernation
|
||||
if (pPlayer->IsSourceTV() || pPlayer->IsReplay())
|
||||
continue;
|
||||
@@ -879,7 +868,7 @@ void PlayerManager::OnClientPrintf(edict_t *pEdict, const char *szMsg)
|
||||
RETURN_META(MRES_IGNORED);
|
||||
|
||||
size_t nMsgLen = strlen(szMsg);
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE || SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
static const int nNumBitsWritten = 0;
|
||||
#else
|
||||
int nNumBitsWritten = pNetChan->GetNumBitsWritten(false); // SVC_Print uses unreliable netchan
|
||||
@@ -897,7 +886,7 @@ void PlayerManager::OnClientPrintf(edict_t *pEdict, const char *szMsg)
|
||||
if (player.m_PrintfBuffer.empty())
|
||||
g_SourceMod.AddFrameAction(PrintfBuffer_FrameAction, (void *)(uintptr_t)player.GetSerial());
|
||||
|
||||
player.m_PrintfBuffer.push_back(szMsg);
|
||||
player.m_PrintfBuffer.append(szMsg);
|
||||
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
@@ -924,21 +913,21 @@ void PlayerManager::OnPrintfFrameAction(unsigned int serial)
|
||||
|
||||
while (!player.m_PrintfBuffer.empty())
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE || SOURCE_ENGINE == SE_DARKMESSIAH
|
||||
#if SOURCE_ENGINE == SE_EPISODEONE
|
||||
static const int nNumBitsWritten = 0;
|
||||
#else
|
||||
int nNumBitsWritten = pNetChan->GetNumBitsWritten(false); // SVC_Print uses unreliable netchan
|
||||
#endif
|
||||
|
||||
std::string &string = player.m_PrintfBuffer.front();
|
||||
ke::AString &string = player.m_PrintfBuffer.front();
|
||||
|
||||
// stop if we'd overflow the SVC_Print buffer (+7 as ceil)
|
||||
if ((nNumBitsWritten + NETMSG_TYPE_BITS + 7) / 8 + string.length() >= SVC_Print_BufferSize)
|
||||
break;
|
||||
|
||||
SH_CALL(engine, &IVEngineServer::ClientPrintf)(player.m_pEdict, string.c_str());
|
||||
SH_CALL(engine, &IVEngineServer::ClientPrintf)(player.m_pEdict, string.chars());
|
||||
|
||||
player.m_PrintfBuffer.pop_front();
|
||||
player.m_PrintfBuffer.popFront();
|
||||
}
|
||||
|
||||
if (!player.m_PrintfBuffer.empty())
|
||||
@@ -1167,18 +1156,14 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
}
|
||||
else if (args.ArgC() > 1 && strcmp(args.Arg(1), "credits") == 0)
|
||||
{
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod would not be possible without:");
|
||||
ClientConsolePrint(pEntity,
|
||||
ClientConsolePrint(pEntity,
|
||||
"SourceMod would not be possible without:");
|
||||
ClientConsolePrint(pEntity,
|
||||
" David \"BAILOPAN\" Anderson, Matt \"pRED\" Woodrow");
|
||||
ClientConsolePrint(pEntity,
|
||||
ClientConsolePrint(pEntity,
|
||||
" Scott \"DS\" Ehlert, Fyren");
|
||||
ClientConsolePrint(pEntity,
|
||||
ClientConsolePrint(pEntity,
|
||||
" Nicholas \"psychonic\" Hastings, Asher \"asherkin\" Baker");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Ruben \"Dr!fter\" Gonzalez, Josh \"KyleS\" Allard");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Michael \"Headline\" Flaherty, Jannik \"Peace-Maker\" Hartung");
|
||||
ClientConsolePrint(pEntity,
|
||||
" Borja \"faluco\" Ferrer, Pavol \"PM OnoTo\" Marko");
|
||||
ClientConsolePrint(pEntity,
|
||||
@@ -1193,7 +1178,7 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
||||
ClientConsolePrint(pEntity,
|
||||
"To see credits, type \"sm credits\"");
|
||||
ClientConsolePrint(pEntity,
|
||||
"Visit https://www.sourcemod.net/");
|
||||
"Visit http://www.sourcemod.net/");
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
@@ -1348,69 +1333,65 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
m_clinfochanged->PushCell(client);
|
||||
m_clinfochanged->Execute(&res, NULL);
|
||||
|
||||
if (pPlayer->IsFakeClient())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IPlayerInfo *info = pPlayer->GetPlayerInfo();
|
||||
const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
|
||||
const char *old_name = pPlayer->m_Name.c_str();
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
const char *networkid_force;
|
||||
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
|
||||
{
|
||||
unsigned int accountId = pPlayer->GetSteamAccountID();
|
||||
logger->LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress());
|
||||
|
||||
pPlayer->Kick("NetworkID spoofing detected.");
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(old_name, new_name) != 0)
|
||||
{
|
||||
if (!pPlayer->IsFakeClient())
|
||||
AdminId id = adminsys->FindAdminByIdentity("name", new_name);
|
||||
if (id != INVALID_ADMIN_ID && pPlayer->GetAdminId() != id)
|
||||
{
|
||||
AdminId id = adminsys->FindAdminByIdentity("name", new_name);
|
||||
if (id != INVALID_ADMIN_ID && pPlayer->GetAdminId() != id)
|
||||
if (!CheckSetAdminName(client, pPlayer, id))
|
||||
{
|
||||
if (!CheckSetAdminName(client, pPlayer, id))
|
||||
{
|
||||
char kickMsg[128];
|
||||
logicore.CoreTranslate(kickMsg, sizeof(kickMsg), "%T", 2, NULL, "Name Reserved", &client);
|
||||
pPlayer->Kick(kickMsg);
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
char kickMsg[128];
|
||||
logicore.CoreTranslate(kickMsg, sizeof(kickMsg), "%T", 2, NULL, "Name Reserved", &client);
|
||||
pPlayer->Kick(kickMsg);
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
else if ((id = adminsys->FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
|
||||
if (id == pPlayer->GetAdminId())
|
||||
{
|
||||
/* This player is changing their name; force them to drop admin privileges! */
|
||||
pPlayer->SetAdminId(INVALID_ADMIN_ID, false);
|
||||
}
|
||||
} else if ((id = adminsys->FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
|
||||
if (id == pPlayer->GetAdminId())
|
||||
{
|
||||
/* This player is changing their name; force them to drop admin privileges! */
|
||||
pPlayer->SetAdminId(INVALID_ADMIN_ID, false);
|
||||
}
|
||||
}
|
||||
|
||||
pPlayer->SetName(new_name);
|
||||
}
|
||||
|
||||
if (!pPlayer->IsFakeClient())
|
||||
if (m_PassInfoVar.size() > 0)
|
||||
{
|
||||
if (m_PassInfoVar.size() > 0)
|
||||
/* Try for a password change */
|
||||
const char *old_pass = pPlayer->m_LastPassword.c_str();
|
||||
const char *new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str());
|
||||
if (strcmp(old_pass, new_pass) != 0)
|
||||
{
|
||||
/* Try for a password change */
|
||||
const char* old_pass = pPlayer->m_LastPassword.c_str();
|
||||
const char* new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str());
|
||||
if (strcmp(old_pass, new_pass) != 0)
|
||||
pPlayer->m_LastPassword.assign(new_pass);
|
||||
if (pPlayer->IsInGame() && pPlayer->IsAuthorized())
|
||||
{
|
||||
pPlayer->m_LastPassword.assign(new_pass);
|
||||
if (pPlayer->IsInGame() && pPlayer->IsAuthorized())
|
||||
{
|
||||
/* If there is already an admin id assigned, this will just bail out. */
|
||||
pPlayer->DoBasicAdminChecks();
|
||||
}
|
||||
/* If there is already an admin id assigned, this will just bail out. */
|
||||
pPlayer->DoBasicAdminChecks();
|
||||
}
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
const char* networkid_force;
|
||||
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
|
||||
{
|
||||
unsigned int accountId = pPlayer->GetSteamAccountID();
|
||||
logger->LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
|
||||
new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress());
|
||||
|
||||
pPlayer->Kick("NetworkID spoofing detected.");
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Notify Extensions */
|
||||
List<IClientListener *>::iterator iter;
|
||||
IClientListener *pListener = NULL;
|
||||
@@ -1424,13 +1405,6 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnClientLanguageChanged(int client, unsigned int language)
|
||||
{
|
||||
m_cllang->PushCell(client);
|
||||
m_cllang->PushCell(language);
|
||||
m_cllang->Execute(NULL);
|
||||
}
|
||||
|
||||
int PlayerManager::GetMaxClients()
|
||||
{
|
||||
return m_maxClients;
|
||||
@@ -1450,11 +1424,6 @@ int PlayerManager::GetNumPlayers()
|
||||
return m_PlayerCount;
|
||||
}
|
||||
|
||||
int PlayerManager::GetNumClients()
|
||||
{
|
||||
return m_ClientCount;
|
||||
}
|
||||
|
||||
int PlayerManager::GetClientOfUserId(int userid)
|
||||
{
|
||||
if (userid < 0 || userid > USHRT_MAX)
|
||||
@@ -1596,10 +1565,7 @@ void PlayerManager::InvalidatePlayer(CPlayer *pPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
auto userid = engine->GetPlayerUserId(pPlayer->m_pEdict);
|
||||
if (userid != -1)
|
||||
m_UserIdLookUp[userid] = 0;
|
||||
|
||||
m_UserIdLookUp[engine->GetPlayerUserId(pPlayer->m_pEdict)] = 0;
|
||||
pPlayer->Disconnect();
|
||||
}
|
||||
|
||||
@@ -2035,7 +2001,7 @@ void CmdMaxplayersCallback()
|
||||
g_Players.MaxPlayersChanged();
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
bool PlayerManager::HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
|
||||
{
|
||||
for (int i = 1; i <= m_maxClients; i++)
|
||||
@@ -2043,9 +2009,7 @@ bool PlayerManager::HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQue
|
||||
if (m_Players[i].m_LanguageCookie == cookie)
|
||||
{
|
||||
unsigned int langid;
|
||||
unsigned int new_langid = (translator->GetLanguageByName(cvarValue, &langid)) ? langid : translator->GetServerLanguage();
|
||||
m_Players[i].m_LangId = new_langid;
|
||||
OnClientLanguageChanged(i, new_langid);
|
||||
m_Players[i].m_LangId = (translator->GetLanguageByName(cvarValue, &langid)) ? langid : translator->GetServerLanguage();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2055,27 +2019,6 @@ bool PlayerManager::HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQue
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IGameEventListener2::FireGameEvent */
|
||||
void PlayerManager::FireGameEvent(IGameEvent *pEvent)
|
||||
{
|
||||
const char *name = pEvent->GetName();
|
||||
|
||||
if (strcmp(name, "player_connect") == 0)
|
||||
{
|
||||
const int client = pEvent->GetInt("index") + 1;
|
||||
const int userid = pEvent->GetInt("userid");
|
||||
|
||||
m_ClientCount++;
|
||||
}
|
||||
else if (strcmp(name, "player_disconnect") == 0)
|
||||
{
|
||||
const int userid = pEvent->GetInt("userid");
|
||||
const int client = m_UserIdLookUp[userid];
|
||||
|
||||
m_ClientCount--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
*** PLAYER CODE ***
|
||||
@@ -2114,8 +2057,7 @@ void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
|| SOURCE_ENGINE == SE_HL2DM \
|
||||
|| SOURCE_ENGINE == SE_BMS \
|
||||
|| SOURCE_ENGINE == SE_INSURGENCY \
|
||||
|| SOURCE_ENGINE == SE_DOI \
|
||||
|| SOURCE_ENGINE == SE_BLADE
|
||||
|| SOURCE_ENGINE == SE_DOI
|
||||
m_pIClient = engine->GetIServer()->GetClient(m_iIndex - 1);
|
||||
#else
|
||||
#if SOURCE_ENGINE == SE_SDK2013
|
||||
@@ -2199,18 +2141,18 @@ void CPlayer::UpdateAuthIds()
|
||||
}
|
||||
|
||||
char szAuthBuffer[64];
|
||||
ke::SafeSprintf(szAuthBuffer, sizeof(szAuthBuffer), "STEAM_%u:%u:%u", steam2universe, m_SteamId.GetAccountID() & 1, m_SteamId.GetAccountID() >> 1);
|
||||
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "STEAM_%u:%u:%u", steam2universe, m_SteamId.GetAccountID() & 1, m_SteamId.GetAccountID() >> 1);
|
||||
|
||||
m_Steam2Id = szAuthBuffer;
|
||||
|
||||
// TODO: make sure all hl2sdks' steamclientpublic.h have k_unSteamUserDesktopInstance.
|
||||
if (m_SteamId.GetUnAccountInstance() == 1 /* k_unSteamUserDesktopInstance */)
|
||||
{
|
||||
ke::SafeSprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID());
|
||||
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID());
|
||||
}
|
||||
else
|
||||
{
|
||||
ke::SafeSprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID(), m_SteamId.GetUnAccountInstance());
|
||||
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID(), m_SteamId.GetUnAccountInstance());
|
||||
}
|
||||
|
||||
m_Steam3Id = szAuthBuffer;
|
||||
@@ -2291,7 +2233,7 @@ void CPlayer::Disconnect()
|
||||
m_bIsSourceTV = false;
|
||||
m_bIsReplay = false;
|
||||
m_Serial.value = -1;
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
m_LanguageCookie = InvalidQueryCvarCookie;
|
||||
#endif
|
||||
ClearNetchannelQueue();
|
||||
@@ -2300,7 +2242,7 @@ void CPlayer::Disconnect()
|
||||
void CPlayer::ClearNetchannelQueue(void)
|
||||
{
|
||||
while (!m_PrintfBuffer.empty())
|
||||
m_PrintfBuffer.pop_front();
|
||||
m_PrintfBuffer.popFront();
|
||||
}
|
||||
|
||||
void CPlayer::SetName(const char *name)
|
||||
@@ -2333,6 +2275,11 @@ void CPlayer::SetName(const char *name)
|
||||
|
||||
const char *CPlayer::GetName()
|
||||
{
|
||||
if (m_Info && m_pEdict->GetUnknown())
|
||||
{
|
||||
return m_Info->GetName();
|
||||
}
|
||||
|
||||
return m_Name.c_str();
|
||||
}
|
||||
|
||||
@@ -2348,7 +2295,7 @@ const char *CPlayer::GetAuthString(bool validated)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_AuthID.c_str();
|
||||
return m_AuthID.chars();
|
||||
}
|
||||
|
||||
const CSteamID &CPlayer::GetSteamId(bool validated)
|
||||
@@ -2369,7 +2316,7 @@ const char *CPlayer::GetSteam2Id(bool validated)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_Steam2Id.c_str();
|
||||
return m_Steam2Id.chars();
|
||||
}
|
||||
|
||||
const char *CPlayer::GetSteam3Id(bool validated)
|
||||
@@ -2379,14 +2326,14 @@ const char *CPlayer::GetSteam3Id(bool validated)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_Steam3Id.c_str();
|
||||
return m_Steam3Id.chars();
|
||||
}
|
||||
|
||||
unsigned int CPlayer::GetSteamAccountID(bool validated)
|
||||
{
|
||||
if (!IsFakeClient() && (!validated || IsAuthStringValidated()))
|
||||
{
|
||||
const CSteamID &id = GetSteamId(validated);
|
||||
const CSteamID &id = GetSteamId();
|
||||
if (id.IsValid())
|
||||
return id.GetAccountID();
|
||||
}
|
||||
@@ -2513,7 +2460,7 @@ void CPlayer::Kick(const char *str)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pClient->Disconnect(str);
|
||||
#else
|
||||
pClient->Disconnect("%s", str);
|
||||
@@ -2631,7 +2578,7 @@ void CPlayer::DoBasicAdminChecks()
|
||||
if (!g_Players.CheckSetAdminName(client, this, id))
|
||||
{
|
||||
int userid = engine->GetPlayerUserId(m_pEdict);
|
||||
g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)(intptr_t)userid, 0);
|
||||
g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)userid, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2646,7 +2593,7 @@ void CPlayer::DoBasicAdminChecks()
|
||||
}
|
||||
|
||||
/* Check steam id */
|
||||
if ((id = adminsys->FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID)
|
||||
if ((id = adminsys->FindAdminByIdentity("steam", m_AuthID.chars())) != INVALID_ADMIN_ID)
|
||||
{
|
||||
if (g_Players.CheckSetAdmin(client, this, id))
|
||||
{
|
||||
@@ -2662,11 +2609,7 @@ unsigned int CPlayer::GetLanguageId()
|
||||
|
||||
void CPlayer::SetLanguageId(unsigned int id)
|
||||
{
|
||||
if(m_LangId != id)
|
||||
{
|
||||
m_LangId = id;
|
||||
g_Players.OnClientLanguageChanged(m_iIndex, id);
|
||||
}
|
||||
m_LangId = id;
|
||||
}
|
||||
|
||||
int CPlayer::GetUserId()
|
||||
|
||||
+8
-18
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 sts=8 sw=4 tw=99 noet :
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
|
||||
@@ -133,9 +133,9 @@ private:
|
||||
String m_Name;
|
||||
String m_Ip;
|
||||
String m_IpNoPort;
|
||||
std::string m_AuthID;
|
||||
std::string m_Steam2Id;
|
||||
std::string m_Steam3Id;
|
||||
ke::AString m_AuthID;
|
||||
ke::AString m_Steam2Id;
|
||||
ke::AString m_Steam3Id;
|
||||
AdminId m_Admin = INVALID_ADMIN_ID;
|
||||
bool m_TempAdmin = false;
|
||||
edict_t *m_pEdict = nullptr;
|
||||
@@ -151,16 +151,15 @@ private:
|
||||
bool m_bIsReplay = false;
|
||||
serial_t m_Serial;
|
||||
CSteamID m_SteamId;
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
QueryCvarCookie_t m_LanguageCookie = InvalidQueryCvarCookie;
|
||||
#endif
|
||||
std::deque<std::string> m_PrintfBuffer;
|
||||
ke::Deque<ke::AString> m_PrintfBuffer;
|
||||
};
|
||||
|
||||
class PlayerManager :
|
||||
public SMGlobalClass,
|
||||
public IPlayerManager,
|
||||
public IGameEventListener2
|
||||
public IPlayerManager
|
||||
{
|
||||
friend class CPlayer;
|
||||
public:
|
||||
@@ -193,7 +192,6 @@ public:
|
||||
#endif
|
||||
void OnClientSettingsChanged(edict_t *pEntity);
|
||||
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
|
||||
void OnClientLanguageChanged(int client, unsigned int language);
|
||||
void OnServerHibernationUpdate(bool bHibernating);
|
||||
void OnClientPrintf(edict_t *pEdict, const char *szMsg);
|
||||
void OnPrintfFrameAction(unsigned int serial);
|
||||
@@ -204,7 +202,6 @@ public: //IPlayerManager
|
||||
IGamePlayer *GetGamePlayer(edict_t *pEdict);
|
||||
int GetMaxClients();
|
||||
int GetNumPlayers();
|
||||
int GetNumClients();
|
||||
int GetClientOfUserId(int userid);
|
||||
bool IsServerActivated();
|
||||
int FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags);
|
||||
@@ -215,11 +212,6 @@ public: //IPlayerManager
|
||||
int GetClientFromSerial(unsigned int serial);
|
||||
void ClearAdminId(AdminId id);
|
||||
void RecheckAnyAdmins();
|
||||
public: // IGameEventListener2
|
||||
void FireGameEvent(IGameEvent *pEvent);
|
||||
#if SOURCE_ENGINE >= SE_ALIENSWARM
|
||||
virtual int GetEventDebugID( void ) { return 42; }
|
||||
#endif
|
||||
public:
|
||||
inline int MaxClients()
|
||||
{
|
||||
@@ -243,7 +235,7 @@ public:
|
||||
{
|
||||
return m_bInCCKVHook;
|
||||
}
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
bool HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
|
||||
#endif
|
||||
private:
|
||||
@@ -261,7 +253,6 @@ private:
|
||||
IForward *m_clcommandkv_post;
|
||||
IForward *m_clinfochanged;
|
||||
IForward *m_clauth;
|
||||
IForward *m_cllang;
|
||||
IForward *m_onActivate;
|
||||
IForward *m_onActivate2;
|
||||
CPlayer *m_Players;
|
||||
@@ -281,7 +272,6 @@ private:
|
||||
int m_SourceTVUserId;
|
||||
int m_ReplayUserId;
|
||||
bool m_bInCCKVHook;
|
||||
int m_ClientCount;
|
||||
private:
|
||||
static const int NETMSG_TYPE_BITS = 5; // SVC_Print overhead for netmsg type
|
||||
static const int SVC_Print_BufferSize = 2048 - 1; // -1 for terminating \0
|
||||
|
||||
+3
-9
@@ -69,13 +69,6 @@ class DefaultMapTimer :
|
||||
public IConVarChangeListener
|
||||
{
|
||||
public:
|
||||
|
||||
#if SOURCE_ENGINE == SE_BMS
|
||||
static constexpr int kMapTimeScaleFactor = 60;
|
||||
#else
|
||||
static constexpr int kMapTimeScaleFactor = 1;
|
||||
#endif
|
||||
|
||||
DefaultMapTimer()
|
||||
{
|
||||
m_bInUse = false;
|
||||
@@ -88,7 +81,7 @@ public:
|
||||
|
||||
int GetMapTimeLimit()
|
||||
{
|
||||
return (mp_timelimit->GetInt() / kMapTimeScaleFactor);
|
||||
return mp_timelimit->GetInt();
|
||||
}
|
||||
|
||||
void SetMapTimerStatus(bool enabled)
|
||||
@@ -112,7 +105,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
extra_time /= (60 / kMapTimeScaleFactor);
|
||||
extra_time /= 60;
|
||||
|
||||
mp_timelimit->SetValue(mp_timelimit->GetInt() + extra_time);
|
||||
}
|
||||
@@ -491,3 +484,4 @@ bool TimerSystem::GetMapTimeLeft(float *time_left)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,13 +118,6 @@ public:
|
||||
return msg;
|
||||
}
|
||||
|
||||
inline bool HasField(const char *pszFieldName)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
return msg->GetReflection()->HasField(*msg, field);
|
||||
}
|
||||
|
||||
inline bool GetInt32(const char *pszFieldName, int32 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
@@ -348,20 +341,6 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetInt64OrUnsigned(const char *pszFieldName, int64 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||
*out = (int64)msg->GetReflection()->GetUInt64(*msg, field);
|
||||
else
|
||||
*out = msg->GetReflection()->GetInt64(*msg, field);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
|
||||
{
|
||||
@@ -388,24 +367,6 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetInt64OrUnsigned(const char *pszFieldName, int64 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||
CHECK_FIELD_NOT_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||
{
|
||||
msg->GetReflection()->SetUInt64(msg, field, (uint64)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->GetReflection()->SetInt64(msg, field, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out)
|
||||
{
|
||||
@@ -423,21 +384,6 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 *out)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||
*out = (int64)msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
|
||||
else
|
||||
*out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value)
|
||||
{
|
||||
@@ -465,25 +411,6 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool SetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||
CHECK_FIELD_REPEATED();
|
||||
CHECK_REPEATED_ELEMENT(index);
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||
{
|
||||
msg->GetReflection()->SetRepeatedUInt64(msg, field, index, (uint64)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->GetReflection()->SetRepeatedInt64(msg, field, index, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
|
||||
{
|
||||
@@ -510,24 +437,6 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool AddInt64OrUnsigned(const char *pszFieldName, int64 value)
|
||||
{
|
||||
GETCHECK_FIELD();
|
||||
CHECK_FIELD_TYPE2(INT64, UINT64);
|
||||
CHECK_FIELD_REPEATED();
|
||||
|
||||
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
|
||||
{
|
||||
msg->GetReflection()->AddUInt64(msg, field, (uint64)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->GetReflection()->AddInt64(msg, field, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool GetBool(const char *pszFieldName, bool *out)
|
||||
{
|
||||
@@ -816,7 +725,7 @@ public:
|
||||
|
||||
inline bool GetColor(const char *pszFieldName, Color *out)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE != SE_BLADE
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
return false;
|
||||
#else
|
||||
GETCHECK_FIELD();
|
||||
@@ -837,7 +746,7 @@ public:
|
||||
|
||||
inline bool SetColor(const char *pszFieldName, const Color &value)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE != SE_BLADE
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
return false;
|
||||
#else
|
||||
GETCHECK_FIELD();
|
||||
@@ -856,7 +765,7 @@ public:
|
||||
|
||||
inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE != SE_BLADE
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
return false;
|
||||
#else
|
||||
GETCHECK_FIELD();
|
||||
@@ -878,7 +787,7 @@ public:
|
||||
|
||||
inline bool SetRepeatedColor(const char *pszFieldName, int index, const Color &value)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE != SE_BLADE
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
return false;
|
||||
#else
|
||||
GETCHECK_FIELD();
|
||||
@@ -898,7 +807,7 @@ public:
|
||||
|
||||
inline bool AddColor(const char *pszFieldName, const Color &value)
|
||||
{
|
||||
#if SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE != SE_BLADE
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
return false;
|
||||
#else
|
||||
GETCHECK_FIELD();
|
||||
|
||||
+18
-29
@@ -35,14 +35,12 @@
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include <cstrike15_usermessage_helpers.h>
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
#include <berimbau_usermessage_helpers.h>
|
||||
#endif
|
||||
#include <amtl/am-string.h>
|
||||
|
||||
UserMessages g_UserMsgs;
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
|
||||
#else
|
||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
@@ -51,7 +49,7 @@ SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRec
|
||||
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
|
||||
#endif
|
||||
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
|
||||
#endif // ==SE_CSGO || ==SE_BLADE
|
||||
#endif // ==SE_CSGO
|
||||
|
||||
UserMessages::UserMessages()
|
||||
#ifndef USE_PROTOBUF_USERMESSAGES
|
||||
@@ -95,7 +93,7 @@ void UserMessages::OnSourceModAllShutdown()
|
||||
{
|
||||
if (m_HookCount)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||
#else
|
||||
@@ -113,8 +111,6 @@ int UserMessages::GetMessageIndex(const char *msg)
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
// Can split this per engine and/or game later
|
||||
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
return g_BerimbauUsermessageHelpers.GetIndex(msg);
|
||||
#else
|
||||
|
||||
int msgid;
|
||||
@@ -152,8 +148,6 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
|
||||
#ifdef USE_PROTOBUF_USERMESSAGES
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
const char *pszName = g_BerimbauUsermessageHelpers.GetName(msgid);
|
||||
#endif
|
||||
if (!pszName)
|
||||
return false;
|
||||
@@ -303,7 +297,7 @@ bool UserMessages::EndMessage()
|
||||
return false;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
if (m_CurFlags & USERMSG_BLOCKHOOKS)
|
||||
{
|
||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
|
||||
@@ -333,7 +327,7 @@ bool UserMessages::EndMessage()
|
||||
} else {
|
||||
engine->MessageEnd();
|
||||
}
|
||||
#endif // SE_CSGO || SE_BLADE
|
||||
#endif // SE_CSGO
|
||||
|
||||
m_InExec = false;
|
||||
m_CurFlags = 0;
|
||||
@@ -418,7 +412,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
|
||||
|
||||
if (!m_HookCount++)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||
#else
|
||||
@@ -444,8 +438,6 @@ const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
return g_BerimbauUsermessageHelpers.GetPrototype(msg_type);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -495,7 +487,7 @@ void UserMessages::_DecRefCounter()
|
||||
{
|
||||
if (--m_HookCount == 0)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
|
||||
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
|
||||
#else
|
||||
@@ -507,17 +499,12 @@ void UserMessages::_DecRefCounter()
|
||||
}
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msg_type);
|
||||
#elif SOURCE_ENGINE == SE_BLADE
|
||||
const char *pszName = g_BerimbauUsermessageHelpers.GetName(msg_type);
|
||||
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||
#endif
|
||||
|
||||
OnStartMessage_Pre(&filter, msg_type, pszName);
|
||||
|
||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||
{
|
||||
int size = msg.ByteSize();
|
||||
@@ -530,7 +517,9 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type,
|
||||
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
|
||||
}
|
||||
|
||||
OnStartMessage_Post(&filter, msg_type, pszName);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
|
||||
#endif
|
||||
|
||||
OnMessageEnd_Pre();
|
||||
if (m_FakeMetaRes == MRES_SUPERCEDE)
|
||||
@@ -562,7 +551,7 @@ void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type
|
||||
RETURN_META(res)
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
@@ -602,7 +591,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|
||||
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
|
||||
@@ -767,7 +756,7 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
|
||||
if (!handled && intercepted)
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
|
||||
#else
|
||||
bf_write *engine_bfw;
|
||||
@@ -779,11 +768,11 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
|
||||
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
|
||||
ENGINE_CALL(MessageEnd)();
|
||||
#endif // SE_CSGO || SE_BLADE
|
||||
#endif // SE_CSGO
|
||||
}
|
||||
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
int size = m_OrigBuffer->ByteSize();
|
||||
uint8 *data = (uint8 *)stackalloc(size);
|
||||
m_OrigBuffer->SerializePartialToArray(data, size);
|
||||
@@ -813,7 +802,7 @@ void UserMessages::OnMessageEnd_Pre()
|
||||
iter++;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
delete pTempMsg;
|
||||
#endif
|
||||
}
|
||||
|
||||
+3
-3
@@ -44,7 +44,7 @@
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#define USE_PROTOBUF_USERMESSAGES
|
||||
#endif
|
||||
|
||||
@@ -102,12 +102,12 @@ public: //IUserMessages
|
||||
bool intercept=false);
|
||||
UserMessageType GetUserMessageType() const;
|
||||
public:
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
|
||||
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
|
||||
|
||||
+16
-16
@@ -36,7 +36,7 @@
|
||||
|
||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
||||
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_DECL_HOOK2_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *, bool);
|
||||
#else
|
||||
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void LinkConCommandBase(ConCommandBase *pBase, bool unknown)
|
||||
#else
|
||||
void LinkConCommandBase(ConCommandBase *pBase)
|
||||
@@ -108,20 +108,20 @@ public:
|
||||
listener = listener->next;
|
||||
}
|
||||
|
||||
while (iter != tracked_bases.end())
|
||||
{
|
||||
if ((*iter)->pBase == pBase)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
iter = tracked_bases.erase(iter);
|
||||
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName());
|
||||
delete pInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
while (iter != tracked_bases.end())
|
||||
{
|
||||
if ((*iter)->pBase == pBase)
|
||||
{
|
||||
pInfo = (*iter);
|
||||
iter = tracked_bases.erase(iter);
|
||||
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName());
|
||||
delete pInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
|
||||
|
||||
+86
-87
@@ -1,95 +1,94 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import os
|
||||
|
||||
for cxx in builder.targets:
|
||||
binary = SM.Library(builder, cxx, 'sourcemod.logic')
|
||||
binary.compiler.cxxincludes += [
|
||||
builder.sourcePath,
|
||||
os.path.join(builder.sourcePath, 'core', 'logic'),
|
||||
os.path.join(builder.sourcePath, 'public'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
||||
]
|
||||
binary.compiler.defines += [
|
||||
'SM_DEFAULT_THREADER',
|
||||
'SM_LOGIC'
|
||||
]
|
||||
binary = SM.Library(builder, 'sourcemod.logic')
|
||||
binary.compiler.cxxincludes += [
|
||||
builder.sourcePath,
|
||||
os.path.join(builder.sourcePath, 'core', 'logic'),
|
||||
os.path.join(builder.sourcePath, 'public'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook')
|
||||
]
|
||||
binary.compiler.defines += [
|
||||
'SM_DEFAULT_THREADER',
|
||||
'SM_LOGIC'
|
||||
]
|
||||
|
||||
if binary.compiler.target.platform == 'linux':
|
||||
binary.compiler.postlink += ['-lpthread', '-lrt']
|
||||
elif binary.compiler.target.platform == 'mac':
|
||||
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||
if builder.target.platform == 'linux':
|
||||
binary.compiler.postlink += ['-lpthread', '-lrt']
|
||||
elif builder.target.platform == 'mac':
|
||||
binary.compiler.cflags += ['-Wno-deprecated-declarations']
|
||||
binary.compiler.postlink += ['-framework', 'CoreServices']
|
||||
|
||||
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.family == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
|
||||
binary.compiler.cxxflags += ['-fno-rtti']
|
||||
elif binary.compiler.family == 'msvc':
|
||||
binary.compiler.cxxflags += ['/GR-']
|
||||
|
||||
binary.sources += [
|
||||
'common_logic.cpp',
|
||||
'smn_adt_array.cpp',
|
||||
'smn_sorting.cpp',
|
||||
'smn_maplists.cpp',
|
||||
'ADTFactory.cpp',
|
||||
'smn_adt_stack.cpp',
|
||||
'BaseWorker.cpp',
|
||||
'ThreadSupport.cpp',
|
||||
'smn_float.cpp',
|
||||
'TextParsers.cpp',
|
||||
'smn_textparse.cpp',
|
||||
'smn_adt_trie.cpp',
|
||||
'smn_functions.cpp',
|
||||
'smn_timers.cpp',
|
||||
'smn_players.cpp',
|
||||
'MemoryUtils.cpp',
|
||||
'smn_admin.cpp',
|
||||
'smn_banning.cpp',
|
||||
'smn_filesystem.cpp',
|
||||
'stringutil.cpp',
|
||||
'Translator.cpp',
|
||||
'PhraseCollection.cpp',
|
||||
'smn_lang.cpp',
|
||||
'smn_string.cpp',
|
||||
'smn_handles.cpp',
|
||||
'smn_datapacks.cpp',
|
||||
'smn_gameconfigs.cpp',
|
||||
'smn_fakenatives.cpp',
|
||||
'GameConfigs.cpp',
|
||||
'sm_crc32.cpp',
|
||||
'smn_profiler.cpp',
|
||||
'ShareSys.cpp',
|
||||
'PluginSys.cpp',
|
||||
'HandleSys.cpp',
|
||||
'NativeOwner.cpp',
|
||||
'ExtensionSys.cpp',
|
||||
'DebugReporter.cpp',
|
||||
'Database.cpp',
|
||||
'smn_database.cpp',
|
||||
'ForwardSys.cpp',
|
||||
'AdminCache.cpp',
|
||||
'sm_trie.cpp',
|
||||
'smn_console.cpp',
|
||||
'ProfileTools.cpp',
|
||||
'Logger.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_menus.cpp',
|
||||
'sprintf.cpp',
|
||||
'LibrarySys.cpp',
|
||||
'RootConsoleMenu.cpp',
|
||||
'CDataPack.cpp',
|
||||
'frame_tasks.cpp',
|
||||
'smn_halflife.cpp',
|
||||
'FrameIterator.cpp',
|
||||
'DatabaseConfBuilder.cpp',
|
||||
'LumpManager.cpp',
|
||||
'smn_entitylump.cpp',
|
||||
'NativeInvoker.cpp',
|
||||
]
|
||||
binary.sources += [
|
||||
'common_logic.cpp',
|
||||
'smn_adt_array.cpp',
|
||||
'smn_sorting.cpp',
|
||||
'smn_maplists.cpp',
|
||||
'ADTFactory.cpp',
|
||||
'smn_adt_stack.cpp',
|
||||
'thread/ThreadWorker.cpp',
|
||||
'thread/BaseWorker.cpp',
|
||||
'ThreadSupport.cpp',
|
||||
'smn_float.cpp',
|
||||
'TextParsers.cpp',
|
||||
'smn_textparse.cpp',
|
||||
'smn_adt_trie.cpp',
|
||||
'smn_functions.cpp',
|
||||
'smn_timers.cpp',
|
||||
'smn_players.cpp',
|
||||
'MemoryUtils.cpp',
|
||||
'smn_admin.cpp',
|
||||
'smn_banning.cpp',
|
||||
'smn_filesystem.cpp',
|
||||
'stringutil.cpp',
|
||||
'Translator.cpp',
|
||||
'PhraseCollection.cpp',
|
||||
'smn_lang.cpp',
|
||||
'smn_string.cpp',
|
||||
'smn_handles.cpp',
|
||||
'smn_datapacks.cpp',
|
||||
'smn_gameconfigs.cpp',
|
||||
'smn_fakenatives.cpp',
|
||||
'GameConfigs.cpp',
|
||||
'sm_crc32.cpp',
|
||||
'smn_profiler.cpp',
|
||||
'ShareSys.cpp',
|
||||
'PluginSys.cpp',
|
||||
'HandleSys.cpp',
|
||||
'NativeOwner.cpp',
|
||||
'ExtensionSys.cpp',
|
||||
'DebugReporter.cpp',
|
||||
'Database.cpp',
|
||||
'smn_database.cpp',
|
||||
'ForwardSys.cpp',
|
||||
'AdminCache.cpp',
|
||||
'sm_trie.cpp',
|
||||
'smn_console.cpp',
|
||||
'ProfileTools.cpp',
|
||||
'Logger.cpp',
|
||||
'smn_core.cpp',
|
||||
'smn_menus.cpp',
|
||||
'sprintf.cpp',
|
||||
'LibrarySys.cpp',
|
||||
'RootConsoleMenu.cpp',
|
||||
'CDataPack.cpp',
|
||||
'frame_tasks.cpp',
|
||||
'smn_halflife.cpp',
|
||||
'FrameIterator.cpp',
|
||||
'NativeInvoker.cpp',
|
||||
]
|
||||
if builder.target.platform == 'windows':
|
||||
binary.sources += ['thread/WinThreads.cpp']
|
||||
else:
|
||||
binary.sources += ['thread/PosixThreads.cpp']
|
||||
|
||||
if binary.compiler.target.arch == 'x86_64':
|
||||
binary.sources += ['PseudoAddrManager.cpp']
|
||||
|
||||
SM.binaries += [builder.Add(binary)]
|
||||
SM.binaries += [builder.Add(binary)]
|
||||
|
||||
@@ -1090,14 +1090,14 @@ bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t ma
|
||||
else if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_')
|
||||
{
|
||||
// non-bot/lan Steam2 Id, strip off the STEAM_* part
|
||||
ke::SafeStrcpy(out, maxlen, &ident[8]);
|
||||
snprintf(out, maxlen, "%s", &ident[8]);
|
||||
return true;
|
||||
}
|
||||
else if (len >= 7 && !strncmp(ident, "[U:", 3) && ident[len-1] == ']')
|
||||
{
|
||||
// Steam3 Id, replicate the Steam2 Post-"STEAM_" part
|
||||
uint32_t accountId = strtoul(&ident[5], nullptr, 10);
|
||||
ke::SafeSprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -1124,7 +1124,7 @@ bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t ma
|
||||
&& accountType == k_EAccountTypeIndividual && accountInstance <= k_unSteamUserWebInstance
|
||||
)
|
||||
{
|
||||
ke::SafeSprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1581,7 +1581,7 @@ bool AdminCache::CanAdminTarget(AdminId id, AdminId target)
|
||||
{
|
||||
id = grp_table[i];
|
||||
num = GetGroupImmunityCount(id);
|
||||
for (unsigned int j=0; j<num; j++)
|
||||
for (unsigned int j=0; j<num; i++)
|
||||
{
|
||||
other = GetGroupImmunity(id, j);
|
||||
for (unsigned int k=0; k<pUser->grp_count; k++)
|
||||
@@ -1843,13 +1843,13 @@ bool AdminCache::DumpCache(const char *filename)
|
||||
fprintf(fp, "\n\t\t\"Overrides\"\n\t\t{\n");
|
||||
if (pGroup->pCmdGrpTable != NULL)
|
||||
{
|
||||
for (OverrideMap::iterator iter = pGroup->pCmdGrpTable->iter(); !iter.empty(); iter.next())
|
||||
iterator_group_grp_override(fp, iter->key.c_str(), iter->value);
|
||||
for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next())
|
||||
iterator_group_grp_override(fp, iter->key.chars(), iter->value);
|
||||
}
|
||||
if (pGroup->pCmdTable != NULL)
|
||||
{
|
||||
for (OverrideMap::iterator iter = pGroup->pCmdTable->iter(); !iter.empty(); iter.next())
|
||||
iterator_group_basic_override(fp, iter->key.c_str(), iter->value);
|
||||
iterator_group_basic_override(fp, iter->key.chars(), iter->value);
|
||||
}
|
||||
fprintf(fp, "\t\t}\n");
|
||||
|
||||
@@ -1924,9 +1924,9 @@ bool AdminCache::DumpCache(const char *filename)
|
||||
|
||||
fprintf(fp, "\"Overrides\"\n{\n");
|
||||
for (FlagMap::iterator iter = m_CmdGrpOverrides.iter(); !iter.empty(); iter.next())
|
||||
iterator_glob_grp_override(fp, iter->key.c_str(), iter->value);
|
||||
iterator_glob_grp_override(fp, iter->key.chars(), iter->value);
|
||||
for (FlagMap::iterator iter = m_CmdOverrides.iter(); !iter.empty(); iter.next())
|
||||
iterator_glob_basic_override(fp, iter->key.c_str(), iter->value);
|
||||
iterator_glob_basic_override(fp, iter->key.chars(), iter->value);
|
||||
fprintf(fp, "}\n");
|
||||
|
||||
fclose(fp);
|
||||
|
||||
+220
-167
@@ -31,274 +31,327 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "CDataPack.h"
|
||||
#include <amtl/am-autoptr.h>
|
||||
#include <amtl/am-vector.h>
|
||||
|
||||
using namespace ke;
|
||||
|
||||
#define DATAPACK_INITIAL_SIZE 64
|
||||
|
||||
CDataPack::CDataPack()
|
||||
{
|
||||
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
|
||||
m_capacity = DATAPACK_INITIAL_SIZE;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
CDataPack::~CDataPack()
|
||||
{
|
||||
Initialize();
|
||||
free(m_pBase);
|
||||
}
|
||||
|
||||
static Vector<AutoPtr<CDataPack>> sDataPackCache;
|
||||
|
||||
IDataPack * CDataPack::New()
|
||||
{
|
||||
if (sDataPackCache.empty())
|
||||
return new CDataPack();
|
||||
|
||||
CDataPack *pack = sDataPackCache.back().take();
|
||||
sDataPackCache.pop();
|
||||
pack->Initialize();
|
||||
return pack;
|
||||
}
|
||||
|
||||
void
|
||||
CDataPack::Free(IDataPack *pack)
|
||||
{
|
||||
sDataPackCache.append(static_cast<CDataPack *>(pack));
|
||||
}
|
||||
|
||||
void CDataPack::Initialize()
|
||||
{
|
||||
position = 0;
|
||||
|
||||
m_curptr = m_pBase;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void CDataPack::CheckSize(size_t typesize)
|
||||
{
|
||||
if (m_curptr - m_pBase + typesize <= m_capacity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pos = m_curptr - m_pBase;
|
||||
do
|
||||
{
|
||||
} while (this->RemoveItem());
|
||||
|
||||
elements.clear();
|
||||
m_capacity *= 2;
|
||||
} while (pos + typesize > m_capacity);
|
||||
|
||||
m_pBase = (char *)realloc(m_pBase, m_capacity);
|
||||
m_curptr = m_pBase + pos;
|
||||
}
|
||||
|
||||
void CDataPack::ResetSize()
|
||||
{
|
||||
Initialize();
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
size_t CDataPack::CreateMemory(size_t size, void **addr)
|
||||
{
|
||||
InternalPack val;
|
||||
val.type = CDataPackType::Raw;
|
||||
val.pData.vval = new uint8_t[size + sizeof(size)];
|
||||
reinterpret_cast<size_t *>(val.pData.vval)[0] = size;
|
||||
elements.emplace(elements.begin() + position, val);
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + size);
|
||||
size_t pos = m_curptr - m_pBase;
|
||||
|
||||
return position++;
|
||||
*(char *)m_curptr = Raw;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = size;
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
if (addr)
|
||||
{
|
||||
*addr = m_curptr;
|
||||
}
|
||||
|
||||
m_curptr += size;
|
||||
m_size += sizeof(char) + sizeof(size_t) + size;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void CDataPack::PackCell(cell_t cell)
|
||||
{
|
||||
InternalPack val;
|
||||
val.type = CDataPackType::Cell;
|
||||
val.pData.cval = cell;
|
||||
elements.emplace(elements.begin() + position, val);
|
||||
position++;
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
||||
|
||||
*(char *)m_curptr = Cell;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(cell_t);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
*(cell_t *)m_curptr = cell;
|
||||
m_curptr += sizeof(cell_t);
|
||||
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
||||
}
|
||||
|
||||
void CDataPack::PackFunction(cell_t function)
|
||||
void CDataPack::PackFloat(float val)
|
||||
{
|
||||
InternalPack val;
|
||||
val.type = CDataPackType::Function;
|
||||
val.pData.cval = function;
|
||||
elements.emplace(elements.begin() + position, val);
|
||||
position++;
|
||||
}
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
|
||||
|
||||
void CDataPack::PackFloat(float floatval)
|
||||
{
|
||||
InternalPack val;
|
||||
val.type = CDataPackType::Float;
|
||||
val.pData.fval = floatval;
|
||||
elements.emplace(elements.begin() + position, val);
|
||||
position++;
|
||||
*(char *)m_curptr = Float;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
*(size_t *)m_curptr = sizeof(float);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
*(float *)m_curptr = val;
|
||||
m_curptr += sizeof(float);
|
||||
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
|
||||
}
|
||||
|
||||
void CDataPack::PackString(const char *string)
|
||||
{
|
||||
InternalPack val;
|
||||
val.type = CDataPackType::String;
|
||||
std::string *sval = new std::string(string);
|
||||
val.pData.sval = sval;
|
||||
elements.emplace(elements.begin() + position, val);
|
||||
position++;
|
||||
}
|
||||
size_t len = strlen(string);
|
||||
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
|
||||
CheckSize(maxsize);
|
||||
|
||||
void CDataPack::PackCellArray(cell_t const *vals, cell_t count)
|
||||
{
|
||||
InternalPack val;
|
||||
val.type = CDataPackType::CellArray;
|
||||
*(char *)m_curptr = String;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
val.pData.aval = new cell_t [count + 1];
|
||||
memcpy(&val.pData.aval[1], vals, sizeof(cell_t) * count);
|
||||
val.pData.aval[0] = count;
|
||||
elements.emplace(elements.begin() + position, val);
|
||||
position++;
|
||||
}
|
||||
// Pack the string length first for buffer overrun checking.
|
||||
*(size_t *)m_curptr = len;
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
void CDataPack::PackFloatArray(cell_t const *vals, cell_t count)
|
||||
{
|
||||
InternalPack val;
|
||||
val.type = CDataPackType::FloatArray;
|
||||
// Now pack the string.
|
||||
memcpy(m_curptr, string, len);
|
||||
m_curptr[len] = '\0';
|
||||
m_curptr += len + 1;
|
||||
|
||||
val.pData.aval = new cell_t [count + 1];
|
||||
memcpy(&val.pData.aval[1], vals, sizeof(cell_t) * count);
|
||||
val.pData.aval[0] = count;
|
||||
elements.emplace(elements.begin() + position, val);
|
||||
position++;
|
||||
m_size += maxsize;
|
||||
}
|
||||
|
||||
void CDataPack::Reset() const
|
||||
{
|
||||
position = 0;
|
||||
m_curptr = m_pBase;
|
||||
}
|
||||
|
||||
size_t CDataPack::GetPosition() const
|
||||
{
|
||||
return position;
|
||||
return static_cast<size_t>(m_curptr - m_pBase);
|
||||
}
|
||||
|
||||
bool CDataPack::SetPosition(size_t pos) const
|
||||
{
|
||||
if (pos > elements.size())
|
||||
if (pos > m_size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_curptr = m_pBase + pos;
|
||||
|
||||
position = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
cell_t CDataPack::ReadCell() const
|
||||
{
|
||||
if (!IsReadable() || elements[position].type != CDataPackType::Cell)
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return 0;
|
||||
|
||||
return elements[position++].pData.cval;
|
||||
}
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Cell)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
cell_t CDataPack::ReadFunction() const
|
||||
{
|
||||
if (!IsReadable() || elements[position].type != CDataPackType::Function)
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
||||
{
|
||||
return 0;
|
||||
|
||||
return elements[position++].pData.cval;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
|
||||
m_curptr += sizeof(cell_t);
|
||||
return val;
|
||||
}
|
||||
|
||||
float CDataPack::ReadFloat() const
|
||||
{
|
||||
if (!IsReadable() || elements[position].type != CDataPackType::Float)
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
|
||||
{
|
||||
return 0;
|
||||
|
||||
return elements[position++].pData.fval;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Float)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
float val = *reinterpret_cast<float *>(m_curptr);
|
||||
m_curptr += sizeof(float);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool CDataPack::IsReadable(size_t bytes) const
|
||||
{
|
||||
return (position < elements.size());
|
||||
return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
|
||||
}
|
||||
|
||||
const char *CDataPack::ReadString(size_t *len) const
|
||||
{
|
||||
if (!IsReadable() || elements[position].type != CDataPackType::String)
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t)))
|
||||
{
|
||||
if (len)
|
||||
*len = 0;
|
||||
return NULL;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != String)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
return nullptr;
|
||||
size_t real_len = *(size_t *)m_curptr;
|
||||
|
||||
m_curptr += sizeof(size_t);
|
||||
char *str = (char *)m_curptr;
|
||||
|
||||
if ((strlen(str) != real_len) || !(IsReadable(real_len+1)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const std::string &val = *elements[position++].pData.sval;
|
||||
if (len)
|
||||
*len = val.size();
|
||||
|
||||
return val.c_str();
|
||||
}
|
||||
|
||||
cell_t *CDataPack::ReadCellArray(cell_t *size) const
|
||||
{
|
||||
if (!IsReadable() || elements[position].type != CDataPackType::CellArray)
|
||||
{
|
||||
if(size)
|
||||
*size = 0;
|
||||
|
||||
return nullptr;
|
||||
*len = real_len;
|
||||
}
|
||||
|
||||
cell_t *val = elements[position].pData.aval;
|
||||
cell_t *ptr = &(val[1]);
|
||||
++position;
|
||||
m_curptr += real_len + 1;
|
||||
|
||||
if (size)
|
||||
*size = val[0];
|
||||
|
||||
return ptr;
|
||||
return str;
|
||||
}
|
||||
|
||||
cell_t *CDataPack::ReadFloatArray(cell_t *size) const
|
||||
void *CDataPack::GetMemory() const
|
||||
{
|
||||
if (!IsReadable() || elements[position].type != CDataPackType::FloatArray)
|
||||
{
|
||||
if(size)
|
||||
*size = 0;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cell_t *val = elements[position].pData.aval;
|
||||
cell_t *ptr = &(val[1]);
|
||||
++position;
|
||||
|
||||
if (size)
|
||||
*size = val[0];
|
||||
|
||||
return ptr;
|
||||
return m_curptr;
|
||||
}
|
||||
|
||||
void *CDataPack::ReadMemory(size_t *size) const
|
||||
{
|
||||
void *ptr = nullptr;
|
||||
if (!IsReadable() || elements[position].type != CDataPackType::Raw)
|
||||
return ptr;
|
||||
if (!IsReadable(sizeof(size_t)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Raw)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
size_t *val = reinterpret_cast<size_t *>(elements[position].pData.vval);
|
||||
ptr = &(val[1]);
|
||||
++position;
|
||||
size_t bytecount = *(size_t *)m_curptr;
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
if (!IsReadable(bytecount))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *ptr = m_curptr;
|
||||
|
||||
if (size)
|
||||
*size = val[0]; /* Egor!!!! */
|
||||
{
|
||||
*size = bytecount;
|
||||
}
|
||||
|
||||
m_curptr += bytecount;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool CDataPack::RemoveItem(size_t pos)
|
||||
void CDataPack::PackFunction(cell_t function)
|
||||
{
|
||||
if (!elements.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
|
||||
|
||||
if (pos == static_cast<size_t>(-1))
|
||||
{
|
||||
pos = position;
|
||||
}
|
||||
|
||||
if (pos >= elements.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*(char *)m_curptr = Function;
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (pos < position) // we're deleting under us, step back
|
||||
{
|
||||
--position;
|
||||
}
|
||||
*(size_t *)m_curptr = sizeof(cell_t);
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
switch (elements[pos].type)
|
||||
{
|
||||
case CDataPackType::Raw:
|
||||
{
|
||||
delete [] elements[pos].pData.vval;
|
||||
break;
|
||||
}
|
||||
*(cell_t *)m_curptr = function;
|
||||
m_curptr += sizeof(cell_t);
|
||||
|
||||
case CDataPackType::String:
|
||||
{
|
||||
delete elements[pos].pData.sval;
|
||||
break;
|
||||
}
|
||||
|
||||
case CDataPackType::CellArray:
|
||||
case CDataPackType::FloatArray:
|
||||
{
|
||||
delete [] elements[pos].pData.aval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
elements.erase(elements.begin() + pos);
|
||||
return true;
|
||||
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
|
||||
}
|
||||
|
||||
cell_t CDataPack::ReadFunction() const
|
||||
{
|
||||
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (*reinterpret_cast<char *>(m_curptr) != Function)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_curptr += sizeof(char);
|
||||
|
||||
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_curptr += sizeof(size_t);
|
||||
|
||||
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
|
||||
m_curptr += sizeof(cell_t);
|
||||
return val;
|
||||
}
|
||||
|
||||
+22
-163
@@ -32,195 +32,54 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||
|
||||
#include <ISourceMod.h>
|
||||
#include <amtl/am-vector.h>
|
||||
#include <amtl/am-string.h>
|
||||
#include <IDataPack.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
enum CDataPackType {
|
||||
Raw,
|
||||
Cell,
|
||||
Float,
|
||||
String,
|
||||
Function,
|
||||
CellArray,
|
||||
FloatArray,
|
||||
};
|
||||
|
||||
class CDataPack
|
||||
class CDataPack : public IDataPack
|
||||
{
|
||||
public:
|
||||
CDataPack();
|
||||
~CDataPack();
|
||||
|
||||
public: // Originally IDataReader
|
||||
/**
|
||||
* @brief Resets the position in the data stream to the beginning.
|
||||
*/
|
||||
static IDataPack *New();
|
||||
static void Free(IDataPack *pack);
|
||||
public: //IDataReader
|
||||
void Reset() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the current stream position.
|
||||
*
|
||||
* @return Index into the stream.
|
||||
*/
|
||||
size_t GetPosition() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the current stream position.
|
||||
*
|
||||
* @param pos Index to set the stream at.
|
||||
* @return True if succeeded, false if out of bounds.
|
||||
*/
|
||||
bool SetPosition(size_t pos) const;
|
||||
|
||||
/**
|
||||
* @brief Reads one cell from the data stream.
|
||||
*
|
||||
* @return A cell read from the current position.
|
||||
*/
|
||||
cell_t ReadCell() const;
|
||||
|
||||
/**
|
||||
* @brief Reads one float from the data stream.
|
||||
*
|
||||
* @return A float read from the current position.
|
||||
*/
|
||||
float ReadFloat() const;
|
||||
|
||||
/**
|
||||
* @brief Reads an array of values from the data stream.
|
||||
*
|
||||
* @param len The size of the array stored at this position to return.
|
||||
* @return A cell array read from the current position.
|
||||
*/
|
||||
cell_t *ReadCellArray(cell_t *len) const;
|
||||
/**
|
||||
* @brief Reads an array of values from the data stream.
|
||||
*
|
||||
* @param len The size of the array stored at this position to return.
|
||||
* @return A cell array read from the current position.
|
||||
*/
|
||||
cell_t *ReadFloatArray(cell_t *len) const;
|
||||
|
||||
/**
|
||||
* @brief Returns whether or not a specified number of bytes from the current stream
|
||||
* position to the end can be read.
|
||||
*
|
||||
* @param bytes Number of bytes to simulate reading.
|
||||
* @return True if can be read, false otherwise.
|
||||
*/
|
||||
bool IsReadable(size_t bytes = 0) const;
|
||||
|
||||
/**
|
||||
* @brief Reads a string from the data stream.
|
||||
*
|
||||
* @param len Optional pointer to store the string length.
|
||||
* @return Pointer to the string, or NULL if out of bounds.
|
||||
*/
|
||||
bool IsReadable(size_t bytes) const;
|
||||
const char *ReadString(size_t *len) const;
|
||||
|
||||
/**
|
||||
* @brief Reads the current position as a generic data type.
|
||||
*
|
||||
* @param size Optional pointer to store the size of the data type.
|
||||
* @return Pointer to the data, or NULL if out of bounds.
|
||||
*/
|
||||
void *GetMemory() const;
|
||||
void *ReadMemory(size_t *size) const;
|
||||
|
||||
/**
|
||||
* @brief Reads a function pointer from the data stream.
|
||||
*
|
||||
* @return A function pointer read from the current position.
|
||||
*/
|
||||
cell_t ReadFunction() const;
|
||||
|
||||
public: // Originally IDataPack
|
||||
/**
|
||||
* @brief Resets the used size of the stream back to zero.
|
||||
*/
|
||||
public: //IDataPack
|
||||
void ResetSize();
|
||||
|
||||
/**
|
||||
* @brief Packs one cell into the data stream.
|
||||
*
|
||||
* @param cell Cell value to write.
|
||||
*/
|
||||
void PackCell(cell_t cell);
|
||||
|
||||
/**
|
||||
* @brief Packs one float into the data stream.
|
||||
*
|
||||
* @param val Float value to write.
|
||||
*/
|
||||
void PackFloat(float val);
|
||||
|
||||
/**
|
||||
* @brief Packs one string into the data stream.
|
||||
* The length is recorded as well for buffer overrun protection.
|
||||
*
|
||||
* @param string String to write.
|
||||
*/
|
||||
void PackString(const char *string);
|
||||
|
||||
/**
|
||||
* @brief Packs an array of cells into the data stream.
|
||||
*
|
||||
* @param vals Cells to write.
|
||||
* @param count Number of cells.
|
||||
*/
|
||||
void PackCellArray(cell_t const *vals, cell_t count);
|
||||
/**
|
||||
* @brief Packs an array of cells into the data stream.
|
||||
*
|
||||
* @param vals Cells to write.
|
||||
* @param count Number of cells.
|
||||
*/
|
||||
void PackFloatArray(cell_t const *vals, cell_t count);
|
||||
|
||||
/**
|
||||
* @brief Creates a generic block of memory in the stream.
|
||||
*
|
||||
* Note that the pointer it returns can be invalidated on further
|
||||
* writing, since the stream size may grow. You may need to double back
|
||||
* and fetch the pointer again.
|
||||
*
|
||||
* @param size Size of the memory to create in the stream.
|
||||
* @param addr Optional pointer to store the relocated memory address.
|
||||
* @return Current position of the stream beforehand.
|
||||
*/
|
||||
size_t CreateMemory(size_t size, void **addr);
|
||||
|
||||
/**
|
||||
* @brief Packs one function pointer into the data stream.
|
||||
*
|
||||
* @param function The function pointer to write.
|
||||
*/
|
||||
void PackFunction(cell_t function);
|
||||
|
||||
public:
|
||||
void Initialize();
|
||||
inline size_t GetCapacity() const { return this->elements.size(); };
|
||||
inline CDataPackType GetCurrentType(void) const { return this->elements[this->position].type; };
|
||||
bool RemoveItem(size_t pos = -1);
|
||||
|
||||
inline size_t GetCapacity() const { return m_capacity; }
|
||||
private:
|
||||
typedef union {
|
||||
cell_t cval;
|
||||
float fval;
|
||||
uint8_t *vval;
|
||||
std::string *sval;
|
||||
cell_t *aval;
|
||||
} InternalPackValue;
|
||||
|
||||
typedef struct {
|
||||
InternalPackValue pData;
|
||||
CDataPackType type;
|
||||
} InternalPack;
|
||||
void CheckSize(size_t sizetype);
|
||||
private:
|
||||
char *m_pBase;
|
||||
mutable char *m_curptr;
|
||||
size_t m_capacity;
|
||||
size_t m_size;
|
||||
|
||||
std::vector<InternalPack> elements;
|
||||
mutable size_t position;
|
||||
enum DataPackType {
|
||||
Raw,
|
||||
Cell,
|
||||
Float,
|
||||
String,
|
||||
Function
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
|
||||
|
||||
+9
-20
@@ -35,7 +35,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ICellArray.h>
|
||||
#include <amtl/am-bits.h>
|
||||
|
||||
extern HandleType_t htCellArray;
|
||||
|
||||
@@ -215,34 +214,24 @@ private:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
size_t newAllocSize = m_AllocSize;
|
||||
/* Set a base allocation size of 8 items */
|
||||
if (!newAllocSize)
|
||||
if (!m_AllocSize)
|
||||
{
|
||||
newAllocSize = 8;
|
||||
}
|
||||
if (!ke::IsUintPtrAddSafe(m_Size, count))
|
||||
{
|
||||
return false;
|
||||
m_AllocSize = 8;
|
||||
}
|
||||
/* If it's not enough, keep doubling */
|
||||
while (m_Size + count > newAllocSize)
|
||||
while (m_Size + count > m_AllocSize)
|
||||
{
|
||||
if (!ke::IsUintPtrMultiplySafe(newAllocSize, 2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
newAllocSize *= 2;
|
||||
m_AllocSize *= 2;
|
||||
}
|
||||
/* finally, allocate the new block */
|
||||
cell_t *data = static_cast<cell_t*>(realloc(m_Data, sizeof(cell_t) * m_BlockSize * newAllocSize));
|
||||
/* Update state if allocation was successful */
|
||||
if (data)
|
||||
if (m_Data)
|
||||
{
|
||||
m_AllocSize = newAllocSize;
|
||||
m_Data = data;
|
||||
m_Data = (cell_t *)realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
||||
} else {
|
||||
m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
|
||||
}
|
||||
return (data != nullptr);
|
||||
return (m_Data != NULL);
|
||||
}
|
||||
private:
|
||||
cell_t *m_Data;
|
||||
|
||||
+250
-87
@@ -34,23 +34,21 @@
|
||||
#include "HandleSys.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include "PluginSys.h"
|
||||
#include <chrono>
|
||||
#include <amtl/am-thread.h>
|
||||
#include <stdlib.h>
|
||||
#include <IThreader.h>
|
||||
#include <bridge/include/ILogger.h>
|
||||
#include <bridge/include/CoreProvider.h>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#define DBPARSE_LEVEL_NONE 0
|
||||
#define DBPARSE_LEVEL_MAIN 1
|
||||
#define DBPARSE_LEVEL_DATABASE 2
|
||||
|
||||
DBManager g_DBMan;
|
||||
static bool s_OneTimeThreaderErrorMsg = false;
|
||||
|
||||
DBManager::DBManager()
|
||||
: m_Terminate(false),
|
||||
m_ParseLevel(0),
|
||||
m_ParseState(0),
|
||||
m_pDefault(NULL)
|
||||
{
|
||||
}
|
||||
@@ -67,29 +65,38 @@ void DBManager::OnSourceModAllInitialized()
|
||||
g_HandleSys.InitAccessDefaults(NULL, &sec);
|
||||
sec.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY;
|
||||
sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY;
|
||||
|
||||
|
||||
m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL);
|
||||
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
|
||||
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
|
||||
m_Builder.SetPath(m_Filename);
|
||||
|
||||
|
||||
g_PluginSys.AddPluginsListener(this);
|
||||
|
||||
|
||||
g_pSM->AddGameFrameHook(&FrameHook);
|
||||
|
||||
auto sm_reload_databases = [this] (int client, const ICommandArgs *args) -> bool {
|
||||
m_Builder.StartParse();
|
||||
return true;
|
||||
};
|
||||
bridge->DefineCommand("sm_reload_databases", "Reparse database configurations file", sm_reload_databases);
|
||||
}
|
||||
|
||||
void DBManager::OnSourceModLevelChange(const char *mapName)
|
||||
{
|
||||
m_Builder.StartParse();
|
||||
SMCError err;
|
||||
SMCStates states = {0, 0};
|
||||
|
||||
/* We lock and don't give up the lock until we're done.
|
||||
* This way the thread's search won't be searching through a
|
||||
* potentially empty/corrupt list, which would be very bad.
|
||||
*/
|
||||
ke::AutoLock lock(&m_ConfigLock);
|
||||
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
|
||||
{
|
||||
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
|
||||
if (err != SMCError_Custom)
|
||||
{
|
||||
const char *txt = textparsers->GetSMCErrorString(err);
|
||||
logger->LogError("[SM] Line %d: %s", states.line, txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBManager::OnSourceModShutdown()
|
||||
@@ -99,6 +106,7 @@ void DBManager::OnSourceModShutdown()
|
||||
g_PluginSys.RemovePluginsListener(this);
|
||||
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
|
||||
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
|
||||
ClearConfigs();
|
||||
}
|
||||
|
||||
unsigned int DBManager::GetInterfaceVersion()
|
||||
@@ -126,10 +134,136 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||
}
|
||||
}
|
||||
|
||||
void DBManager::ReadSMC_ParseStart()
|
||||
{
|
||||
ClearConfigs();
|
||||
m_ParseLevel = 0;
|
||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||
m_DefDriver.clear();
|
||||
}
|
||||
|
||||
void DBManager::ClearConfigs()
|
||||
{
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
delete (*iter);
|
||||
m_confs.clear();
|
||||
}
|
||||
|
||||
ConfDbInfo s_CurInfo;
|
||||
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
{
|
||||
m_ParseLevel++;
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_NONE)
|
||||
{
|
||||
if (strcmp(name, "Databases") == 0)
|
||||
{
|
||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||
} else {
|
||||
m_ParseLevel++;
|
||||
}
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||
s_CurInfo = ConfDbInfo();
|
||||
s_CurInfo.name = name;
|
||||
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||
m_ParseLevel++;
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
{
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_MAIN)
|
||||
{
|
||||
if (strcmp(key, "driver_default") == 0)
|
||||
{
|
||||
m_DefDriver.assign(value);
|
||||
}
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||
if (strcmp(key, "driver") == 0)
|
||||
{
|
||||
if (strcmp(value, "default") != 0)
|
||||
{
|
||||
s_CurInfo.driver = value;
|
||||
}
|
||||
} else if (strcmp(key, "database") == 0) {
|
||||
s_CurInfo.database = value;
|
||||
} else if (strcmp(key, "host") == 0) {
|
||||
s_CurInfo.host = value;
|
||||
} else if (strcmp(key, "user") == 0) {
|
||||
s_CurInfo.user = value;
|
||||
} else if (strcmp(key, "pass") == 0) {
|
||||
s_CurInfo.pass = value;
|
||||
} else if (strcmp(key, "timeout") == 0) {
|
||||
s_CurInfo.info.maxTimeout = atoi(value);
|
||||
} else if (strcmp(key, "port") == 0) {
|
||||
s_CurInfo.info.port = atoi(value);
|
||||
}
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
{
|
||||
m_ParseLevel--;
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
||||
{
|
||||
ConfDbInfo *cdb = new ConfDbInfo();
|
||||
|
||||
cdb->name = s_CurInfo.name;
|
||||
cdb->driver = s_CurInfo.driver;
|
||||
cdb->host = s_CurInfo.host;
|
||||
cdb->user = s_CurInfo.user;
|
||||
cdb->pass = s_CurInfo.pass;
|
||||
cdb->database = s_CurInfo.database;
|
||||
cdb->realDriver = s_CurInfo.realDriver;
|
||||
cdb->info.maxTimeout = s_CurInfo.info.maxTimeout;
|
||||
cdb->info.port = s_CurInfo.info.port;
|
||||
|
||||
cdb->info.driver = cdb->driver.c_str();
|
||||
cdb->info.database = cdb->database.c_str();
|
||||
cdb->info.host = cdb->host.c_str();
|
||||
cdb->info.user = cdb->user.c_str();
|
||||
cdb->info.pass = cdb->pass.c_str();
|
||||
|
||||
/* Save it.. */
|
||||
m_confs.push_back(cdb);
|
||||
|
||||
/* Go up one level */
|
||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||
return SMCResult_Halt;
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||
{
|
||||
}
|
||||
|
||||
bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
|
||||
{
|
||||
ConfDbInfoList &list = m_Builder.GetConfigList();
|
||||
ke::RefPtr<ConfDbInfo> pInfo = list.GetDatabaseConf(name);
|
||||
ConfDbInfo *pInfo = GetDatabaseConf(name);
|
||||
|
||||
if (!pInfo)
|
||||
{
|
||||
@@ -148,12 +282,11 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
|
||||
/* Try to assign a real driver pointer */
|
||||
if (pInfo->info.driver[0] == '\0')
|
||||
{
|
||||
std::string defaultDriver = list.GetDefaultDriver();
|
||||
if (!m_pDefault && defaultDriver.length() > 0)
|
||||
if (!m_pDefault && m_DefDriver.size() > 0)
|
||||
{
|
||||
m_pDefault = FindOrLoadDriver(defaultDriver.c_str());
|
||||
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
|
||||
}
|
||||
dname = defaultDriver.length() ? defaultDriver.c_str() : "default";
|
||||
dname = m_DefDriver.size() ? m_DefDriver.c_str() : "default";
|
||||
pInfo->realDriver = m_pDefault;
|
||||
} else {
|
||||
pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
|
||||
@@ -177,6 +310,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
|
||||
*pdb = NULL;
|
||||
|
||||
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -189,7 +323,7 @@ void DBManager::AddDriver(IDBDriver *pDriver)
|
||||
*/
|
||||
KillWorkerThread();
|
||||
|
||||
m_drivers.push_back(pDriver);
|
||||
m_drivers.push_back(pDriver);
|
||||
}
|
||||
|
||||
void DBManager::RemoveDriver(IDBDriver *pDriver)
|
||||
@@ -209,11 +343,14 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
|
||||
}
|
||||
}
|
||||
|
||||
ConfDbInfoList &list = m_Builder.GetConfigList();
|
||||
for (auto conf : list) {
|
||||
if (conf->realDriver == pDriver)
|
||||
/* Make sure NOTHING references this! */
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
{
|
||||
ConfDbInfo &db = *(*iter);
|
||||
if (db.realDriver == pDriver)
|
||||
{
|
||||
conf->realDriver = NULL;
|
||||
db.realDriver = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,11 +389,9 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
|
||||
|
||||
IDBDriver *DBManager::GetDefaultDriver()
|
||||
{
|
||||
ConfDbInfoList &list = m_Builder.GetConfigList();
|
||||
std::string defaultDriver = list.GetDefaultDriver();
|
||||
if (!m_pDefault && defaultDriver.length() > 0)
|
||||
if (!m_pDefault && m_DefDriver.size() > 0)
|
||||
{
|
||||
m_pDefault = FindOrLoadDriver(defaultDriver.c_str());
|
||||
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str());
|
||||
}
|
||||
|
||||
return m_pDefault;
|
||||
@@ -319,25 +454,29 @@ IDBDriver *DBManager::GetDriver(unsigned int index)
|
||||
|
||||
const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
|
||||
{
|
||||
ConfDbInfoList &list = m_Builder.GetConfigList();
|
||||
ke::RefPtr<ConfDbInfo> info = list.GetDatabaseConf(name);
|
||||
ConfDbInfo *info = GetDatabaseConf(name);
|
||||
if (!info)
|
||||
{
|
||||
// couldn't find requested conf, return default if exists
|
||||
info = list.GetDefaultConfiguration();
|
||||
if (!info)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &info->info;
|
||||
}
|
||||
|
||||
ke::RefPtr<ConfDbInfo> DBManager::GetDatabaseConf(const char *name)
|
||||
ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
|
||||
{
|
||||
ConfDbInfoList &list = m_Builder.GetConfigList();
|
||||
return list.GetDatabaseConf(name);
|
||||
List<ConfDbInfo *>::iterator iter;
|
||||
|
||||
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
|
||||
{
|
||||
ConfDbInfo &conf = *(*iter);
|
||||
if (conf.name == name)
|
||||
{
|
||||
return &conf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IDBDriver *DBManager::FindOrLoadDriver(const char *name)
|
||||
@@ -376,12 +515,13 @@ void DBManager::KillWorkerThread()
|
||||
if (m_Worker)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_Lock);
|
||||
ke::AutoLock lock(&m_QueueEvent);
|
||||
m_Terminate = true;
|
||||
m_QueueEvent.notify_all();
|
||||
m_QueueEvent.Notify();
|
||||
}
|
||||
m_Worker->join();
|
||||
m_Worker->Join();
|
||||
m_Worker = nullptr;
|
||||
s_OneTimeThreaderErrorMsg = false;
|
||||
m_Terminate = false;
|
||||
}
|
||||
}
|
||||
@@ -397,17 +537,27 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
|
||||
|
||||
if (!m_Worker)
|
||||
{
|
||||
m_Worker = ke::NewThread("SM Database Worker", [this]() -> void {
|
||||
m_Worker = new ke::Thread([this]() -> void {
|
||||
Run();
|
||||
});
|
||||
}, "SM SQL Worker");
|
||||
if (!m_Worker->Succeeded())
|
||||
{
|
||||
if (!s_OneTimeThreaderErrorMsg)
|
||||
{
|
||||
logger->LogError("[SM] Unable to create db threader (error unknown)");
|
||||
s_OneTimeThreaderErrorMsg = true;
|
||||
}
|
||||
m_Worker = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add to the queue */
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_Lock);
|
||||
ke::AutoLock lock(&m_QueueEvent);
|
||||
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio);
|
||||
queue.push(op);
|
||||
m_QueueEvent.notify_one();
|
||||
m_QueueEvent.Notify();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -438,7 +588,7 @@ void DBManager::Run()
|
||||
|
||||
void DBManager::ThreadMain()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_Lock);
|
||||
ke::AutoLock lock(&m_QueueEvent);
|
||||
|
||||
while (true) {
|
||||
// The lock has been acquired. Grab everything we can out of the
|
||||
@@ -446,43 +596,46 @@ void DBManager::ThreadMain()
|
||||
// we process all operations we can before checking to terminate.
|
||||
// There's no risk of starvation since the main thread blocks on us
|
||||
// terminating.
|
||||
auto queue = &m_OpQueue.GetLikelyQueue();
|
||||
if (queue->empty()) {
|
||||
// If the queue is empty and we've been asked to stop, leave now.
|
||||
if (m_Terminate)
|
||||
return;
|
||||
|
||||
// Otherwise, wait for something to happen.
|
||||
m_QueueEvent.wait(lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
IDBThreadOperation *op = queue->first();
|
||||
queue->pop();
|
||||
|
||||
// Unlock the queue when we run the query, so the main thread can
|
||||
// keep pumping events. We re-acquire the lock to check for more
|
||||
// items. It's okay if we terminate while unlocked; the main
|
||||
// thread would be blocked and we'd need to flush the queue
|
||||
// anyway, so after we've depleted the queue here, we'll just
|
||||
// reach the terminate at the top of the loop.
|
||||
lock.unlock();
|
||||
op->RunThreadPart();
|
||||
|
||||
// Re-acquire the lock and give the data back to the main thread
|
||||
// immediately. We use a separate lock to minimize game thread
|
||||
// contention.
|
||||
while (true)
|
||||
{
|
||||
std::lock_guard<std::mutex> think_lock(m_ThinkLock);
|
||||
m_ThinkQueue.push(op);
|
||||
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
|
||||
if (queue.empty())
|
||||
break;
|
||||
|
||||
IDBThreadOperation *op = queue.first();
|
||||
queue.pop();
|
||||
|
||||
// Unlock the queue when we run the query, so the main thread can
|
||||
// keep pumping events. We re-acquire the lock to check for more
|
||||
// items. It's okay if we terminate while unlocked; the main
|
||||
// thread would be blocked and we'd need to flush the queue
|
||||
// anyway, so after we've depleted the queue here, we'll just
|
||||
// reach the terminate at the top of the loop.
|
||||
{
|
||||
ke::AutoUnlock unlock(&m_QueueEvent);
|
||||
op->RunThreadPart();
|
||||
|
||||
ke::AutoLock lock(&m_ThinkLock);
|
||||
m_ThinkQueue.push(op);
|
||||
}
|
||||
|
||||
|
||||
if (!m_Terminate)
|
||||
{
|
||||
ke::AutoUnlock unlock(&m_QueueEvent);
|
||||
#ifdef _WIN32
|
||||
Sleep(20);
|
||||
#else
|
||||
usleep(20000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we add a 20ms delay after processing a query. This is
|
||||
// questionable but the intent is to avoid starving the game thread.
|
||||
if (!m_Terminate)
|
||||
std::this_thread::sleep_for(20ms);
|
||||
if (m_Terminate)
|
||||
return;
|
||||
|
||||
lock.lock();
|
||||
// Release the lock and wait for a signal.
|
||||
m_QueueEvent.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,7 +650,7 @@ void DBManager::RunFrame()
|
||||
/* Dump one thing per-frame so the server stays sane. */
|
||||
IDBThreadOperation *op;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_ThinkLock);
|
||||
ke::AutoLock lock(&m_ThinkLock);
|
||||
op = m_ThinkQueue.first();
|
||||
m_ThinkQueue.pop();
|
||||
}
|
||||
@@ -576,13 +729,23 @@ void DBManager::OnPluginWillUnload(IPlugin *plugin)
|
||||
}
|
||||
}
|
||||
|
||||
std::string DBManager::GetDefaultDriverName()
|
||||
void DBManager::LockConfig()
|
||||
{
|
||||
ConfDbInfoList &list = m_Builder.GetConfigList();
|
||||
return list.GetDefaultDriver();
|
||||
m_ConfigLock.Lock();
|
||||
}
|
||||
|
||||
void DBManager::UnlockConfig()
|
||||
{
|
||||
m_ConfigLock.Unlock();
|
||||
}
|
||||
|
||||
const char *DBManager::GetDefaultDriverName()
|
||||
{
|
||||
return m_DefDriver.c_str();
|
||||
}
|
||||
|
||||
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)
|
||||
{
|
||||
g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver);
|
||||
}
|
||||
|
||||
|
||||
+37
-14
@@ -32,27 +32,39 @@
|
||||
#ifndef _INCLUDE_DATABASE_MANAGER_H_
|
||||
#define _INCLUDE_DATABASE_MANAGER_H_
|
||||
|
||||
#include <IDBDriver.h>
|
||||
#include "common_logic.h"
|
||||
#include <sh_vector.h>
|
||||
#include <am-string.h>
|
||||
#include <sh_string.h>
|
||||
#include <sh_list.h>
|
||||
#include <ITextParsers.h>
|
||||
#include <IThreader.h>
|
||||
#include <IPluginSys.h>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <am-thread-utils.h>
|
||||
#include "sm_simple_prioqueue.h"
|
||||
#include <am-refcounting.h>
|
||||
#include "DatabaseConfBuilder.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
struct ConfDbInfo
|
||||
{
|
||||
ConfDbInfo() : realDriver(NULL)
|
||||
{
|
||||
}
|
||||
String name;
|
||||
String driver;
|
||||
String host;
|
||||
String user;
|
||||
String pass;
|
||||
String database;
|
||||
IDBDriver *realDriver;
|
||||
DatabaseInfo info;
|
||||
};
|
||||
|
||||
class DBManager :
|
||||
public IDBManager,
|
||||
public SMGlobalClass,
|
||||
public IHandleTypeDispatch,
|
||||
public ITextListener_SMC,
|
||||
public IPluginsListener
|
||||
{
|
||||
public:
|
||||
@@ -71,7 +83,6 @@ public: //IDBManager
|
||||
void AddDriver(IDBDriver *pDrivera);
|
||||
void RemoveDriver(IDBDriver *pDriver);
|
||||
const DatabaseInfo *FindDatabaseConf(const char *name);
|
||||
ke::RefPtr<ConfDbInfo> GetDatabaseConf(const char *name);
|
||||
bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength);
|
||||
unsigned int GetDriverCount();
|
||||
IDBDriver *GetDriver(unsigned int index);
|
||||
@@ -79,16 +90,25 @@ public: //IDBManager
|
||||
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
|
||||
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
|
||||
void AddDependency(IExtension *myself, IDBDriver *driver);
|
||||
public: //ITextListener_SMC
|
||||
void ReadSMC_ParseStart();
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||
void ReadSMC_ParseEnd(bool halted, bool failed);
|
||||
public: //ke::IRunnable
|
||||
void Run();
|
||||
void ThreadMain();
|
||||
public: //IPluginsListener
|
||||
void OnPluginWillUnload(IPlugin *plugin);
|
||||
public:
|
||||
ConfDbInfo *GetDatabaseConf(const char *name);
|
||||
IDBDriver *FindOrLoadDriver(const char *name);
|
||||
IDBDriver *GetDefaultDriver();
|
||||
std::string GetDefaultDriverName();
|
||||
const char *GetDefaultDriverName();
|
||||
bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio);
|
||||
void LockConfig();
|
||||
void UnlockConfig();
|
||||
void RunFrame();
|
||||
inline HandleType_t GetDatabaseType()
|
||||
{
|
||||
@@ -104,16 +124,19 @@ private:
|
||||
PrioQueue<IDBThreadOperation *> m_OpQueue;
|
||||
Queue<IDBThreadOperation *> m_ThinkQueue;
|
||||
CVector<bool> m_drSafety; /* which drivers are safe? */
|
||||
std::unique_ptr<std::thread> m_Worker;
|
||||
std::condition_variable m_QueueEvent;
|
||||
std::mutex m_ThinkLock;
|
||||
std::mutex m_Lock;
|
||||
ke::AutoPtr<ke::Thread> m_Worker;
|
||||
ke::ConditionVariable m_QueueEvent;
|
||||
ke::Mutex m_ConfigLock;
|
||||
ke::Mutex m_ThinkLock;
|
||||
bool m_Terminate;
|
||||
|
||||
DatabaseConfBuilder m_Builder;
|
||||
List<ConfDbInfo *> m_confs;
|
||||
HandleType_t m_DriverType;
|
||||
HandleType_t m_DatabaseType;
|
||||
String m_DefDriver;
|
||||
char m_Filename[PLATFORM_MAX_PATH];
|
||||
unsigned int m_ParseLevel;
|
||||
unsigned int m_ParseState;
|
||||
IDBDriver *m_pDefault;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2018 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include "DatabaseConfBuilder.h"
|
||||
#include <bridge/include/ILogger.h>
|
||||
|
||||
#define DBPARSE_LEVEL_NONE 0
|
||||
#define DBPARSE_LEVEL_MAIN 1
|
||||
#define DBPARSE_LEVEL_DATABASE 2
|
||||
|
||||
DatabaseConfBuilder::DatabaseConfBuilder()
|
||||
: m_ParseList(),
|
||||
m_InfoList()
|
||||
{
|
||||
}
|
||||
|
||||
void DatabaseConfBuilder::SetPath(char *str)
|
||||
{
|
||||
m_Filename = str;
|
||||
}
|
||||
|
||||
DatabaseConfBuilder::~DatabaseConfBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
ConfDbInfoList &DatabaseConfBuilder::GetConfigList()
|
||||
{
|
||||
return m_InfoList;
|
||||
}
|
||||
|
||||
void DatabaseConfBuilder::StartParse()
|
||||
{
|
||||
SMCError err;
|
||||
SMCStates states = {0, 0};
|
||||
if ((err = textparsers->ParseFile_SMC(m_Filename.c_str(), this, &states)) != SMCError_Okay)
|
||||
{
|
||||
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename.c_str());
|
||||
if (err != SMCError_Custom)
|
||||
{
|
||||
const char *txt = textparsers->GetSMCErrorString(err);
|
||||
logger->LogError("[SM] Line %d: %s", states.line, txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseConfBuilder::ReadSMC_ParseStart()
|
||||
{
|
||||
m_ParseLevel = 0;
|
||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||
|
||||
m_ParseList.clear();
|
||||
}
|
||||
|
||||
SMCResult DatabaseConfBuilder::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
{
|
||||
m_ParseLevel++;
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_NONE)
|
||||
{
|
||||
if (strcmp(name, "Databases") == 0)
|
||||
{
|
||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||
} else {
|
||||
m_ParseLevel++;
|
||||
}
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||
m_ParseCurrent = new ConfDbInfo();
|
||||
m_ParseCurrent->name = name;
|
||||
m_ParseState = DBPARSE_LEVEL_DATABASE;
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||
m_ParseLevel++;
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
SMCResult DatabaseConfBuilder::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
{
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_MAIN)
|
||||
{
|
||||
if (strcmp(key, "driver_default") == 0)
|
||||
{
|
||||
m_ParseList.SetDefaultDriver(value);
|
||||
}
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
|
||||
if (strcmp(key, "driver") == 0)
|
||||
{
|
||||
if (strcmp(value, "default") != 0)
|
||||
{
|
||||
m_ParseCurrent->driver = value;
|
||||
}
|
||||
} else if (strcmp(key, "database") == 0) {
|
||||
m_ParseCurrent->database = value;
|
||||
} else if (strcmp(key, "host") == 0) {
|
||||
m_ParseCurrent->host = value;
|
||||
} else if (strcmp(key, "user") == 0) {
|
||||
m_ParseCurrent->user = value;
|
||||
} else if (strcmp(key, "pass") == 0) {
|
||||
m_ParseCurrent->pass = value;
|
||||
} else if (strcmp(key, "timeout") == 0) {
|
||||
m_ParseCurrent->info.maxTimeout = atoi(value);
|
||||
} else if (strcmp(key, "port") == 0) {
|
||||
m_ParseCurrent->info.port = atoi(value);
|
||||
}
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
SMCResult DatabaseConfBuilder::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
if (m_ParseLevel)
|
||||
{
|
||||
m_ParseLevel--;
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
|
||||
{
|
||||
m_ParseCurrent->info.driver = m_ParseCurrent->driver.c_str();
|
||||
m_ParseCurrent->info.database = m_ParseCurrent->database.c_str();
|
||||
m_ParseCurrent->info.host = m_ParseCurrent->host.c_str();
|
||||
m_ParseCurrent->info.user = m_ParseCurrent->user.c_str();
|
||||
m_ParseCurrent->info.pass = m_ParseCurrent->pass.c_str();
|
||||
|
||||
/* Save it.. */
|
||||
m_ParseCurrent->AddRef();
|
||||
m_ParseList.push_back(m_ParseCurrent);
|
||||
m_ParseCurrent = nullptr;
|
||||
|
||||
/* Go up one level */
|
||||
m_ParseState = DBPARSE_LEVEL_MAIN;
|
||||
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
|
||||
m_ParseState = DBPARSE_LEVEL_NONE;
|
||||
return SMCResult_Halt;
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
void DatabaseConfBuilder::ReadSMC_ParseEnd(bool halted, bool failed)
|
||||
{
|
||||
m_InfoList.clear();
|
||||
m_InfoList = m_ParseList;
|
||||
m_ParseList.clear();
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2018 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_DATABASE_CONF_BUILDER_H_
|
||||
#define _INCLUDE_DATABASE_CONF_BUILDER_H_
|
||||
|
||||
#include <IDBDriver.h>
|
||||
#include <ITextParsers.h>
|
||||
#include "common_logic.h"
|
||||
|
||||
#include <am-vector.h>
|
||||
#include <am-string.h>
|
||||
#include <am-refcounting.h>
|
||||
#include <am-refcounting-threadsafe.h>
|
||||
|
||||
class ConfDbInfo : public ke::RefcountedThreadsafe<ConfDbInfo>
|
||||
{
|
||||
public:
|
||||
ConfDbInfo() : realDriver(NULL)
|
||||
{
|
||||
}
|
||||
std::string name;
|
||||
std::string driver;
|
||||
std::string host;
|
||||
std::string user;
|
||||
std::string pass;
|
||||
std::string database;
|
||||
IDBDriver *realDriver;
|
||||
DatabaseInfo info;
|
||||
};
|
||||
|
||||
class ConfDbInfoList : public std::vector<ke::RefPtr<ConfDbInfo>>
|
||||
{
|
||||
/* Allow internal usage of ConfDbInfoList */
|
||||
friend class DBManager;
|
||||
friend class DatabaseConfBuilder;
|
||||
private:
|
||||
std::string& GetDefaultDriver() {
|
||||
return m_DefDriver;
|
||||
}
|
||||
|
||||
ke::RefPtr<ConfDbInfo> GetDatabaseConf(const char *name) {
|
||||
for (size_t i = 0; i < this->size(); i++)
|
||||
{
|
||||
ke::RefPtr<ConfDbInfo> current = this->at(i);
|
||||
/* If we run into the default configuration, then we'll save it
|
||||
* for the next call to GetDefaultConfiguration */
|
||||
if (strcmp(current->name.c_str(), "default") == 0)
|
||||
{
|
||||
m_DefaultConfig = current;
|
||||
}
|
||||
if (strcmp(current->name.c_str(), name) == 0)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ke::RefPtr<ConfDbInfo> GetDefaultConfiguration() {
|
||||
return m_DefaultConfig;
|
||||
}
|
||||
void SetDefaultDriver(const char *input) {
|
||||
m_DefDriver = std::string(input);
|
||||
}
|
||||
private:
|
||||
ke::RefPtr<ConfDbInfo> m_DefaultConfig;
|
||||
std::string m_DefDriver;
|
||||
};
|
||||
|
||||
|
||||
class DatabaseConfBuilder : public ITextListener_SMC
|
||||
{
|
||||
public:
|
||||
DatabaseConfBuilder();
|
||||
~DatabaseConfBuilder();
|
||||
void StartParse();
|
||||
void SetPath(char* path);
|
||||
ConfDbInfoList &GetConfigList();
|
||||
public: //ITextListener_SMC
|
||||
void ReadSMC_ParseStart();
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||
void ReadSMC_ParseEnd(bool halted, bool failed);
|
||||
|
||||
private:
|
||||
unsigned int m_ParseLevel;
|
||||
unsigned int m_ParseState;
|
||||
ConfDbInfo *m_ParseCurrent;
|
||||
ConfDbInfoList m_ParseList;
|
||||
private:
|
||||
std::string m_Filename;
|
||||
ConfDbInfoList m_InfoList;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_DATABASE_CONF_BUILDER_H_
|
||||
@@ -29,11 +29,11 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <ISourceMod.h>
|
||||
#include <IPluginSys.h>
|
||||
#include <stdarg.h>
|
||||
#include "DebugReporter.h"
|
||||
#include "Logger.h"
|
||||
#include <am-string.h>
|
||||
|
||||
DebugReport g_DbgReporter;
|
||||
|
||||
@@ -69,13 +69,13 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
|
||||
ke::SafeVsprintf(buffer, sizeof(buffer), message, ap);
|
||||
|
||||
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
|
||||
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||
|
||||
if (err >= 0) {
|
||||
const char *error = g_pSourcePawn2->GetErrorString(err);
|
||||
if (error)
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
else
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
if (error)
|
||||
{
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
|
||||
} else {
|
||||
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
|
||||
}
|
||||
|
||||
g_Logger.LogError("[SM] %s", buffer);
|
||||
@@ -194,53 +194,35 @@ void DebugReport::ReportError(const IErrorReport &report, IFrameIterator &iter)
|
||||
g_Logger.LogError("[SM] Blaming: %s", blame);
|
||||
}
|
||||
|
||||
std::vector<std::string> arr = GetStackTrace(&iter);
|
||||
for (size_t i = 0; i < arr.size(); i++)
|
||||
if (!iter.Done())
|
||||
{
|
||||
g_Logger.LogError("%s", arr[i].c_str());
|
||||
}
|
||||
}
|
||||
g_Logger.LogError("[SM] Call stack trace:");
|
||||
|
||||
std::vector<std::string> DebugReport::GetStackTrace(IFrameIterator *iter)
|
||||
{
|
||||
char temp[3072];
|
||||
std::vector<std::string> trace;
|
||||
iter->Reset();
|
||||
|
||||
if (!iter->Done())
|
||||
{
|
||||
trace.push_back("[SM] Call stack trace:");
|
||||
|
||||
for (int index = 0; !iter->Done(); iter->Next(), index++)
|
||||
for (int index = 0; !iter.Done(); iter.Next(), index++)
|
||||
{
|
||||
const char *fn = iter->FunctionName();
|
||||
const char *fn = iter.FunctionName();
|
||||
if (!fn)
|
||||
{
|
||||
fn = "<unknown function>";
|
||||
}
|
||||
if (iter->IsNativeFrame())
|
||||
if (iter.IsNativeFrame())
|
||||
{
|
||||
g_pSM->Format(temp, sizeof(temp), "[SM] [%d] %s", index, fn);
|
||||
trace.push_back(temp);
|
||||
g_Logger.LogError("[SM] [%d] %s", index, fn);
|
||||
continue;
|
||||
}
|
||||
if (iter->IsScriptedFrame())
|
||||
if (iter.IsScriptedFrame())
|
||||
{
|
||||
const char *file = iter->FilePath();
|
||||
const char *file = iter.FilePath();
|
||||
if (!file)
|
||||
{
|
||||
file = "<unknown>";
|
||||
}
|
||||
g_pSM->Format(temp, sizeof(temp), "[SM] [%d] Line %d, %s::%s",
|
||||
g_Logger.LogError("[SM] [%d] Line %d, %s::%s",
|
||||
index,
|
||||
iter->LineNumber(),
|
||||
iter.LineNumber(),
|
||||
file,
|
||||
fn);
|
||||
|
||||
trace.push_back(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
|
||||
#include "sp_vm_api.h"
|
||||
#include "common_logic.h"
|
||||
#include <am-vector.h>
|
||||
#include <am-string.h>
|
||||
|
||||
class DebugReport :
|
||||
public SMGlobalClass,
|
||||
@@ -47,12 +45,9 @@ public: // IDebugListener
|
||||
void ReportError(const IErrorReport &report, IFrameIterator &iter);
|
||||
void OnDebugSpew(const char *msg, ...);
|
||||
public:
|
||||
// If err is -1, caller assumes the automatic reporting by SourcePawn is
|
||||
// good enough, and only wants the supplemental logging provided here.
|
||||
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
|
||||
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
|
||||
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
|
||||
std::vector<std::string> GetStackTrace(IFrameIterator *iter);
|
||||
private:
|
||||
int _GetPluginIndex(IPluginContext *ctx);
|
||||
};
|
||||
|
||||
+123
-83
@@ -30,9 +30,6 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ExtensionSys.h"
|
||||
#include <ILibrarySys.h>
|
||||
#include <ISourceMod.h>
|
||||
@@ -76,68 +73,73 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
|
||||
/* Special case for new bintools binary */
|
||||
if (strcmp(filename, "bintools.ext") == 0)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/" PLATFORM_ARCH_FOLDER "%s." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
goto normal;
|
||||
}
|
||||
else
|
||||
|
||||
/* Zeroth, see if there is an engine specific build in the new place. */
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s.%s." PLATFORM_LIB_EXT,
|
||||
filename,
|
||||
bridge->gamesuffix);
|
||||
|
||||
if (libsys->IsPathFile(path))
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
|
||||
if (strcmp(bridge->gamesuffix, "2.tf2") == 0
|
||||
|| strcmp(bridge->gamesuffix, "2.dods") == 0
|
||||
|| strcmp(bridge->gamesuffix, "2.hl2dm") == 0
|
||||
)
|
||||
{
|
||||
/* Zeroth, see if there is an engine specific build in the new place. */
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/" PLATFORM_ARCH_FOLDER "%s.%s." PLATFORM_LIB_EXT,
|
||||
filename,
|
||||
bridge->gamesuffix);
|
||||
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
if (!libsys->IsPathFile(path))
|
||||
if (libsys->IsPathFile(path))
|
||||
{
|
||||
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
|
||||
if (strcmp(bridge->gamesuffix, "2.tf2") == 0
|
||||
|| strcmp(bridge->gamesuffix, "2.dods") == 0
|
||||
|| strcmp(bridge->gamesuffix, "2.hl2dm") == 0
|
||||
)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/" PLATFORM_ARCH_FOLDER "%s.2.ep2v." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
}
|
||||
else if (strcmp(bridge->gamesuffix, "2.nd") == 0)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/" PLATFORM_ARCH_FOLDER "%s.2.l4d2." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
}
|
||||
|
||||
//Try further
|
||||
if (!libsys->IsPathFile(path))
|
||||
{
|
||||
/* First see if there is an engine specific build! */
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/" PLATFORM_ARCH_FOLDER "auto.%s/%s." PLATFORM_LIB_EXT,
|
||||
filename,
|
||||
bridge->gamesuffix);
|
||||
|
||||
/* Try the "normal" version */
|
||||
if (!libsys->IsPathFile(path))
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/" PLATFORM_ARCH_FOLDER "%s." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
}
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
else if (strcmp(bridge->gamesuffix, "2.nd") == 0)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
|
||||
if (libsys->IsPathFile(path))
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* First see if there is an engine specific build! */
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
|
||||
filename,
|
||||
bridge->gamesuffix);
|
||||
|
||||
/* Try the "normal" version */
|
||||
if (!libsys->IsPathFile(path))
|
||||
{
|
||||
normal:
|
||||
g_pSM->BuildPath(Path_SM,
|
||||
path,
|
||||
PLATFORM_MAX_PATH,
|
||||
"extensions/%s." PLATFORM_LIB_EXT,
|
||||
filename);
|
||||
}
|
||||
|
||||
found:
|
||||
Initialize(filename, path, bRequired);
|
||||
}
|
||||
|
||||
@@ -174,7 +176,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
|
||||
{
|
||||
m_pLib->CloseLibrary();
|
||||
m_pLib = NULL;
|
||||
ke::SafeStrcpy(error, maxlength, "Unable to find extension entry point");
|
||||
snprintf(error, maxlength, "Unable to find extension entry point");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -240,13 +242,11 @@ void CLocalExtension::Unload()
|
||||
m_pLib->CloseLibrary();
|
||||
m_pLib = NULL;
|
||||
}
|
||||
|
||||
m_bFullyLoaded = false;
|
||||
}
|
||||
|
||||
bool CRemoteExtension::Reload(char *error, size_t maxlength)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, "Remote extensions do not support reloading");
|
||||
snprintf(error, maxlength, "Remote extensions do not support reloading");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -280,13 +280,13 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
|
||||
{
|
||||
if (!m_pAPI)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, "No IExtensionInterface instance provided");
|
||||
snprintf(error, maxlength, "No IExtensionInterface instance provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_pAPI->GetExtensionVersion() > SMINTERFACE_EXTENSIONAPI_VERSION)
|
||||
{
|
||||
ke::SafeSprintf(error, maxlength, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION);
|
||||
snprintf(error, maxlength, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ bool CExtension::Load(char *error, size_t maxlength)
|
||||
/* Check if we're past load time */
|
||||
if (!bridge->IsMapLoading())
|
||||
{
|
||||
MarkAllLoaded();
|
||||
m_pAPI->OnExtensionsAllLoaded();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -421,20 +421,65 @@ void CExtension::AddChildDependent(CExtension *pOther, SMInterface *iface)
|
||||
m_ChildDeps.push_back(info);
|
||||
}
|
||||
|
||||
// note: dependency iteration deprecated since 1.10
|
||||
ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface)
|
||||
{
|
||||
return nullptr;
|
||||
List<IfaceInfo>::iterator iter = m_Deps.begin();
|
||||
|
||||
if (iter == m_Deps.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pOwner)
|
||||
{
|
||||
*pOwner = (*iter).owner;
|
||||
}
|
||||
if (pInterface)
|
||||
{
|
||||
*pInterface = (*iter).iface;
|
||||
}
|
||||
|
||||
List<IfaceInfo>::iterator *pIter = new List<IfaceInfo>::iterator(iter);
|
||||
|
||||
return (ITERATOR *)pIter;
|
||||
}
|
||||
|
||||
bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface)
|
||||
{
|
||||
return false;
|
||||
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
|
||||
List<IfaceInfo>::iterator _iter;
|
||||
|
||||
if (_iter == m_Deps.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_iter++;
|
||||
|
||||
if (pOwner)
|
||||
{
|
||||
*pOwner = (*_iter).owner;
|
||||
}
|
||||
if (pInterface)
|
||||
{
|
||||
*pInterface = (*_iter).iface;
|
||||
}
|
||||
|
||||
*pIter = _iter;
|
||||
|
||||
if (_iter == m_Deps.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CExtension::FreeDependencyIterator(ITERATOR *iter)
|
||||
{
|
||||
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
|
||||
|
||||
delete pIter;
|
||||
}
|
||||
|
||||
void CExtension::AddInterface(SMInterface *pInterface)
|
||||
@@ -448,7 +493,7 @@ bool CExtension::IsRunning(char *error, size_t maxlength)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, m_Error.c_str());
|
||||
snprintf(error, maxlength, "%s", m_Error.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -501,7 +546,7 @@ void CExtensionManager::TryAutoload()
|
||||
|
||||
g_pSM->BuildPath(Path_SM, path, sizeof(path), "extensions");
|
||||
|
||||
std::unique_ptr<IDirectory> pDir(libsys->OpenDirectory(path));
|
||||
ke::AutoPtr<IDirectory> pDir(libsys->OpenDirectory(path));
|
||||
if (!pDir)
|
||||
return;
|
||||
|
||||
@@ -530,7 +575,7 @@ void CExtensionManager::TryAutoload()
|
||||
}
|
||||
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
len = ke::SafeStrcpy(file, sizeof(file), lfile);
|
||||
len = ke::SafeSprintf(file, sizeof(file), "%s", lfile);
|
||||
strcpy(&file[len - 9], ".ext");
|
||||
|
||||
LoadAutoExtension(file);
|
||||
@@ -546,7 +591,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
|
||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||
{
|
||||
char path2[PLATFORM_MAX_PATH];
|
||||
ke::SafeStrcpy(path2, sizeof(path2), path);
|
||||
ke::SafeSprintf(path2, sizeof(path2), "%s", path);
|
||||
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||
return LoadAutoExtension(path2, bErrorOnMissing);
|
||||
}
|
||||
@@ -633,18 +678,12 @@ IExtension *CExtensionManager::FindExtensionByName(const char *ext)
|
||||
|
||||
IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size_t maxlength)
|
||||
{
|
||||
if (strstr(file, "..") != NULL)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, "Cannot load extensions outside the \"extensions\" folder.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove platform extension if it's there. Compat hack. */
|
||||
const char *ext = libsys->GetFileExtension(file);
|
||||
if (ext && strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
|
||||
{
|
||||
char path2[PLATFORM_MAX_PATH];
|
||||
ke::SafeStrcpy(path2, sizeof(path2), file);
|
||||
ke::SafeSprintf(path2, sizeof(path2), "%s", file);
|
||||
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
|
||||
return LoadExtension(path2, error, maxlength);
|
||||
}
|
||||
@@ -1097,7 +1136,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
|
||||
if (pExt->unload_code == (unsigned)atoi(unload))
|
||||
{
|
||||
char filename[PLATFORM_MAX_PATH];
|
||||
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
|
||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
||||
UnloadExtension(pExt);
|
||||
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
||||
}
|
||||
@@ -1112,7 +1151,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
|
||||
|| (!pExt->m_ChildDeps.size() && !pExt->m_Dependents.size()))
|
||||
{
|
||||
char filename[PLATFORM_MAX_PATH];
|
||||
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
|
||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
||||
UnloadExtension(pExt);
|
||||
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
|
||||
return;
|
||||
@@ -1182,6 +1221,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
|
||||
rootmenu->ConsolePrint(" -> %s", pPlugin->GetFilename());
|
||||
}
|
||||
}
|
||||
srand(static_cast<int>(time(NULL)));
|
||||
pExt->unload_code = (rand() % 877) + 123; //123 to 999
|
||||
rootmenu->ConsolePrint("[SM] To verify unloading %s, please use the following: ", pExt->GetFilename());
|
||||
rootmenu->ConsolePrint("[SM] sm exts unload %d %d", num, pExt->unload_code);
|
||||
@@ -1212,7 +1252,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
|
||||
char filename[PLATFORM_MAX_PATH];
|
||||
char error[255];
|
||||
|
||||
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
|
||||
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
|
||||
|
||||
if (pExt->Reload(error, sizeof(error)))
|
||||
{
|
||||
@@ -1374,7 +1414,7 @@ bool CLocalExtension::IsSameFile(const char *file)
|
||||
|
||||
bool CRemoteExtension::IsSameFile(const char *file)
|
||||
{
|
||||
/* Check full path and name passed in from LoadExternal */
|
||||
return strcmp(file, m_Path.c_str()) == 0 || strcmp(file, m_File.c_str()) == 0;
|
||||
/* :TODO: this could be better, but no one uses this API anyway. */
|
||||
return strcmp(file, m_Path.c_str()) == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned
|
||||
{
|
||||
scripts->AddFunctionsToForward(name, fwd);
|
||||
|
||||
m_managed.push_back(fwd);
|
||||
m_managed.append(fwd);
|
||||
}
|
||||
|
||||
return fwd;
|
||||
@@ -78,7 +78,7 @@ IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType
|
||||
|
||||
if (fwd)
|
||||
{
|
||||
m_unmanaged.push_back(fwd);
|
||||
m_unmanaged.append(fwd);
|
||||
}
|
||||
|
||||
return fwd;
|
||||
@@ -751,9 +751,9 @@ bool CForward::AddFunction(IPluginFunction *func)
|
||||
return false;
|
||||
|
||||
if (func->IsRunnable())
|
||||
m_functions.push_back(func);
|
||||
m_functions.append(func);
|
||||
else
|
||||
m_paused.push_back(func);
|
||||
m_paused.append(func);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -780,7 +780,7 @@ const char *CForward::GetForwardName()
|
||||
|
||||
unsigned int CForward::GetFunctionCount()
|
||||
{
|
||||
return m_functions.size();
|
||||
return m_functions.length();
|
||||
}
|
||||
|
||||
ExecType CForward::GetExecType()
|
||||
|
||||
@@ -36,7 +36,7 @@ SafeFrameIterator::SafeFrameIterator(IFrameIterator *it)
|
||||
while (!it->Done())
|
||||
{
|
||||
FrameInfo info = FrameInfo(it);
|
||||
frames.push_back(info);
|
||||
frames.append(info);
|
||||
it->Next();
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ SafeFrameIterator::SafeFrameIterator(IFrameIterator *it)
|
||||
|
||||
bool SafeFrameIterator::Done() const
|
||||
{
|
||||
return current >= frames.size();
|
||||
return current >= frames.length();
|
||||
}
|
||||
|
||||
bool SafeFrameIterator::Next()
|
||||
@@ -77,7 +77,7 @@ const char *SafeFrameIterator::FunctionName() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return frames[current].FunctionName.c_str();
|
||||
return frames[current].FunctionName.chars();
|
||||
}
|
||||
|
||||
const char *SafeFrameIterator::FilePath() const
|
||||
@@ -87,5 +87,5 @@ const char *SafeFrameIterator::FilePath() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return frames[current].FilePath.c_str();
|
||||
return frames[current].FilePath.chars();
|
||||
}
|
||||
|
||||
@@ -48,18 +48,16 @@ public:
|
||||
*/
|
||||
struct FrameInfo
|
||||
{
|
||||
std::string FunctionName;
|
||||
std::string FilePath;
|
||||
ke::AString FunctionName;
|
||||
ke::AString FilePath;
|
||||
unsigned LineNumber;
|
||||
|
||||
FrameInfo(IFrameIterator *it)
|
||||
{
|
||||
LineNumber = it->LineNumber();
|
||||
|
||||
if (it->FunctionName())
|
||||
FunctionName = it->FunctionName();
|
||||
if (it->FilePath())
|
||||
FilePath = it->FilePath();
|
||||
FunctionName = it->FunctionName();
|
||||
FilePath = it->FilePath();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,5 +73,5 @@ public:
|
||||
|
||||
private:
|
||||
size_t current;
|
||||
std::vector<FrameInfo> frames;
|
||||
};
|
||||
ke::Vector<FrameInfo> frames;
|
||||
};
|
||||
+61
-117
@@ -66,31 +66,27 @@ static const char *g_pParseEngine = NULL;
|
||||
#define PSTATE_GAMEDEFS_OFFSETS 3
|
||||
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4
|
||||
#define PSTATE_GAMEDEFS_KEYS 5
|
||||
#define PSTATE_GAMEDEFS_KEYS_PLATFORM 6
|
||||
#define PSTATE_GAMEDEFS_SUPPORTED 7
|
||||
#define PSTATE_GAMEDEFS_SIGNATURES 8
|
||||
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 9
|
||||
#define PSTATE_GAMEDEFS_CRC 10
|
||||
#define PSTATE_GAMEDEFS_CRC_BINARY 11
|
||||
#define PSTATE_GAMEDEFS_CUSTOM 12
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES 13
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 14
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 15
|
||||
|
||||
#if defined PLATFORM_X86
|
||||
#define PLATFORM_ARCH_SUFFIX ""
|
||||
#elif defined PLATFORM_X64
|
||||
#define PLATFORM_ARCH_SUFFIX "64"
|
||||
#endif
|
||||
#define PSTATE_GAMEDEFS_SUPPORTED 6
|
||||
#define PSTATE_GAMEDEFS_SIGNATURES 7
|
||||
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 8
|
||||
#define PSTATE_GAMEDEFS_CRC 9
|
||||
#define PSTATE_GAMEDEFS_CRC_BINARY 10
|
||||
#define PSTATE_GAMEDEFS_CUSTOM 11
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES 12
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 13
|
||||
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 14
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
#define PLATFORM_NAME "windows" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_NAME "windows"
|
||||
#define PLATFORM_SERVER_BINARY "server.dll"
|
||||
#elif defined PLATFORM_LINUX
|
||||
#define PLATFORM_NAME "linux" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_COMPAT_ALT "mac" PLATFORM_ARCH_SUFFIX /* Alternate platform name if game data is missing for primary one */
|
||||
#define PLATFORM_NAME "linux"
|
||||
#define PLATFORM_COMPAT_ALT "mac" /* Alternate platform name if game data is missing for primary one */
|
||||
#define PLATFORM_SERVER_BINARY "server_i486.so"
|
||||
#elif defined PLATFORM_APPLE
|
||||
#define PLATFORM_NAME "mac" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_COMPAT_ALT "linux" PLATFORM_ARCH_SUFFIX
|
||||
#define PLATFORM_NAME "mac"
|
||||
#define PLATFORM_COMPAT_ALT "linux"
|
||||
#define PLATFORM_SERVER_BINARY "server.dylib"
|
||||
#endif
|
||||
|
||||
struct TempSigInfo
|
||||
@@ -150,23 +146,6 @@ static inline bool IsPlatformCompatible(const char *platform, bool *hadPrimaryMa
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline time_t GetFileModTime(const char *path)
|
||||
{
|
||||
char filepath[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_SM, filepath, sizeof(filepath), "gamedata/%s.txt", path);
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
struct _stat64 s;
|
||||
if (_stat64(filepath, &s) != 0)
|
||||
#elif defined PLATFORM_POSIX
|
||||
struct stat s;
|
||||
if (stat(filepath, &s) != 0)
|
||||
#endif
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return s.st_mtime;
|
||||
}
|
||||
|
||||
CGameConfig::CGameConfig(const char *file, const char *engine)
|
||||
{
|
||||
strncopy(m_File, file, sizeof(m_File));
|
||||
@@ -174,8 +153,6 @@ CGameConfig::CGameConfig(const char *file, const char *engine)
|
||||
m_CustomLevel = 0;
|
||||
m_CustomHandler = NULL;
|
||||
|
||||
m_ModTime = GetFileModTime(file);
|
||||
|
||||
if (!engine)
|
||||
m_pEngine = bridge->GetSourceEngineName();
|
||||
else
|
||||
@@ -222,7 +199,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
{
|
||||
bShouldBeReadingDefault = true;
|
||||
m_ParseState = PSTATE_GAMEDEFS;
|
||||
m_Game = name;
|
||||
strncopy(m_Game, name, sizeof(m_Game));
|
||||
} else {
|
||||
m_IgnoreLevel++;
|
||||
}
|
||||
@@ -238,7 +215,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
{
|
||||
m_ParseState = PSTATE_GAMEDEFS_KEYS;
|
||||
}
|
||||
else if ((strcmp(name, "#supported") == 0) && (m_Game == "#default"))
|
||||
else if ((strcmp(name, "#supported") == 0) && (strcmp(m_Game, "#default") == 0))
|
||||
{
|
||||
m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
|
||||
/* Ignore this section unless we get a game. */
|
||||
@@ -275,25 +252,18 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PSTATE_GAMEDEFS_KEYS:
|
||||
{
|
||||
m_Key = name;
|
||||
m_ParseState = PSTATE_GAMEDEFS_KEYS_PLATFORM;
|
||||
matched_platform = false;
|
||||
break;
|
||||
}
|
||||
case PSTATE_GAMEDEFS_OFFSETS:
|
||||
{
|
||||
m_Prop.clear();
|
||||
m_Class.clear();
|
||||
m_offset = name;
|
||||
m_Prop[0] = '\0';
|
||||
m_Class[0] = '\0';
|
||||
strncopy(m_offset, name, sizeof(m_offset));
|
||||
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
|
||||
matched_platform = false;
|
||||
break;
|
||||
}
|
||||
case PSTATE_GAMEDEFS_SIGNATURES:
|
||||
{
|
||||
m_offset = name;
|
||||
strncopy(m_offset, name, sizeof(m_offset));
|
||||
s_TempSig.Reset();
|
||||
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
|
||||
matched_platform = false;
|
||||
@@ -312,10 +282,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
FILE *fp;
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
char binName[64];
|
||||
bridge->FormatSourceBinaryName(name, binName, sizeof(binName));
|
||||
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "bin/%s", binName);
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "bin/" PLATFORM_SERVER_BINARY);
|
||||
if ((fp = fopen(path, "rb")) == NULL)
|
||||
{
|
||||
ke::SafeSprintf(error, sizeof(error), "Could not open binary: %s", path);
|
||||
@@ -338,7 +305,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
if (error[0] != '\0')
|
||||
{
|
||||
m_IgnoreLevel = 1;
|
||||
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game.c_str(), m_CurFile);
|
||||
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
|
||||
logger->LogError("[SM] %s", error);
|
||||
} else {
|
||||
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
|
||||
@@ -353,12 +320,12 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
}
|
||||
case PSTATE_GAMEDEFS_ADDRESSES:
|
||||
{
|
||||
m_Address.clear();
|
||||
m_AddressSignature.clear();
|
||||
m_Address[0] = '\0';
|
||||
m_AddressSignature[0] = '\0';
|
||||
m_AddressReadCount = 0;
|
||||
m_AddressLastIsOffset = false;
|
||||
|
||||
m_Address = name;
|
||||
strncopy(m_Address, name, sizeof(m_Address));
|
||||
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
|
||||
|
||||
break;
|
||||
@@ -371,10 +338,9 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0 &&
|
||||
strcmp(name, "linux64") != 0 && strcmp(name, "windows64") != 0 && strcmp(name, "mac64") != 0)
|
||||
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0)
|
||||
{
|
||||
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address.c_str(), m_CurFile);
|
||||
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||
}
|
||||
m_IgnoreLevel = 1;
|
||||
@@ -383,7 +349,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||
}
|
||||
/* No sub-sections allowed:
|
||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
||||
case PSTATE_GAMEDEFS_KEYS_PLATFORM:
|
||||
case PSTATE_GAMEDEFS_KEYS:
|
||||
case PSTATE_GAMEDEFS_SUPPORTED:
|
||||
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
||||
case PSTATE_GAMEDEFS_CRC_BINARY:
|
||||
@@ -411,22 +377,15 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
{
|
||||
if (strcmp(key, "class") == 0)
|
||||
{
|
||||
m_Class = value;
|
||||
strncopy(m_Class, value, sizeof(m_Class));
|
||||
} else if (strcmp(key, "prop") == 0) {
|
||||
m_Prop = value;
|
||||
strncopy(m_Prop, value, sizeof(m_Prop));
|
||||
} else if (IsPlatformCompatible(key, &matched_platform)) {
|
||||
m_Offsets.replace(m_offset.c_str(), static_cast<int>(strtol(value, NULL, 0)));
|
||||
m_Offsets.replace(m_offset, atoi(value));
|
||||
}
|
||||
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
|
||||
std::string vstr(value);
|
||||
m_Keys.replace(key, std::move(vstr));
|
||||
}
|
||||
else if (m_ParseState == PSTATE_GAMEDEFS_KEYS_PLATFORM) {
|
||||
if (IsPlatformCompatible(key, &matched_platform))
|
||||
{
|
||||
std::string vstr(value);
|
||||
m_Keys.replace(m_Key.c_str(), std::move(vstr));
|
||||
}
|
||||
ke::AString vstr(value);
|
||||
m_Keys.replace(key, ke::Move(vstr));
|
||||
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
|
||||
if (strcmp(key, "game") == 0)
|
||||
{
|
||||
@@ -476,7 +435,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
int limit = sizeof(m_AddressRead)/sizeof(m_AddressRead[0]);
|
||||
if (m_AddressLastIsOffset)
|
||||
{
|
||||
logger->LogError("[SM] Error parsing Address \"%s\", 'offset' entry must be the last entry (gameconf \"%s\")", m_Address.c_str(), m_CurFile);
|
||||
logger->LogError("[SM] Error parsing Address \"%s\", 'offset' entry must be the last entry (gameconf \"%s\")", m_Address, m_CurFile);
|
||||
}
|
||||
else if (m_AddressReadCount < limit)
|
||||
{
|
||||
@@ -484,15 +443,15 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||
{
|
||||
m_AddressLastIsOffset = true;
|
||||
}
|
||||
m_AddressRead[m_AddressReadCount] = static_cast<int>(strtol(value, NULL, 0));
|
||||
m_AddressRead[m_AddressReadCount] = atoi(value);
|
||||
m_AddressReadCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address.c_str(), limit, m_CurFile);
|
||||
logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
|
||||
}
|
||||
} else if (strcmp(key, "signature") == 0) {
|
||||
m_AddressSignature = value;
|
||||
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
|
||||
}
|
||||
} else if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) {
|
||||
return m_CustomHandler->ReadSMC_KeyValue(states, key, value);
|
||||
@@ -540,32 +499,28 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
m_ParseState = PSTATE_GAMEDEFS;
|
||||
break;
|
||||
}
|
||||
case PSTATE_GAMEDEFS_KEYS_PLATFORM:
|
||||
{
|
||||
m_ParseState = PSTATE_GAMEDEFS_KEYS;
|
||||
break;
|
||||
}
|
||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
||||
{
|
||||
/* Parse the offset... */
|
||||
if (!m_Class.empty() && !m_Prop.empty())
|
||||
if (m_Class[0] != '\0'
|
||||
&& m_Prop[0] != '\0')
|
||||
{
|
||||
SendProp *pProp = gamehelpers->FindInSendTable(m_Class.c_str(), m_Prop.c_str());
|
||||
SendProp *pProp = gamehelpers->FindInSendTable(m_Class, m_Prop);
|
||||
if (pProp)
|
||||
{
|
||||
int val = gamehelpers->GetSendPropOffset(pProp);
|
||||
m_Offsets.replace(m_offset.c_str(), val);
|
||||
m_Props.replace(m_offset.c_str(), pProp);
|
||||
m_Offsets.replace(m_offset, val);
|
||||
m_Props.replace(m_offset, pProp);
|
||||
} else {
|
||||
/* Check if it's a non-default game and no offsets exist */
|
||||
if ((m_Game != "*" && m_Game != "#default")
|
||||
&& (!m_Offsets.retrieve(m_offset.c_str())))
|
||||
if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
|
||||
&& (!m_Offsets.retrieve(m_offset)))
|
||||
{
|
||||
logger->LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
|
||||
m_Class.c_str(),
|
||||
m_Prop.c_str(),
|
||||
m_Class,
|
||||
m_Prop,
|
||||
m_CurFile,
|
||||
m_Game.c_str());
|
||||
m_Game);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -673,7 +628,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
}
|
||||
}
|
||||
|
||||
m_Sigs.replace(m_offset.c_str(), final_addr);
|
||||
m_Sigs.replace(m_offset, final_addr);
|
||||
}
|
||||
|
||||
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
|
||||
@@ -689,10 +644,10 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES;
|
||||
|
||||
if (!m_Address.empty() && !m_AddressSignature.empty())
|
||||
if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0')
|
||||
{
|
||||
AddressConf addrConf(std::move(m_AddressSignature), m_AddressReadCount, m_AddressRead, m_AddressLastIsOffset);
|
||||
m_Addresses.replace(m_Address.c_str(), addrConf);
|
||||
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead, m_AddressLastIsOffset);
|
||||
m_Addresses.replace(m_Address, addrConf);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -810,10 +765,7 @@ public:
|
||||
(!had_game && matched_engine) ||
|
||||
(matched_engine && matched_game))
|
||||
{
|
||||
if (fileList->find(cur_file) == fileList->end())
|
||||
{
|
||||
fileList->push_back(cur_file);
|
||||
}
|
||||
fileList->push_back(cur_file);
|
||||
}
|
||||
state = MSTATE_MAIN;
|
||||
}
|
||||
@@ -1022,10 +974,10 @@ bool CGameConfig::GetOffset(const char *key, int *value)
|
||||
|
||||
const char *CGameConfig::GetKeyValue(const char *key)
|
||||
{
|
||||
StringHashMap<std::string>::Result r = m_Keys.find(key);
|
||||
StringHashMap<ke::AString>::Result r = m_Keys.find(key);
|
||||
if (!r.found())
|
||||
return NULL;
|
||||
return r->value.c_str();
|
||||
return r->value.chars();
|
||||
}
|
||||
|
||||
//memory addresses below 0x10000 are automatically considered invalid for dereferencing
|
||||
@@ -1043,7 +995,7 @@ bool CGameConfig::GetAddress(const char *key, void **retaddr)
|
||||
AddressConf &addrConf = r->value;
|
||||
|
||||
void *addr;
|
||||
if (!GetMemSig(addrConf.signatureName.c_str(), &addr))
|
||||
if (!GetMemSig(addrConf.signatureName, &addr))
|
||||
{
|
||||
*retaddr = NULL;
|
||||
return false;
|
||||
@@ -1076,11 +1028,11 @@ static inline unsigned minOf(unsigned a, unsigned b)
|
||||
return a <= b ? a : b;
|
||||
}
|
||||
|
||||
CGameConfig::AddressConf::AddressConf(std::string&& sigName, unsigned readCount, int *read, bool lastIsOffset)
|
||||
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset)
|
||||
{
|
||||
unsigned readLimit = minOf(readCount, sizeof(this->read) / sizeof(this->read[0]));
|
||||
|
||||
this->signatureName = std::move(sigName);
|
||||
strncopy(signatureName, sigName, sizeof(signatureName) / sizeof(signatureName[0]));
|
||||
this->readCount = readLimit;
|
||||
memcpy(&this->read[0], read, sizeof(this->read[0])*readLimit);
|
||||
|
||||
@@ -1153,17 +1105,9 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
|
||||
|
||||
if (m_Lookup.retrieve(file, &pConfig))
|
||||
{
|
||||
bool ret = true;
|
||||
time_t modtime = GetFileModTime(file);
|
||||
if (pConfig->m_ModTime != modtime)
|
||||
{
|
||||
pConfig->m_ModTime = modtime;
|
||||
ret = pConfig->Reparse(error, maxlength);
|
||||
}
|
||||
|
||||
pConfig->AddRef();
|
||||
*_pConfig = pConfig;
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
pConfig = new CGameConfig(file);
|
||||
|
||||
@@ -81,16 +81,15 @@ private:
|
||||
char m_CurFile[PLATFORM_MAX_PATH];
|
||||
StringHashMap<int> m_Offsets;
|
||||
StringHashMap<SendProp *> m_Props;
|
||||
StringHashMap<std::string> m_Keys;
|
||||
StringHashMap<ke::AString> m_Keys;
|
||||
StringHashMap<void *> m_Sigs;
|
||||
/* Parse states */
|
||||
int m_ParseState;
|
||||
unsigned int m_IgnoreLevel;
|
||||
std::string m_Class;
|
||||
std::string m_Prop;
|
||||
std::string m_offset;
|
||||
std::string m_Game;
|
||||
std::string m_Key;
|
||||
char m_Class[64];
|
||||
char m_Prop[64];
|
||||
char m_offset[64];
|
||||
char m_Game[256];
|
||||
bool bShouldBeReadingDefault;
|
||||
bool had_game;
|
||||
bool matched_game;
|
||||
@@ -105,25 +104,24 @@ private:
|
||||
/* Support for reading Addresses */
|
||||
struct AddressConf
|
||||
{
|
||||
std::string signatureName;
|
||||
char signatureName[64];
|
||||
int readCount;
|
||||
int read[8];
|
||||
bool lastIsOffset;
|
||||
|
||||
AddressConf(std::string&& sigName, unsigned readCount, int *read, bool lastIsOffset);
|
||||
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset);
|
||||
|
||||
AddressConf() {}
|
||||
};
|
||||
|
||||
std::string m_Address;
|
||||
std::string m_AddressSignature;
|
||||
char m_Address[64];
|
||||
char m_AddressSignature[64];
|
||||
int m_AddressReadCount;
|
||||
int m_AddressRead[8];
|
||||
bool m_AddressLastIsOffset;
|
||||
StringHashMap<AddressConf> m_Addresses;
|
||||
const char *m_pEngine;
|
||||
const char *m_pBaseEngine;
|
||||
time_t m_ModTime;
|
||||
};
|
||||
|
||||
class GameConfigManager :
|
||||
|
||||
+15
-104
@@ -30,7 +30,6 @@
|
||||
*/
|
||||
|
||||
#include "HandleSys.h"
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "common_logic.h"
|
||||
@@ -39,20 +38,10 @@
|
||||
#include "PluginSys.h"
|
||||
#include <am-string.h>
|
||||
#include <bridge/include/ILogger.h>
|
||||
#include <bridge/include/CoreProvider.h>
|
||||
#include <ISourceMod.h>
|
||||
|
||||
#include "sm_platform.h"
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
#include "sm_invalidparamhandler.h"
|
||||
#endif
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
HandleSystem g_HandleSys;
|
||||
|
||||
QHandle *ignore_handle;
|
||||
extern ConVar *g_datetime_format;
|
||||
|
||||
inline HandleType_t TypeParent(HandleType_t type)
|
||||
{
|
||||
@@ -217,7 +206,7 @@ HandleType_t HandleSystem::CreateType(const char *name,
|
||||
pType->dispatch = dispatch;
|
||||
if (name && name[0] != '\0')
|
||||
{
|
||||
pType->name = std::make_unique<std::string>(name);
|
||||
pType->name = new ke::AString(name);
|
||||
m_TypeLookup.insert(name, pType);
|
||||
}
|
||||
|
||||
@@ -301,28 +290,6 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type,
|
||||
}
|
||||
}
|
||||
|
||||
if (owner)
|
||||
{
|
||||
owner->num_handles++;
|
||||
if (!owner->warned_handle_usage && owner->num_handles >= HANDLESYS_WARN_USAGE)
|
||||
{
|
||||
owner->warned_handle_usage = true;
|
||||
|
||||
std::string path = "<unknown>";
|
||||
if (auto plugin = scripts->FindPluginByIdentity(owner))
|
||||
{
|
||||
path = "plugin "s + plugin->GetFilename();
|
||||
}
|
||||
else if (auto ext = g_Extensions.GetExtensionFromIdent(owner))
|
||||
{
|
||||
path = "extension "s + ext->GetFilename();
|
||||
}
|
||||
|
||||
logger->LogError("[SM] Warning: %s is using more than %d handles!",
|
||||
path.c_str(), HANDLESYS_WARN_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
QHandle *pHandle = &m_Handles[handle];
|
||||
|
||||
assert(pHandle->set == false);
|
||||
@@ -344,7 +311,7 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type,
|
||||
|
||||
/* Create the hash value */
|
||||
Handle_t hash = pHandle->serial;
|
||||
hash <<= HANDLESYS_HANDLE_BITS;
|
||||
hash <<= 16;
|
||||
hash |= handle;
|
||||
|
||||
/* Add a reference count to the type */
|
||||
@@ -463,7 +430,7 @@ Handle_t HandleSystem::CreateHandleInt(HandleType_t type,
|
||||
|
||||
pHandle->object = object;
|
||||
pHandle->clone = 0;
|
||||
pHandle->timestamp = g_pSM->GetAdjustedTime();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -508,7 +475,7 @@ HandleError HandleSystem::GetHandle(Handle_t handle,
|
||||
unsigned int *in_index,
|
||||
bool ignoreFree)
|
||||
{
|
||||
unsigned int serial = (handle >> HANDLESYS_HANDLE_BITS);
|
||||
unsigned int serial = (handle >> 16);
|
||||
unsigned int index = (handle & HANDLESYS_HANDLE_MASK);
|
||||
|
||||
if (index == 0 || index > m_HandleTail || index > HANDLESYS_MAX_HANDLES)
|
||||
@@ -664,7 +631,7 @@ Handle_t HandleSystem::FastCloneHandle(Handle_t hndl)
|
||||
void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
unsigned int serial = (hndl >> HANDLESYS_HANDLE_BITS);
|
||||
unsigned int serial = (hndl >> 16);
|
||||
#endif
|
||||
index = (hndl & HANDLESYS_HANDLE_MASK);
|
||||
|
||||
@@ -688,9 +655,6 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
||||
|
||||
QHandleType *pType = &m_Types[pHandle->type];
|
||||
|
||||
if (pHandle->owner && pHandle->owner->num_handles > 0)
|
||||
pHandle->owner->num_handles--;
|
||||
|
||||
if (pHandle->clone)
|
||||
{
|
||||
/* If we're a clone, decrease the parent reference count */
|
||||
@@ -961,7 +925,7 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
|
||||
|
||||
/* Remove it from the type cache. */
|
||||
if (pType->name)
|
||||
m_TypeLookup.remove(pType->name->c_str());
|
||||
m_TypeLookup.remove(pType->name->chars());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1050,8 +1014,6 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
||||
unsigned int * pCount = new unsigned int[HANDLESYS_TYPEARRAY_SIZE+1];
|
||||
memset(pCount, 0, ((HANDLESYS_TYPEARRAY_SIZE + 1) * sizeof(unsigned int)));
|
||||
|
||||
const QHandle *oldest = nullptr;
|
||||
const QHandle *newest = nullptr;
|
||||
for (unsigned int i = 1; i <= m_HandleTail; ++i)
|
||||
{
|
||||
const QHandle &Handle = m_Handles[i];
|
||||
@@ -1068,15 +1030,6 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
||||
highest_index = ((Handle.type) + 1);
|
||||
}
|
||||
|
||||
if (!oldest || oldest->timestamp > Handle.timestamp)
|
||||
{
|
||||
oldest = &Handle;
|
||||
}
|
||||
if (!newest || newest->timestamp < Handle.timestamp)
|
||||
{
|
||||
newest = &Handle;
|
||||
}
|
||||
|
||||
if (Handle.clone != 0)
|
||||
{
|
||||
continue;
|
||||
@@ -1098,39 +1051,13 @@ bool HandleSystem::TryAndFreeSomeHandles()
|
||||
}
|
||||
|
||||
if (m_Types[i].name)
|
||||
pTypeName = m_Types[i].name->c_str();
|
||||
pTypeName = m_Types[i].name->chars();
|
||||
else
|
||||
pTypeName = "ANON";
|
||||
|
||||
HANDLE_LOG_VERY_BAD("Type\t%-20.20s|\tCount\t%u", pTypeName, pCount[i]);
|
||||
}
|
||||
|
||||
const char *fmt = bridge->GetCvarString(g_datetime_format);
|
||||
|
||||
char oldstamp[256], newstamp[256]; // 256 should be more than enough
|
||||
|
||||
// scope for InvalidParameterHandler
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
InvalidParameterHandler p;
|
||||
#endif
|
||||
size_t written = strftime(oldstamp, sizeof(oldstamp), fmt, localtime(&oldest->timestamp));
|
||||
if (!written)
|
||||
{
|
||||
ke::SafeStrcpy(oldstamp, sizeof(oldstamp), "INVALID");
|
||||
}
|
||||
|
||||
written = strftime(newstamp, sizeof(newstamp), fmt, localtime(&newest->timestamp));
|
||||
if (!written)
|
||||
{
|
||||
ke::SafeStrcpy(newstamp, sizeof(newstamp), "INVALID");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HANDLE_LOG_VERY_BAD("--------------------------------------------------------------------------");
|
||||
HANDLE_LOG_VERY_BAD("Oldest Living Handle: %s created at %s", m_Types[oldest->type].name->c_str(), oldstamp);
|
||||
HANDLE_LOG_VERY_BAD("Newest Living Handle: %s created at %s", m_Types[newest->type].name->c_str(), newstamp);
|
||||
HANDLE_LOG_VERY_BAD("-- Approximately %d bytes of memory are in use by (%u) Handles.\n", total_size, total);
|
||||
delete [] pCount;
|
||||
|
||||
@@ -1154,10 +1081,8 @@ static void rep(const HandleReporter &fn, const char *fmt, ...)
|
||||
void HandleSystem::Dump(const HandleReporter &fn)
|
||||
{
|
||||
unsigned int total_size = 0;
|
||||
rep(fn, "%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s\t%-30.30s", "Handle", "Owner", "Type", "Memory", "Time Created");
|
||||
rep(fn, "---------------------------------------------------------------------------------------------");
|
||||
|
||||
const char *fmt = bridge->GetCvarString(g_datetime_format);
|
||||
rep(fn, "%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
|
||||
rep(fn, "--------------------------------------------------------------------------");
|
||||
for (unsigned int i = 1; i <= m_HandleTail; i++)
|
||||
{
|
||||
if (m_Handles[i].set != HandleSet_Used)
|
||||
@@ -1165,12 +1090,12 @@ void HandleSystem::Dump(const HandleReporter &fn)
|
||||
continue;
|
||||
}
|
||||
/* Get the index */
|
||||
unsigned int index = (m_Handles[i].serial << HANDLESYS_HANDLE_BITS) | i;
|
||||
unsigned int index = (m_Handles[i].serial << 16) | i;
|
||||
/* Determine the owner */
|
||||
const char *owner = "UNKNOWN";
|
||||
if (m_Handles[i].owner)
|
||||
{
|
||||
IdentityToken_t *pOwner = m_Handles[i].owner;
|
||||
IdentityToken_t *pOwner = m_Handles[i].owner;
|
||||
if (pOwner == g_pCoreIdent)
|
||||
{
|
||||
owner = "CORE";
|
||||
@@ -1206,7 +1131,7 @@ void HandleSystem::Dump(const HandleReporter &fn)
|
||||
unsigned int parentIdx;
|
||||
bool bresult;
|
||||
if (pType->name)
|
||||
type = pType->name->c_str();
|
||||
type = pType->name->chars();
|
||||
|
||||
if ((parentIdx = m_Handles[i].clone) != 0)
|
||||
{
|
||||
@@ -1225,33 +1150,19 @@ void HandleSystem::Dump(const HandleReporter &fn)
|
||||
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size);
|
||||
}
|
||||
|
||||
char date[256]; // 256 should be more than enough
|
||||
size_t written = 0;
|
||||
// scope for InvalidParameterHandler
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
InvalidParameterHandler p;
|
||||
#endif
|
||||
written = strftime(date, sizeof(date), fmt, localtime(&m_Handles[i].timestamp));
|
||||
}
|
||||
|
||||
if (!written)
|
||||
{
|
||||
ke::SafeStrcpy(date, sizeof(date), "INVALID");
|
||||
}
|
||||
|
||||
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|
||||
|| !bresult)
|
||||
{
|
||||
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s\t%-30.30s", index, owner, type, "-1", date);
|
||||
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer[32];
|
||||
ke::SafeSprintf(buffer, sizeof(buffer), "%d", size);
|
||||
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s\t%-30.30s", index, owner, type, buffer, date);
|
||||
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
|
||||
total_size += size;
|
||||
}
|
||||
}
|
||||
rep(fn, "-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
|
||||
}
|
||||
|
||||
|
||||
+8
-15
@@ -32,27 +32,21 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
|
||||
#define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
|
||||
|
||||
#include <IHandleSys.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <sm_namehashset.h>
|
||||
#include <amtl/am-string.h>
|
||||
#include <amtl/am-function.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <sm_namehashset.h>
|
||||
#include "common_logic.h"
|
||||
|
||||
#define HANDLESYS_HANDLE_BITS 20
|
||||
#define HANDLESYS_MAX_HANDLES ((1 << HANDLESYS_HANDLE_BITS) - 1)
|
||||
#define HANDLESYS_MAX_HANDLES (1<<15)
|
||||
#define HANDLESYS_MAX_TYPES (1<<9)
|
||||
#define HANDLESYS_MAX_SUBTYPES 0xF
|
||||
#define HANDLESYS_SUBTYPE_MASK 0xF
|
||||
#define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
|
||||
#define HANDLESYS_SERIAL_BITS (32 - HANDLESYS_HANDLE_BITS)
|
||||
#define HANDLESYS_MAX_SERIALS (1 << HANDLESYS_SERIAL_BITS)
|
||||
#define HANDLESYS_SERIAL_MASK (((1 << HANDLESYS_SERIAL_BITS) - 1) << HANDLESYS_HANDLE_BITS)
|
||||
#define HANDLESYS_HANDLE_MASK ((1 << HANDLESYS_HANDLE_BITS) - 1)
|
||||
#define HANDLESYS_WARN_USAGE 100000
|
||||
#define HANDLESYS_MAX_SERIALS 0xFFFF
|
||||
#define HANDLESYS_SERIAL_MASK 0xFFFF0000
|
||||
#define HANDLESYS_HANDLE_MASK 0x0000FFFF
|
||||
|
||||
#define HANDLESYS_MEMUSAGE_MIN_VERSION 3
|
||||
|
||||
@@ -93,7 +87,6 @@ struct QHandle
|
||||
bool access_special; /* Whether or not access rules are special or type-derived */
|
||||
bool is_destroying; /* Whether or not the handle is being destroyed */
|
||||
HandleAccess sec; /* Security rules */
|
||||
time_t timestamp; /* Creation timestamp */
|
||||
/* The following variables are unrelated to the Handle array, and used
|
||||
* as an inlined chain of information */
|
||||
unsigned int freeID; /* ID of a free handle in the free handle chain */
|
||||
@@ -111,7 +104,7 @@ struct QHandleType
|
||||
TypeAccess typeSec;
|
||||
HandleAccess hndlSec;
|
||||
unsigned int opened;
|
||||
std::unique_ptr<std::string> name;
|
||||
ke::AutoPtr<ke::AString> name;
|
||||
|
||||
static inline bool matches(const char *key, const QHandleType *type)
|
||||
{
|
||||
@@ -123,7 +116,7 @@ struct QHandleType
|
||||
}
|
||||
};
|
||||
|
||||
typedef ke::Function<void(const char *)> HandleReporter;
|
||||
typedef ke::Lambda<void(const char *)> HandleReporter;
|
||||
|
||||
class HandleSystem :
|
||||
public IHandleSys
|
||||
|
||||
@@ -66,7 +66,7 @@ CDirectory::CDirectory(const char *path)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
char newpath[PLATFORM_MAX_PATH];
|
||||
ke::SafeSprintf(newpath, sizeof(newpath), "%s\\*.*", path);
|
||||
snprintf(newpath, sizeof(newpath), "%s\\*.*", path);
|
||||
m_dir = FindFirstFileA(newpath, &m_fd);
|
||||
if (!IsValid())
|
||||
{
|
||||
@@ -78,7 +78,7 @@ CDirectory::CDirectory(const char *path)
|
||||
{
|
||||
/* :TODO: we need to read past "." and ".."! */
|
||||
ep = readdir(m_dir);
|
||||
ke::SafeStrcpy(m_origpath, PLATFORM_MAX_PATH, path);
|
||||
snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path);
|
||||
} else {
|
||||
ep = NULL;
|
||||
}
|
||||
@@ -125,9 +125,7 @@ bool CDirectory::IsEntryDirectory()
|
||||
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
||||
#elif defined PLATFORM_POSIX
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
int ret = ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
if (static_cast<size_t>(ret) >= sizeof(temppath))
|
||||
return false;
|
||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
return ke::file::IsDirectory(temppath);
|
||||
#endif
|
||||
}
|
||||
@@ -138,9 +136,7 @@ bool CDirectory::IsEntryFile()
|
||||
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
|
||||
#elif defined PLATFORM_POSIX
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
int ret = ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
if (static_cast<size_t>(ret) >= sizeof(temppath))
|
||||
return false;
|
||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
return ke::file::IsFile(temppath);
|
||||
#endif
|
||||
}
|
||||
@@ -230,7 +226,7 @@ void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
|
||||
const char *ae = strerror_r(code, error, maxlength);
|
||||
if (ae != error)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, ae);
|
||||
ke::SafeSprintf(error, maxlength, "%s", ae);
|
||||
}
|
||||
#elif defined PLATFORM_POSIX
|
||||
strerror_r(code, error, maxlength);
|
||||
@@ -309,12 +305,12 @@ size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return ke::SafeStrcpy(buffer, maxlength, &path[i+1]);
|
||||
return ke::SafeSprintf(buffer, maxlength, "%s", &path[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* We scanned and found no path separator */
|
||||
return ke::SafeStrcpy(buffer, maxlength, path);
|
||||
return ke::SafeSprintf(buffer, maxlength, "%s", path);
|
||||
}
|
||||
|
||||
bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime)
|
||||
|
||||
+285
-185
@@ -40,6 +40,10 @@
|
||||
|
||||
Logger g_Logger;
|
||||
|
||||
/**
|
||||
* :TODO: This should be creating the log folder if it doesn't exist
|
||||
*/
|
||||
|
||||
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||
const char *value,
|
||||
ConfigSource source,
|
||||
@@ -56,7 +60,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||
} else if (strcasecmp(value, "off") == 0) {
|
||||
state = false;
|
||||
} else {
|
||||
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
||||
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
@@ -64,7 +68,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||
{
|
||||
state ? EnableLogging() : DisableLogging();
|
||||
} else {
|
||||
m_Active = state;
|
||||
m_InitialState = state;
|
||||
}
|
||||
|
||||
return ConfigResult_Accept;
|
||||
@@ -77,7 +81,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||
} else if (strcasecmp(value, "game") == 0) {
|
||||
m_Mode = LoggingMode_Game;
|
||||
} else {
|
||||
ke::SafeStrcpy(error, maxlength, "Invalid value: must be [daily|map|game]");
|
||||
ke::SafeSprintf(error, maxlength, "Invalid value: must be [daily|map|game]");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
|
||||
@@ -89,12 +93,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
|
||||
|
||||
void Logger::OnSourceModStartup(bool late)
|
||||
{
|
||||
char buff[PLATFORM_MAX_PATH];
|
||||
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs");
|
||||
if (!libsys->IsPathDirectory(buff))
|
||||
{
|
||||
libsys->CreateFolder(buff);
|
||||
}
|
||||
InitLogger(m_Mode);
|
||||
}
|
||||
|
||||
void Logger::OnSourceModAllShutdown()
|
||||
@@ -104,7 +103,127 @@ void Logger::OnSourceModAllShutdown()
|
||||
|
||||
void Logger::OnSourceModLevelChange(const char *mapName)
|
||||
{
|
||||
_MapChange(mapName);
|
||||
MapChange(mapName);
|
||||
}
|
||||
|
||||
void Logger::_NewMapFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Append "Log file closed" to previous log file */
|
||||
_CloseFile();
|
||||
|
||||
char _filename[256];
|
||||
int i = 0;
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
while (true)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
|
||||
FILE *fp = fopen(_filename, "r");
|
||||
if (!fp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
i++;
|
||||
}
|
||||
m_NrmFileName.assign(_filename);
|
||||
|
||||
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
|
||||
if (!fp)
|
||||
{
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
} else {
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_CloseFile()
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (!m_NrmFileName.empty())
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogMessage("Log file closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_NrmFileName.clear();
|
||||
}
|
||||
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fp = fopen(m_ErrFileName.c_str(), "r+");
|
||||
if (fp)
|
||||
{
|
||||
fseek(fp, 0, SEEK_END);
|
||||
LogError("Error log file session closed.");
|
||||
fclose(fp);
|
||||
}
|
||||
m_ErrFileName.clear();
|
||||
}
|
||||
|
||||
void Logger::InitLogger(LoggingMode mode)
|
||||
{
|
||||
m_Mode = mode;
|
||||
m_Active = m_InitialState;
|
||||
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
|
||||
switch (m_Mode)
|
||||
{
|
||||
case LoggingMode_PerMap:
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
m_DelayedStart = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LoggingMode_Daily:
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_DailyPrintHdr = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* do nothing... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::CloseLogger()
|
||||
@@ -112,13 +231,6 @@ void Logger::CloseLogger()
|
||||
_CloseFile();
|
||||
}
|
||||
|
||||
void Logger::_CloseFile()
|
||||
{
|
||||
_CloseNormal();
|
||||
_CloseError();
|
||||
_CloseFatal();
|
||||
}
|
||||
|
||||
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
|
||||
{
|
||||
if (!m_Active)
|
||||
@@ -147,6 +259,11 @@ void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
|
||||
|
||||
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static ConVar *sv_logecho = bridge->FindConVar("sv_logecho");
|
||||
|
||||
char buffer[3072];
|
||||
@@ -165,12 +282,15 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
|
||||
ke::SafeSprintf(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
|
||||
bridge->ConPrint(conBuffer);
|
||||
}
|
||||
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||
{
|
||||
if (!m_Active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[3072];
|
||||
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
|
||||
|
||||
@@ -178,8 +298,8 @@ void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
|
||||
fprintf(fp, "L %s: %s\n", date, buffer);
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
@@ -204,14 +324,63 @@ void Logger::LogMessageEx(const char *vafmt, va_list ap)
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *pFile = _OpenNormal();
|
||||
if (!pFile)
|
||||
if (m_DelayedStart)
|
||||
{
|
||||
return;
|
||||
m_DelayedStart = false;
|
||||
_NewMapFile();
|
||||
}
|
||||
|
||||
LogToOpenFileEx(pFile, vafmt, ap);
|
||||
fclose(pFile);
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
FILE *fp = NULL;
|
||||
if (m_Mode == LoggingMode_PerMap)
|
||||
{
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
_NewMapFile();
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
if (!fp)
|
||||
{
|
||||
goto print_error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_NrmCurDay != curtime->tm_mday)
|
||||
{
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_NrmFileName.assign(_filename);
|
||||
m_NrmCurDay = curtime->tm_mday;
|
||||
m_DailyPrintHdr = true;
|
||||
}
|
||||
fp = fopen(m_NrmFileName.c_str(), "a+");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
if (m_DailyPrintHdr)
|
||||
{
|
||||
char date[32];
|
||||
m_DailyPrintHdr = false;
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
} else {
|
||||
goto print_error;
|
||||
}
|
||||
|
||||
return;
|
||||
print_error:
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
}
|
||||
|
||||
void Logger::LogError(const char *vafmt, ...)
|
||||
@@ -229,20 +398,72 @@ void Logger::LogErrorEx(const char *vafmt, va_list ap)
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *pFile = _OpenError();
|
||||
if (!pFile)
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
if (curtime->tm_mday != m_ErrCurDay)
|
||||
{
|
||||
return;
|
||||
char _filename[256];
|
||||
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrFileName.assign(_filename);
|
||||
m_ErrCurDay = curtime->tm_mday;
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
LogToOpenFileEx(pFile, vafmt, ap);
|
||||
fclose(pFile);
|
||||
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
|
||||
if (fp)
|
||||
{
|
||||
if (!m_ErrMapStart)
|
||||
{
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(fp, "L %s: SourceMod error session started\n", date);
|
||||
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
m_ErrMapStart = true;
|
||||
}
|
||||
LogToOpenFileEx(fp, vafmt, ap);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
LogFatal("[SM] Logging has been disabled.");
|
||||
m_Active = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_MapChange(const char *mapname)
|
||||
void Logger::MapChange(const char *mapname)
|
||||
{
|
||||
m_CurrentMapName = mapname;
|
||||
_UpdateFiles(true);
|
||||
m_CurMapName.assign(mapname);
|
||||
|
||||
switch (m_Mode)
|
||||
{
|
||||
case LoggingMode_Daily:
|
||||
{
|
||||
LogMessage("-------- Mapchange to %s --------", mapname);
|
||||
break;
|
||||
}
|
||||
case LoggingMode_PerMap:
|
||||
{
|
||||
_NewMapFile();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* Do nothing... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ErrMapStart)
|
||||
{
|
||||
LogError("Error log file session closed.");
|
||||
}
|
||||
m_ErrMapStart = false;
|
||||
}
|
||||
|
||||
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
||||
@@ -259,6 +480,30 @@ void Logger::_PrintToGameLog(const char *fmt, va_list ap)
|
||||
bridge->LogToGame(msg);
|
||||
}
|
||||
|
||||
const char *Logger::GetLogFileName(LogType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LogType_Normal:
|
||||
{
|
||||
return m_NrmFileName.c_str();
|
||||
}
|
||||
case LogType_Error:
|
||||
{
|
||||
return m_ErrFileName.c_str();
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoggingMode Logger::GetLoggingMode() const
|
||||
{
|
||||
return m_Mode;
|
||||
}
|
||||
|
||||
void Logger::EnableLogging()
|
||||
{
|
||||
if (m_Active)
|
||||
@@ -294,161 +539,16 @@ void Logger::LogFatalEx(const char *msg, va_list ap)
|
||||
* It's already implemented twice which is bad.
|
||||
*/
|
||||
|
||||
FILE *pFile = _OpenFatal();
|
||||
if (!pFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogToOpenFileEx(pFile, msg, ap);
|
||||
fclose(pFile);
|
||||
}
|
||||
|
||||
void Logger::_UpdateFiles(bool bLevelChange)
|
||||
{
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
if (!bLevelChange && curtime->tm_mday == m_Day)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Day = curtime->tm_mday;
|
||||
|
||||
char buff[PLATFORM_MAX_PATH];
|
||||
ke::SafeSprintf(buff, sizeof(buff), "%04d%02d%02d", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
|
||||
|
||||
std::string currentDate(buff);
|
||||
|
||||
if (m_Mode == LoggingMode_PerMap)
|
||||
{
|
||||
if (bLevelChange)
|
||||
{
|
||||
for (size_t iter = 0; iter < static_cast<size_t>(-1); ++iter)
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s%u.log", currentDate.c_str(), iter);
|
||||
if (!libsys->IsPathFile(buff))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ke::SafeStrcpy(buff, sizeof(buff), m_NormalFileName.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s.log", currentDate.c_str());
|
||||
}
|
||||
|
||||
if (m_NormalFileName.compare(buff))
|
||||
{
|
||||
_CloseNormal();
|
||||
m_NormalFileName = buff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bLevelChange)
|
||||
{
|
||||
LogMessage("-------- Mapchange to %s --------", m_CurrentMapName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/errors_%s.log", currentDate.c_str());
|
||||
if (bLevelChange || m_ErrorFileName.compare(buff))
|
||||
{
|
||||
_CloseError();
|
||||
m_ErrorFileName = buff;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *Logger::_OpenNormal()
|
||||
{
|
||||
_UpdateFiles();
|
||||
|
||||
FILE *pFile = fopen(m_NormalFileName.c_str(), "a+");
|
||||
if (pFile == NULL)
|
||||
{
|
||||
_LogFatalOpen(m_NormalFileName);
|
||||
return pFile;
|
||||
}
|
||||
|
||||
if (!m_DamagedNormalFile)
|
||||
{
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
char date[32];
|
||||
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(pFile, "L %s: SourceMod log file session started (file \"%s\") (Version \"%s\")\n", date, m_NormalFileName.c_str(), SOURCEMOD_VERSION);
|
||||
m_DamagedNormalFile = true;
|
||||
}
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
FILE *Logger::_OpenError()
|
||||
{
|
||||
_UpdateFiles();
|
||||
|
||||
FILE *pFile = fopen(m_ErrorFileName.c_str(), "a+");
|
||||
if (pFile == NULL)
|
||||
{
|
||||
_LogFatalOpen(m_ErrorFileName);
|
||||
return pFile;
|
||||
}
|
||||
|
||||
if (!m_DamagedErrorFile)
|
||||
{
|
||||
time_t t = g_pSM->GetAdjustedTime();
|
||||
tm *curtime = localtime(&t);
|
||||
|
||||
char date[32];
|
||||
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
|
||||
fprintf(pFile, "L %s: SourceMod error session started\n", date);
|
||||
fprintf(pFile, "L %s: Info (map \"%s\") (file \"%s\")\n", date, m_CurrentMapName.c_str(), m_ErrorFileName.c_str());
|
||||
m_DamagedErrorFile = true;
|
||||
}
|
||||
|
||||
return pFile;
|
||||
}
|
||||
|
||||
FILE *Logger::_OpenFatal()
|
||||
{
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
|
||||
return fopen(path, "at");
|
||||
}
|
||||
|
||||
void Logger::_LogFatalOpen(std::string &str)
|
||||
{
|
||||
char error[255];
|
||||
libsys->GetPlatformError(error, sizeof(error));
|
||||
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", str.c_str());
|
||||
LogFatal("[SM] Platform returned error: \"%s\"", error);
|
||||
}
|
||||
|
||||
void Logger::_CloseNormal()
|
||||
{
|
||||
if (m_DamagedNormalFile)
|
||||
FILE *fp = fopen(path, "at");
|
||||
if (fp)
|
||||
{
|
||||
LogMessage("Log file closed.");
|
||||
m_DamagedNormalFile = false;
|
||||
m_Active = true;
|
||||
LogToOpenFileEx(fp, msg, ap);
|
||||
m_Active = false;
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_CloseError()
|
||||
{
|
||||
if (m_DamagedErrorFile)
|
||||
{
|
||||
LogError("Error log file session closed.");
|
||||
m_DamagedErrorFile = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::_CloseFatal()
|
||||
{
|
||||
}
|
||||
|
||||
+20
-22
@@ -34,9 +34,11 @@
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <stdio.h>
|
||||
#include <amtl/am-string.h>
|
||||
#include <sh_string.h>
|
||||
#include <bridge/include/ILogger.h>
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
enum LogType
|
||||
{
|
||||
LogType_Normal,
|
||||
@@ -53,7 +55,9 @@ enum LoggingMode
|
||||
class Logger : public SMGlobalClass, public ILogger
|
||||
{
|
||||
public:
|
||||
Logger() : m_Day(-1), m_Mode(LoggingMode_Daily), m_Active(true), m_DamagedNormalFile(false), m_DamagedErrorFile(false)
|
||||
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
|
||||
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
|
||||
m_InitialState(true)
|
||||
{
|
||||
}
|
||||
public: //SMGlobalClass
|
||||
@@ -66,6 +70,7 @@ public: //SMGlobalClass
|
||||
void OnSourceModAllShutdown();
|
||||
void OnSourceModLevelChange(const char *mapName);
|
||||
public:
|
||||
void InitLogger(LoggingMode mode);
|
||||
void CloseLogger();
|
||||
void EnableLogging();
|
||||
void DisableLogging();
|
||||
@@ -80,32 +85,25 @@ public:
|
||||
/* This version does not print to console, and is thus thread-safe */
|
||||
void LogToFileOnly(FILE *fp, const char *msg, ...);
|
||||
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
|
||||
void MapChange(const char *mapname);
|
||||
const char *GetLogFileName(LogType type) const;
|
||||
LoggingMode GetLoggingMode() const;
|
||||
private:
|
||||
void _MapChange(const char *mapname);
|
||||
|
||||
void _CloseFile();
|
||||
void _CloseNormal();
|
||||
void _CloseError();
|
||||
void _CloseFatal();
|
||||
|
||||
FILE *_OpenNormal();
|
||||
FILE *_OpenError();
|
||||
FILE *_OpenFatal();
|
||||
|
||||
void _LogFatalOpen(std::string &str);
|
||||
void _NewMapFile();
|
||||
void _PrintToGameLog(const char *fmt, va_list ap);
|
||||
void _UpdateFiles(bool bLevelChange = false);
|
||||
private:
|
||||
std::string m_NormalFileName;
|
||||
std::string m_ErrorFileName;
|
||||
std::string m_CurrentMapName;
|
||||
|
||||
int m_Day;
|
||||
|
||||
String m_NrmFileName;
|
||||
String m_ErrFileName;
|
||||
String m_CurMapName;
|
||||
LoggingMode m_Mode;
|
||||
int m_NrmCurDay;
|
||||
int m_ErrCurDay;
|
||||
bool m_ErrMapStart;
|
||||
bool m_Active;
|
||||
bool m_DamagedNormalFile;
|
||||
bool m_DamagedErrorFile;
|
||||
bool m_DelayedStart;
|
||||
bool m_DailyPrintHdr;
|
||||
bool m_InitialState;
|
||||
};
|
||||
|
||||
extern Logger g_Logger;
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* Entity Lump Manager
|
||||
* Copyright (C) 2021-2022 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "LumpManager.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
EntityLumpParseResult::operator bool() const {
|
||||
return m_Status == Status_OK;
|
||||
}
|
||||
|
||||
EntityLumpParseResult EntityLumpManager::Parse(const char* pMapEntities) {
|
||||
m_Entities.clear();
|
||||
|
||||
std::istringstream mapEntities(pMapEntities);
|
||||
|
||||
for (;;) {
|
||||
std::string token;
|
||||
mapEntities >> std::ws >> token >> std::ws;
|
||||
|
||||
// Assert that we're at the start of a new block, otherwise we're done parsing
|
||||
if (token != "{") {
|
||||
if (token == "\0") {
|
||||
break;
|
||||
} else {
|
||||
return EntityLumpParseResult {
|
||||
Status_UnexpectedChar, mapEntities.tellg()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse key / value pairs until we reach a closing brace. We currently assume there
|
||||
* are only quoted keys / values up to the next closing brace.
|
||||
*
|
||||
* The SDK suggests that there are cases that could use non-quoted symbols and nested
|
||||
* braces (`shared/mapentities_shared.cpp::MapEntity_ParseToken`), but I haven't seen
|
||||
* those in practice.
|
||||
*/
|
||||
EntityLumpEntry entry;
|
||||
while (mapEntities.peek() != '}') {
|
||||
std::string key, value;
|
||||
|
||||
if (mapEntities.peek() != '"') {
|
||||
return EntityLumpParseResult {
|
||||
Status_UnexpectedChar, mapEntities.tellg()
|
||||
};
|
||||
}
|
||||
mapEntities >> quoted(key) >> std::ws;
|
||||
|
||||
if (mapEntities.peek() != '"') {
|
||||
return EntityLumpParseResult {
|
||||
Status_UnexpectedChar, mapEntities.tellg()
|
||||
};
|
||||
}
|
||||
mapEntities >> quoted(value) >> std::ws;
|
||||
|
||||
entry.emplace_back(key, value);
|
||||
}
|
||||
mapEntities.get();
|
||||
m_Entities.push_back(std::make_shared<EntityLumpEntry>(entry));
|
||||
}
|
||||
|
||||
return EntityLumpParseResult{};
|
||||
}
|
||||
|
||||
std::string EntityLumpManager::Dump() {
|
||||
std::ostringstream stream;
|
||||
for (const auto& entry : m_Entities) {
|
||||
// ignore empty entries
|
||||
if (entry->empty()) {
|
||||
continue;
|
||||
}
|
||||
stream << "{\n";
|
||||
for (const auto& pair : *entry) {
|
||||
stream << '"' << pair.first << "\" \"" << pair.second << '"' << '\n';
|
||||
}
|
||||
stream << "}\n";
|
||||
}
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::weak_ptr<EntityLumpEntry> EntityLumpManager::Get(size_t index) {
|
||||
return m_Entities[index];
|
||||
}
|
||||
|
||||
void EntityLumpManager::Erase(size_t index) {
|
||||
m_Entities.erase(m_Entities.begin() + index);
|
||||
}
|
||||
|
||||
void EntityLumpManager::Insert(size_t index) {
|
||||
m_Entities.emplace(m_Entities.begin() + index, std::make_shared<EntityLumpEntry>());
|
||||
}
|
||||
|
||||
size_t EntityLumpManager::Append() {
|
||||
auto it = m_Entities.emplace(m_Entities.end(), std::make_shared<EntityLumpEntry>());
|
||||
return std::distance(m_Entities.begin(), it);
|
||||
}
|
||||
|
||||
size_t EntityLumpManager::Length() {
|
||||
return m_Entities.size();
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* Entity Lump Manager
|
||||
* Copyright (C) 2021-2022 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_LUMPMANAGER_H_
|
||||
#define _INCLUDE_LUMPMANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Entity lump manager. Provides a list that stores a list of key / value pairs and the
|
||||
* functionality to (de)serialize it from / to an entity string.
|
||||
* This file and its corresponding .cpp should be compilable independently of SourceMod;
|
||||
* the SourceMod interop is located within smn_entitylump.
|
||||
*
|
||||
* @file lumpmanager.h
|
||||
* @brief Class definition for object that parses lumps.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief A container of key / value pairs.
|
||||
*/
|
||||
using EntityLumpEntry = std::vector<std::pair<std::string, std::string>>;
|
||||
|
||||
enum EntityLumpParseStatus {
|
||||
Status_OK,
|
||||
Status_UnexpectedChar,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Result of parsing an entity lump. On a parse error, m_Status is not Status_OK and
|
||||
* m_Position indicates the offset within the string that caused the parse error.
|
||||
*/
|
||||
struct EntityLumpParseResult {
|
||||
EntityLumpParseStatus m_Status;
|
||||
std::streamoff m_Position;
|
||||
|
||||
operator bool() const;
|
||||
const char* Description() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Manages entity lump entries.
|
||||
*/
|
||||
class EntityLumpManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Parses the map entities string into an internal representation.
|
||||
*/
|
||||
EntityLumpParseResult Parse(const char* pMapEntities);
|
||||
|
||||
/**
|
||||
* @brief Dumps the current internal representation out to an std::string.
|
||||
*/
|
||||
std::string Dump();
|
||||
|
||||
/**
|
||||
* @brief Returns a weak reference to an EntityLumpEntry. Used for handles on the scripting side.
|
||||
*/
|
||||
std::weak_ptr<EntityLumpEntry> Get(size_t index);
|
||||
|
||||
/**
|
||||
* @brief Removes an EntityLumpEntry at the given index, shifting down all entries after it by one.
|
||||
*/
|
||||
void Erase(size_t index);
|
||||
|
||||
/**
|
||||
* @brief Inserts a new EntityLumpEntry at the given index, shifting up the entries previously at the index and after it up by one.
|
||||
*/
|
||||
void Insert(size_t index);
|
||||
|
||||
/**
|
||||
* @brief Adds a new EntityLumpEntry to the end. Returns the index of the entry.
|
||||
*/
|
||||
size_t Append();
|
||||
|
||||
/**
|
||||
* @brief Returns the number of EntityLumpEntry items in the list.
|
||||
*/
|
||||
size_t Length();
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<EntityLumpEntry>> m_Entities;
|
||||
};
|
||||
|
||||
#endif // _INCLUDE_LUMPMANAGER_H_
|
||||
+104
-165
@@ -43,19 +43,45 @@
|
||||
#include <mach-o/dyld_images.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/nlist.h>
|
||||
|
||||
/* Define things from 10.6 SDK for older SDKs */
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
struct task_dyld_info
|
||||
{
|
||||
mach_vm_address_t all_image_info_addr;
|
||||
mach_vm_size_t all_image_info_size;
|
||||
};
|
||||
typedef struct task_dyld_info task_dyld_info_data_t;
|
||||
#define TASK_DYLD_INFO 17
|
||||
#define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
|
||||
#endif // MAC_OS_X_VERSION_10_6
|
||||
#endif // PLATFORM_APPLE
|
||||
|
||||
MemoryUtils g_MemUtils;
|
||||
|
||||
MemoryUtils::MemoryUtils()
|
||||
{
|
||||
m_InfoMap.init();
|
||||
#ifdef PLATFORM_APPLE
|
||||
|
||||
task_dyld_info_data_t dyld_info;
|
||||
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
||||
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
|
||||
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
|
||||
Gestalt(gestaltSystemVersionMajor, &m_OSXMajor);
|
||||
Gestalt(gestaltSystemVersionMinor, &m_OSXMinor);
|
||||
|
||||
/* Get pointer to struct that describes all loaded mach-o images in process */
|
||||
if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
|
||||
{
|
||||
task_dyld_info_data_t dyld_info;
|
||||
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
||||
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
|
||||
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct nlist list[2];
|
||||
memset(list, 0, sizeof(list));
|
||||
list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
|
||||
nlist("/usr/lib/dyld", list);
|
||||
m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -78,19 +104,20 @@ void MemoryUtils::OnSourceModAllInitialized()
|
||||
|
||||
void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len)
|
||||
{
|
||||
const DynLibInfo* lib = nullptr;
|
||||
DynLibInfo lib;
|
||||
bool found;
|
||||
char *ptr, *end;
|
||||
|
||||
if ((lib = GetLibraryInfo(libPtr)) == nullptr)
|
||||
memset(&lib, 0, sizeof(DynLibInfo));
|
||||
|
||||
if (!GetLibraryInfo(libPtr, lib))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search in the original unaltered state of the binary.
|
||||
char *start = lib->originalCopy.get();
|
||||
char *ptr = start;
|
||||
char *end = ptr + lib->memorySize - len;
|
||||
ptr = reinterpret_cast<char *>(lib.baseAddress);
|
||||
end = ptr + lib.memorySize - len;
|
||||
|
||||
bool found;
|
||||
while (ptr < end)
|
||||
{
|
||||
found = true;
|
||||
@@ -103,9 +130,8 @@ void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t l
|
||||
}
|
||||
}
|
||||
|
||||
// Translate the found offset into the actual live binary memory space.
|
||||
if (found)
|
||||
return reinterpret_cast<char *>(lib->baseAddress) + (ptr - start);
|
||||
return ptr;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
@@ -117,31 +143,17 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
/* Add this this library into the cache */
|
||||
GetLibraryInfo(handle);
|
||||
return GetProcAddress((HMODULE)handle, symbol);
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef Elf32_Ehdr ElfHeader;
|
||||
typedef Elf32_Shdr ElfSHeader;
|
||||
typedef Elf32_Sym ElfSymbol;
|
||||
#define ELF_SYM_TYPE ELF32_ST_TYPE
|
||||
#else
|
||||
typedef Elf64_Ehdr ElfHeader;
|
||||
typedef Elf64_Shdr ElfSHeader;
|
||||
typedef Elf64_Sym ElfSymbol;
|
||||
#define ELF_SYM_TYPE ELF64_ST_TYPE
|
||||
#endif
|
||||
|
||||
struct link_map *dlmap;
|
||||
struct stat dlstat;
|
||||
int dlfile;
|
||||
uintptr_t map_base;
|
||||
ElfHeader *file_hdr;
|
||||
ElfSHeader *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
|
||||
ElfSymbol *symtab;
|
||||
Elf32_Ehdr *file_hdr;
|
||||
Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
|
||||
Elf32_Sym *symtab;
|
||||
const char *shstrtab, *strtab;
|
||||
uint16_t section_count;
|
||||
uint32_t symbol_count;
|
||||
@@ -165,9 +177,6 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add this this library into the cache */
|
||||
GetLibraryInfo((void *)dlmap->l_addr);
|
||||
|
||||
/* If we don't have a symbol table for this library, then create one */
|
||||
if (table == NULL)
|
||||
{
|
||||
@@ -195,7 +204,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
|
||||
/* Map library file into memory */
|
||||
file_hdr = (ElfHeader *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
|
||||
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
|
||||
map_base = (uintptr_t)file_hdr;
|
||||
if (file_hdr == MAP_FAILED)
|
||||
{
|
||||
@@ -210,7 +219,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sections = (ElfSHeader *)(map_base + file_hdr->e_shoff);
|
||||
sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
|
||||
section_count = file_hdr->e_shnum;
|
||||
/* Get ELF section header string table */
|
||||
shstrtab_hdr = §ions[file_hdr->e_shstrndx];
|
||||
@@ -219,7 +228,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
/* Iterate sections while looking for ELF symbol table and string table */
|
||||
for (uint16_t i = 0; i < section_count; i++)
|
||||
{
|
||||
ElfSHeader &hdr = sections[i];
|
||||
Elf32_Shdr &hdr = sections[i];
|
||||
const char *section_name = shstrtab + hdr.sh_name;
|
||||
|
||||
if (strcmp(section_name, ".symtab") == 0)
|
||||
@@ -239,15 +248,15 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symtab = (ElfSymbol *)(map_base + symtab_hdr->sh_offset);
|
||||
symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
|
||||
strtab = (const char *)(map_base + strtab_hdr->sh_offset);
|
||||
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
|
||||
|
||||
/* Iterate symbol table starting from the position we were at last time */
|
||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||
{
|
||||
ElfSymbol &sym = symtab[i];
|
||||
unsigned char sym_type = ELF_SYM_TYPE(sym.st_info);
|
||||
Elf32_Sym &sym = symtab[i];
|
||||
unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
|
||||
const char *sym_name = strtab + sym.st_name;
|
||||
Symbol *cur_sym;
|
||||
|
||||
@@ -271,29 +280,14 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
return symbol_entry ? symbol_entry->address : NULL;
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef struct mach_header MachHeader;
|
||||
typedef struct segment_command MachSegment;
|
||||
typedef struct nlist MachSymbol;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
|
||||
#else
|
||||
typedef struct mach_header_64 MachHeader;
|
||||
typedef struct segment_command_64 MachSegment;
|
||||
typedef struct nlist_64 MachSymbol;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
|
||||
#endif
|
||||
|
||||
typedef struct load_command MachLoadCmd;
|
||||
typedef struct symtab_command MachSymHeader;
|
||||
|
||||
|
||||
uintptr_t dlbase, linkedit_addr;
|
||||
uint32_t image_count;
|
||||
MachHeader *file_hdr;
|
||||
MachLoadCmd *loadcmds;
|
||||
MachSegment *linkedit_hdr;
|
||||
MachSymHeader *symtab_hdr;
|
||||
MachSymbol *symtab;
|
||||
struct mach_header *file_hdr;
|
||||
struct load_command *loadcmds;
|
||||
struct segment_command *linkedit_hdr;
|
||||
struct symtab_command *symtab_hdr;
|
||||
struct nlist *symtab;
|
||||
const char *strtab;
|
||||
uint32_t loadcmd_count;
|
||||
uint32_t symbol_count;
|
||||
@@ -331,9 +325,6 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
/* Uh oh, we couldn't find a matching handle */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add this this library into the cache */
|
||||
GetLibraryInfo((void *)dlbase);
|
||||
|
||||
/* See if we already have a symbol table for this library */
|
||||
for (size_t i = 0; i < m_SymTables.size(); i++)
|
||||
@@ -366,16 +357,16 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
|
||||
/* If symbol isn't in our table, then we have to locate it in memory */
|
||||
|
||||
file_hdr = (MachHeader *)dlbase;
|
||||
loadcmds = (MachLoadCmd *)(dlbase + sizeof(MachHeader));
|
||||
file_hdr = (struct mach_header *)dlbase;
|
||||
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
|
||||
loadcmd_count = file_hdr->ncmds;
|
||||
|
||||
/* Loop through load commands until we find the ones for the symbol table */
|
||||
for (uint32_t i = 0; i < loadcmd_count; i++)
|
||||
{
|
||||
if (loadcmds->cmd == MACH_LOADCMD_SEGMENT && !linkedit_hdr)
|
||||
if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
|
||||
{
|
||||
MachSegment *seg = (MachSegment *)loadcmds;
|
||||
struct segment_command *seg = (struct segment_command *)loadcmds;
|
||||
if (strcmp(seg->segname, "__LINKEDIT") == 0)
|
||||
{
|
||||
linkedit_hdr = seg;
|
||||
@@ -387,7 +378,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
else if (loadcmds->cmd == LC_SYMTAB)
|
||||
{
|
||||
symtab_hdr = (MachSymHeader *)loadcmds;
|
||||
symtab_hdr = (struct symtab_command *)loadcmds;
|
||||
if (linkedit_hdr)
|
||||
{
|
||||
break;
|
||||
@@ -395,7 +386,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
|
||||
/* Load commands are not of a fixed size which is why we add the size */
|
||||
loadcmds = (MachLoadCmd *)((uintptr_t)loadcmds + loadcmds->cmdsize);
|
||||
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
|
||||
}
|
||||
|
||||
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
|
||||
@@ -405,14 +396,14 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
}
|
||||
|
||||
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
|
||||
symtab = (MachSymbol *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
|
||||
symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
|
||||
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
|
||||
symbol_count = symtab_hdr->nsyms;
|
||||
|
||||
/* Iterate symbol table starting from the position we were at last time */
|
||||
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
|
||||
{
|
||||
MachSymbol &sym = symtab[i];
|
||||
struct nlist &sym = symtab[i];
|
||||
/* Ignore the prepended underscore on all symbols, so +1 here */
|
||||
const char *sym_name = strtab + sym.n_un.n_strx + 1;
|
||||
Symbol *cur_sym;
|
||||
@@ -438,27 +429,17 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
|
||||
#endif
|
||||
}
|
||||
|
||||
const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
|
||||
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
|
||||
{
|
||||
uintptr_t baseAddr;
|
||||
|
||||
if (libPtr == NULL)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
DynLibInfo lib;
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_I386;
|
||||
const WORD PE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
|
||||
#else
|
||||
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_AMD64;
|
||||
const WORD PE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
|
||||
#endif
|
||||
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *pe;
|
||||
@@ -467,7 +448,7 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
|
||||
|
||||
if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
baseAddr = reinterpret_cast<uintptr_t>(info.AllocationBase);
|
||||
@@ -479,21 +460,23 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
|
||||
opt = &pe->OptionalHeader;
|
||||
|
||||
/* Check PE magic and signature */
|
||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != PE_NT_OPTIONAL_HDR_MAGIC)
|
||||
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check architecture */
|
||||
if (file->Machine != PE_FILE_MACHINE)
|
||||
/* Check architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->Machine != IMAGE_FILE_MACHINE_I386)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library */
|
||||
if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Finally, we can do this */
|
||||
@@ -501,73 +484,57 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef Elf32_Ehdr ElfHeader;
|
||||
typedef Elf32_Phdr ElfPHeader;
|
||||
const unsigned char ELF_CLASS = ELFCLASS32;
|
||||
const uint16_t ELF_MACHINE = EM_386;
|
||||
#else
|
||||
typedef Elf64_Ehdr ElfHeader;
|
||||
typedef Elf64_Phdr ElfPHeader;
|
||||
const unsigned char ELF_CLASS = ELFCLASS64;
|
||||
const uint16_t ELF_MACHINE = EM_X86_64;
|
||||
#endif
|
||||
|
||||
Dl_info info;
|
||||
ElfHeader *file;
|
||||
ElfPHeader *phdr;
|
||||
Elf32_Ehdr *file;
|
||||
Elf32_Phdr *phdr;
|
||||
uint16_t phdrCount;
|
||||
|
||||
if (!dladdr(libPtr, &info))
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!info.dli_fbase || !info.dli_fname)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is for our insane sanity checks :o */
|
||||
baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase);
|
||||
file = reinterpret_cast<ElfHeader *>(baseAddr);
|
||||
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
|
||||
|
||||
/* Check ELF magic */
|
||||
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF version */
|
||||
if (file->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Check ELF endianness */
|
||||
if (file->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ELF architecture */
|
||||
if (file->e_ident[EI_CLASS] != ELF_CLASS || file->e_machine != ELF_MACHINE)
|
||||
/* Check ELF architecture, which is 32-bit/x86 right now
|
||||
* Should change this for 64-bit if Valve gets their act together
|
||||
*/
|
||||
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library/shared object */
|
||||
if (file->e_type != ET_DYN)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
phdrCount = file->e_phnum;
|
||||
phdr = reinterpret_cast<ElfPHeader *>(baseAddr + file->e_phoff);
|
||||
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
|
||||
|
||||
for (uint16_t i = 0; i < phdrCount; i++)
|
||||
{
|
||||
ElfPHeader &hdr = phdr[i];
|
||||
Elf32_Phdr &hdr = phdr[i];
|
||||
|
||||
/* We only really care about the segment with executable code */
|
||||
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
|
||||
@@ -586,88 +553,60 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef struct mach_header MachHeader;
|
||||
typedef struct segment_command MachSegment;
|
||||
const uint32_t MACH_MAGIC = MH_MAGIC;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
|
||||
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_I386;
|
||||
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_I386_ALL;
|
||||
#else
|
||||
typedef struct mach_header_64 MachHeader;
|
||||
typedef struct segment_command_64 MachSegment;
|
||||
const uint32_t MACH_MAGIC = MH_MAGIC_64;
|
||||
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
|
||||
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_X86_64;
|
||||
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_X86_64_ALL;
|
||||
#endif
|
||||
|
||||
Dl_info info;
|
||||
MachHeader *file;
|
||||
MachSegment *seg;
|
||||
struct mach_header *file;
|
||||
struct segment_command *seg;
|
||||
uint32_t cmd_count;
|
||||
|
||||
if (!dladdr(libPtr, &info))
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!info.dli_fbase || !info.dli_fname)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is for our insane sanity checks :o */
|
||||
baseAddr = (uintptr_t)info.dli_fbase;
|
||||
file = (MachHeader *)baseAddr;
|
||||
file = (struct mach_header *)baseAddr;
|
||||
|
||||
/* Check Mach-O magic */
|
||||
if (file->magic != MACH_MAGIC)
|
||||
if (file->magic != MH_MAGIC)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check architecture */
|
||||
if (file->cputype != MACH_CPU_TYPE || file->cpusubtype != MACH_CPU_SUBTYPE)
|
||||
/* Check architecture (32-bit/x86) */
|
||||
if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For our purposes, this must be a dynamic library */
|
||||
if (file->filetype != MH_DYLIB)
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd_count = file->ncmds;
|
||||
seg = (MachSegment *)(baseAddr + sizeof(MachHeader));
|
||||
seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header));
|
||||
|
||||
/* Add up memory sizes of mapped segments */
|
||||
for (uint32_t i = 0; i < cmd_count; i++)
|
||||
{
|
||||
if (seg->cmd == MACH_LOADCMD_SEGMENT)
|
||||
if (seg->cmd == LC_SEGMENT)
|
||||
{
|
||||
lib.memorySize += seg->vmsize;
|
||||
}
|
||||
|
||||
seg = (MachSegment *)((uintptr_t)seg + seg->cmdsize);
|
||||
seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
|
||||
|
||||
LibraryInfoMap::Insert i = m_InfoMap.findForAdd(lib.baseAddress);
|
||||
if (i.found())
|
||||
{
|
||||
// We already loaded this binary before.
|
||||
return &i->value;
|
||||
}
|
||||
|
||||
// Keep a copy of the binary in its initial unpatched state for lookup.
|
||||
lib.originalCopy = std::make_unique<char[]>(lib.memorySize);
|
||||
memcpy(lib.originalCopy.get(), lib.baseAddress, lib.memorySize);
|
||||
m_InfoMap.add(i, lib.baseAddress, std::move(lib));
|
||||
|
||||
return &i->value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <IMemoryUtils.h>
|
||||
#include <am-hashmap.h>
|
||||
#include <memory>
|
||||
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||
#include <sh_vector.h>
|
||||
#include "sm_symtable.h"
|
||||
@@ -51,7 +49,6 @@ struct DynLibInfo
|
||||
{
|
||||
void *baseAddress;
|
||||
size_t memorySize;
|
||||
std::unique_ptr<char[]> originalCopy;
|
||||
};
|
||||
|
||||
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||
@@ -76,7 +73,7 @@ public: // IMemoryUtils
|
||||
void *FindPattern(const void *libPtr, const char *pattern, size_t len);
|
||||
void *ResolveSymbol(void *handle, const char *symbol);
|
||||
public:
|
||||
const DynLibInfo *GetLibraryInfo(const void *libPtr);
|
||||
bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
|
||||
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
|
||||
private:
|
||||
CVector<LibSymbolTable *> m_SymTables;
|
||||
@@ -86,8 +83,6 @@ private:
|
||||
SInt32 m_OSXMinor;
|
||||
#endif
|
||||
#endif
|
||||
typedef ke::HashMap<void *, DynLibInfo, ke::PointerPolicy<void> > LibraryInfoMap;
|
||||
LibraryInfoMap m_InfoMap;
|
||||
};
|
||||
|
||||
extern MemoryUtils g_MemUtils;
|
||||
|
||||
+17
-9
@@ -46,14 +46,16 @@ struct FakeNative
|
||||
FakeNative(const char *name, IPluginFunction *fun)
|
||||
: name(name),
|
||||
ctx(fun->GetParentContext()),
|
||||
call(fun)
|
||||
call(fun),
|
||||
gate(NULL)
|
||||
{
|
||||
}
|
||||
~FakeNative();
|
||||
|
||||
std::string name;
|
||||
ke::AString name;
|
||||
IPluginContext *ctx;
|
||||
IPluginFunction *call;
|
||||
ke::RefPtr<INativeCallback> wrapper;
|
||||
SPVM_NATIVE_FUNC gate;
|
||||
};
|
||||
|
||||
struct Native : public ke::Refcounted<Native>
|
||||
@@ -61,25 +63,31 @@ struct Native : public ke::Refcounted<Native>
|
||||
Native(CNativeOwner *owner, const sp_nativeinfo_t *native)
|
||||
: owner(owner),
|
||||
native(native),
|
||||
fake(nullptr)
|
||||
fake(NULL)
|
||||
{
|
||||
}
|
||||
Native(CNativeOwner *owner, std::unique_ptr<FakeNative>&& fake)
|
||||
Native(CNativeOwner *owner, FakeNative *fake)
|
||||
: owner(owner),
|
||||
native(nullptr),
|
||||
fake(std::move(fake))
|
||||
native(NULL),
|
||||
fake(fake)
|
||||
{
|
||||
}
|
||||
|
||||
CNativeOwner *owner;
|
||||
const sp_nativeinfo_t *native;
|
||||
std::unique_ptr<FakeNative> fake;
|
||||
ke::AutoPtr<FakeNative> fake;
|
||||
|
||||
SPVM_NATIVE_FUNC func() const
|
||||
{
|
||||
if (native)
|
||||
return native->func;
|
||||
return fake->gate;
|
||||
}
|
||||
const char *name() const
|
||||
{
|
||||
if (native)
|
||||
return native->name;
|
||||
return fake->name.c_str();
|
||||
return fake->name.chars();
|
||||
}
|
||||
|
||||
static inline bool matches(const char *name, const ke::RefPtr<Native> &entry)
|
||||
|
||||
@@ -273,10 +273,7 @@ NativeInvoker::Invoke(cell_t *result)
|
||||
/* Make the call if we can */
|
||||
if (ok)
|
||||
{
|
||||
if(native_->native)
|
||||
*result = native_->native->func(context_, _temp_params);
|
||||
else
|
||||
*result = native_->fake->wrapper->Invoke(context_, _temp_params);
|
||||
*result = native_->func()(context_, _temp_params);
|
||||
}
|
||||
|
||||
/* i should be equal to the last valid parameter + 1 */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
#include <amtl/am-autoptr.h>
|
||||
#include <amtl/am-refcounting.h>
|
||||
#include "Native.h"
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ void CNativeOwner::AddNatives(const sp_nativeinfo_t *natives)
|
||||
for (const sp_nativeinfo_t *native = natives; native->func && native->name; native++)
|
||||
g_ShareSys.AddNativeToCache(this, native);
|
||||
|
||||
m_natives.push_back(natives);
|
||||
m_natives.append(natives);
|
||||
}
|
||||
|
||||
void CNativeOwner::UnbindWeakRef(const WeakNative &ref)
|
||||
@@ -90,14 +90,14 @@ void CNativeOwner::DropEverything()
|
||||
}
|
||||
|
||||
/* Strip all of our natives from the cache */
|
||||
for (size_t i = 0; i < m_natives.size(); i++) {
|
||||
for (size_t i = 0; i < m_natives.length(); i++) {
|
||||
const sp_nativeinfo_t *natives = m_natives[i];
|
||||
for (const sp_nativeinfo_t *native = natives; native->func && native->name; native++)
|
||||
g_ShareSys.ClearNativeFromCache(this, native->name);
|
||||
}
|
||||
m_natives.clear();
|
||||
|
||||
for (size_t i = 0; i < m_fakes.size(); i++)
|
||||
for (size_t i = 0; i < m_fakes.length(); i++)
|
||||
g_ShareSys.ClearNativeFromCache(this, m_fakes[i]->name());
|
||||
m_fakes.clear();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <sp_vm_types.h>
|
||||
#include <sh_list.h>
|
||||
#include <am-linkedlist.h>
|
||||
#include <am-vector.h>
|
||||
#include "common_logic.h"
|
||||
#include "Native.h"
|
||||
@@ -79,8 +80,8 @@ protected:
|
||||
List<CPlugin *> m_Dependents;
|
||||
unsigned int m_nMarkSerial;
|
||||
List<WeakNative> m_WeakRefs;
|
||||
std::vector<const sp_nativeinfo_t *> m_natives;
|
||||
std::vector<ke::RefPtr<Native> > m_fakes;
|
||||
ke::Vector<const sp_nativeinfo_t *> m_natives;
|
||||
ke::Vector<ke::RefPtr<Native> > m_fakes;
|
||||
};
|
||||
|
||||
extern CNativeOwner g_CoreNatives;
|
||||
|
||||
+53
-70
@@ -45,6 +45,7 @@
|
||||
#include "Logger.h"
|
||||
#include "frame_tasks.h"
|
||||
#include <amtl/am-string.h>
|
||||
#include <amtl/am-linkedlist.h>
|
||||
#include <bridge/include/IVEngineServerBridge.h>
|
||||
#include <bridge/include/CoreProvider.h>
|
||||
|
||||
@@ -74,11 +75,11 @@ CPlugin::CPlugin(const char *file)
|
||||
m_serial = ++MySerial;
|
||||
m_errormsg[0] = '\0';
|
||||
m_DateTime[0] = '\0';
|
||||
ke::SafeStrcpy(m_filename, sizeof(m_filename), file);
|
||||
ke::SafeSprintf(m_filename, sizeof(m_filename), "%s", file);
|
||||
|
||||
memset(&m_info, 0, sizeof(m_info));
|
||||
|
||||
m_pPhrases.reset(g_Translator.CreatePhraseCollection());
|
||||
m_pPhrases = g_Translator.CreatePhraseCollection();
|
||||
}
|
||||
|
||||
CPlugin::~CPlugin()
|
||||
@@ -226,7 +227,7 @@ bool CPlugin::SetProperty(const char *prop, void *ptr)
|
||||
|
||||
IPluginRuntime *CPlugin::GetRuntime()
|
||||
{
|
||||
return m_pRuntime.get();
|
||||
return m_pRuntime;
|
||||
}
|
||||
|
||||
void CPlugin::EvictWithError(PluginStatus status, const char *error_fmt, ...)
|
||||
@@ -275,7 +276,7 @@ bool CPlugin::ReadInfo()
|
||||
sm_plugininfo_c_t *cinfo;
|
||||
cell_t local_addr;
|
||||
|
||||
auto update_field = [base](cell_t addr, std::string *dest) {
|
||||
auto update_field = [base](cell_t addr, ke::AString *dest) {
|
||||
const char* ptr;
|
||||
if (base->LocalToString(addr, (char **)&ptr) == SP_ERROR_NONE)
|
||||
*dest = ptr;
|
||||
@@ -482,7 +483,7 @@ bool CPlugin::TryCompile()
|
||||
g_pSM->BuildPath(Path_SM, fullpath, sizeof(fullpath), "plugins/%s", m_filename);
|
||||
|
||||
char loadmsg[255];
|
||||
m_pRuntime.reset(g_pSourcePawn2->LoadBinaryFromFile(fullpath, loadmsg, sizeof(loadmsg)));
|
||||
m_pRuntime = g_pSourcePawn2->LoadBinaryFromFile(fullpath, loadmsg, sizeof(loadmsg));
|
||||
if (!m_pRuntime) {
|
||||
EvictWithError(Plugin_BadLoad, "Unable to load plugin (%s)", loadmsg);
|
||||
return false;
|
||||
@@ -523,11 +524,11 @@ PluginType CPlugin::GetType()
|
||||
|
||||
const sm_plugininfo_t *CPlugin::GetPublicInfo()
|
||||
{
|
||||
m_info.author = info_author_.c_str();
|
||||
m_info.description = info_description_.c_str();
|
||||
m_info.name = info_name_.c_str();
|
||||
m_info.url = info_url_.c_str();
|
||||
m_info.version = info_version_.c_str();
|
||||
m_info.author = info_author_.chars();
|
||||
m_info.description = info_description_.chars();
|
||||
m_info.name = info_name_.chars();
|
||||
m_info.url = info_url_.chars();
|
||||
m_info.version = info_version_.chars();
|
||||
return &m_info;
|
||||
}
|
||||
|
||||
@@ -657,7 +658,7 @@ time_t CPlugin::GetFileTimeStamp()
|
||||
|
||||
IPhraseCollection *CPlugin::GetPhrases()
|
||||
{
|
||||
return m_pPhrases.get();
|
||||
return m_pPhrases;
|
||||
}
|
||||
|
||||
void CPlugin::DependencyDropped(CPlugin *pOwner)
|
||||
@@ -673,7 +674,7 @@ void CPlugin::DependencyDropped(CPlugin *pOwner)
|
||||
}
|
||||
|
||||
unsigned int unbound = 0;
|
||||
for (size_t i = 0; i < pOwner->m_fakes.size(); i++)
|
||||
for (size_t i = 0; i < pOwner->m_fakes.length(); i++)
|
||||
{
|
||||
ke::RefPtr<Native> entry(pOwner->m_fakes[i]);
|
||||
|
||||
@@ -772,13 +773,13 @@ bool CPlugin::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKEN
|
||||
if (!entry)
|
||||
return false;
|
||||
|
||||
m_fakes.push_back(entry);
|
||||
m_fakes.append(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPlugin::BindFakeNativesTo(CPlugin *other)
|
||||
{
|
||||
for (size_t i = 0; i < m_fakes.size(); i++)
|
||||
for (size_t i = 0; i < m_fakes.length(); i++)
|
||||
g_ShareSys.BindNativeToPlugin(other, m_fakes[i]);
|
||||
}
|
||||
|
||||
@@ -789,7 +790,7 @@ void CPlugin::BindFakeNativesTo(CPlugin *other)
|
||||
CPluginManager::CPluginIterator::CPluginIterator(ReentrantList<CPlugin *>& in)
|
||||
{
|
||||
for (PluginIter iter(in); !iter.done(); iter.next())
|
||||
mylist.push_back(*iter);
|
||||
mylist.append(*iter);
|
||||
current = mylist.begin();
|
||||
g_PluginSys.AddPluginsListener(this);
|
||||
}
|
||||
@@ -846,7 +847,11 @@ CPluginManager::~CPluginManager()
|
||||
|
||||
void CPluginManager::Shutdown()
|
||||
{
|
||||
UnloadAll();
|
||||
List<CPlugin *>::iterator iter;
|
||||
|
||||
for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
|
||||
UnloadPlugin(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
void CPluginManager::LoadAll(const char *config_path, const char *plugins_path)
|
||||
@@ -900,7 +905,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
if (localpath == NULL)
|
||||
{
|
||||
/* If no path yet, don't add a former slash */
|
||||
ke::SafeStrcpy(new_local, sizeof(new_local), dir->GetEntryName());
|
||||
ke::SafeSprintf(new_local, sizeof(new_local), "%s", dir->GetEntryName());
|
||||
} else {
|
||||
libsys->PathFormat(new_local, sizeof(new_local), "%s/%s", localpath, dir->GetEntryName());
|
||||
}
|
||||
@@ -915,7 +920,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
|
||||
char plugin[PLATFORM_MAX_PATH];
|
||||
if (localpath == NULL)
|
||||
{
|
||||
ke::SafeStrcpy(plugin, sizeof(plugin), name);
|
||||
ke::SafeSprintf(plugin, sizeof(plugin), "%s", name);
|
||||
} else {
|
||||
libsys->PathFormat(plugin, sizeof(plugin), "%s/%s", localpath, name);
|
||||
}
|
||||
@@ -974,20 +979,6 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
|
||||
LoadRes res;
|
||||
|
||||
*wasloaded = false;
|
||||
|
||||
if (strstr(path, "..") != NULL)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, "Cannot load plugins outside the \"plugins\" folder");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *ext = libsys->GetFileExtension(path);
|
||||
if (!ext || strcmp(ext, "smx") != 0)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, "Plugin files must have the \".smx\" file extension");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((res=LoadPlugin(&pl, path, true, PluginType_MapUpdated)) == LoadRes_Failure)
|
||||
{
|
||||
ke::SafeStrcpy(error, maxlength, pl->GetErrorMsg());
|
||||
@@ -1003,9 +994,9 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
|
||||
|
||||
if (res == LoadRes_NeverLoad) {
|
||||
if (m_LoadingLocked)
|
||||
ke::SafeStrcpy(error, maxlength, "There is a global plugin loading lock in effect");
|
||||
ke::SafeSprintf(error, maxlength, "There is a global plugin loading lock in effect");
|
||||
else
|
||||
ke::SafeStrcpy(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
|
||||
ke::SafeSprintf(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1042,7 +1033,7 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
|
||||
|
||||
void CPluginManager::AddPlugin(CPlugin *pPlugin)
|
||||
{
|
||||
m_plugins.push_back(pPlugin);
|
||||
m_plugins.append(pPlugin);
|
||||
m_LoadLookup.insert(pPlugin->GetFilename(), pPlugin);
|
||||
|
||||
pPlugin->SetRegistered();
|
||||
@@ -1174,7 +1165,7 @@ bool CPlugin::ForEachExtVar(const ExtVarCallback& callback)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPlugin::ForEachLibrary(ke::Function<void(const char *)> callback)
|
||||
void CPlugin::ForEachLibrary(ke::Lambda<void(const char *)> callback)
|
||||
{
|
||||
for (auto iter = m_Libraries.begin(); iter != m_Libraries.end(); iter++)
|
||||
callback((*iter).c_str());
|
||||
@@ -1186,7 +1177,7 @@ void CPlugin::AddRequiredLib(const char *name)
|
||||
m_RequiredLibs.push_back(name);
|
||||
}
|
||||
|
||||
bool CPlugin::ForEachRequiredLib(ke::Function<bool(const char *)> callback)
|
||||
bool CPlugin::ForEachRequiredLib(ke::Lambda<bool(const char *)> callback)
|
||||
{
|
||||
for (auto iter = m_RequiredLibs.begin(); iter != m_RequiredLibs.end(); iter++) {
|
||||
if (!callback((*iter).c_str()))
|
||||
@@ -1220,7 +1211,7 @@ void CPluginManager::LoadExtensions(CPlugin *pPlugin)
|
||||
}
|
||||
return true;
|
||||
};
|
||||
pPlugin->ForEachExtVar(std::move(callback));
|
||||
pPlugin->ForEachExtVar(ke::Move(callback));
|
||||
}
|
||||
|
||||
bool CPluginManager::RequireExtensions(CPlugin *pPlugin)
|
||||
@@ -1256,7 +1247,7 @@ bool CPluginManager::RequireExtensions(CPlugin *pPlugin)
|
||||
return true;
|
||||
};
|
||||
|
||||
return pPlugin->ForEachExtVar(std::move(callback));
|
||||
return pPlugin->ForEachExtVar(ke::Move(callback));
|
||||
}
|
||||
|
||||
CPlugin *CPluginManager::CompileAndPrep(const char *path)
|
||||
@@ -1286,7 +1277,7 @@ bool CPluginManager::MalwareCheckPass(CPlugin *pPlugin)
|
||||
unsigned char *pCodeHash = pPlugin->GetRuntime()->GetCodeHash();
|
||||
|
||||
char codeHashBuf[40];
|
||||
ke::SafeStrcpy(codeHashBuf, sizeof(codeHashBuf), "plugin_");
|
||||
ke::SafeSprintf(codeHashBuf, 40, "plugin_");
|
||||
for (int i = 0; i < 16; i++)
|
||||
ke::SafeSprintf(codeHashBuf + 7 + (i * 2), 3, "%02x", pCodeHash[i]);
|
||||
|
||||
@@ -1499,9 +1490,6 @@ void CPluginManager::Purge(CPlugin *plugin)
|
||||
if (plugin->GetStatus() == Plugin_Running)
|
||||
plugin->Call_OnPluginEnd();
|
||||
|
||||
m_pOnNotifyPluginUnloaded->PushCell(plugin->GetMyHandle());
|
||||
m_pOnNotifyPluginUnloaded->Execute(NULL);
|
||||
|
||||
// Notify listeners of unloading.
|
||||
if (plugin->EnteredSecondPass()) {
|
||||
for (ListenerIter iter(m_listeners); !iter.done(); iter.next())
|
||||
@@ -1548,12 +1536,12 @@ CPlugin *CPluginManager::GetPluginByCtx(const sp_context_t *ctx)
|
||||
|
||||
unsigned int CPluginManager::GetPluginCount()
|
||||
{
|
||||
return m_plugins.size();
|
||||
return m_plugins.length();
|
||||
}
|
||||
|
||||
void CPluginManager::AddPluginsListener(IPluginsListener *listener)
|
||||
{
|
||||
m_listeners.push_back(listener);
|
||||
m_listeners.append(listener);
|
||||
}
|
||||
|
||||
void CPluginManager::RemovePluginsListener(IPluginsListener *listener)
|
||||
@@ -1590,7 +1578,6 @@ void CPluginManager::OnSourceModAllInitialized()
|
||||
|
||||
m_pOnLibraryAdded = forwardsys->CreateForward("OnLibraryAdded", ET_Ignore, 1, NULL, Param_String);
|
||||
m_pOnLibraryRemoved = forwardsys->CreateForward("OnLibraryRemoved", ET_Ignore, 1, NULL, Param_String);
|
||||
m_pOnNotifyPluginUnloaded = forwardsys->CreateForward("OnNotifyPluginUnloaded", ET_Ignore, 1, NULL, Param_Cell);
|
||||
}
|
||||
|
||||
void CPluginManager::OnSourceModShutdown()
|
||||
@@ -1605,7 +1592,6 @@ void CPluginManager::OnSourceModShutdown()
|
||||
|
||||
forwardsys->ReleaseForward(m_pOnLibraryAdded);
|
||||
forwardsys->ReleaseForward(m_pOnLibraryRemoved);
|
||||
forwardsys->ReleaseForward(m_pOnNotifyPluginUnloaded);
|
||||
}
|
||||
|
||||
ConfigResult CPluginManager::OnSourceModConfigChanged(const char *key,
|
||||
@@ -1621,7 +1607,7 @@ ConfigResult CPluginManager::OnSourceModConfigChanged(const char *key,
|
||||
} else if (strcasecmp(value, "no") == 0) {
|
||||
m_bBlockBadPlugins = false;
|
||||
} else {
|
||||
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
|
||||
return ConfigResult_Reject;
|
||||
}
|
||||
return ConfigResult_Accept;
|
||||
@@ -1715,9 +1701,6 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
|
||||
char buffer[256];
|
||||
unsigned int id = 1;
|
||||
int plnum = GetPluginCount();
|
||||
char plstr[10];
|
||||
ke::SafeSprintf(plstr, sizeof(plstr), "%d", plnum);
|
||||
int plpadding = strlen(plstr);
|
||||
|
||||
if (!plnum)
|
||||
{
|
||||
@@ -1726,10 +1709,10 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
|
||||
}
|
||||
else
|
||||
{
|
||||
rootmenu->ConsolePrint("[SM] Listing %d plugin%s:", plnum, (plnum > 1) ? "s" : "");
|
||||
rootmenu->ConsolePrint("[SM] Listing %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : "");
|
||||
}
|
||||
|
||||
std::list<CPlugin *> fail_list;
|
||||
ke::LinkedList<CPlugin *> fail_list;
|
||||
|
||||
for (PluginIter iter(m_plugins); !iter.done(); iter.next(), id++) {
|
||||
CPlugin *pl = (*iter);
|
||||
@@ -1738,19 +1721,19 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
|
||||
const sm_plugininfo_t *info = pl->GetPublicInfo();
|
||||
if (pl->GetStatus() != Plugin_Running && !pl->IsSilentlyFailed())
|
||||
{
|
||||
len += ke::SafeSprintf(buffer, sizeof(buffer), " %0*d <%s>", plpadding, id, GetStatusText(pl->GetDisplayStatus()));
|
||||
len += ke::SafeSprintf(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetDisplayStatus()));
|
||||
|
||||
/* Plugin has failed to load. */
|
||||
fail_list.push_back(pl);
|
||||
fail_list.append(pl);
|
||||
}
|
||||
else
|
||||
{
|
||||
len += ke::SafeSprintf(buffer, sizeof(buffer), " %0*d", plpadding, id);
|
||||
len += ke::SafeSprintf(buffer, sizeof(buffer), " %02d", id);
|
||||
}
|
||||
if (pl->GetStatus() < Plugin_Created || pl->GetStatus() == Plugin_Evicted)
|
||||
{
|
||||
if (pl->IsSilentlyFailed())
|
||||
len += ke::SafeStrcpy(&buffer[len], sizeof(buffer)-len, " Disabled:");
|
||||
len += ke::SafeSprintf(&buffer[len], sizeof(buffer)-len, " Disabled:");
|
||||
len += ke::SafeSprintf(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
if (IS_STR_FILLED(info->version))
|
||||
{
|
||||
@@ -1859,11 +1842,11 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
|
||||
if (pl->GetStatus() < Plugin_Created)
|
||||
{
|
||||
const sm_plugininfo_t *info = pl->GetPublicInfo();
|
||||
ke::SafeStrcpy(name, sizeof(name), (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
ke::SafeSprintf(name, sizeof(name), (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
|
||||
}
|
||||
else
|
||||
{
|
||||
ke::SafeStrcpy(name, sizeof(name), pl->GetFilename());
|
||||
ke::SafeSprintf(name, sizeof(name), "%s", pl->GetFilename());
|
||||
}
|
||||
|
||||
if (UnloadPlugin(pl))
|
||||
@@ -1975,11 +1958,11 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
|
||||
if (IPluginRuntime *runtime = pl->GetRuntime()) {
|
||||
unsigned char *pCodeHash = runtime->GetCodeHash();
|
||||
unsigned char *pDataHash = runtime->GetDataHash();
|
||||
|
||||
|
||||
char combinedHash[33];
|
||||
for (int i = 0; i < 16; i++)
|
||||
ke::SafeSprintf(combinedHash + (i * 2), 3, "%02x", pCodeHash[i] ^ pDataHash[i]);
|
||||
|
||||
|
||||
rootmenu->ConsolePrint(" Hash: %s", combinedHash);
|
||||
}
|
||||
} else {
|
||||
@@ -2047,8 +2030,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
|
||||
//the unload/reload attempt next frame will print a message
|
||||
case PluginState::WaitingToUnload:
|
||||
case PluginState::WaitingToUnloadAndReload:
|
||||
rootmenu->ConsolePrint("[SM] Plugin %s will be reloaded on the next frame.", name);
|
||||
break;
|
||||
return;
|
||||
|
||||
default:
|
||||
rootmenu->ConsolePrint("[SM] Failed to reload plugin %s.", name);
|
||||
@@ -2078,7 +2060,7 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl, bool print)
|
||||
if (state == PluginState::WaitingToUnloadAndReload)
|
||||
return false;
|
||||
|
||||
std::string filename(pl->GetFilename());
|
||||
ke::AString filename(pl->GetFilename());
|
||||
PluginType ptype = pl->GetType();
|
||||
|
||||
int id = 1;
|
||||
@@ -2093,13 +2075,13 @@ bool CPluginManager::ReloadPlugin(CPlugin *pl, bool print)
|
||||
{
|
||||
pl->SetWaitingToUnload(true);
|
||||
ScheduleTaskForNextFrame([this, id, filename, ptype, print]() -> void {
|
||||
ReloadPluginImpl(id, filename.c_str(), ptype, print);
|
||||
ReloadPluginImpl(id, filename.chars(), ptype, print);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ReloadPluginImpl(id, filename.c_str(), ptype, false);
|
||||
ReloadPluginImpl(id, filename.chars(), ptype, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2108,7 +2090,7 @@ void CPluginManager::ReloadPluginImpl(int id, const char filename[], PluginType
|
||||
char error[128];
|
||||
bool wasloaded;
|
||||
IPlugin *newpl = LoadPlugin(filename, true, ptype, error, sizeof(error), &wasloaded);
|
||||
if (!newpl)
|
||||
if (!newpl)
|
||||
{
|
||||
rootmenu->ConsolePrint("[SM] Plugin %s failed to reload: %s.", filename, error);
|
||||
return;
|
||||
@@ -2223,6 +2205,7 @@ void CPluginManager::UnloadAll()
|
||||
int CPluginManager::GetOrderOfPlugin(IPlugin *pl)
|
||||
{
|
||||
int id = 1;
|
||||
List<CPlugin *>::iterator iter;
|
||||
|
||||
for (PluginIter iter(m_plugins); !iter.done(); iter.next()) {
|
||||
if ((*iter) == pl)
|
||||
@@ -2287,7 +2270,7 @@ void CPluginManager::FreePluginList(const CVector<SMPlugin *> *list)
|
||||
delete const_cast<CVector<SMPlugin *> *>(list);
|
||||
}
|
||||
|
||||
void CPluginManager::ForEachPlugin(ke::Function<void(CPlugin *)> callback)
|
||||
void CPluginManager::ForEachPlugin(ke::Lambda<void(CPlugin *)> callback)
|
||||
{
|
||||
for (PluginIter iter(m_plugins); !iter.done(); iter.next())
|
||||
callback(*iter);
|
||||
@@ -2365,7 +2348,7 @@ public:
|
||||
{
|
||||
ke::RefPtr<PluginsListenerV1Wrapper> wrapper = new PluginsListenerV1Wrapper(listener);
|
||||
|
||||
v1_wrappers_.push_back(wrapper);
|
||||
v1_wrappers_.append(wrapper);
|
||||
g_PluginSys.AddPluginsListener(wrapper);
|
||||
}
|
||||
|
||||
@@ -2408,4 +2391,4 @@ static OldPluginAPI sOldPluginAPI;
|
||||
IPluginManager *CPluginManager::GetOldAPI()
|
||||
{
|
||||
return &sOldPluginAPI;
|
||||
}
|
||||
}
|
||||
+46
-27
@@ -32,12 +32,9 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
||||
#define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <IPluginSys.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <IForwardSys.h>
|
||||
@@ -58,6 +55,9 @@
|
||||
#include <bridge/include/IScriptManager.h>
|
||||
#include <am-function.h>
|
||||
#include <ReentrantList.h>
|
||||
#ifdef PLATFORM_APPLE
|
||||
#include <cctype>
|
||||
#endif
|
||||
|
||||
class CPlayer;
|
||||
|
||||
@@ -132,10 +132,10 @@ public:
|
||||
bool required;
|
||||
};
|
||||
|
||||
typedef ke::Function<bool(const sp_pubvar_t *, const ExtVar& ext)> ExtVarCallback;
|
||||
typedef ke::Lambda<bool(const sp_pubvar_t *, const ExtVar& ext)> ExtVarCallback;
|
||||
bool ForEachExtVar(const ExtVarCallback& callback);
|
||||
|
||||
void ForEachLibrary(ke::Function<void(const char *)> callback);
|
||||
void ForEachLibrary(ke::Lambda<void(const char *)> callback);
|
||||
public:
|
||||
/**
|
||||
* Creates a plugin object with default values.
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
}
|
||||
|
||||
void AddRequiredLib(const char *name);
|
||||
bool ForEachRequiredLib(ke::Function<bool(const char *)> callback);
|
||||
bool ForEachRequiredLib(ke::Lambda<bool(const char *)> callback);
|
||||
|
||||
bool HasMissingFakeNatives() const {
|
||||
return m_FakeNativesMissing;
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
return m_LibraryMissing;
|
||||
}
|
||||
bool HasFakeNatives() const {
|
||||
return m_fakes.size() > 0;
|
||||
return m_fakes.length() > 0;
|
||||
}
|
||||
|
||||
// True if we got far enough into the second pass to call OnPluginLoaded
|
||||
@@ -270,8 +270,8 @@ private:
|
||||
char m_errormsg[256];
|
||||
|
||||
// Internal properties that must by reset if the runtime is evicted.
|
||||
std::unique_ptr<IPluginRuntime> m_pRuntime;
|
||||
std::unique_ptr<CPhraseCollection> m_pPhrases;
|
||||
ke::AutoPtr<IPluginRuntime> m_pRuntime;
|
||||
ke::AutoPtr<CPhraseCollection> m_pPhrases;
|
||||
IPluginContext *m_pContext;
|
||||
sp_pubvar_t *m_MaxClientsVar;
|
||||
StringHashMap<void *> m_Props;
|
||||
@@ -289,11 +289,11 @@ private:
|
||||
|
||||
// Cached.
|
||||
sm_plugininfo_t m_info;
|
||||
std::string info_name_;
|
||||
std::string info_author_;
|
||||
std::string info_description_;
|
||||
std::string info_version_;
|
||||
std::string info_url_;
|
||||
ke::AString info_name_;
|
||||
ke::AString info_author_;
|
||||
ke::AString info_description_;
|
||||
ke::AString info_version_;
|
||||
ke::AString info_url_;
|
||||
};
|
||||
|
||||
class CPluginManager :
|
||||
@@ -320,8 +320,8 @@ public:
|
||||
void Release();
|
||||
void OnPluginDestroyed(IPlugin *plugin) override;
|
||||
private:
|
||||
std::list<CPlugin *> mylist;
|
||||
std::list<CPlugin *>::iterator current;
|
||||
ke::LinkedList<CPlugin *> mylist;
|
||||
ke::LinkedList<CPlugin *>::iterator current;
|
||||
};
|
||||
friend class CPluginManager::CPluginIterator;
|
||||
public: //IScriptManager
|
||||
@@ -435,7 +435,7 @@ public:
|
||||
|
||||
void _SetPauseState(CPlugin *pPlugin, bool pause);
|
||||
|
||||
void ForEachPlugin(ke::Function<void(CPlugin *)> callback);
|
||||
void ForEachPlugin(ke::Lambda<void(CPlugin *)> callback);
|
||||
private:
|
||||
LoadRes LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type);
|
||||
|
||||
@@ -476,7 +476,7 @@ private:
|
||||
private:
|
||||
ReentrantList<IPluginsListener *> m_listeners;
|
||||
ReentrantList<CPlugin *> m_plugins;
|
||||
std::list<CPluginIterator *> m_iterators;
|
||||
ke::LinkedList<CPluginIterator *> m_iterators;
|
||||
|
||||
typedef decltype(m_listeners)::iterator ListenerIter;
|
||||
typedef decltype(m_plugins)::iterator PluginIter;
|
||||
@@ -487,8 +487,17 @@ private:
|
||||
{
|
||||
/* For windows & mac, we convert the path to lower-case in order to avoid duplicate plugin loading */
|
||||
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
|
||||
std::string lower = ke::Lowercase(key.c_str());
|
||||
return detail::CharsAndLength(lower.c_str()).hash();
|
||||
const char *original = key.chars();
|
||||
char *copy = strdup(original);
|
||||
|
||||
for (size_t i = 0; copy[i]; ++i)
|
||||
{
|
||||
copy[i] = tolower(copy[i]);
|
||||
}
|
||||
|
||||
uint32_t hash = detail::CharsAndLength(copy).hash();
|
||||
free(copy);
|
||||
return hash;
|
||||
#else
|
||||
return key.hash();
|
||||
#endif
|
||||
@@ -496,14 +505,25 @@ private:
|
||||
|
||||
static inline bool matches(const char *file, const CPlugin *plugin)
|
||||
{
|
||||
const char *pluginFileChars = const_cast<CPlugin*>(plugin)->GetFilename();
|
||||
const char *pluginFile = const_cast<CPlugin*>(plugin)->GetFilename();
|
||||
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
|
||||
std::string pluginFile = ke::Lowercase(pluginFileChars);
|
||||
std::string input = ke::Lowercase(file);
|
||||
size_t fileLen = strlen(file);
|
||||
if (fileLen != strlen(pluginFile))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return pluginFile == input;
|
||||
for (size_t i = 0; i < fileLen; ++i)
|
||||
{
|
||||
if (tolower(file[i]) != tolower(pluginFile[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return strcmp(pluginFileChars, file) == 0;
|
||||
return strcmp(pluginFile, file) == 0;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -523,7 +543,6 @@ private:
|
||||
// Forwards
|
||||
IForward *m_pOnLibraryAdded;
|
||||
IForward *m_pOnLibraryRemoved;
|
||||
IForward *m_pOnNotifyPluginUnloaded;
|
||||
};
|
||||
|
||||
extern CPluginManager g_PluginSys;
|
||||
|
||||
@@ -52,7 +52,7 @@ ProfileToolManager::OnSourceModShutdown()
|
||||
IProfilingTool *
|
||||
ProfileToolManager::FindToolByName(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < tools_.size(); i++) {
|
||||
for (size_t i = 0; i < tools_.length(); i++) {
|
||||
if (strcmp(tools_[i]->Name(), name) == 0)
|
||||
return tools_[i];
|
||||
}
|
||||
@@ -97,7 +97,7 @@ ProfileToolManager::StartFromConsole(IProfilingTool *tool)
|
||||
void
|
||||
ProfileToolManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *args)
|
||||
{
|
||||
if (tools_.size() == 0) {
|
||||
if (tools_.length() == 0) {
|
||||
rootmenu->ConsolePrint("No profiling tools are enabled.");
|
||||
return;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ ProfileToolManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs
|
||||
|
||||
if (strcmp(cmdname, "list") == 0) {
|
||||
rootmenu->ConsolePrint("Profiling tools:");
|
||||
for (size_t i = 0; i < tools_.size(); i++) {
|
||||
for (size_t i = 0; i < tools_.length(); i++) {
|
||||
rootmenu->DrawGenericOption(tools_[i]->Name(), tools_[i]->Description());
|
||||
}
|
||||
return;
|
||||
@@ -135,7 +135,7 @@ ProfileToolManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs
|
||||
if (strcmp(cmdname, "start") == 0) {
|
||||
if (!default_) {
|
||||
default_ = FindToolByName("vprof");
|
||||
if (!default_ && tools_.size() > 0)
|
||||
if (!default_ && tools_.length() > 0)
|
||||
default_ = tools_[0];
|
||||
if (!default_) {
|
||||
rootmenu->ConsolePrint("Could not find any profiler to use.");
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *args) override;
|
||||
|
||||
void RegisterTool(IProfilingTool *tool) {
|
||||
tools_.push_back(tool);
|
||||
tools_.append(tool);
|
||||
}
|
||||
|
||||
bool IsActive() const {
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
void StartFromConsole(IProfilingTool *tool);
|
||||
|
||||
private:
|
||||
std::vector<IProfilingTool *> tools_;
|
||||
ke::Vector<IProfilingTool *> tools_;
|
||||
IProfilingTool *active_;
|
||||
IProfilingTool *default_;
|
||||
bool enabled_;
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2017 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#include "PseudoAddrManager.h"
|
||||
#ifdef PLATFORM_APPLE
|
||||
#include <mach/mach.h>
|
||||
#include <mach/vm_region.h>
|
||||
#endif
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
PseudoAddressManager::PseudoAddressManager() : m_NumEntries(0)
|
||||
{
|
||||
}
|
||||
|
||||
// A pseudo address consists of a table index in the upper 6 bits and an offset in the
|
||||
// lower 26 bits. The table consists of memory allocation base addresses.
|
||||
void *PseudoAddressManager::FromPseudoAddress(uint32_t paddr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
uint8_t index = paddr >> PSEUDO_OFFSET_BITS;
|
||||
uint32_t offset = paddr & ((1 << PSEUDO_OFFSET_BITS) - 1);
|
||||
|
||||
if (index >= m_NumEntries)
|
||||
return nullptr;
|
||||
|
||||
return reinterpret_cast<void *>(uintptr_t(m_AllocBases[index]) + offset);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t PseudoAddressManager::ToPseudoAddress(void *addr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
uint8_t index = 0;
|
||||
uint32_t offset = 0;
|
||||
bool hasEntry = false;
|
||||
void *base = GetAllocationBase(addr);
|
||||
|
||||
if (base) {
|
||||
for (int i = 0; i < m_NumEntries; i++) {
|
||||
if (m_AllocBases[i] == base) {
|
||||
index = i;
|
||||
hasEntry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hasEntry) {
|
||||
index = m_NumEntries;
|
||||
if (m_NumEntries < SM_ARRAYSIZE(m_AllocBases))
|
||||
m_AllocBases[m_NumEntries++] = base;
|
||||
else
|
||||
return 0; // Table is full
|
||||
}
|
||||
|
||||
ptrdiff_t diff = uintptr_t(addr) - uintptr_t(base);
|
||||
|
||||
// Ensure difference fits in 26 bits
|
||||
if (diff > (UINT32_MAX >> PSEUDO_INDEX_BITS))
|
||||
return 0;
|
||||
|
||||
return (index << PSEUDO_OFFSET_BITS) | diff;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *PseudoAddressManager::GetAllocationBase(void *ptr)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
if (!VirtualQuery(ptr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
|
||||
return nullptr;
|
||||
return info.AllocationBase;
|
||||
|
||||
#elif defined PLATFORM_APPLE
|
||||
|
||||
#ifdef PLATFORM_X86
|
||||
typedef vm_region_info_t mach_vm_region_info_t;
|
||||
typedef vm_region_basic_info_data_t mach_vm_region_basic_info_data_t;
|
||||
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO;
|
||||
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT;
|
||||
#define mach_vm_region vm_region
|
||||
#elif defined PLATFORM_X64
|
||||
typedef vm_region_info_64_t mach_vm_region_info_t ;
|
||||
typedef vm_region_basic_info_data_64_t mach_vm_region_basic_info_data_t;
|
||||
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO_64;
|
||||
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
#define mach_vm_region vm_region_64
|
||||
#endif
|
||||
vm_size_t size;
|
||||
vm_address_t vmaddr = reinterpret_cast<vm_address_t>(ptr);
|
||||
mach_vm_region_basic_info_data_t info;
|
||||
memory_object_name_t obj;
|
||||
vm_region_flavor_t flavor = MACH_VM_REGION_BASIC_INFO;
|
||||
mach_msg_type_number_t count = MACH_VM_REGION_BASIC_INFO_COUNT;
|
||||
|
||||
kern_return_t kr = mach_vm_region(mach_task_self(), &vmaddr, &size, flavor,
|
||||
reinterpret_cast<mach_vm_region_info_t>(&info),
|
||||
&count, &obj);
|
||||
|
||||
if (kr != KERN_SUCCESS)
|
||||
return nullptr;
|
||||
|
||||
return reinterpret_cast<void *>(vmaddr);
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
|
||||
|
||||
// Format:
|
||||
// lower upper prot stuff path
|
||||
// 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat
|
||||
FILE *fp = fopen("/proc/self/maps", "r");
|
||||
if (fp) {
|
||||
uintptr_t lower, upper;
|
||||
while (fscanf(fp, "%" PRIxPTR "-%" PRIxPTR, &lower, &upper) != EOF) {
|
||||
if (addr >= lower && addr <= upper) {
|
||||
fclose(fp);
|
||||
return reinterpret_cast<void *>(lower);
|
||||
}
|
||||
|
||||
// Read to end of line
|
||||
int c;
|
||||
while ((c = fgetc(fp)) != '\n') {
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
if (c == EOF)
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2017 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||
#define _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||
|
||||
#include "common_logic.h"
|
||||
|
||||
class PseudoAddressManager
|
||||
{
|
||||
public:
|
||||
PseudoAddressManager();
|
||||
public:
|
||||
void *FromPseudoAddress(uint32_t paddr);
|
||||
uint32_t ToPseudoAddress(void *addr);
|
||||
private:
|
||||
void *GetAllocationBase(void *ptr);
|
||||
private:
|
||||
static constexpr uint8_t PSEUDO_OFFSET_BITS = 26;
|
||||
static constexpr uint8_t PSEUDO_INDEX_BITS = sizeof(uint32_t) * 8 - PSEUDO_OFFSET_BITS;
|
||||
void *m_AllocBases[1 << PSEUDO_INDEX_BITS];
|
||||
uint8_t m_NumEntries;
|
||||
};
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
|
||||
@@ -166,7 +166,7 @@ void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
|
||||
{
|
||||
buffer[len++] = ' ';
|
||||
}
|
||||
len += ke::SafeSprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
|
||||
len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
|
||||
ConsolePrint("%s", buffer);
|
||||
}
|
||||
}
|
||||
@@ -221,15 +221,11 @@ void RootConsoleMenu::OnRootConsoleCommand(const char *cmdname, const ICommandAr
|
||||
ConsolePrint(" Fyren");
|
||||
ConsolePrint(" Nicholas \"psychonic\" Hastings");
|
||||
ConsolePrint(" Asher \"asherkin\" Baker");
|
||||
ConsolePrint(" Ruben \"Dr!fter\" Gonzalez");
|
||||
ConsolePrint(" Josh \"KyleS\" Allard");
|
||||
ConsolePrint(" Michael \"Headline\" Flaherty");
|
||||
ConsolePrint(" Jannik \"Peace-Maker\" Hartung");
|
||||
ConsolePrint(" Borja \"faluco\" Ferrer");
|
||||
ConsolePrint(" Pavol \"PM OnoTo\" Marko");
|
||||
ConsolePrint(" Special thanks to Liam, ferret, and Mani");
|
||||
ConsolePrint(" Special thanks to Viper and SteamFriends");
|
||||
ConsolePrint(" https://www.sourcemod.net/");
|
||||
ConsolePrint(" http://www.sourcemod.net/");
|
||||
}
|
||||
else if (strcmp(cmdname, "version") == 0)
|
||||
{
|
||||
@@ -260,7 +256,7 @@ static bool sm_dump_handles(int client, const ICommandArgs *args)
|
||||
auto write_handles_to_game = [] (const char *str) -> void
|
||||
{
|
||||
char buffer[1024];
|
||||
size_t len = ke::SafeStrcpy(buffer, sizeof(buffer)-2, str);
|
||||
size_t len = ke::SafeSprintf(buffer, sizeof(buffer)-2, "%s", str);
|
||||
|
||||
buffer[len] = '\n';
|
||||
buffer[len+1] = '\0';
|
||||
|
||||
+23
-42
@@ -29,16 +29,13 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ShareSys.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include <ILibrarySys.h>
|
||||
#include "common_logic.h"
|
||||
#include "PluginSys.h"
|
||||
#include "HandleSys.h"
|
||||
#include <assert.h>
|
||||
|
||||
using namespace ke;
|
||||
|
||||
@@ -165,16 +162,18 @@ bool ShareSystem::RequestInterface(const char *iface_name,
|
||||
SMInterface **pIface)
|
||||
{
|
||||
/* See if the interface exists */
|
||||
List<IfaceInfo>::iterator iter;
|
||||
SMInterface *iface;
|
||||
IExtension *iface_owner = nullptr;
|
||||
IExtension *iface_owner;
|
||||
bool found = false;
|
||||
for (auto iter = m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
|
||||
for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
|
||||
{
|
||||
IfaceInfo &info = *iter;
|
||||
IfaceInfo &info = (*iter);
|
||||
iface = info.iface;
|
||||
if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
|
||||
{
|
||||
if (iface->GetInterfaceVersion() == iface_vers || iface->IsVersionCompatible(iface_vers))
|
||||
if (iface->GetInterfaceVersion() == iface_vers
|
||||
|| iface->IsVersionCompatible(iface_vers))
|
||||
{
|
||||
iface_owner = info.owner;
|
||||
found = true;
|
||||
@@ -364,11 +363,11 @@ void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, const sp_native_t *native
|
||||
}
|
||||
}
|
||||
|
||||
auto rt = pPlugin->GetRuntime();
|
||||
if (pEntry->fake)
|
||||
rt->UpdateNativeBindingObject(index, pEntry->fake->wrapper, flags, nullptr);
|
||||
else
|
||||
rt->UpdateNativeBinding(index, pEntry->native->func, flags, nullptr);
|
||||
pPlugin->GetRuntime()->UpdateNativeBinding(
|
||||
index,
|
||||
pEntry->func(),
|
||||
flags,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
AlreadyRefed<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
|
||||
@@ -382,6 +381,11 @@ AlreadyRefed<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const s
|
||||
return entry.forget();
|
||||
}
|
||||
|
||||
FakeNative::~FakeNative()
|
||||
{
|
||||
g_pSourcePawn2->DestroyFakeNative(gate);
|
||||
}
|
||||
|
||||
void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
|
||||
{
|
||||
NativeCache::Result r = m_NtvCache.find(name);
|
||||
@@ -398,44 +402,21 @@ void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
|
||||
m_NtvCache.remove(r);
|
||||
}
|
||||
|
||||
class DynamicNative final : public INativeCallback
|
||||
{
|
||||
public:
|
||||
DynamicNative(SPVM_FAKENATIVE_FUNC callback, void* data)
|
||||
: callback_(callback),
|
||||
data_(data)
|
||||
{}
|
||||
|
||||
void AddRef() override {
|
||||
refcount_++;
|
||||
}
|
||||
void Release() override {
|
||||
assert(refcount_ > 0);
|
||||
if (--refcount_ == 0)
|
||||
delete this;
|
||||
}
|
||||
int Invoke(IPluginContext* ctx, const cell_t* params) override {
|
||||
return callback_(ctx, params, data_);
|
||||
}
|
||||
|
||||
private:
|
||||
size_t refcount_ = 0;
|
||||
SPVM_FAKENATIVE_FUNC callback_;
|
||||
void* data_;
|
||||
};
|
||||
|
||||
AlreadyRefed<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
|
||||
{
|
||||
RefPtr<Native> entry(FindNative(name));
|
||||
if (entry)
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<FakeNative> fake(new FakeNative(name, pFunc));
|
||||
fake->wrapper = new DynamicNative(func, fake.get());
|
||||
AutoPtr<FakeNative> fake(new FakeNative(name, pFunc));
|
||||
|
||||
fake->gate = g_pSourcePawn2->CreateFakeNative(func, fake);
|
||||
if (!fake->gate)
|
||||
return nullptr;
|
||||
|
||||
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
|
||||
|
||||
entry = new Native(owner, std::move(fake));
|
||||
entry = new Native(owner, fake.take());
|
||||
m_NtvCache.insert(name, entry);
|
||||
|
||||
return entry.forget();
|
||||
|
||||
@@ -49,11 +49,9 @@ namespace SourceMod
|
||||
{
|
||||
struct IdentityToken_t
|
||||
{
|
||||
Handle_t ident = 0;
|
||||
void *ptr = nullptr;
|
||||
IdentityType_t type = 0;
|
||||
size_t num_handles = 0;
|
||||
bool warned_handle_usage = false;
|
||||
Handle_t ident;
|
||||
void *ptr;
|
||||
IdentityType_t type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ SMCError TextParsers::ParseSMCFile(const char *file,
|
||||
fclose(fp);
|
||||
|
||||
errstr = GetSMCErrorString(result);
|
||||
ke::SafeStrcpy(buffer, maxsize, errstr != NULL ? errstr : "Unknown error");
|
||||
ke::SafeSprintf(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -195,7 +195,7 @@ SMCError TextParsers::ParseSMCStream(const char *stream,
|
||||
result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states);
|
||||
|
||||
const char *errstr = GetSMCErrorString(result);
|
||||
ke::SafeStrcpy(buffer, maxsize, errstr != NULL ? errstr : "Unknown error");
|
||||
ke::SafeSprintf(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* vim: set ts=4 sw=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
|
||||
@@ -29,518 +29,17 @@
|
||||
* Version: $Id$
|
||||
*/
|
||||
#include <sm_platform.h>
|
||||
#include <amtl/am-deque.h>
|
||||
#include <amtl/am-maybe.h>
|
||||
#include <amtl/am-thread.h>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include "BaseWorker.h"
|
||||
#include "ThreadSupport.h"
|
||||
#include "common_logic.h"
|
||||
|
||||
static constexpr unsigned int DEFAULT_THINK_TIME_MS = 20;
|
||||
|
||||
class CompatWorker final : public IThreadWorker
|
||||
{
|
||||
public:
|
||||
explicit CompatWorker(IThreadWorkerCallbacks* callbacks);
|
||||
~CompatWorker();
|
||||
|
||||
void MakeThread(IThread *pThread) override;
|
||||
IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) override;
|
||||
IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) override;
|
||||
void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) override;
|
||||
unsigned int RunFrame() override;
|
||||
bool Pause() override;
|
||||
bool Unpause() override;
|
||||
bool Start() override;
|
||||
bool Stop(bool flush) override;
|
||||
WorkerState GetStatus(unsigned int *numThreads) override;
|
||||
void SetMaxThreadsPerFrame(unsigned int threads) override;
|
||||
void SetThinkTimePerFrame(unsigned int thinktime) override;
|
||||
|
||||
private:
|
||||
void Flush();
|
||||
void Worker();
|
||||
void RunWork(SWThreadHandle* handle);
|
||||
void RunWorkLocked(std::unique_lock<std::mutex>* lock, SWThreadHandle* handle);
|
||||
|
||||
private:
|
||||
IThreadWorkerCallbacks* callbacks_;
|
||||
WorkerState state_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable work_cv_;
|
||||
std::deque<SWThreadHandle*> work_;
|
||||
std::unique_ptr<std::thread> thread_;
|
||||
std::atomic<unsigned int> jobs_per_wakeup_;
|
||||
std::atomic<unsigned int> wait_between_jobs_;
|
||||
};
|
||||
|
||||
CompatWorker::CompatWorker(IThreadWorkerCallbacks* callbacks)
|
||||
: callbacks_(callbacks),
|
||||
state_(Worker_Stopped),
|
||||
jobs_per_wakeup_(SM_DEFAULT_THREADS_PER_FRAME),
|
||||
wait_between_jobs_(DEFAULT_THINK_TIME_MS)
|
||||
{
|
||||
}
|
||||
|
||||
CompatWorker::~CompatWorker()
|
||||
{
|
||||
Stop(false /* ignored */);
|
||||
Flush();
|
||||
}
|
||||
|
||||
bool CompatWorker::Start()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (state_ != Worker_Stopped)
|
||||
return false;
|
||||
|
||||
thread_ = ke::NewThread("SM CompatWorker Thread", [this]() -> void {
|
||||
Worker();
|
||||
});
|
||||
|
||||
state_ = Worker_Running;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompatWorker::Stop(bool)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (state_ <= Worker_Stopped)
|
||||
return false;
|
||||
|
||||
state_ = Worker_Stopped;
|
||||
work_cv_.notify_all();
|
||||
}
|
||||
|
||||
thread_->join();
|
||||
thread_ = nullptr;
|
||||
|
||||
Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompatWorker::Pause()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (state_ != Worker_Running)
|
||||
return false;
|
||||
|
||||
state_ = Worker_Paused;
|
||||
work_cv_.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompatWorker::Unpause()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (state_ != Worker_Paused)
|
||||
return false;
|
||||
|
||||
state_ = Worker_Running;
|
||||
work_cv_.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CompatWorker::Flush()
|
||||
{
|
||||
while (!work_.empty()) {
|
||||
auto handle = ke::PopFront(&work_);
|
||||
handle->GetThread()->OnTerminate(handle, true);
|
||||
if (handle->m_params.flags & Thread_AutoRelease)
|
||||
delete handle;
|
||||
}
|
||||
}
|
||||
|
||||
void CompatWorker::Worker()
|
||||
{
|
||||
// Note: this must be first to ensure an ordering between Worker() and
|
||||
// Start(). It must also be outside of the loop to ensure the lock is
|
||||
// held across wakeup and retesting the predicates.
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
if (callbacks_) {
|
||||
lock.unlock();
|
||||
callbacks_->OnWorkerStart(this);
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
typedef std::chrono::system_clock Clock;
|
||||
typedef std::chrono::time_point<Clock> TimePoint;
|
||||
|
||||
auto can_work = [this]() -> bool {
|
||||
return state_ == Worker_Running && !work_.empty();
|
||||
};
|
||||
|
||||
ke::Maybe<TimePoint> wait;
|
||||
unsigned int work_in_frame = 0;
|
||||
for (;;) {
|
||||
if (state_ == Worker_Stopped)
|
||||
break;
|
||||
|
||||
if (!can_work()) {
|
||||
// Wait for work or a Stop.
|
||||
work_cv_.wait(lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wait.isValid()) {
|
||||
// Wait until the specified time has passed. If we wake up with a
|
||||
// timeout, then the wait has elapsed, so reset the holder.
|
||||
if (work_cv_.wait_until(lock, wait.get()) == std::cv_status::timeout)
|
||||
wait = ke::Nothing();
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(state_ == Worker_Running);
|
||||
assert(!work_.empty());
|
||||
|
||||
SWThreadHandle* handle = ke::PopFront(&work_);
|
||||
RunWorkLocked(&lock, handle);
|
||||
work_in_frame++;
|
||||
|
||||
// If we've reached our max jobs per "frame", signal that the next
|
||||
// immediate job must be delayed. We retain the old ThreadWorker
|
||||
// behavior by checking if the queue has more work. Thus, a delay
|
||||
// only occurs if two jobs would be processed in the same wakeup.
|
||||
if (work_in_frame >= jobs_per_wakeup_ && wait_between_jobs_ && can_work())
|
||||
wait = ke::Some(Clock::now() + std::chrono::milliseconds(wait_between_jobs_));
|
||||
}
|
||||
|
||||
assert(lock.owns_lock());
|
||||
|
||||
while (!work_.empty()) {
|
||||
SWThreadHandle* handle = ke::PopFront(&work_);
|
||||
RunWorkLocked(&lock, handle);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CompatWorker::RunFrame()
|
||||
{
|
||||
unsigned int nprocessed = 0;
|
||||
for (unsigned int i = 1; i <= jobs_per_wakeup_; i++) {
|
||||
SWThreadHandle* handle;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (work_.empty())
|
||||
break;
|
||||
handle = ke::PopFront(&work_);
|
||||
}
|
||||
|
||||
RunWork(handle);
|
||||
nprocessed++;
|
||||
}
|
||||
return nprocessed;
|
||||
}
|
||||
|
||||
void CompatWorker::RunWorkLocked(std::unique_lock<std::mutex>* lock, SWThreadHandle* handle)
|
||||
{
|
||||
lock->unlock();
|
||||
RunWork(handle);
|
||||
lock->lock();
|
||||
}
|
||||
|
||||
void CompatWorker::RunWork(SWThreadHandle* handle)
|
||||
{
|
||||
bool autorelease = !!(handle->m_params.flags & Thread_AutoRelease);
|
||||
handle->m_state = Thread_Running;
|
||||
handle->GetThread()->RunThread(handle);
|
||||
handle->m_state = Thread_Done;
|
||||
handle->GetThread()->OnTerminate(handle, false);
|
||||
if (autorelease)
|
||||
delete handle;
|
||||
}
|
||||
|
||||
void CompatWorker::MakeThread(IThread *pThread)
|
||||
{
|
||||
ThreadParams params;
|
||||
params.flags = Thread_AutoRelease;
|
||||
MakeThread(pThread, ¶ms);
|
||||
}
|
||||
|
||||
IThreadHandle *CompatWorker::MakeThread(IThread *pThread, ThreadFlags flags)
|
||||
{
|
||||
ThreadParams params;
|
||||
params.flags = flags;
|
||||
return MakeThread(pThread, ¶ms);
|
||||
}
|
||||
|
||||
IThreadHandle *CompatWorker::MakeThread(IThread *pThread, const ThreadParams *params)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
ThreadParams def_params;
|
||||
if (!params)
|
||||
params = &def_params;
|
||||
|
||||
if (state_ <= Worker_Stopped)
|
||||
return nullptr;
|
||||
|
||||
SWThreadHandle* handle = new SWThreadHandle(this, params, pThread);
|
||||
work_.push_back(handle);
|
||||
work_cv_.notify_one();
|
||||
return handle;
|
||||
}
|
||||
|
||||
void CompatWorker::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
|
||||
{
|
||||
min = ThreadPrio_Normal;
|
||||
max = ThreadPrio_Normal;
|
||||
}
|
||||
|
||||
void CompatWorker::SetMaxThreadsPerFrame(unsigned int threads)
|
||||
{
|
||||
jobs_per_wakeup_ = threads;
|
||||
}
|
||||
|
||||
void CompatWorker::SetThinkTimePerFrame(unsigned int thinktime)
|
||||
{
|
||||
wait_between_jobs_ = thinktime;
|
||||
}
|
||||
|
||||
WorkerState CompatWorker::GetStatus(unsigned int *numThreads)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
// This number is meaningless and the status is racy.
|
||||
if (numThreads)
|
||||
*numThreads = jobs_per_wakeup_;
|
||||
return state_;
|
||||
}
|
||||
|
||||
class CompatThread final : public IThreadHandle
|
||||
{
|
||||
public:
|
||||
CompatThread(IThread* callbacks, const ThreadParams* params);
|
||||
|
||||
bool WaitForThread() override;
|
||||
void DestroyThis() override;
|
||||
IThreadCreator *Parent() override;
|
||||
void GetParams(ThreadParams *ptparams) override;
|
||||
ThreadPriority GetPriority() override;
|
||||
bool SetPriority(ThreadPriority prio) override;
|
||||
ThreadState GetState() override;
|
||||
bool Unpause() override;
|
||||
|
||||
private:
|
||||
void Run();
|
||||
|
||||
private:
|
||||
IThread* callbacks_;
|
||||
ThreadParams params_;
|
||||
std::unique_ptr<std::thread> thread_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable check_cv_;
|
||||
std::atomic<bool> finished_;
|
||||
};
|
||||
|
||||
CompatThread::CompatThread(IThread* callbacks, const ThreadParams* params)
|
||||
: callbacks_(callbacks),
|
||||
params_(*params)
|
||||
{
|
||||
if (!(params_.flags & Thread_CreateSuspended))
|
||||
Unpause();
|
||||
}
|
||||
|
||||
bool CompatThread::Unpause()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (thread_)
|
||||
return false;
|
||||
|
||||
thread_ = ke::NewThread("SM CompatThread", [this]() -> void {
|
||||
Run();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CompatThread::Run()
|
||||
{
|
||||
// Create an ordering between when the thread runs and when thread_ is assigned.
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
lock.unlock();
|
||||
callbacks_->RunThread(this);
|
||||
finished_ = true;
|
||||
callbacks_->OnTerminate(this, false);
|
||||
|
||||
if (params_.flags & Thread_AutoRelease) {
|
||||
// There should be no handles outstanding, so it's safe to self-destruct.
|
||||
thread_->detach();
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
lock.lock();
|
||||
callbacks_ = nullptr;
|
||||
check_cv_.notify_all();
|
||||
}
|
||||
|
||||
bool CompatThread::WaitForThread()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
for (;;) {
|
||||
// When done, callbacks are unset. If paused, this will deadlock.
|
||||
if (!callbacks_)
|
||||
break;
|
||||
check_cv_.wait(lock);
|
||||
}
|
||||
|
||||
thread_->join();
|
||||
return true;
|
||||
}
|
||||
|
||||
ThreadState CompatThread::GetState()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (!thread_)
|
||||
return Thread_Paused;
|
||||
return finished_ ? Thread_Done : Thread_Running;
|
||||
}
|
||||
|
||||
void CompatThread::DestroyThis()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
ThreadPriority CompatThread::GetPriority()
|
||||
{
|
||||
return ThreadPrio_Normal;
|
||||
}
|
||||
|
||||
bool CompatThread::SetPriority(ThreadPriority prio)
|
||||
{
|
||||
return prio == ThreadPrio_Normal;
|
||||
}
|
||||
|
||||
IThreadCreator *CompatThread::Parent()
|
||||
{
|
||||
return g_pThreader;
|
||||
}
|
||||
|
||||
void CompatThread::GetParams(ThreadParams *ptparams)
|
||||
{
|
||||
*ptparams = params_;
|
||||
}
|
||||
|
||||
class CompatMutex : public IMutex
|
||||
{
|
||||
public:
|
||||
bool TryLock() {
|
||||
return mutex_.try_lock();
|
||||
}
|
||||
void Lock() {
|
||||
mutex_.lock();
|
||||
}
|
||||
void Unlock() {
|
||||
mutex_.unlock();
|
||||
}
|
||||
void DestroyThis() {
|
||||
delete this;
|
||||
}
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
class CompatThreader final : public IThreader
|
||||
{
|
||||
public:
|
||||
void MakeThread(IThread *pThread) override;
|
||||
IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) override;
|
||||
IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) override;
|
||||
void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) override;
|
||||
IMutex *MakeMutex() override;
|
||||
void ThreadSleep(unsigned int ms) override;
|
||||
IEventSignal *MakeEventSignal() override;
|
||||
IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded) override;
|
||||
void DestroyWorker(IThreadWorker *pWorker) override;
|
||||
} sCompatThreader;
|
||||
|
||||
void CompatThreader::MakeThread(IThread *pThread)
|
||||
{
|
||||
ThreadParams params;
|
||||
params.flags = Thread_AutoRelease;
|
||||
MakeThread(pThread, ¶ms);
|
||||
}
|
||||
|
||||
IThreadHandle *CompatThreader::MakeThread(IThread *pThread, ThreadFlags flags)
|
||||
{
|
||||
ThreadParams params;
|
||||
params.flags = flags;
|
||||
return MakeThread(pThread, ¶ms);
|
||||
}
|
||||
|
||||
IThreadHandle *CompatThreader::MakeThread(IThread *pThread, const ThreadParams *params)
|
||||
{
|
||||
ThreadParams def_params;
|
||||
if (!params)
|
||||
params = &def_params;
|
||||
|
||||
return new CompatThread(pThread, params);
|
||||
}
|
||||
|
||||
void CompatThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
|
||||
{
|
||||
min = ThreadPrio_Normal;
|
||||
max = ThreadPrio_Normal;
|
||||
}
|
||||
|
||||
IMutex *CompatThreader::MakeMutex()
|
||||
{
|
||||
return new CompatMutex();
|
||||
}
|
||||
|
||||
void CompatThreader::ThreadSleep(unsigned int ms)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||
}
|
||||
|
||||
class CompatEventSignal final : public IEventSignal
|
||||
{
|
||||
public:
|
||||
void Wait() override {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
cv_.wait(lock);
|
||||
}
|
||||
void Signal() override {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
cv_.notify_all();
|
||||
}
|
||||
void DestroyThis() override {
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cv_;
|
||||
};
|
||||
|
||||
IEventSignal *CompatThreader::MakeEventSignal()
|
||||
{
|
||||
return new CompatEventSignal();
|
||||
}
|
||||
|
||||
IThreadWorker *CompatThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
|
||||
{
|
||||
if (!threaded)
|
||||
return new BaseWorker(hooks);
|
||||
return new CompatWorker(hooks);
|
||||
}
|
||||
|
||||
void CompatThreader::DestroyWorker(IThreadWorker *pWorker)
|
||||
{
|
||||
delete pWorker;
|
||||
}
|
||||
|
||||
IThreader *g_pThreader = &sCompatThreader;
|
||||
#if defined PLATFORM_POSIX
|
||||
#include "thread/PosixThreads.h"
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
#include "thread/WinThreads.h"
|
||||
#endif
|
||||
|
||||
MainThreader g_MainThreader;
|
||||
IThreader *g_pThreader = &g_MainThreader;
|
||||
|
||||
class RegThreadStuff : public SMGlobalClass
|
||||
{
|
||||
|
||||
@@ -32,13 +32,49 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
||||
#define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <IThreader.h>
|
||||
#include <am-thread-utils.h>
|
||||
#include <am-utility.h>
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
class CompatMutex : public IMutex
|
||||
{
|
||||
public:
|
||||
bool TryLock() {
|
||||
return mutex_.TryLock();
|
||||
}
|
||||
void Lock() {
|
||||
mutex_.Lock();
|
||||
}
|
||||
void Unlock() {
|
||||
mutex_.Unlock();
|
||||
}
|
||||
void DestroyThis() {
|
||||
delete this;
|
||||
}
|
||||
private:
|
||||
ke::Mutex mutex_;
|
||||
};
|
||||
|
||||
class CompatCondVar : public IEventSignal
|
||||
{
|
||||
public:
|
||||
void Wait() {
|
||||
ke::AutoLock lock(&cv_);
|
||||
cv_.Wait();
|
||||
}
|
||||
void Signal() {
|
||||
ke::AutoLock lock(&cv_);
|
||||
cv_.Notify();
|
||||
}
|
||||
void DestroyThis() {
|
||||
delete this;
|
||||
}
|
||||
private:
|
||||
ke::ConditionVariable cv_;
|
||||
};
|
||||
|
||||
extern IThreader *g_pThreader;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
|
||||
|
||||
@@ -940,7 +940,7 @@ bool Translator::AddLanguage(const char *langcode, const char *description)
|
||||
Language *pLanguage = new Language;
|
||||
idx = m_Languages.size();
|
||||
|
||||
ke::SafeStrcpy(pLanguage->m_code2, sizeof(pLanguage->m_code2), langcode);
|
||||
ke::SafeSprintf(pLanguage->m_code2, sizeof(pLanguage->m_code2), "%s", langcode);
|
||||
pLanguage->m_CanonicalName = m_pStringTab->AddString(lower);
|
||||
|
||||
m_LCodeLookup.insert(langcode, idx);
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
#include "sprintf.h"
|
||||
#include "LibrarySys.h"
|
||||
#include "RootConsoleMenu.h"
|
||||
#include "CDataPack.h"
|
||||
#include "CellArray.h"
|
||||
#include "smn_entitylump.h"
|
||||
#include <bridge/include/BridgeAPI.h>
|
||||
#include <bridge/include/IProviderCallbacks.h>
|
||||
|
||||
@@ -86,11 +86,6 @@ IScriptManager *scripts = &g_PluginSys;
|
||||
IExtensionSys *extsys = &g_Extensions;
|
||||
ILogger *logger = &g_Logger;
|
||||
CNativeOwner g_CoreNatives;
|
||||
#ifdef PLATFORM_X64
|
||||
PseudoAddressManager pseudoAddr;
|
||||
#endif
|
||||
|
||||
EntityLumpParseResult lastParseResult;
|
||||
|
||||
static void AddCorePhraseFile(const char *filename)
|
||||
{
|
||||
@@ -120,53 +115,6 @@ static void RegisterProfiler(IProfilingTool *tool)
|
||||
g_ProfileToolManager.RegisterTool(tool);
|
||||
}
|
||||
|
||||
static void *FromPseudoAddress(uint32_t paddr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
return pseudoAddr.FromPseudoAddress(paddr);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t ToPseudoAddress(void *addr)
|
||||
{
|
||||
#ifdef PLATFORM_X64
|
||||
return pseudoAddr.ToPseudoAddress(addr);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SetEntityLumpWritable(bool writable)
|
||||
{
|
||||
g_bLumpAvailableForWriting = writable;
|
||||
|
||||
// write-lock causes the map entities to be serialized out to string
|
||||
if (!writable)
|
||||
{
|
||||
g_strMapEntities = lumpmanager->Dump();
|
||||
}
|
||||
}
|
||||
|
||||
static bool ParseEntityLumpString(const char *pMapEntities, int &status, size_t &position)
|
||||
{
|
||||
lastParseResult = lumpmanager->Parse(pMapEntities);
|
||||
status = static_cast<int>(lastParseResult.m_Status);
|
||||
position = static_cast<size_t>(lastParseResult.m_Position);
|
||||
return lastParseResult;
|
||||
}
|
||||
|
||||
// returns nullptr if the original lump failed to parse
|
||||
static const char* GetEntityLumpString()
|
||||
{
|
||||
if (!lastParseResult)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return g_strMapEntities.c_str();
|
||||
}
|
||||
|
||||
// Defined in smn_filesystem.cpp.
|
||||
extern bool OnLogPrint(const char *msg);
|
||||
|
||||
@@ -198,13 +146,10 @@ static sm_logic_t logic =
|
||||
GenerateError,
|
||||
AddNatives,
|
||||
RegisterProfiler,
|
||||
CDataPack::New,
|
||||
CDataPack::Free,
|
||||
CellArray::New,
|
||||
CellArray::Free,
|
||||
FromPseudoAddress,
|
||||
ToPseudoAddress,
|
||||
SetEntityLumpWritable,
|
||||
ParseEntityLumpString,
|
||||
GetEntityLumpString,
|
||||
&g_PluginSys,
|
||||
&g_ShareSys,
|
||||
&g_Extensions,
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
#define _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
|
||||
|
||||
#include "../sm_globals.h"
|
||||
#ifdef PLATFORM_X64
|
||||
#include "PseudoAddrManager.h"
|
||||
#endif
|
||||
|
||||
namespace SourceMod {
|
||||
class CoreProvider;
|
||||
@@ -60,7 +57,6 @@ class IVEngineServerBridge;
|
||||
#endif
|
||||
} // namespace SourceMod
|
||||
struct ServerGlobals;
|
||||
class PseudoAddressManager;
|
||||
|
||||
extern SourceMod::CoreProvider *bridge;
|
||||
extern SourceMod::IHandleSys *handlesys;
|
||||
@@ -80,7 +76,6 @@ extern SourceMod::IScriptManager *scripts;
|
||||
extern SourceMod::IExtensionSys *extsys;
|
||||
extern SourceMod::ILogger *logger;
|
||||
extern SourceMod::IMenuManager *menus;
|
||||
extern PseudoAddressManager pseudoAddr;
|
||||
|
||||
#if defined SM_LOGIC
|
||||
extern SourceMod::IVEngineServerBridge *engine;
|
||||
|
||||
@@ -26,17 +26,16 @@
|
||||
// or <http://www.sourcemod.net/license.php>.
|
||||
#include "frame_tasks.h"
|
||||
#include <am-vector.h>
|
||||
#include <utility>
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
std::vector<ke::Function<void()>> sNextTasks;
|
||||
std::vector<ke::Function<void()>> sWorkTasks;
|
||||
ke::Vector<ke::Lambda<void()>> sNextTasks;
|
||||
ke::Vector<ke::Lambda<void()>> sWorkTasks;
|
||||
|
||||
void
|
||||
SourceMod::ScheduleTaskForNextFrame(ke::Function<void()>&& task)
|
||||
SourceMod::ScheduleTaskForNextFrame(ke::Lambda<void()>&& task)
|
||||
{
|
||||
sNextTasks.push_back(std::forward<decltype(task)>(task));
|
||||
sNextTasks.append(ke::Forward<decltype(task)>(task));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -46,11 +45,11 @@ SourceMod::RunScheduledFrameTasks(bool simulating)
|
||||
return;
|
||||
|
||||
// Swap.
|
||||
std::vector<ke::Function<void()>> temp(std::move(sNextTasks));
|
||||
sNextTasks = std::move(sWorkTasks);
|
||||
sWorkTasks = std::move(temp);
|
||||
ke::Vector<ke::Lambda<void()>> temp(ke::Move(sNextTasks));
|
||||
sNextTasks = ke::Move(sWorkTasks);
|
||||
sWorkTasks = ke::Move(temp);
|
||||
|
||||
for (size_t i = 0; i < sWorkTasks.size(); i++)
|
||||
for (size_t i = 0; i < sWorkTasks.length(); i++)
|
||||
sWorkTasks[i]();
|
||||
sWorkTasks.clear();
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,10 @@
|
||||
|
||||
namespace SourceMod {
|
||||
|
||||
void ScheduleTaskForNextFrame(ke::Function<void()>&& task);
|
||||
void ScheduleTaskForNextFrame(ke::Lambda<void()>&& task);
|
||||
|
||||
void RunScheduledFrameTasks(bool simulating);
|
||||
|
||||
}
|
||||
|
||||
#endif // _include_sourcemod_logic_frame_tasks_h_
|
||||
#endif // _include_sourcemod_logic_frame_tasks_h_
|
||||
@@ -89,6 +89,6 @@ unsigned int UTIL_CRC32(const void *pdata, size_t data_length)
|
||||
crc = CRCTable[c] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,11 +75,7 @@ static cell_t CreateArray(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
if (params[2])
|
||||
{
|
||||
if (!array->resize(params[2]))
|
||||
{
|
||||
delete array;
|
||||
return pContext->ThrowNativeError("Failed to resize array to startsize \"%u\".", params[2]);
|
||||
}
|
||||
array->resize(params[2]);
|
||||
}
|
||||
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellArray, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
|
||||
@@ -83,48 +83,6 @@ static cell_t CreateStack(IPluginContext *pContext, const cell_t *params)
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t ClearStack(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
CellArray *array;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&array)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
}
|
||||
|
||||
array->clear();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t CloneStack(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
CellArray *oldArray;
|
||||
HandleError err;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellStack, &sec, (void **)&oldArray)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
||||
}
|
||||
|
||||
ICellArray *array = oldArray->clone();
|
||||
if (!array)
|
||||
{
|
||||
return pContext->ThrowNativeError("Failed to clone stack. Out of memory.");
|
||||
}
|
||||
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellStack, array, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete array;
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
static cell_t PushStackCell(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
CellArray *array;
|
||||
@@ -429,7 +387,6 @@ static cell_t GetStackBlockSize(IPluginContext *pContext, const cell_t *params)
|
||||
REGISTER_NATIVES(cellStackNatives)
|
||||
{
|
||||
{"CreateStack", CreateStack},
|
||||
{"CloneStack", CloneStack},
|
||||
{"IsStackEmpty", IsStackEmpty},
|
||||
{"PopStackArray", PopStackArray},
|
||||
{"PopStackCell", PopStackCell},
|
||||
@@ -441,8 +398,6 @@ REGISTER_NATIVES(cellStackNatives)
|
||||
|
||||
// Transitional syntax support.
|
||||
{"ArrayStack.ArrayStack", CreateStack},
|
||||
{"ArrayStack.Clear", ClearStack},
|
||||
{"ArrayStack.Clone", CloneStack},
|
||||
{"ArrayStack.Pop", ArrayStack_Pop},
|
||||
{"ArrayStack.PopString", ArrayStack_PopString},
|
||||
{"ArrayStack.PopArray", ArrayStack_PopArray},
|
||||
|
||||
@@ -30,10 +30,8 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common_logic.h"
|
||||
#include <am-moveable.h>
|
||||
#include <am-refcounting.h>
|
||||
#include <sm_stringhashmap.h>
|
||||
#include "sm_memtable.h"
|
||||
@@ -104,7 +102,7 @@ public:
|
||||
assert(isArray());
|
||||
return reinterpret_cast<cell_t *>(raw()->base());
|
||||
}
|
||||
char *c_str() const {
|
||||
char *chars() const {
|
||||
assert(isString());
|
||||
return reinterpret_cast<char *>(raw()->base());
|
||||
}
|
||||
@@ -183,7 +181,7 @@ struct TrieSnapshot
|
||||
}
|
||||
|
||||
size_t length;
|
||||
std::unique_ptr<int[]> keys;
|
||||
ke::AutoPtr<int[]> keys;
|
||||
BaseStringTable strings;
|
||||
};
|
||||
|
||||
@@ -350,27 +348,6 @@ static cell_t SetTrieString(IPluginContext *pContext, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t ContainsKeyInTrie(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
CellTrie *pTrie;
|
||||
HandleError err;
|
||||
HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
Handle_t hndl = params[1];
|
||||
|
||||
if ((err = handlesys->ReadHandle(hndl, htCellTrie, &sec, (void **)&pTrie)) != HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
char *key;
|
||||
pContext->LocalToString(params[2], &key);
|
||||
|
||||
StringHashMap<Entry>::Result r = pTrie->map.find(key);
|
||||
|
||||
return r.found() ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t RemoveFromTrie(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
CellTrie *pTrie;
|
||||
@@ -539,7 +516,7 @@ static cell_t GetTrieString(IPluginContext *pContext, const cell_t *params)
|
||||
return 0;
|
||||
|
||||
size_t written;
|
||||
pContext->StringToLocalUTF8(params[3], params[4], r->value.c_str(), &written);
|
||||
pContext->StringToLocalUTF8(params[3], params[4], r->value.chars(), &written);
|
||||
|
||||
*pSize = (cell_t)written;
|
||||
return 1;
|
||||
@@ -579,10 +556,10 @@ static cell_t CreateTrieSnapshot(IPluginContext *pContext, const cell_t *params)
|
||||
|
||||
TrieSnapshot *snapshot = new TrieSnapshot;
|
||||
snapshot->length = pTrie->map.elements();
|
||||
snapshot->keys = std::make_unique<int[]>(snapshot->length);
|
||||
snapshot->keys = ke::MakeUnique<int[]>(snapshot->length);
|
||||
size_t i = 0;
|
||||
for (StringHashMap<Entry>::iterator iter = pTrie->map.iter(); !iter.empty(); iter.next(), i++)
|
||||
snapshot->keys[i] = snapshot->strings.AddString(iter->key.c_str(), iter->key.length());
|
||||
snapshot->keys[i] = snapshot->strings.AddString(iter->key.chars(), iter->key.length());
|
||||
assert(i == snapshot->length);
|
||||
|
||||
if ((hndl = handlesys->CreateHandle(htSnapshot, snapshot, pContext->GetIdentity(), g_pCoreIdent, NULL))
|
||||
@@ -657,56 +634,6 @@ static cell_t GetTrieSnapshotKey(IPluginContext *pContext, const cell_t *params)
|
||||
return written;
|
||||
}
|
||||
|
||||
static cell_t CloneTrie(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
HandleError err;
|
||||
HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
CellTrie *pOldTrie;
|
||||
if ((err = handlesys->ReadHandle(params[1], htCellTrie, &sec, (void **)&pOldTrie))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||
}
|
||||
|
||||
CellTrie *pNewTrie = new CellTrie;
|
||||
Handle_t hndl = handlesys->CreateHandle(htCellTrie, pNewTrie, pContext->GetIdentity(), g_pCoreIdent, NULL);
|
||||
if (!hndl)
|
||||
{
|
||||
delete pNewTrie;
|
||||
return hndl;
|
||||
}
|
||||
|
||||
for (StringHashMap<Entry>::iterator it = pOldTrie->map.iter(); !it.empty(); it.next())
|
||||
{
|
||||
const char *key = it->key.c_str();
|
||||
StringHashMap<Entry>::Insert insert = pNewTrie->map.findForAdd(key);
|
||||
if (pNewTrie->map.add(insert, key))
|
||||
{
|
||||
StringHashMap<Entry>::Result result = pOldTrie->map.find(key);
|
||||
if (result->value.isCell())
|
||||
{
|
||||
insert->value.setCell(result->value.cell());
|
||||
}
|
||||
else if (result->value.isString())
|
||||
{
|
||||
insert->value.setString(result->value.c_str());
|
||||
}
|
||||
else if (result->value.isArray())
|
||||
{
|
||||
insert->value.setArray(result->value.array(), result->value.arrayLength());
|
||||
}
|
||||
else
|
||||
{
|
||||
handlesys->FreeHandle(hndl, NULL);
|
||||
return pContext->ThrowNativeError("Unhandled data type encountered, file a bug and reference pr #852");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hndl;
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(trieNatives)
|
||||
{
|
||||
{"ClearTrie", ClearTrie},
|
||||
@@ -731,14 +658,12 @@ REGISTER_NATIVES(trieNatives)
|
||||
{"StringMap.GetArray", GetTrieArray},
|
||||
{"StringMap.GetString", GetTrieString},
|
||||
{"StringMap.GetValue", GetTrieValue},
|
||||
{"StringMap.ContainsKey", ContainsKeyInTrie},
|
||||
{"StringMap.Remove", RemoveFromTrie},
|
||||
{"StringMap.SetArray", SetTrieArray},
|
||||
{"StringMap.SetString", SetTrieString},
|
||||
{"StringMap.SetValue", SetTrieValue},
|
||||
{"StringMap.Size.get", GetTrieSize},
|
||||
{"StringMap.Snapshot", CreateTrieSnapshot},
|
||||
{"StringMap.Clone", CloneTrie},
|
||||
|
||||
{"StringMapSnapshot.Length.get", TrieSnapshotLength},
|
||||
{"StringMapSnapshot.KeyBufferSize", TrieSnapshotKeyBufferSize},
|
||||
|
||||
@@ -127,8 +127,6 @@ static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
|
||||
}
|
||||
}
|
||||
|
||||
g_pSM->SetGlobalTarget(index);
|
||||
|
||||
char buffer[1024];
|
||||
char *fmt;
|
||||
int arg = 3;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user