Compare commits

..

17 Commits

Author SHA1 Message Date
BotoX
178202a5b3 Add "Restart Current Map" to sm_map menu. 2019-11-01 01:17:42 +01:00
BotoX
60f3268236 Fix GetClientCount(false) 2019-10-20 12:28:44 +02:00
BotoX
64b3c8fbd8 Add damageCustom argument to SDKHooks_TakeDamage native. 2019-10-20 12:28:44 +02:00
BotoX
4c4629fca7 fix IsMapValid behavior change by a2246af121 2019-10-20 12:28:44 +02:00
BotoX
8749877c62 fix rare crash bug in SDKTools GetGameRulesProxyEnt 2019-10-20 12:28:44 +02:00
BotoX
102b01c626 Add OnEntitySpawned to SDKHooks. 2019-10-20 12:28:44 +02:00
BotoX
8e07790997 Implement per-client randomized menus with MenuShufflePerClient native.
Add MenuSetClientMapping native.
2019-10-20 12:28:44 +02:00
BotoX
a701408c71 Changes on sm_*say 2019-10-20 12:28:44 +02:00
BotoX
2d0fff79a8 Fix HookEntityOutput/HookSingleEntityOutput bugs in sdktools. 2019-10-20 12:28:44 +02:00
BotoX
9da44d67f1 Add GetClientIClient native. 2019-10-20 12:28:44 +02:00
Obuss
1847f5e2dc Logging changes to various base plugins. 2019-10-20 12:28:44 +02:00
BotoX
0dd3361050 Avoid losing console messages.
Buffers up to 16k bytes of SVC_Print if buffer would overflow, then sends chunks every frame.
Sends up to 2048 bytes per frame and does not split messages.
2019-10-20 12:28:44 +02:00
BotoX
11d12aad11 Extend function calling API for natives and allow catching exceptions.
Change sourcepawn url.
2019-10-20 12:28:44 +02:00
BotoX
8ac0c18674 Fix @spec not targeting clients in unassigned team. 2019-10-20 12:28:44 +02:00
BotoX
a0b8153f4b Added hack to make plugins open a menu with all possible targets on ReplyToTargetError COMMAND_TARGET_AMBIGUOUS.
Explanation:
There are two clients in the server, one named gene, the other one "Ene ~special characters~".
An admin issues "sm_slay Ene" and gets following error message: More than one client matched the given pattern.
What this hack will do is: Use GetCmdArg(0, ...); to get the command name "sm_slay".
Use GetCmdArgString(...); to get the arguments supplied to the command.
Use GetLastProcessTargetString(...); (which was implemented in this commit) to retrieve the arguments that were passed to the last ProcessTargetString call.
It will then pass this data to the DynamicTargeting plugin through its AmbiguousMenu native.
The plugin will open up a menu on the client and list all targets which match the pattern that was supplied to ProcessTargetString.
If the client selects a menu entry, FakeClientCommand will be used to re-execute the command with the correct target.
2019-10-20 12:28:44 +02:00
BotoX
a363587be9 Added client id to MultiTargetFilter forward. 2019-10-20 12:28:44 +02:00
BotoX
fdcce81a41 Add more macros to CDetour. 2019-10-20 12:28:44 +02:00
466 changed files with 36095 additions and 77899 deletions

View File

@ -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

View File

@ -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

6
.gitignore vendored
View File

@ -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/*

4
.gitmodules vendored
View File

@ -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

View File

@ -1,86 +1,118 @@
git:
depth: 3
sudo: false
language: cpp
os: linux
dist: xenial
dist: trusty
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-3.9
- 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
- clang-3.9
- 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,css,tf2,l4d2,csgo,dota
- ambuild

View File

@ -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):
@ -22,33 +19,23 @@ class SDK(object):
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
def shouldBuild(self, target, archs):
if target.platform not in self.platformSpec:
return False
if not len([i for i in self.platformSpec[target.platform] if i in archs]):
return False
return True
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']
'linux': ['x86', 'x64'],
'mac': ['x64']
}
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'),
@ -65,19 +52,13 @@ SDKMap = {
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, '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]
@ -99,19 +80,32 @@ def ResolveEnvPath(env, folder):
def Normalize(path):
return os.path.abspath(os.path.normpath(path))
def SetArchFlags(compiler):
def SetArchFlags(compiler, arch, platform):
if compiler.behavior == 'gcc':
if compiler.target.arch == 'x86_64':
compiler.cflags += ['-fPIC']
if arch == 'x86':
compiler.cflags += ['-m32']
compiler.linkflags += ['-m32']
if platform == 'mac':
compiler.linkflags += ['-arch', 'i386']
elif arch == 'x64':
compiler.cflags += ['-m64', '-fPIC']
compiler.linkflags += ['-m64']
if platform == 'mac':
compiler.linkflags += ['-arch', 'x86_64']
elif compiler.like('msvc'):
if compiler.target.arch == 'x86_64':
compiler.defines += ['WIN64']
if builder.target.arch == 'x86':
compiler.linkflags += ['/MACHINE:X86']
elif builder.target.arch == 'x64':
compiler.linkflags += ['/MACHINE:X64']
def AppendArchSuffix(binary, name, arch):
if arch == 'x64':
binary.localFolder = name + '.x64'
class SMConfig(object):
def __init__(self):
self.sdks = {}
self.binaries = []
self.spvm = []
self.extensions = []
self.generated_headers = None
self.mms_root = None
@ -120,32 +114,7 @@ class SMConfig(object):
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.')
self.archs = builder.target.arch.replace('x86_64', 'x64').split(',')
def use_auto_versioning(self):
if builder.backend != 'amb2':
@ -174,33 +143,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 sdk.shouldBuild(builder.target, self.archs):
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 and len(sdk_list):
raise Exception('No SDKs were found that build on {0}-{1}, nothing to do.'.format(
builder.target.platform, builder.target.arch))
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')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
@ -212,7 +179,6 @@ 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:
@ -221,40 +187,32 @@ class SMConfig(object):
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.')
raise Exception('Could not find a path to MySQL!')
self.mysql_root['x86'] = Normalize(self.mysql_root['x86'])
if 'x86_64' in self.target_archs:
# For now, ignore 64-bit MySQL on Windows
if 'x64' in self.archs and builder.target.platform != 'windows':
if builder.options.mysql64_path:
self.mysql_root['x86_64'] = builder.options.mysql64_path
self.mysql_root['x64'] = 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']:
self.mysql_root['x64'] = ResolveEnvPath('MYSQL55_64', 'mysql-5.' + str(i) + '-x86_64')
if self.mysql_root['x64']:
break
if not self.mysql_root['x86_64'] or not os.path.isdir(self.mysql_root['x86_64']):
if not self.mysql_root['x64'] or not os.path.isdir(self.mysql_root['x64']):
raise Exception('Could not find a path to 64-bit MySQL!')
self.mysql_root['x86_64'] = Normalize(self.mysql_root['x86_64'])
self.mysql_root['x64'] = Normalize(self.mysql_root['x64'])
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))
if not set(self.archs).issubset(['x86', 'x64']):
raise Exception('Unknown target architecture: {0}'.format(builder.target.arch))
for cxx in self.all_targets:
self.configure_cxx(cxx)
cxx = builder.DetectCxx()
def configure_cxx(self, cxx):
if cxx.family == 'msvc':
if cxx.version < 1900:
raise Exception('Only MSVC 2015 and later are supported, c++14 support is required.')
if cxx.family == 'gcc':
if cxx.version < 'gcc-4.9':
raise Exception('Only GCC versions 4.9 or greater are supported, c++14 support is required.')
if cxx.family == 'clang':
if cxx.version < 'clang-3.4':
raise Exception('Only clang versions 3.4 or greater are supported, c++14 support is required.')
if cxx.like('msvc') and len(self.archs) > 1:
raise Exception('Building multiple archs with MSVC is not currently supported')
if cxx.like('gcc'):
self.configure_gcc(cxx)
@ -270,11 +228,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.
@ -312,13 +270,9 @@ class SMConfig(object):
'-msse',
'-fvisibility=hidden',
]
if cxx.version == 'apple-clang-6.0' or cxx.version == 'clang-3.4':
cxx.cxxflags += ['-std=c++1y']
else:
cxx.cxxflags += ['-std=c++14']
cxx.cxxflags += [
'-std=c++11',
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
@ -327,11 +281,11 @@ class SMConfig(object):
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']
@ -351,35 +305,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']
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']
@ -425,29 +358,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 +365,22 @@ 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',
'-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':
def AddVersioning(self, binary, arch):
if builder.target.platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
@ -489,38 +388,31 @@ 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[arch]]
binary.compiler.sourcedeps += SM.generated_headers
return binary
def LibraryBuilder(self, compiler, name):
def LibraryBuilder(self, compiler, name, arch):
binary = compiler.Library(name)
self.AddVersioning(binary)
AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
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):
def ProgramBuilder(self, compiler, name, arch):
binary = compiler.Program(name)
self.AddVersioning(binary)
AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
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'):
@ -529,23 +421,25 @@ class SMConfig(object):
binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE']
return binary
def StaticLibraryBuilder(self, compiler, name):
return compiler.StaticLibrary(name)
def StaticLibraryBuilder(self, compiler, name, arch):
binary = compiler.StaticLibrary(name)
AppendArchSuffix(binary, name, arch)
return binary;
def Library(self, context, compiler, name):
compiler = compiler.clone()
SetArchFlags(compiler)
return self.LibraryBuilder(compiler, name)
def Library(self, context, name, arch):
compiler = context.cxx.clone()
SetArchFlags(compiler, arch, builder.target.platform)
return self.LibraryBuilder(compiler, name, arch)
def Program(self, context, compiler, name):
compiler = compiler.clone()
SetArchFlags(compiler)
return self.ProgramBuilder(compiler, name)
def Program(self, context, name, arch):
compiler = context.cxx.clone()
SetArchFlags(compiler, arch, builder.target.platform)
return self.ProgramBuilder(compiler, name, arch)
def StaticLibrary(self, context, compiler, name):
compiler = compiler.clone()
SetArchFlags(compiler)
return self.StaticLibraryBuilder(compiler, name)
def StaticLibrary(self, context, name, arch):
compiler = context.cxx.clone()
SetArchFlags(compiler, arch, builder.target.platform)
return self.StaticLibraryBuilder(compiler, name, arch)
def ConfigureForExtension(self, context, compiler):
compiler.cxxincludes += [
@ -558,15 +452,15 @@ class SMConfig(object):
]
return compiler
def ExtLibrary(self, context, compiler, name):
binary = self.Library(context, compiler, name)
SetArchFlags(compiler)
def ExtLibrary(self, context, name, arch):
binary = self.Library(context, name, arch)
self.ConfigureForExtension(context, binary.compiler)
return binary
def ConfigureForHL2(self, context, binary, sdk):
def ConfigureForHL2(self, binary, sdk, arch):
compiler = binary.compiler
SetArchFlags(compiler)
SetArchFlags(compiler, arch, builder.target.platform)
compiler.cxxincludes += [
os.path.join(self.mms_root, 'core'),
@ -603,16 +497,13 @@ 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.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':
if arch == 'x64':
compiler.defines += ['X64BITS', 'PLATFORM_64BITS']
# For everything after Swarm, this needs to be defined for entity networking
@ -621,142 +512,107 @@ class SMConfig(object):
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++')
if sdk.name == 'csgo' and builder.target.platform == 'linux':
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']
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':
elif arch == 'x64':
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':
elif arch == 'x64':
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'] or arch == 'x64':
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')]
if arch == 'x64':
compiler.postlink += [compiler.Dep(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']:
elif arch == 'x64' and sdk.name == 'csgo':
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)
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, arch):
binary = self.Library(context, name, arch)
self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(context, binary, sdk)
return self.ConfigureForHL2(binary, sdk, arch)
def HL2Config(self, project, context, compiler, name, sdk):
binary = project.Configure(compiler, name,
'{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch))
self.AddVersioning(binary)
return self.ConfigureForHL2(context, binary, sdk)
def HL2Project(self, context, name):
project = context.cxx.LibraryProject(name)
self.ConfigureForExtension(context, project.compiler)
return project
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)
def HL2Config(self, project, name, sdk, arch):
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
return self.ConfigureForHL2(binary, sdk, arch)
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,53 +624,23 @@ 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())
if not getattr(builder.options, 'scripting_only', False):
for cxx in SM.all_targets:
SM.spvm += [
SP.libsourcepawn[cxx.target.arch]
for arch in SM.archs:
SM.binaries += [
SP.libsourcepawn[arch]
]
if getattr(builder.options, 'scripting_only', False):
BuildScripts = [
'tools/buildbot/PackageHelpers',
'tools/buildbot/ToolsPackageScript',
]
else:
BuildScripts = [
BuildScripts = [
'loader/AMBuilder',
'core/AMBuilder',
'core/logic/AMBuilder',
@ -822,10 +648,8 @@ else:
'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',
@ -833,12 +657,11 @@ else:
'extensions/tf2/AMBuilder',
'extensions/topmenus/AMBuilder',
'extensions/updater/AMBuilder',
]
]
if builder.backend == 'amb2':
if builder.backend == 'amb2':
BuildScripts += [
'plugins/AMBuilder',
'tools/buildbot/PackageHelpers',
'tools/buildbot/PackageScript',
]

View File

@ -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

View File

@ -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;

View File

@ -73,9 +73,6 @@ struct sm_logic_t
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;

View File

@ -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"
}

BIN
configs/geoip/GeoIP.dat Normal file

Binary file not shown.

View File

@ -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;

View File

@ -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');

View File

@ -12,38 +12,31 @@ except:
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,
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_argument('--mysql-path', type=str, dest='mysql_path', default=None,
parser.options.add_option('--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,
parser.options.add_option('--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.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',
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_argument('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
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()

View File

@ -1,8 +1,7 @@
# 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,22 +37,22 @@ 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]:
for arch in SM.archs:
if not arch in sdk.platformSpec[builder.target.platform]:
continue
binary_name = 'sourcemod.' + sdk.ext
binary = SM.HL2Config(project, builder, cxx, binary_name, sdk)
SM.ConfigureForExtension(builder, binary.compiler)
binary = SM.HL2Config(project, binary_name, sdk, arch)
compiler = binary.compiler
compiler.cxxincludes += [
builder.sourcePath
]
@ -64,72 +63,51 @@ for sdk_name in SM.sdks:
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 += ['_ALLOW_KEYWORD_MACROS']
if cxx.target.platform == 'linux':
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':
if sdk.name == 'csgo':
if builder.target.platform == 'linux':
if arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
elif compiler.target.arch == 'x86_64':
elif arch == 'x64':
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':
elif builder.target.platform == 'mac':
if arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
elif compiler.target.arch == 'x86_64':
elif arch == 'x64':
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
elif compiler.target.platform == 'windows':
elif builder.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:
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')
lib_path = os.path.join(sdk.path, 'lib', 'win32', '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)
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']:
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'),
]
SM.binaries += builder.Add(project)

View File

@ -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);
}

View File

@ -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;

View File

@ -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)
{
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)
{
/* 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;
@ -338,8 +359,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 +380,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;
@ -377,7 +398,7 @@ bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
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 +425,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 +495,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;
@ -541,6 +562,10 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
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);
@ -623,7 +648,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);

View File

@ -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,12 @@
#include <IAdminSystem.h>
#include "concmd_cleaner.h"
#include "GameHooks.h"
#include <sm_namehashset.h>
#include <am-autoptr.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 +55,7 @@ struct ConCmdInfo;
struct CommandGroup : public ke::Refcounted<CommandGroup>
{
std::list<CmdHook *> hooks;
ke::LinkedList<CmdHook *> hooks;
};
struct AdminCmdInfo
@ -81,11 +78,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 +89,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;
@ -109,32 +104,12 @@ struct ConCmdInfo
pCmd = nullptr;
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;
@ -178,6 +153,11 @@ private:
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 +167,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 */
};

View File

@ -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;
}

View File

@ -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;
return strcmp(name, info->pVar->GetName()) == 0;
}
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 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;

View File

@ -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;

View File

@ -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()

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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)
{

View File

@ -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

View File

@ -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;
}
};

View File

@ -45,10 +45,9 @@
#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")
@ -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()
{
@ -145,7 +143,6 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
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,
@ -183,7 +180,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))
@ -321,41 +317,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 +516,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 +543,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 +580,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 +610,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 +645,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 +670,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);
@ -1234,45 +1212,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 +1245,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,17 +1258,11 @@ 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;
}
@ -1388,36 +1316,8 @@ bool CHalfLife2::IsMapValid(const char *map)
return FindMap(map) == SMFindMapResult::Found;
}
#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,58 +1327,28 @@ 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
{

View File

@ -179,12 +179,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 +229,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 +271,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
};

View File

@ -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));
}

View File

@ -32,11 +32,9 @@
#ifndef _INCLUDE_MENUSTYLE_BASE_H
#define _INCLUDE_MENUSTYLE_BASE_H
#include <memory>
#include <utility>
#include <IMenuManager.h>
#include <IPlayerHelpers.h>
#include <am-autoptr.h>
#include <am-string.h>
#include <am-vector.h>
#include "sm_fastlink.h"
@ -53,8 +51,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 +61,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 +70,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 +164,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 +176,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

View File

@ -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
@ -470,16 +462,7 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
sizeof(display_pkt),
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 +483,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 +576,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);

View File

@ -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)
{

View File

@ -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;
@ -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);
@ -250,7 +249,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);
@ -412,7 +410,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 +517,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 +525,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 +671,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 +714,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 +786,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 +873,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 +891,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 +918,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())
@ -1175,10 +1169,6 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
" Scott \"DS\" Ehlert, Fyren");
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 +1183,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,13 +1338,29 @@ 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 (strcmp(old_name, new_name) != 0)
#if SOURCE_ENGINE >= SE_LEFT4DEAD
const char *networkid_force;
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
{
if (!pPlayer->IsFakeClient())
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)
{
AdminId id = adminsys->FindAdminByIdentity("name", new_name);
if (id != INVALID_ADMIN_ID && pPlayer->GetAdminId() != id)
@ -1366,26 +1372,21 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
pPlayer->Kick(kickMsg);
RETURN_META(MRES_IGNORED);
}
}
else if ((id = adminsys->FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
} 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)
{
/* 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());
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);
@ -1396,21 +1397,6 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
}
}
}
#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 +1410,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;
@ -1596,10 +1575,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 +2011,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 +2019,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;
}
@ -2114,8 +2088,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
@ -2291,7 +2264,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 +2273,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 +2306,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 +2326,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 +2347,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 +2357,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 +2491,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);
@ -2646,7 +2624,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 +2640,7 @@ unsigned int CPlayer::GetLanguageId()
void CPlayer::SetLanguageId(unsigned int id)
{
if(m_LangId != id)
{
m_LangId = id;
g_Players.OnClientLanguageChanged(m_iIndex, id);
}
}
int CPlayer::GetUserId()

View File

@ -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,10 +151,10 @@ 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 :
@ -193,7 +193,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);
@ -217,9 +216,6 @@ public: //IPlayerManager
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 +239,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 +257,6 @@ private:
IForward *m_clcommandkv_post;
IForward *m_clinfochanged;
IForward *m_clauth;
IForward *m_cllang;
IForward *m_onActivate;
IForward *m_onActivate2;
CPlayer *m_Players;

View File

@ -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;
}

View File

@ -816,7 +816,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 +837,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 +856,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 +878,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 +898,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();

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -1,8 +1,8 @@
# 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')
for arch in SM.archs:
binary = SM.Library(builder, 'sourcemod.logic', arch)
binary.compiler.cxxincludes += [
builder.sourcePath,
os.path.join(builder.sourcePath, 'core', 'logic'),
@ -17,9 +17,9 @@ for cxx in builder.targets:
'SM_LOGIC'
]
if binary.compiler.target.platform == 'linux':
if builder.target.platform == 'linux':
binary.compiler.postlink += ['-lpthread', '-lrt']
elif binary.compiler.target.platform == 'mac':
elif builder.target.platform == 'mac':
binary.compiler.cflags += ['-Wno-deprecated-declarations']
binary.compiler.postlink += ['-framework', 'CoreServices']
@ -35,7 +35,8 @@ for cxx in builder.targets:
'smn_maplists.cpp',
'ADTFactory.cpp',
'smn_adt_stack.cpp',
'BaseWorker.cpp',
'thread/ThreadWorker.cpp',
'thread/BaseWorker.cpp',
'ThreadSupport.cpp',
'smn_float.cpp',
'TextParsers.cpp',
@ -84,12 +85,15 @@ for cxx in builder.targets:
'smn_halflife.cpp',
'FrameIterator.cpp',
'DatabaseConfBuilder.cpp',
'LumpManager.cpp',
'smn_entitylump.cpp',
'NativeInvoker.cpp',
]
if binary.compiler.target.arch == 'x86_64':
if arch == 'x64':
binary.sources += ['PseudoAddrManager.cpp']
if builder.target.platform == 'windows':
binary.sources += ['thread/WinThreads.cpp']
else:
binary.sources += ['thread/PosixThreads.cpp']
SM.binaries += [builder.Add(binary)]

View File

@ -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);

View File

@ -31,10 +31,8 @@
#include <stdlib.h>
#include <string.h>
#include <memory>
#include "CDataPack.h"
#include <amtl/am-autoptr.h>
CDataPack::CDataPack()
{
@ -46,15 +44,33 @@ CDataPack::~CDataPack()
Initialize();
}
static ke::Vector<ke::AutoPtr<CDataPack>> sDataPackCache;
CDataPack *CDataPack::New()
{
if (sDataPackCache.empty())
return new CDataPack();
CDataPack *pack = sDataPackCache.back().take();
sDataPackCache.pop();
pack->Initialize();
return pack;
}
void
CDataPack::Free(CDataPack *pack)
{
sDataPackCache.append(static_cast<CDataPack *>(pack));
}
void CDataPack::Initialize()
{
position = 0;
do
{
} while (this->RemoveItem());
elements.clear();
position = 0;
}
void CDataPack::ResetSize()
@ -68,7 +84,7 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
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);
elements.insert(position, val);
return position++;
}
@ -78,8 +94,7 @@ void CDataPack::PackCell(cell_t cell)
InternalPack val;
val.type = CDataPackType::Cell;
val.pData.cval = cell;
elements.emplace(elements.begin() + position, val);
position++;
elements.insert(position++, val);
}
void CDataPack::PackFunction(cell_t function)
@ -87,8 +102,7 @@ void CDataPack::PackFunction(cell_t function)
InternalPack val;
val.type = CDataPackType::Function;
val.pData.cval = function;
elements.emplace(elements.begin() + position, val);
position++;
elements.insert(position++, val);
}
void CDataPack::PackFloat(float floatval)
@ -96,42 +110,16 @@ void CDataPack::PackFloat(float floatval)
InternalPack val;
val.type = CDataPackType::Float;
val.pData.fval = floatval;
elements.emplace(elements.begin() + position, val);
position++;
elements.insert(position++, val);
}
void CDataPack::PackString(const char *string)
{
InternalPack val;
val.type = CDataPackType::String;
std::string *sval = new std::string(string);
ke::AString *sval = new ke::AString(string);
val.pData.sval = sval;
elements.emplace(elements.begin() + position, val);
position++;
}
void CDataPack::PackCellArray(cell_t const *vals, cell_t count)
{
InternalPack val;
val.type = CDataPackType::CellArray;
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++;
}
void CDataPack::PackFloatArray(cell_t const *vals, cell_t count)
{
InternalPack val;
val.type = CDataPackType::FloatArray;
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++;
elements.insert(position++, val);
}
void CDataPack::Reset() const
@ -146,7 +134,7 @@ size_t CDataPack::GetPosition() const
bool CDataPack::SetPosition(size_t pos) const
{
if (pos > elements.size())
if (pos > elements.length())
return false;
position = pos;
@ -179,7 +167,7 @@ float CDataPack::ReadFloat() const
bool CDataPack::IsReadable(size_t bytes) const
{
return (position < elements.size());
return (position < elements.length());
}
const char *CDataPack::ReadString(size_t *len) const
@ -192,51 +180,11 @@ const char *CDataPack::ReadString(size_t *len) const
return nullptr;
}
const std::string &val = *elements[position++].pData.sval;
const ke::AString &val = *elements[position++].pData.sval;
if (len)
*len = val.size();
*len = val.length();
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;
}
cell_t *val = elements[position].pData.aval;
cell_t *ptr = &(val[1]);
++position;
if (size)
*size = val[0];
return ptr;
}
cell_t *CDataPack::ReadFloatArray(cell_t *size) 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 val.chars();
}
void *CDataPack::ReadMemory(size_t *size) const
@ -257,7 +205,7 @@ void *CDataPack::ReadMemory(size_t *size) const
bool CDataPack::RemoveItem(size_t pos)
{
if (!elements.size())
if (!elements.length())
{
return false;
}
@ -266,8 +214,7 @@ bool CDataPack::RemoveItem(size_t pos)
{
pos = position;
}
if (pos >= elements.size())
if (pos >= elements.length())
{
return false;
}
@ -281,7 +228,7 @@ bool CDataPack::RemoveItem(size_t pos)
{
case CDataPackType::Raw:
{
delete [] elements[pos].pData.vval;
delete elements[pos].pData.vval;
break;
}
@ -290,15 +237,8 @@ bool CDataPack::RemoveItem(size_t pos)
delete elements[pos].pData.sval;
break;
}
case CDataPackType::CellArray:
case CDataPackType::FloatArray:
{
delete [] elements[pos].pData.aval;
break;
}
}
elements.erase(elements.begin() + pos);
elements.remove(pos);
return true;
}

View File

@ -43,9 +43,7 @@ enum CDataPackType {
Cell,
Float,
String,
Function,
CellArray,
FloatArray,
Function
};
class CDataPack
@ -54,6 +52,9 @@ public:
CDataPack();
~CDataPack();
static CDataPack *New();
static void Free(CDataPack *pack);
public: // Originally IDataReader
/**
* @brief Resets the position in the data stream to the beginning.
@ -89,21 +90,6 @@ public: // Originally IDataReader
*/
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.
@ -164,21 +150,6 @@ public: // Originally IDataPack
*/
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.
*
@ -201,7 +172,7 @@ public: // Originally IDataPack
public:
void Initialize();
inline size_t GetCapacity() const { return this->elements.size(); };
inline size_t GetCapacity() const { return this->elements.length(); };
inline CDataPackType GetCurrentType(void) const { return this->elements[this->position].type; };
bool RemoveItem(size_t pos = -1);
@ -210,8 +181,7 @@ private:
cell_t cval;
float fval;
uint8_t *vval;
std::string *sval;
cell_t *aval;
ke::AString *sval;
} InternalPackValue;
typedef struct {
@ -219,7 +189,7 @@ private:
CDataPackType type;
} InternalPack;
std::vector<InternalPack> elements;
ke::Vector<InternalPack> elements;
mutable size_t position;
};

View File

@ -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,30 @@ 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))
m_AllocSize *= 2;
}
/* finally, allocate the new block */
if (m_Data)
{
cell_t *data = static_cast<cell_t*>(realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize));
if (!data) // allocation failure
{
return false;
}
newAllocSize *= 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)
{
m_AllocSize = newAllocSize;
m_Data = data;
} else {
m_Data = static_cast<cell_t*>(malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize));
}
return (data != nullptr);
return (m_Data != nullptr);
}
private:
cell_t *m_Data;

View File

@ -34,20 +34,17 @@
#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),
@ -128,8 +125,8 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
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);
ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> pInfo = list->GetDatabaseConf(name);
if (!pInfo)
{
@ -148,12 +145,12 @@ 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();
ke::AString defaultDriver = list->GetDefaultDriver();
if (!m_pDefault && defaultDriver.length() > 0)
{
m_pDefault = FindOrLoadDriver(defaultDriver.c_str());
m_pDefault = FindOrLoadDriver(defaultDriver.chars());
}
dname = defaultDriver.length() ? defaultDriver.c_str() : "default";
dname = defaultDriver.length() ? defaultDriver.chars() : "default";
pInfo->realDriver = m_pDefault;
} else {
pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
@ -209,14 +206,17 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
}
}
ConfDbInfoList &list = m_Builder.GetConfigList();
for (auto conf : list) {
if (conf->realDriver == pDriver)
ConfDbInfoList *list = m_Builder.GetConfigList();
for (size_t i = 0; i < list->length(); i++)
{
conf->realDriver = NULL;
ke::RefPtr<ConfDbInfo> current = list->at(i);
if (current->realDriver == pDriver)
{
current->realDriver = NULL;
}
}
/* Someone unloaded the default driver? Silly.. */
if (pDriver == m_pDefault)
{
@ -252,11 +252,11 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
IDBDriver *DBManager::GetDefaultDriver()
{
ConfDbInfoList &list = m_Builder.GetConfigList();
std::string defaultDriver = list.GetDefaultDriver();
ConfDbInfoList *list = m_Builder.GetConfigList();
ke::AString defaultDriver = list->GetDefaultDriver();
if (!m_pDefault && defaultDriver.length() > 0)
{
m_pDefault = FindOrLoadDriver(defaultDriver.c_str());
m_pDefault = FindOrLoadDriver(defaultDriver.chars());
}
return m_pDefault;
@ -319,12 +319,12 @@ 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);
ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> info = list->GetDatabaseConf(name);
if (!info)
{
// couldn't find requested conf, return default if exists
info = list.GetDefaultConfiguration();
info = list->GetDefaultConfiguration();
if (!info)
{
return NULL;
@ -334,10 +334,11 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
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);
ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> info(list->GetDatabaseConf(name));
return info;
}
IDBDriver *DBManager::FindOrLoadDriver(const char *name)
@ -376,12 +377,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 +399,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 +450,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,19 +458,14 @@ 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;
while (true)
{
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
if (queue.empty())
break;
// Otherwise, wait for something to happen.
m_QueueEvent.wait(lock);
continue;
}
IDBThreadOperation *op = queue->first();
queue->pop();
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
@ -466,23 +473,31 @@ void DBManager::ThreadMain()
// 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();
{
ke::AutoUnlock unlock(&m_QueueEvent);
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.
{
std::lock_guard<std::mutex> think_lock(m_ThinkLock);
ke::AutoLock lock(&m_ThinkLock);
m_ThinkQueue.push(op);
}
// 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);
lock.lock();
if (!m_Terminate)
{
ke::AutoUnlock unlock(&m_QueueEvent);
#ifdef _WIN32
Sleep(20);
#else
usleep(20000);
#endif
}
}
if (m_Terminate)
return;
// Release the lock and wait for a signal.
m_QueueEvent.Wait();
}
}
@ -497,7 +512,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,10 +591,10 @@ void DBManager::OnPluginWillUnload(IPlugin *plugin)
}
}
std::string DBManager::GetDefaultDriverName()
ke::AString DBManager::GetDefaultDriverName()
{
ConfDbInfoList &list = m_Builder.GetConfigList();
return list.GetDefaultDriver();
ConfDbInfoList *list = m_Builder.GetConfigList();
return list->GetDefaultDriver();
}
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)

View File

@ -38,10 +38,7 @@
#include <sh_list.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"
@ -71,7 +68,7 @@ public: //IDBManager
void AddDriver(IDBDriver *pDrivera);
void RemoveDriver(IDBDriver *pDriver);
const DatabaseInfo *FindDatabaseConf(const char *name);
ke::RefPtr<ConfDbInfo> GetDatabaseConf(const char *name);
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);
@ -87,7 +84,7 @@ public: //IPluginsListener
public:
IDBDriver *FindOrLoadDriver(const char *name);
IDBDriver *GetDefaultDriver();
std::string GetDefaultDriverName();
ke::AString GetDefaultDriverName();
bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio);
void RunFrame();
inline HandleType_t GetDatabaseType()
@ -104,10 +101,9 @@ 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_ThinkLock;
bool m_Terminate;
DatabaseConfBuilder m_Builder;

View File

@ -36,8 +36,8 @@
#define DBPARSE_LEVEL_DATABASE 2
DatabaseConfBuilder::DatabaseConfBuilder()
: m_ParseList(),
m_InfoList()
: m_ParseList(nullptr),
m_InfoList(new ConfDbInfoList())
{
}
@ -50,7 +50,7 @@ DatabaseConfBuilder::~DatabaseConfBuilder()
{
}
ConfDbInfoList &DatabaseConfBuilder::GetConfigList()
ConfDbInfoList *DatabaseConfBuilder::GetConfigList()
{
return m_InfoList;
}
@ -59,9 +59,9 @@ void DatabaseConfBuilder::StartParse()
{
SMCError err;
SMCStates states = {0, 0};
if ((err = textparsers->ParseFile_SMC(m_Filename.c_str(), this, &states)) != SMCError_Okay)
if ((err = textparsers->ParseFile_SMC(m_Filename.chars(), this, &states)) != SMCError_Okay)
{
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename.c_str());
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename.chars());
if (err != SMCError_Custom)
{
const char *txt = textparsers->GetSMCErrorString(err);
@ -75,7 +75,7 @@ void DatabaseConfBuilder::ReadSMC_ParseStart()
m_ParseLevel = 0;
m_ParseState = DBPARSE_LEVEL_NONE;
m_ParseList.clear();
m_ParseList = new ConfDbInfoList();
}
SMCResult DatabaseConfBuilder::ReadSMC_NewSection(const SMCStates *states, const char *name)
@ -116,7 +116,7 @@ SMCResult DatabaseConfBuilder::ReadSMC_KeyValue(const SMCStates *states, const c
{
if (strcmp(key, "driver_default") == 0)
{
m_ParseList.SetDefaultDriver(value);
m_ParseList->SetDefaultDriver(value);
}
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
if (strcmp(key, "driver") == 0)
@ -153,15 +153,15 @@ SMCResult DatabaseConfBuilder::ReadSMC_LeavingSection(const SMCStates *states)
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();
m_ParseCurrent->info.driver = m_ParseCurrent->driver.chars();
m_ParseCurrent->info.database = m_ParseCurrent->database.chars();
m_ParseCurrent->info.host = m_ParseCurrent->host.chars();
m_ParseCurrent->info.user = m_ParseCurrent->user.chars();
m_ParseCurrent->info.pass = m_ParseCurrent->pass.chars();
/* Save it.. */
m_ParseCurrent->AddRef();
m_ParseList.push_back(m_ParseCurrent);
m_ParseList->append(m_ParseCurrent);
m_ParseCurrent = nullptr;
/* Go up one level */
@ -176,7 +176,9 @@ SMCResult DatabaseConfBuilder::ReadSMC_LeavingSection(const SMCStates *states)
void DatabaseConfBuilder::ReadSMC_ParseEnd(bool halted, bool failed)
{
m_InfoList.clear();
m_InfoList->ReleaseMembers();
delete m_InfoList;
m_InfoList = m_ParseList;
m_ParseList.clear();
m_ParseList = nullptr;
}

View File

@ -38,7 +38,6 @@
#include <am-vector.h>
#include <am-string.h>
#include <am-refcounting.h>
#include <am-refcounting-threadsafe.h>
class ConfDbInfo : public ke::RefcountedThreadsafe<ConfDbInfo>
@ -47,53 +46,58 @@ public:
ConfDbInfo() : realDriver(NULL)
{
}
std::string name;
std::string driver;
std::string host;
std::string user;
std::string pass;
std::string database;
ke::AString name;
ke::AString driver;
ke::AString host;
ke::AString user;
ke::AString pass;
ke::AString database;
IDBDriver *realDriver;
DatabaseInfo info;
};
class ConfDbInfoList : public std::vector<ke::RefPtr<ConfDbInfo>>
class ConfDbInfoList : public ke::Vector<ConfDbInfo *>
{
/* Allow internal usage of ConfDbInfoList */
friend class DBManager;
friend class DatabaseConfBuilder;
private:
std::string& GetDefaultDriver() {
ke::AString& GetDefaultDriver() {
return m_DefDriver;
}
ke::RefPtr<ConfDbInfo> GetDatabaseConf(const char *name) {
for (size_t i = 0; i < this->size(); i++)
ConfDbInfo *GetDatabaseConf(const char *name) {
for (size_t i = 0; i < this->length(); i++)
{
ke::RefPtr<ConfDbInfo> current = this->at(i);
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)
if (strcmp(current->name.chars(), "default") == 0)
{
m_DefaultConfig = current;
}
if (strcmp(current->name.c_str(), name) == 0)
if (strcmp(current->name.chars(), name) == 0)
{
return current;
}
}
return nullptr;
}
ke::RefPtr<ConfDbInfo> GetDefaultConfiguration() {
ConfDbInfo *GetDefaultConfiguration() {
return m_DefaultConfig;
}
void SetDefaultDriver(const char *input) {
m_DefDriver = std::string(input);
m_DefDriver = ke::AString(input);
}
void ReleaseMembers() {
for (size_t i = 0; i < this->length(); i++) {
ConfDbInfo *current = this->at(i);
current->Release();
}
}
private:
ke::RefPtr<ConfDbInfo> m_DefaultConfig;
std::string m_DefDriver;
ConfDbInfo *m_DefaultConfig;
ke::AString m_DefDriver;
};
@ -104,7 +108,7 @@ public:
~DatabaseConfBuilder();
void StartParse();
void SetPath(char* path);
ConfDbInfoList &GetConfigList();
ConfDbInfoList *GetConfigList();
public: //ITextListener_SMC
void ReadSMC_ParseStart();
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
@ -116,10 +120,10 @@ private:
unsigned int m_ParseLevel;
unsigned int m_ParseState;
ConfDbInfo *m_ParseCurrent;
ConfDbInfoList m_ParseList;
ConfDbInfoList *m_ParseList;
private:
std::string m_Filename;
ConfDbInfoList m_InfoList;
ke::AString m_Filename;
ConfDbInfoList *m_InfoList;
};
#endif //_INCLUDE_DATABASE_CONF_BUILDER_H_

View File

@ -69,12 +69,12 @@ 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();
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
} else {
g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
}
@ -194,22 +194,22 @@ 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++)
ke::Vector<ke::AString> arr = GetStackTrace(&iter);
for (size_t i = 0; i < arr.length(); i++)
{
g_Logger.LogError("%s", arr[i].c_str());
g_Logger.LogError("%s", arr[i].chars());
}
}
std::vector<std::string> DebugReport::GetStackTrace(IFrameIterator *iter)
ke::Vector<ke::AString> DebugReport::GetStackTrace(IFrameIterator *iter)
{
char temp[3072];
std::vector<std::string> trace;
ke::Vector<ke::AString> trace;
iter->Reset();
if (!iter->Done())
{
trace.push_back("[SM] Call stack trace:");
trace.append("[SM] Call stack trace:");
for (int index = 0; !iter->Done(); iter->Next(), index++)
{
@ -221,7 +221,7 @@ std::vector<std::string> DebugReport::GetStackTrace(IFrameIterator *iter)
if (iter->IsNativeFrame())
{
g_pSM->Format(temp, sizeof(temp), "[SM] [%d] %s", index, fn);
trace.push_back(temp);
trace.append(temp);
continue;
}
if (iter->IsScriptedFrame())
@ -237,7 +237,7 @@ std::vector<std::string> DebugReport::GetStackTrace(IFrameIterator *iter)
file,
fn);
trace.push_back(temp);
trace.append(temp);
}
}
}

View File

@ -47,12 +47,10 @@ 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);
ke::Vector<ke::AString> GetStackTrace(IFrameIterator *iter);
private:
int _GetPluginIndex(IPluginContext *ctx);
};

View File

@ -30,9 +30,6 @@
*/
#include <stdlib.h>
#include <memory>
#include "ExtensionSys.h"
#include <ILibrarySys.h>
#include <ISourceMod.h>
@ -79,7 +76,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/" PLATFORM_ARCH_FOLDER "%s." PLATFORM_LIB_EXT,
"extensions/%s." PLATFORM_LIB_EXT,
filename);
}
else
@ -88,7 +85,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/" PLATFORM_ARCH_FOLDER "%s.%s." PLATFORM_LIB_EXT,
"extensions/%s.%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
@ -103,7 +100,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/" PLATFORM_ARCH_FOLDER "%s.2.ep2v." PLATFORM_LIB_EXT,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
}
else if (strcmp(bridge->gamesuffix, "2.nd") == 0)
@ -111,7 +108,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/" PLATFORM_ARCH_FOLDER "%s.2.l4d2." PLATFORM_LIB_EXT,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
}
@ -122,7 +119,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/" PLATFORM_ARCH_FOLDER "auto.%s/%s." PLATFORM_LIB_EXT,
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
@ -132,7 +129,7 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/" PLATFORM_ARCH_FOLDER "%s." PLATFORM_LIB_EXT,
"extensions/%s." PLATFORM_LIB_EXT,
filename);
}
}
@ -240,8 +237,6 @@ void CLocalExtension::Unload()
m_pLib->CloseLibrary();
m_pLib = NULL;
}
m_bFullyLoaded = false;
}
bool CRemoteExtension::Reload(char *error, size_t maxlength)
@ -306,7 +301,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;
@ -501,7 +496,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;
@ -633,15 +628,9 @@ 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);
@ -1182,6 +1171,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);
@ -1374,7 +1364,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;
}

View File

@ -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()

View File

@ -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();
}

View File

@ -48,17 +48,15 @@ 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();
}
};
@ -75,5 +73,5 @@ public:
private:
size_t current;
std::vector<FrameInfo> frames;
ke::Vector<FrameInfo> frames;
};

View File

@ -85,12 +85,15 @@ static const char *g_pParseEngine = NULL;
#if defined PLATFORM_WINDOWS
#define PLATFORM_NAME "windows" PLATFORM_ARCH_SUFFIX
#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_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_SERVER_BINARY "server.dylib"
#endif
struct TempSigInfo
@ -150,23 +153,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 +160,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 +206,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 +222,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. */
@ -277,23 +261,23 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
}
case PSTATE_GAMEDEFS_KEYS:
{
m_Key = name;
strncopy(m_Key, name, sizeof(m_Key));
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 +296,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 +319,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 +334,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;
@ -374,7 +355,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
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)
{
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;
@ -411,21 +392,21 @@ 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));
ke::AString vstr(value);
m_Keys.replace(key, ke::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(m_Key, ke::Move(vstr));
}
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
if (strcmp(key, "game") == 0)
@ -476,7 +457,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 +465,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);
@ -548,24 +529,25 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
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 +655,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 +671,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;
@ -809,12 +791,9 @@ public:
(!had_engine && matched_game) ||
(!had_game && matched_engine) ||
(matched_engine && matched_game))
{
if (fileList->find(cur_file) == fileList->end())
{
fileList->push_back(cur_file);
}
}
state = MSTATE_MAIN;
}
else if (state == MSTATE_MAIN)
@ -1022,10 +1001,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 +1022,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 +1055,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 +1132,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);

View File

@ -81,16 +81,16 @@ 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];
char m_Key[64];
bool bShouldBeReadingDefault;
bool had_game;
bool matched_game;
@ -105,25 +105,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 :

View File

@ -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,7 +1090,7 @@ 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)
@ -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);
}

View File

@ -32,27 +32,22 @@
#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-autoptr.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 +88,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 +105,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 +117,7 @@ struct QHandleType
}
};
typedef ke::Function<void(const char *)> HandleReporter;
typedef ke::Lambda<void(const char *)> HandleReporter;
class HandleSystem :
public IHandleSys

View File

@ -319,7 +319,7 @@ void Logger::_UpdateFiles(bool bLevelChange)
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);
ke::AString currentDate(buff);
if (m_Mode == LoggingMode_PerMap)
{
@ -327,7 +327,7 @@ void Logger::_UpdateFiles(bool 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);
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s%u.log", currentDate.chars(), iter);
if (!libsys->IsPathFile(buff))
{
break;
@ -336,12 +336,12 @@ void Logger::_UpdateFiles(bool bLevelChange)
}
else
{
ke::SafeStrcpy(buff, sizeof(buff), m_NormalFileName.c_str());
ke::SafeStrcpy(buff, sizeof(buff), m_NormalFileName.chars());
}
}
else
{
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s.log", currentDate.c_str());
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s.log", currentDate.chars());
}
if (m_NormalFileName.compare(buff))
@ -353,11 +353,11 @@ void Logger::_UpdateFiles(bool bLevelChange)
{
if (bLevelChange)
{
LogMessage("-------- Mapchange to %s --------", m_CurrentMapName.c_str());
LogMessage("-------- Mapchange to %s --------", m_CurrentMapName.chars());
}
}
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/errors_%s.log", currentDate.c_str());
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/errors_%s.log", currentDate.chars());
if (bLevelChange || m_ErrorFileName.compare(buff))
{
_CloseError();
@ -369,7 +369,7 @@ FILE *Logger::_OpenNormal()
{
_UpdateFiles();
FILE *pFile = fopen(m_NormalFileName.c_str(), "a+");
FILE *pFile = fopen(m_NormalFileName.chars(), "a+");
if (pFile == NULL)
{
_LogFatalOpen(m_NormalFileName);
@ -383,7 +383,7 @@ FILE *Logger::_OpenNormal()
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);
fprintf(pFile, "L %s: SourceMod log file session started (file \"%s\") (Version \"%s\")\n", date, m_NormalFileName.chars(), SOURCEMOD_VERSION);
m_DamagedNormalFile = true;
}
@ -394,7 +394,7 @@ FILE *Logger::_OpenError()
{
_UpdateFiles();
FILE *pFile = fopen(m_ErrorFileName.c_str(), "a+");
FILE *pFile = fopen(m_ErrorFileName.chars(), "a+");
if (pFile == NULL)
{
_LogFatalOpen(m_ErrorFileName);
@ -409,7 +409,7 @@ FILE *Logger::_OpenError()
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());
fprintf(pFile, "L %s: Info (map \"%s\") (file \"%s\")\n", date, m_CurrentMapName.chars(), m_ErrorFileName.chars());
m_DamagedErrorFile = true;
}
@ -423,11 +423,11 @@ FILE *Logger::_OpenFatal()
return fopen(path, "at");
}
void Logger::_LogFatalOpen(std::string &str)
void Logger::_LogFatalOpen(ke::AString &str)
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", str.c_str());
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", str.chars());
LogFatal("[SM] Platform returned error: \"%s\"", error);
}

View File

@ -92,13 +92,13 @@ private:
FILE *_OpenError();
FILE *_OpenFatal();
void _LogFatalOpen(std::string &str);
void _LogFatalOpen(ke::AString &str);
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;
ke::AString m_NormalFileName;
ke::AString m_ErrorFileName;
ke::AString m_CurrentMapName;
int m_Day;

View File

@ -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();
}

View File

@ -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_

View File

@ -49,7 +49,6 @@ MemoryUtils g_MemUtils;
MemoryUtils::MemoryUtils()
{
m_InfoMap.init();
#ifdef PLATFORM_APPLE
task_dyld_info_data_t dyld_info;
@ -78,19 +77,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 +103,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,8 +116,6 @@ 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
@ -165,9 +162,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)
{
@ -332,9 +326,6 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
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++)
{
@ -438,25 +429,21 @@ 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;
@ -467,7 +454,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 +466,21 @@ 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)
{
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 */
@ -520,12 +507,12 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
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 */
@ -535,31 +522,31 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
/* 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;
return false;
}
/* 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)
{
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;
@ -609,12 +596,12 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
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 */
@ -624,19 +611,19 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
/* Check Mach-O magic */
if (file->magic != MACH_MAGIC)
{
return nullptr;
return false;
}
/* Check architecture */
if (file->cputype != MACH_CPU_TYPE || file->cpusubtype != MACH_CPU_SUBTYPE)
{
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;
@ -657,17 +644,5 @@ const DynLibInfo *MemoryUtils::GetLibraryInfo(const void *libPtr)
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;
}

View File

@ -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;

View File

@ -33,6 +33,7 @@
#include <IShareSys.h>
#include <IHandleSys.h>
#include <am-autoptr.h>
#include <am-string.h>
#include <am-utility.h>
#include <am-refcounting.h>
@ -46,14 +47,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 +64,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)

View File

@ -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 */

View File

@ -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"

View File

@ -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();
}

View File

@ -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;

View File

@ -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>
@ -78,7 +79,7 @@ CPlugin::CPlugin(const char *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)
@ -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());
@ -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)
@ -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,
@ -1729,7 +1715,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
rootmenu->ConsolePrint("[SM] Listing %d plugin%s:", plnum, (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);
@ -1741,7 +1727,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
len += ke::SafeSprintf(buffer, sizeof(buffer), " %0*d <%s>", plpadding, id, GetStatusText(pl->GetDisplayStatus()));
/* Plugin has failed to load. */
fail_list.push_back(pl);
fail_list.append(pl);
}
else
{
@ -2047,8 +2033,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 +2063,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 +2078,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;
}
@ -2223,6 +2208,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 +2273,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 +2351,7 @@ public:
{
ke::RefPtr<PluginsListenerV1Wrapper> wrapper = new PluginsListenerV1Wrapper(listener);
v1_wrappers_.push_back(wrapper);
v1_wrappers_.append(wrapper);
g_PluginSys.AddPluginsListener(wrapper);
}

View File

@ -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>
@ -132,10 +129,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 +215,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 +224,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 +267,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 +286,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 +317,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 +432,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 +473,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 +484,10 @@ 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();
ke::AString original(key.chars());
ke::AString lower = original.lowercase();
return detail::CharsAndLength(lower.chars()).hash();
#else
return key.hash();
#endif
@ -498,8 +497,8 @@ private:
{
const char *pluginFileChars = const_cast<CPlugin*>(plugin)->GetFilename();
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
std::string pluginFile = ke::Lowercase(pluginFileChars);
std::string input = ke::Lowercase(file);
ke::AString pluginFile = ke::AString(pluginFileChars).lowercase();
ke::AString input = ke::AString(file).lowercase();
return pluginFile == input;
#else
@ -523,7 +522,6 @@ private:
// Forwards
IForward *m_pOnLibraryAdded;
IForward *m_pOnLibraryRemoved;
IForward *m_pOnNotifyPluginUnloaded;
};
extern CPluginManager g_PluginSys;

View File

@ -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.");

View File

@ -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_;

View File

@ -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)
{

View File

@ -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;
@ -364,11 +361,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 +379,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 +400,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();

View File

@ -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;
};
};

View File

@ -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, &params);
}
IThreadHandle *CompatWorker::MakeThread(IThread *pThread, ThreadFlags flags)
{
ThreadParams params;
params.flags = flags;
return MakeThread(pThread, &params);
}
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, &params);
}
IThreadHandle *CompatThreader::MakeThread(IThread *pThread, ThreadFlags flags)
{
ThreadParams params;
params.flags = flags;
return MakeThread(pThread, &params);
}
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
{

View File

@ -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

View File

@ -56,7 +56,6 @@
#include "LibrarySys.h"
#include "RootConsoleMenu.h"
#include "CellArray.h"
#include "smn_entitylump.h"
#include <bridge/include/BridgeAPI.h>
#include <bridge/include/IProviderCallbacks.h>
@ -90,8 +89,6 @@ CNativeOwner g_CoreNatives;
PseudoAddressManager pseudoAddr;
#endif
EntityLumpParseResult lastParseResult;
static void AddCorePhraseFile(const char *filename)
{
g_pCorePhrases->AddPhraseFile(filename);
@ -138,35 +135,6 @@ static uint32_t ToPseudoAddress(void *addr)
#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);
@ -202,9 +170,6 @@ static sm_logic_t logic =
CellArray::Free,
FromPseudoAddress,
ToPseudoAddress,
SetEntityLumpWritable,
ParseEntityLumpString,
GetEntityLumpString,
&g_PluginSys,
&g_ShareSys,
&g_Extensions,

View File

@ -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();
}

View File

@ -31,7 +31,7 @@
namespace SourceMod {
void ScheduleTaskForNextFrame(ke::Function<void()>&& task);
void ScheduleTaskForNextFrame(ke::Lambda<void()>&& task);
void RunScheduledFrameTasks(bool simulating);

View File

@ -89,6 +89,6 @@ unsigned int UTIL_CRC32(const void *pdata, size_t data_length)
crc = CRCTable[c] ^ (crc >> 8);
}
return ~crc;
return crc;
}

View File

@ -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);

View File

@ -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},

View File

@ -30,10 +30,9 @@
*/
#include <stdlib.h>
#include <memory>
#include "common_logic.h"
#include <am-autoptr.h>
#include <am-moveable.h>
#include <am-refcounting.h>
#include <sm_stringhashmap.h>
#include "sm_memtable.h"
@ -104,7 +103,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 +182,7 @@ struct TrieSnapshot
}
size_t length;
std::unique_ptr<int[]> keys;
ke::AutoPtr<int[]> keys;
BaseStringTable strings;
};
@ -350,27 +349,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 +517,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 +557,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 +635,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 +659,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},

View File

@ -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;

View File

@ -32,7 +32,6 @@
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <list>
#include "common_logic.h"
#include "Logger.h"
@ -46,7 +45,6 @@
#if defined PLATFORM_WINDOWS
#include <windows.h>
#include "sm_invalidparamhandler.h"
#elif defined PLATFORM_POSIX
#include <limits.h>
#include <unistd.h>
@ -57,7 +55,6 @@
#include <bridge/include/CoreProvider.h>
#include <bridge/include/IScriptManager.h>
#include <bridge/include/IExtensionBridge.h>
#include <sh_vector.h>
using namespace SourceMod;
using namespace SourcePawn;
@ -68,7 +65,7 @@ HandleType_t g_FrameIter;
IForward *g_OnLogAction = NULL;
ConVar *g_datetime_format = NULL;
static ConVar *sm_datetime_format = NULL;
class CoreNativeHelpers :
public SMGlobalClass,
@ -94,7 +91,7 @@ public:
Param_Cell,
Param_String);
g_datetime_format = bridge->FindConVar("sm_datetime_format");
sm_datetime_format = bridge->FindConVar("sm_datetime_format");
}
void OnHandleDestroy(HandleType_t type, void *object)
{
@ -116,71 +113,6 @@ public:
}
} g_CoreNativeHelpers;
/**
* @brief Nearly identical to the standard core plugin iterator
* with one key difference. Next doesn't increment the counter
* the first time it is ran. This is a hack for the methodmap..
*/
class CMMPluginIterator
: public IPluginIterator,
public IPluginsListener
{
public:
CMMPluginIterator(const CVector<SMPlugin *> *list)
: m_hasStarted(false)
{
for(auto iter = list->begin(); iter != list->end(); ++iter) {
m_list.push_back(*iter);
}
scripts->FreePluginList(list);
m_current = m_list.begin();
scripts->AddPluginsListener(this);
}
virtual ~CMMPluginIterator()
{
scripts->RemovePluginsListener(this);
}
virtual bool MorePlugins() override
{
return (m_current != m_list.end());
}
virtual IPlugin *GetPlugin() override
{
return *m_current;
}
virtual void NextPlugin() override
{
if(!m_hasStarted)
{
m_hasStarted = true;
return;
}
m_current++;
}
virtual void Release() override
{
delete this;
}
public:
virtual void OnPluginDestroyed(IPlugin *plugin) override
{
if (*m_current == plugin)
m_current = m_list.erase(m_current);
else
m_list.remove(static_cast<SMPlugin *>(plugin));
}
private:
std::list<SMPlugin *> m_list;
std::list<SMPlugin *>::iterator m_current;
bool m_hasStarted;
};
void LogAction(Handle_t hndl, int type, int client, int target, const char *message)
{
if (g_OnLogAction->GetFunctionCount())
@ -213,7 +145,7 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess
g_Logger.LogMessage("[%s] %s", logtag, message);
}
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
{
char buffer[512];
@ -241,6 +173,19 @@ static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
return static_cast<cell_t>(t);
}
#if defined SUBPLATFORM_SECURECRT
void _ignore_invalid_parameter(
const wchar_t * expression,
const wchar_t * function,
const wchar_t * file,
unsigned int line,
uintptr_t pReserved
)
{
/* Wow we don't care, thanks Microsoft. */
}
#endif
static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
{
char *format, *buffer;
@ -249,20 +194,19 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
if (format == NULL)
{
format = const_cast<char *>(bridge->GetCvarString(g_datetime_format));
format = const_cast<char *>(bridge->GetCvarString(sm_datetime_format));
}
time_t t;
size_t written = 0;
// scope for InvalidParameterHandler
{
#ifdef PLATFORM_WINDOWS
InvalidParameterHandler p;
#if defined SUBPLATFORM_SECURECRT
_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
#endif
time_t t = (params[4] == -1) ? g_pSM->GetAdjustedTime() : (time_t)params[4];
size_t written = strftime(buffer, params[2], format, localtime(&t));
#if defined SUBPLATFORM_SECURECRT
_set_invalid_parameter_handler(handler);
#endif
t = (params[4] == -1) ? g_pSM->GetAdjustedTime() : (time_t)params[4];
written = strftime(buffer, params[2], format, localtime(&t));
}
if (params[2] && format[0] != '\0' && !written)
{
@ -331,60 +275,6 @@ static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
return pPlugin->GetMyHandle();
}
static cell_t PluginIterator_Create(IPluginContext *pContext, const cell_t *params)
{
IPluginIterator *iter = new CMMPluginIterator(scripts->ListPlugins());
Handle_t hndl = handlesys->CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE)
{
iter->Release();
}
return hndl;
}
static cell_t PluginIterator_Next(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleSecurity sec{pContext->GetIdentity(), g_pCoreIdent};
HandleError err{};
IPluginIterator *pIter = nullptr;
if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
{
return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
}
if(!pIter->MorePlugins())
return 0;
pIter->NextPlugin();
return 1;
}
static cell_t PluginIterator_Plugin_get(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = (Handle_t)params[1];
HandleSecurity sec{pContext->GetIdentity(), g_pCoreIdent};
HandleError err{};
IPluginIterator *pIter = nullptr;
if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
{
return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
}
IPlugin *pPlugin = pIter->GetPlugin();
if (!pPlugin)
{
return BAD_HANDLE;
}
return pPlugin->GetMyHandle();
}
IPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
{
if (hndl == BAD_HANDLE)
@ -868,34 +758,18 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
NumberType size = static_cast<NumberType>(params[3]);
// new parameter added after SM 1.10; defaults to true for backwards compatibility
bool updateMemAccess = true;
if (params[0] >= 4)
{
updateMemAccess = params[4];
}
switch(size)
{
case NumberType_Int8:
if (updateMemAccess)
{
SourceHook::SetMemAccess(addr, sizeof(uint8_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
}
*reinterpret_cast<uint8_t*>(addr) = data;
break;
case NumberType_Int16:
if (updateMemAccess)
{
SourceHook::SetMemAccess(addr, sizeof(uint16_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
}
*reinterpret_cast<uint16_t*>(addr) = data;
break;
case NumberType_Int32:
if (updateMemAccess)
{
SourceHook::SetMemAccess(addr, sizeof(uint32_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
}
*reinterpret_cast<uint32_t*>(addr) = data;
break;
default:
@ -1069,16 +943,16 @@ static cell_t LogStackTrace(IPluginContext *pContext, const cell_t *params)
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
IFrameIterator *it = pContext->CreateFrameIterator();
std::vector<std::string> arr = g_DbgReporter.GetStackTrace(it);
ke::Vector<ke::AString> arr = g_DbgReporter.GetStackTrace(it);
pContext->DestroyFrameIterator(it);
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
g_Logger.LogError("[SM] Stack trace requested: %s", buffer);
g_Logger.LogError("[SM] Called from: %s", pPlugin->GetFilename());
for (size_t i = 0; i < arr.size(); ++i)
for (size_t i = 0; i < arr.length(); ++i)
{
g_Logger.LogError("%s", arr[i].c_str());
g_Logger.LogError("%s", arr[i].chars());
}
return 0;
}
@ -1121,9 +995,5 @@ REGISTER_NATIVES(coreNatives)
{"FrameIterator.LineNumber.get", FrameIterator_LineNumber},
{"FrameIterator.GetFunctionName", FrameIterator_GetFunctionName},
{"FrameIterator.GetFilePath", FrameIterator_GetFilePath},
{"PluginIterator.PluginIterator", PluginIterator_Create},
{"PluginIterator.Next", PluginIterator_Next},
{"PluginIterator.Plugin.get", PluginIterator_Plugin_get},
{NULL, NULL},
};

View File

@ -29,8 +29,6 @@
* Version: $Id$
*/
#include <memory>
#include "common_logic.h"
#include "Database.h"
#include "ExtensionSys.h"
@ -64,11 +62,11 @@ struct Transaction
{
struct Entry
{
std::string query;
ke::AString query;
cell_t data;
};
std::vector<Entry> entries;
ke::Vector<Entry> entries;
};
class DatabaseHelpers :
@ -457,7 +455,7 @@ static cell_t ConnectToDbAsync(IPluginContext *pContext, const cell_t *params, A
g_pSM->Format(error,
sizeof(error),
"Could not find driver \"%s\"",
pInfo->driver[0] == '\0' ? g_DBMan.GetDefaultDriverName().c_str() : pInfo->driver);
pInfo->driver[0] == '\0' ? g_DBMan.GetDefaultDriverName().chars() : pInfo->driver);
} else if (!driver->IsThreadSafe()) {
g_pSM->Format(error,
sizeof(error),
@ -1540,9 +1538,9 @@ static cell_t SQL_AddQuery(IPluginContext *pContext, const cell_t *params)
Transaction::Entry entry;
entry.query = query;
entry.data = params[3];
txn->entries.push_back(std::move(entry));
txn->entries.append(ke::Move(entry));
return cell_t(txn->entries.size() - 1);
return cell_t(txn->entries.length() - 1);
}
class TTransactOp : public IDBThreadOperation
@ -1564,7 +1562,7 @@ public:
~TTransactOp()
{
for (size_t i = 0; i < results_.size(); i++)
for (size_t i = 0; i < results_.length(); i++)
results_[i]->Destroy();
results_.clear();
}
@ -1585,7 +1583,7 @@ public:
private:
bool Succeeded() const
{
return error_.size() == 0;
return error_.length() == 0;
}
void SetDbError()
@ -1617,16 +1615,16 @@ private:
return;
}
for (size_t i = 0; i < txn_->entries.size(); i++)
for (size_t i = 0; i < txn_->entries.length(); i++)
{
Transaction::Entry &entry = txn_->entries[i];
IQuery *result = Exec(entry.query.c_str());
IQuery *result = Exec(entry.query.chars());
if (!result)
{
failIndex_ = (cell_t)i;
return;
}
results_.push_back(result);
results_.append(result);
}
if (!db_->DoSimpleQuery("COMMIT"))
@ -1667,11 +1665,11 @@ private:
// Add an extra refcount for the handle.
db_->AddRef();
assert(results_.size() == txn_->entries.size());
assert(results_.length() == txn_->entries.length());
std::unique_ptr<cell_t[]> data = std::make_unique<cell_t[]>(results_.size());
std::unique_ptr<cell_t[]> handles = std::make_unique<cell_t[]>(results_.size());
for (size_t i = 0; i < results_.size(); i++)
ke::AutoPtr<cell_t[]> data = ke::MakeUnique<cell_t[]>(results_.length());
ke::AutoPtr<cell_t[]> handles = ke::MakeUnique<cell_t[]>(results_.length());
for (size_t i = 0; i < results_.length(); i++)
{
CombinedQuery *obj = new CombinedQuery(results_[i], db_);
Handle_t rh = CreateLocalHandle(hCombinedQueryType, obj, &sec);
@ -1682,7 +1680,7 @@ private:
delete obj;
for (size_t iter = 0; iter < i; iter++)
handlesys->FreeHandle(handles[iter], &sec);
for (size_t iter = i; iter < results_.size(); iter++)
for (size_t iter = i; iter < results_.length(); iter++)
results_[iter]->Destroy();
handlesys->FreeHandle(dbh, &sec);
results_.clear();
@ -1698,15 +1696,15 @@ private:
{
success_->PushCell(dbh);
success_->PushCell(data_);
success_->PushCell(txn_->entries.size());
success_->PushArray(handles.get(), results_.size());
success_->PushArray(data.get(), results_.size());
success_->PushCell(txn_->entries.length());
success_->PushArray(handles.get(), results_.length());
success_->PushArray(data.get(), results_.length());
success_->Execute(NULL);
}
// Cleanup. Note we clear results_, since freeing their handles will
// call Destroy(), and we don't want to double-free in ~TTransactOp.
for (size_t i = 0; i < results_.size(); i++)
for (size_t i = 0; i < results_.length(); i++)
handlesys->FreeHandle(handles[i], &sec);
handlesys->FreeHandle(dbh, &sec);
results_.clear();
@ -1730,8 +1728,8 @@ public:
{
HandleSecurity sec(ident_, g_pCoreIdent);
std::unique_ptr<cell_t[]> data = std::make_unique<cell_t[]>(txn_->entries.size());
for (size_t i = 0; i < txn_->entries.size(); i++)
ke::AutoPtr<cell_t[]> data = ke::MakeUnique<cell_t[]>(txn_->entries.length());
for (size_t i = 0; i < txn_->entries.length(); i++)
data[i] = txn_->entries[i].data;
Handle_t dbh = CreateLocalHandle(g_DBMan.GetDatabaseType(), db_, &sec);
@ -1745,10 +1743,10 @@ public:
{
failure_->PushCell(dbh);
failure_->PushCell(data_);
failure_->PushCell(txn_->entries.size());
failure_->PushString(error_.c_str());
failure_->PushCell(txn_->entries.length());
failure_->PushString(error_.chars());
failure_->PushCell(failIndex_);
failure_->PushArray(data.get(), txn_->entries.size());
failure_->PushArray(data.get(), txn_->entries.length());
failure_->Execute(NULL);
}
@ -1764,8 +1762,8 @@ private:
IPluginFunction *failure_;
cell_t data_;
AutoHandleRooter autoHandle_;
std::string error_;
std::vector<IQuery *> results_;
ke::AString error_;
ke::Vector<IQuery *> results_;
cell_t failIndex_;
};

View File

@ -61,7 +61,7 @@ public:
}
void OnHandleDestroy(HandleType_t type, void *object)
{
delete reinterpret_cast<CDataPack *>(object);
CDataPack::Free(reinterpret_cast<CDataPack *>(object));
}
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{
@ -73,7 +73,7 @@ public:
static cell_t smn_CreateDataPack(IPluginContext *pContext, const cell_t *params)
{
CDataPack *pDataPack = new CDataPack();
CDataPack *pDataPack = CDataPack::New();
if (!pDataPack)
{
@ -166,62 +166,6 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
return 1;
}
static cell_t smn_WritePackCellArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!params[4])
{
pDataPack->RemoveItem();
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
pDataPack->PackCellArray(pArray, params[3]);
return 1;
}
static cell_t smn_WritePackFloatArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!params[4])
{
pDataPack->RemoveItem();
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
pDataPack->PackFloatArray(pArray, params[3]);
return 1;
}
static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
@ -368,108 +312,6 @@ static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *param
return pDataPack->ReadFunction();
}
static cell_t smn_ReadPackCellArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!pDataPack->IsReadable())
{
pContext->ReportError("Data pack operation is out of bounds.");
return 0;
}
if (pDataPack->GetCurrentType() != CDataPackType::CellArray)
{
pContext->ReportError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::CellArray);
return 0;
}
cell_t packCount = 0;
cell_t *pData = pDataPack->ReadCellArray(&packCount);
if(pData == nullptr || packCount == 0)
{
pContext->ReportError("Invalid data pack operation: current position isn't an array!");
return 0;
}
cell_t count = params[3];
if(packCount > count)
{
pContext->ReportError("Input buffer too small (needed %d, got %d).", packCount, count);
return 0;
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
memcpy(pArray, pData, sizeof(cell_t) * count);
return 1;
}
static cell_t smn_ReadPackFloatArray(IPluginContext *pContext, const cell_t *params)
{
HandleError herr;
HandleSecurity sec;
sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent;
Handle_t hndl = static_cast<Handle_t>(params[1]);
CDataPack *pDataPack = nullptr;
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None)
{
pContext->ReportError("Invalid data pack handle %x (error %d).", hndl, herr);
return 0;
}
if (!pDataPack->IsReadable())
{
pContext->ReportError("Data pack operation is out of bounds.");
return 0;
}
if (pDataPack->GetCurrentType() != CDataPackType::FloatArray)
{
pContext->ReportError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::FloatArray);
return 0;
}
cell_t packCount = 0;
cell_t *pData = pDataPack->ReadFloatArray(&packCount);
if(pData == nullptr || packCount == 0)
{
pContext->ReportError("Invalid data pack operation: current position isn't an array!");
return 0;
}
cell_t count = params[3];
if(packCount > count)
{
pContext->ReportError("Input buffer too small (needed %d, got %d).", packCount, count);
return 0;
}
cell_t *pArray;
pContext->LocalToPhysAddr(params[2], &pArray);
memcpy(pArray, pData, sizeof(cell_t) * count);
return 1;
}
static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
@ -584,14 +426,10 @@ REGISTER_NATIVES(datapacknatives)
{"DataPack.WriteFloat", smn_WritePackFloat},
{"DataPack.WriteString", smn_WritePackString},
{"DataPack.WriteFunction", smn_WritePackFunction},
{"DataPack.WriteCellArray", smn_WritePackCellArray},
{"DataPack.WriteFloatArray", smn_WritePackFloatArray},
{"DataPack.ReadCell", smn_ReadPackCell},
{"DataPack.ReadFloat", smn_ReadPackFloat},
{"DataPack.ReadString", smn_ReadPackString},
{"DataPack.ReadFunction", smn_ReadPackFunction},
{"DataPack.ReadCellArray", smn_ReadPackCellArray},
{"DataPack.ReadFloatArray", smn_ReadPackFloatArray},
{"DataPack.Reset", smn_ResetPack},
{"DataPack.Position.get", smn_GetPackPosition},
{"DataPack.Position.set", smn_SetPackPosition},

View File

@ -1,367 +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 "HandleSys.h"
#include "common_logic.h"
#include "LumpManager.h"
#include <algorithm>
HandleType_t g_EntityLumpEntryType;
std::string g_strMapEntities;
bool g_bLumpAvailableForWriting = false;
static EntityLumpManager s_LumpManager;
EntityLumpManager *lumpmanager = &s_LumpManager;
class LumpManagerNatives :
public IHandleTypeDispatch,
public SMGlobalClass
{
public: //SMGlobalClass
void OnSourceModAllInitialized()
{
g_EntityLumpEntryType = handlesys->CreateType("EntityLumpEntry", this, 0, NULL, NULL, g_pCoreIdent, NULL);
}
void OnSourceModShutdown()
{
handlesys->RemoveType(g_EntityLumpEntryType, g_pCoreIdent);
}
public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void* object)
{
if (type == g_EntityLumpEntryType)
{
delete reinterpret_cast<std::weak_ptr<EntityLumpEntry>*>(object);
}
}
};
static LumpManagerNatives s_LumpManagerNatives;
cell_t sm_LumpManagerGet(IPluginContext *pContext, const cell_t *params) {
int index = params[1];
if (index < 0 || index >= static_cast<int>(lumpmanager->Length())) {
return pContext->ThrowNativeError("Invalid index %d", index);
}
std::weak_ptr<EntityLumpEntry>* pReference = new std::weak_ptr<EntityLumpEntry>;
*pReference = lumpmanager->Get(index);
return handlesys->CreateHandle(g_EntityLumpEntryType, pReference,
pContext->GetIdentity(), g_pCoreIdent, NULL);
}
cell_t sm_LumpManagerErase(IPluginContext *pContext, const cell_t *params) {
if (!g_bLumpAvailableForWriting) {
return pContext->ThrowNativeError("Cannot use EntityLump.Erase() outside of OnMapInit");
}
int index = params[1];
if (index < 0 || index >= static_cast<int>(lumpmanager->Length())) {
return pContext->ThrowNativeError("Invalid index %d", index);
}
lumpmanager->Erase(index);
return 0;
}
cell_t sm_LumpManagerInsert(IPluginContext *pContext, const cell_t *params) {
if (!g_bLumpAvailableForWriting) {
return pContext->ThrowNativeError("Cannot use EntityLump.Insert() outside of OnMapInit");
}
int index = params[1];
if (index < 0 || index > static_cast<int>(lumpmanager->Length())) {
return pContext->ThrowNativeError("Invalid index %d", index);
}
lumpmanager->Insert(index);
return 0;
}
cell_t sm_LumpManagerAppend(IPluginContext *pContext, const cell_t *params) {
if (!g_bLumpAvailableForWriting) {
return pContext->ThrowNativeError("Cannot use EntityLump.Append() outside of OnMapInit");
}
return lumpmanager->Append();
}
cell_t sm_LumpManagerLength(IPluginContext *pContext, const cell_t *params) {
return lumpmanager->Length();
}
cell_t sm_LumpEntryGet(IPluginContext *pContext, const cell_t *params) {
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
Handle_t hndl = static_cast<Handle_t>(params[1]);
std::weak_ptr<EntityLumpEntry>* entryref = nullptr;
if ((err = handlesys->ReadHandle(hndl, g_EntityLumpEntryType, &sec, (void**) &entryref)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (error: %d)", hndl, err);
}
if (entryref->expired()) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (reference expired)", hndl);
}
auto entry = entryref->lock();
int index = params[2];
if (index < 0 || index >= static_cast<int>(entry->size())) {
return pContext->ThrowNativeError("Invalid index %d", index);
}
const auto& pair = (*entry)[index];
size_t nBytes;
pContext->StringToLocalUTF8(params[3], params[4], pair.first.c_str(), &nBytes);
pContext->StringToLocalUTF8(params[5], params[6], pair.second.c_str(), &nBytes);
return 0;
}
cell_t sm_LumpEntryUpdate(IPluginContext *pContext, const cell_t *params) {
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
Handle_t hndl = static_cast<Handle_t>(params[1]);
std::weak_ptr<EntityLumpEntry>* entryref = nullptr;
if ((err = handlesys->ReadHandle(hndl, g_EntityLumpEntryType, &sec, (void**) &entryref)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (error: %d)", hndl, err);
}
if (entryref->expired()) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (reference expired)", hndl);
}
if (!g_bLumpAvailableForWriting) {
return pContext->ThrowNativeError("Cannot use EntityLumpEntry.Update() outside of OnMapInit");
}
auto entry = entryref->lock();
int index = params[2];
if (index < 0 || index >= static_cast<int>(entry->size())) {
return pContext->ThrowNativeError("Invalid index %d", index);
}
char *key, *value;
pContext->LocalToStringNULL(params[3], &key);
pContext->LocalToStringNULL(params[4], &value);
auto& pair = (*entry)[index];
if (key != nullptr) {
pair.first = key;
}
if (value != nullptr) {
pair.second = value;
}
return 0;
}
cell_t sm_LumpEntryInsert(IPluginContext *pContext, const cell_t *params) {
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
Handle_t hndl = static_cast<Handle_t>(params[1]);
std::weak_ptr<EntityLumpEntry>* entryref = nullptr;
if ((err = handlesys->ReadHandle(hndl, g_EntityLumpEntryType, &sec, (void**) &entryref)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (error: %d)", hndl, err);
}
if (entryref->expired()) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (reference expired)", hndl);
}
if (!g_bLumpAvailableForWriting) {
return pContext->ThrowNativeError("Cannot use EntityLumpEntry.Insert() outside of OnMapInit");
}
auto entry = entryref->lock();
int index = params[2];
if (index < 0 || index > static_cast<int>(entry->size())) {
return pContext->ThrowNativeError("Invalid index %d", index);
}
char *key, *value;
pContext->LocalToString(params[3], &key);
pContext->LocalToString(params[4], &value);
entry->emplace(entry->begin() + index, key, value);
return 0;
}
cell_t sm_LumpEntryErase(IPluginContext *pContext, const cell_t *params) {
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
Handle_t hndl = static_cast<Handle_t>(params[1]);
std::weak_ptr<EntityLumpEntry>* entryref = nullptr;
if ((err = handlesys->ReadHandle(hndl, g_EntityLumpEntryType, &sec, (void**) &entryref)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (error: %d)", hndl, err);
}
if (entryref->expired()) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (reference expired)", hndl);
}
if (!g_bLumpAvailableForWriting) {
return pContext->ThrowNativeError("Cannot use EntityLumpEntry.Erase() outside of OnMapInit");
}
auto entry = entryref->lock();
int index = params[2];
if (index < 0 || index >= static_cast<int>(entry->size())) {
return pContext->ThrowNativeError("Invalid index %d", index);
}
entry->erase(entry->begin() + index);
return 0;
}
cell_t sm_LumpEntryAppend(IPluginContext *pContext, const cell_t *params) {
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
Handle_t hndl = static_cast<Handle_t>(params[1]);
std::weak_ptr<EntityLumpEntry>* entryref = nullptr;
if ((err = handlesys->ReadHandle(hndl, g_EntityLumpEntryType, &sec, (void**) &entryref)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (error: %d)", hndl, err);
}
if (entryref->expired()) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (reference expired)", hndl);
}
if (!g_bLumpAvailableForWriting) {
return pContext->ThrowNativeError("Cannot use EntityLumpEntry.Append() outside of OnMapInit");
}
auto entry = entryref->lock();
char *key, *value;
pContext->LocalToString(params[2], &key);
pContext->LocalToString(params[3], &value);
entry->emplace_back(key, value);
return 0;
}
cell_t sm_LumpEntryFindKey(IPluginContext *pContext, const cell_t *params) {
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
Handle_t hndl = static_cast<Handle_t>(params[1]);
std::weak_ptr<EntityLumpEntry>* entryref = nullptr;
if ((err = handlesys->ReadHandle(hndl, g_EntityLumpEntryType, &sec, (void**) &entryref)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (error: %d)", hndl, err);
}
if (entryref->expired()) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (reference expired)", hndl);
}
// start from the index after the current one
int start = params[3] + 1;
auto entry = entryref->lock();
if (start < 0 || start >= static_cast<int>(entry->size())) {
return -1;
}
char *key;
pContext->LocalToString(params[2], &key);
auto matches_key = [&key](std::pair<std::string,std::string> pair) {
return pair.first == key;
};
auto result = std::find_if(entry->begin() + start, entry->end(), matches_key);
if (result == entry->end()) {
return -1;
}
return std::distance(entry->begin(), result);
}
cell_t sm_LumpEntryLength(IPluginContext *pContext, const cell_t *params) {
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
HandleError err;
Handle_t hndl = static_cast<Handle_t>(params[1]);
std::weak_ptr<EntityLumpEntry>* entryref = nullptr;
if ((err = handlesys->ReadHandle(hndl, g_EntityLumpEntryType, &sec, (void**) &entryref)) != HandleError_None) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (error: %d)", hndl, err);
}
if (entryref->expired()) {
return pContext->ThrowNativeError("Invalid EntityLumpEntry handle %x (reference expired)", hndl);
}
auto entry = entryref->lock();
return entry->size();
}
REGISTER_NATIVES(entityLumpNatives)
{
{ "EntityLump.Get", sm_LumpManagerGet },
{ "EntityLump.Erase", sm_LumpManagerErase },
{ "EntityLump.Insert", sm_LumpManagerInsert },
{ "EntityLump.Append", sm_LumpManagerAppend },
{ "EntityLump.Length", sm_LumpManagerLength },
{ "EntityLumpEntry.Get", sm_LumpEntryGet },
{ "EntityLumpEntry.Update", sm_LumpEntryUpdate },
{ "EntityLumpEntry.Insert", sm_LumpEntryInsert },
{ "EntityLumpEntry.Erase", sm_LumpEntryErase },
{ "EntityLumpEntry.Append", sm_LumpEntryAppend },
{ "EntityLumpEntry.FindKey", sm_LumpEntryFindKey },
{ "EntityLumpEntry.Length.get", sm_LumpEntryLength },
{NULL, NULL}
};

View File

@ -1,44 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2022-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_SOURCEMOD_ENTITYLUMP_H_
#define _INCLUDE_SOURCEMOD_ENTITYLUMP_H_
#include <IHandleSys.h>
#include "LumpManager.h"
using namespace SourceMod;
extern std::string g_strMapEntities;
extern bool g_bLumpAvailableForWriting;
extern EntityLumpManager *lumpmanager;
#endif // _INCLUDE_SOURCEMOD_ENTITYLUMP_H_

View File

@ -414,7 +414,7 @@ static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
DetectExceptions eh(pContext);
written = atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
if (eh.HasException())
return pContext->GetLastNativeError();
return 0;
}
cell_t *addr;

View File

@ -29,13 +29,12 @@
* Version: $Id$
*/
#include <memory>
#include "common_logic.h"
#include <IPluginSys.h>
#include <IHandleSys.h>
#include <IForwardSys.h>
#include <ISourceMod.h>
#include <amtl/am-autoptr.h>
#include "ShareSys.h"
#include "NativeInvoker.h"
@ -747,7 +746,7 @@ struct SMFrameActionData
static void PawnFrameAction(void *pData)
{
std::unique_ptr<SMFrameActionData> frame(reinterpret_cast<SMFrameActionData *>(pData));
ke::AutoPtr<SMFrameActionData> frame(reinterpret_cast<SMFrameActionData *>(pData));
IPlugin *pPlugin = pluginsys->PluginFromHandle(frame->ownerhandle, NULL);
if (!pPlugin)
{

View File

@ -162,38 +162,6 @@ static cell_t smn_GameConfGetAddress(IPluginContext *pCtx, const cell_t *params)
#endif
}
static cell_t smn_GameConfGetMemSig(IPluginContext *pCtx, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr;
HandleSecurity sec;
IGameConfig *gc;
sec.pOwner = NULL;
sec.pIdentity = g_pCoreIdent;
if ((herr=handlesys->ReadHandle(hndl, g_GameConfigsType, &sec, (void **)&gc))
!= HandleError_None)
{
return pCtx->ThrowNativeError("Invalid game config handle %x (error %d)", hndl, herr);
}
char *key;
void *val;
pCtx->LocalToString(params[2], &key);
if (!gc->GetMemSig(key, &val))
{
return 0;
}
#ifdef PLATFORM_X86
return (cell_t)val;
#else
return pseudoAddr.ToPseudoAddress(val);
#endif
}
static GameConfigsNatives s_GameConfigsNatives;
REGISTER_NATIVES(gameconfignatives)
@ -208,6 +176,5 @@ REGISTER_NATIVES(gameconfignatives)
{"GameData.GetOffset", smn_GameConfGetOffset},
{"GameData.GetKeyValue", smn_GameConfGetKeyValue},
{"GameData.GetAddress", smn_GameConfGetAddress},
{"GameData.GetMemSig", smn_GameConfGetMemSig},
{NULL, NULL}
};

View File

@ -592,10 +592,7 @@ private:
}
}
char realpath[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", pMapList->path);
if (!libsys->FileTime(realpath, FileTime_LastChange, &last_time)
if (!libsys->FileTime(pMapList->path, FileTime_LastChange, &last_time)
|| last_time > pMapList->last_modified_time)
{
/* Reparse */

View File

@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@ -141,6 +141,10 @@ public:
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
bool OnSetHandlerOption(const char *option, const void *data);
#if 0
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display);
#endif
private:
cell_t DoAction(IBaseMenu *menu, MenuAction action, cell_t param1, cell_t param2, cell_t def_res=0);
private:
@ -481,6 +485,7 @@ void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *
if (num_items > 1)
{
/* Yes, we do. */
srand(time(NULL));
winning_item = rand() % num_items;
winning_item = results->item_list[winning_item].item;
} else {
@ -492,44 +497,80 @@ void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *
unsigned int winning_votes = results->item_list[0].count;
DoAction(menu, MenuAction_VoteEnd, winning_item, (total_votes << 16) | (winning_votes & 0xFFFF));
return;
}
} else {
IPluginContext *pContext = m_pVoteResults->GetParentContext();
AutoEnterHeapScope heap_scope(pContext);
bool no_call = false;
int err;
/* First array */
cell_t client_array_address = -1;
if (cell_t client_array_size = results->num_clients * 2) {
auto init = std::make_unique<cell_t[]>(client_array_size);
for (unsigned int i = 0; i < results->num_clients; i++) {
init[i * 2] = results->client_list[i].client;
init[i * 2 + 1] = results->client_list[i].item;
cell_t *client_array_base = NULL;
cell_t client_array_size = results->num_clients + (results->num_clients * 2);
if (client_array_size)
{
if ((err = pContext->HeapAlloc(client_array_size, &client_array_address, &client_array_base))
!= SP_ERROR_NONE)
{
g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for client list.", client_array_size * sizeof(cell_t));
no_call = true;
} else {
cell_t target_offs = sizeof(cell_t) * results->num_clients;
cell_t *cur_index = client_array_base;
cell_t *cur_array;
for (unsigned int i=0; i<results->num_clients; i++)
{
/* Copy the array index */
*cur_index = target_offs;
/* Get the current array address */
cur_array = (cell_t *)((char *)cur_index + target_offs);
/* Store information */
cur_array[0] = results->client_list[i].client;
cur_array[1] = results->client_list[i].item;
/* Adjust for the new target by subtracting one indirection
* and adding one array.
*/
target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
cur_index++;
}
if (!pContext->HeapAlloc2dArray(results->num_clients, 2, &client_array_address, init.get())) {
g_DbgReporter.GenerateError(pContext, m_fnVoteResult, -1,
"Menu callback could not allocate cells for client list.");
return;
}
}
/* Second array */
cell_t item_array_address = -1;
if (cell_t item_array_size = results->num_items * 2) {
auto init = std::make_unique<cell_t[]>(item_array_size);
for (unsigned int i = 0; i < results->num_items; i++) {
init[i * 2] = results->item_list[i].item;
init[i * 2 + 1] = results->item_list[i].count;
cell_t *item_array_base = NULL;
cell_t item_array_size = results->num_items + (results->num_items * 2);
if (item_array_size)
{
if ((err = pContext->HeapAlloc(item_array_size, &item_array_address, &item_array_base))
!= SP_ERROR_NONE)
{
g_DbgReporter.GenerateError(pContext, m_fnVoteResult, err, "Menu callback could not allocate %d bytes for item list.", item_array_size);
no_call = true;
} else {
cell_t target_offs = sizeof(cell_t) * results->num_items;
cell_t *cur_index = item_array_base;
cell_t *cur_array;
for (unsigned int i=0; i<results->num_items; i++)
{
/* Copy the array index */
*cur_index = target_offs;
/* Get the current array address */
cur_array = (cell_t *)((char *)cur_index + target_offs);
/* Store information */
cur_array[0] = results->item_list[i].item;
cur_array[1] = results->item_list[i].count;
/* Adjust for the new target by subtracting one indirection
* and adding one array.
*/
target_offs += (sizeof(cell_t) * 2) - sizeof(cell_t);
cur_index++;
}
if (!pContext->HeapAlloc2dArray(results->num_items, 2, &item_array_address, init.get())) {
g_DbgReporter.GenerateError(pContext, m_fnVoteResult, -1,
"Menu callback could not allocate %d cells for item list.",
item_array_size);
return;
}
}
/* Finally, push everything */
if (!no_call)
{
m_pVoteResults->PushCell(menu->GetHandle());
m_pVoteResults->PushCell(results->num_votes);
m_pVoteResults->PushCell(results->num_clients);
@ -537,6 +578,18 @@ void CMenuHandler::OnMenuVoteResults(IBaseMenu *menu, const menu_vote_result_t *
m_pVoteResults->PushCell(results->num_items);
m_pVoteResults->PushCell(item_array_address);
m_pVoteResults->Execute(NULL);
}
/* Free what we allocated, in reverse order as required */
if (item_array_address != -1)
{
pContext->HeapPop(item_array_address);
}
if (client_array_address != -1)
{
pContext->HeapPop(client_array_address);
}
}
}
bool CMenuHandler::OnSetHandlerOption(const char *option, const void *data)
@ -962,7 +1015,7 @@ static cell_t GetMenuExitBackButton(IPluginContext *pContext, const cell_t *para
return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
}
return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXITBACK) == MENUFLAG_BUTTON_EXITBACK) ? 1 : 0;
return ((menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXITBACK) == MENUFLAG_BUTTON_EXIT) ? 1 : 0;
}
static cell_t SetMenuExitButton(IPluginContext *pContext, const cell_t *params)

View File

@ -35,7 +35,6 @@
#include "common_logic.h"
#include "CellArray.h"
#include <IHandleSys.h>
#include <amtl/am-raii.h>
/***********************************
* About the double array hack *
@ -92,6 +91,8 @@ enum SortOrder
void sort_random(cell_t *array, cell_t size)
{
srand((unsigned int)time(NULL));
for (int i = size-1; i > 0; i--)
{
int n = rand() % (i + 1);
@ -196,7 +197,7 @@ static cell_t sm_SortFloats(IPluginContext *pContext, const cell_t *params)
static cell_t *g_CurStringArray = NULL;
static cell_t *g_CurRebaseMap = NULL;
int sort_strings_asc_legacy(const void *blk1, const void *blk2)
int sort_strings_asc(const void *blk1, const void *blk2)
{
cell_t reloc1 = *(cell_t *)blk1;
cell_t reloc2 = *(cell_t *)blk2;
@ -207,7 +208,7 @@ int sort_strings_asc_legacy(const void *blk1, const void *blk2)
return strcmp(str1, str2);
}
int sort_strings_desc_legacy(const void *blk1, const void *blk2)
int sort_strings_desc(const void *blk1, const void *blk2)
{
cell_t reloc1 = *(cell_t *)blk1;
cell_t reloc2 = *(cell_t *)blk2;
@ -218,7 +219,7 @@ int sort_strings_desc_legacy(const void *blk1, const void *blk2)
return strcmp(str2, str1);
}
static cell_t sm_SortStrings_Legacy(IPluginContext *pContext, const cell_t *params)
static cell_t sm_SortStrings(IPluginContext *pContext, const cell_t *params)
{
cell_t *array;
cell_t array_size = params[2];
@ -246,11 +247,11 @@ static cell_t sm_SortStrings_Legacy(IPluginContext *pContext, const cell_t *para
if (type == Sort_Ascending)
{
qsort(array, array_size, sizeof(cell_t), sort_strings_asc_legacy);
qsort(array, array_size, sizeof(cell_t), sort_strings_asc);
}
else if (type == Sort_Descending)
{
qsort(array, array_size, sizeof(cell_t), sort_strings_desc_legacy);
qsort(array, array_size, sizeof(cell_t), sort_strings_desc);
}
else
{
@ -276,69 +277,6 @@ static cell_t sm_SortStrings_Legacy(IPluginContext *pContext, const cell_t *para
return 1;
}
static IPluginContext* sSortContext = nullptr;
int sort_strings_asc(const void *blk1, const void *blk2)
{
cell_t str_addr1 = *(cell_t *)blk1;
cell_t str_addr2 = *(cell_t *)blk2;
char *str1;
char *str2;
if (sSortContext->LocalToString(str_addr1, &str1) != SP_ERROR_NONE ||
sSortContext->LocalToString(str_addr2, &str2) != SP_ERROR_NONE)
{
return 0;
}
return strcmp(str1, str2);
}
int sort_strings_desc(const void *blk1, const void *blk2)
{
cell_t str_addr1 = *(cell_t *)blk1;
cell_t str_addr2 = *(cell_t *)blk2;
char *str1;
char *str2;
if (sSortContext->LocalToString(str_addr1, &str1) != SP_ERROR_NONE ||
sSortContext->LocalToString(str_addr2, &str2) != SP_ERROR_NONE)
{
return 0;
}
return strcmp(str2, str1);
}
static cell_t sm_SortStrings(IPluginContext *pContext, const cell_t *params)
{
auto rt = pContext->GetRuntime();
if (!rt->UsesDirectArrays())
return sm_SortStrings_Legacy(pContext, params);
cell_t *array;
cell_t array_size = params[2];
cell_t type = params[3];
pContext->LocalToPhysAddr(params[1], &array);
ke::SaveAndSet<IPluginContext*> set_context(&sSortContext, pContext);
if (type == Sort_Ascending)
{
qsort(array, array_size, sizeof(cell_t), sort_strings_asc);
}
else if (type == Sort_Descending)
{
qsort(array, array_size, sizeof(cell_t), sort_strings_desc);
}
else
{
sort_random(array, array_size);
}
return 1;
}
struct sort_info
{
IPluginFunction *pFunc;
@ -399,7 +337,7 @@ static cell_t sm_SortCustom1D(IPluginContext *pContext, const cell_t *params)
return 1;
}
static int sort2d_amx_custom_legacy(const void *elem1, const void *elem2)
int sort2d_amx_custom(const void *elem1, const void *elem2)
{
if (g_SortInfo.eh->HasException())
return 0;
@ -425,7 +363,7 @@ static int sort2d_amx_custom_legacy(const void *elem1, const void *elem2)
return result;
}
static cell_t sm_SortCustom2D_Legacy(IPluginContext *pContext, const cell_t *params)
static cell_t sm_SortCustom2D(IPluginContext *pContext, const cell_t *params)
{
cell_t *array;
cell_t array_size = params[2];
@ -465,7 +403,7 @@ static cell_t sm_SortCustom2D_Legacy(IPluginContext *pContext, const cell_t *par
array[i] = i;
}
qsort(array, array_size, sizeof(cell_t), sort2d_amx_custom_legacy);
qsort(array, array_size, sizeof(cell_t), sort2d_amx_custom);
/** Fixup process! */
for (int i=0; i<array_size; i++)
@ -483,55 +421,6 @@ static cell_t sm_SortCustom2D_Legacy(IPluginContext *pContext, const cell_t *par
return 1;
}
static int sort2d_amx_custom(const void *elem1, const void *elem2)
{
if (g_SortInfo.eh->HasException())
return 0;
cell_t iv1 = *(cell_t *)elem1;
cell_t iv2 = *(cell_t *)elem2;
cell_t result = 0;
g_SortInfo.pFunc->PushCell(iv1);
g_SortInfo.pFunc->PushCell(iv2);
g_SortInfo.pFunc->PushCell(g_SortInfo.array_addr);
g_SortInfo.pFunc->PushCell(g_SortInfo.hndl);
g_SortInfo.pFunc->Invoke(&result);
return result;
}
static cell_t sm_SortCustom2D(IPluginContext *pContext, const cell_t *params)
{
auto rt = pContext->GetRuntime();
if (!rt->UsesDirectArrays())
return sm_SortCustom2D_Legacy(pContext, params);
cell_t *array;
cell_t array_size = params[2];
IPluginFunction *pFunction;
pContext->LocalToPhysAddr(params[1], &array);
if ((pFunction=pContext->GetFunctionById(params[3])) == NULL)
{
return pContext->ThrowNativeError("Function %x is not a valid function", params[3]);
}
sort_info oldinfo = g_SortInfo;
DetectExceptions eh(pContext);
g_SortInfo.pFunc = pFunction;
g_SortInfo.hndl = params[4];
g_SortInfo.array_addr = params[1];
g_SortInfo.eh = &eh;
qsort(array, array_size, sizeof(cell_t), sort2d_amx_custom);
g_SortInfo = oldinfo;
return 1;
}
enum SortType
{
Sort_Integer = 0,
@ -553,6 +442,8 @@ void sort_adt_random(CellArray *cArray)
{
size_t arraysize = cArray->size();
srand((unsigned int)time(NULL));
for (int i = arraysize-1; i > 0; i--)
{
int n = rand() % (i + 1);

View File

@ -139,22 +139,6 @@ static cell_t StringToIntEx(IPluginContext *pCtx, const cell_t *params)
return dummy - str;
}
static cell_t StringToInt64(IPluginContext *pCtx, const cell_t *params)
{
char *str, *dummy = NULL;
cell_t *addr;
pCtx->LocalToString(params[1], &str);
pCtx->LocalToPhysAddr(params[2], &addr);
// uint64_t for correct signed right shift.
uint64_t number = (uint64_t)strtoll(str, &dummy, params[3]);
addr[0] = (cell_t)(number & 0xFFFFFFFFull);
addr[1] = (cell_t)(number >> 32ull);
return dummy - str;
}
static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
{
char *str;
@ -164,17 +148,6 @@ static cell_t sm_numtostr(IPluginContext *pCtx, const cell_t *params)
return static_cast<cell_t>(res);
}
static cell_t Int64ToString(IPluginContext *pCtx, const cell_t *params)
{
cell_t *num;
char *str;
pCtx->LocalToPhysAddr(params[1], &num);
pCtx->LocalToString(params[2], &str);
size_t res = ke::SafeSprintf(str, params[3], "%" KE_FMT_I64, (uint64_t)num[1] << 32ll | (uint32_t)num[0]);
return static_cast<cell_t>(res);
}
static cell_t sm_strtofloat(IPluginContext *pCtx, const cell_t *params)
{
char *str, *dummy;
@ -618,7 +591,6 @@ REGISTER_NATIVES(basicStrings)
{"FormatEx", sm_formatex},
{"GetCharBytes", GetCharBytes},
{"IntToString", sm_numtostr},
{"Int64ToString", Int64ToString},
{"IsCharAlpha", IsCharAlpha},
{"IsCharLower", IsCharLower},
{"IsCharMB", IsCharMB},
@ -635,7 +607,6 @@ REGISTER_NATIVES(basicStrings)
{"strcopy", sm_strcopy},
{"StringToInt", sm_strconvint},
{"StringToIntEx", StringToIntEx},
{"StringToInt64", StringToInt64},
{"StringToFloat", sm_strtofloat},
{"StringToFloatEx", StringToFloatEx},
{"StripQuotes", StripQuotes},

Some files were not shown because too many files have changed in this diff Show More