Compare commits

..

1 Commits

Author SHA1 Message Date
Scott Ehlert
6518777115 Tagged 1.70 2006-07-19 20:17:28 +00:00
2885 changed files with 370227 additions and 882904 deletions

24
.gitattributes vendored
View File

@ -1,24 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# Tell GitHub that these files are SourcePawn
*.inc text linguist-language=sourcepawn
*.sma text linguist-language=sourcepawn
# Custom for Visual Studio
*.cs diff=csharp
# Sources
*.C text
*.cc text
*.cxx text
*.cpp text
*.c++ text
*.hpp text
*.h text
*.h++ text
*.hh text
# Compiled Object files
*.o binary
*.obj binary

View File

@ -1,74 +0,0 @@
# Contributing to AMX Mod X
## Issue reports
Please consider the following guidelines when reporting an issue.
#### Not for general support
This is not the right place to get help with using or installing AMX Mod X, or for issues with specific, third-party AMX Mod X plugins or extensions.
For help with AMX Mod X, please consult the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=3). Similarly, for assistance with, or to report issues with, third-party AMX Mod X plugins or extensions, you should post in the existing thread for that plugin or extension on the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=3).
#### Details, details, details
Provide as much detail as possible when reporting an issue.
For bugs or other undesired behavior, answers to the following questions are a great start:
* What is the issue?
* What behavior are you expecting instead?
* On what operating system is the game server running?
* What game is the game server running?
* What exact versions (full x.y.z.a version number) of Metamod and AMX Mod X are installed on the game server?
* What is the specific, shortest path to reproducing this issue? If this issue can be reproduced with plugin code, please try to shorten it to the minimum required to trigger the problem.
If this is a feature request, the following are helpful. Generally, not all will apply, but whatever you can answer ahead of time will shorten back and forth conversation.
* What is your end goal, or what are you trying to accomplish?
* Why is this necessary, or what benefit do you see with it?
* Will this be useful to others?
#### Issues with security implications
Please report any security bugs to [security@alliedmods.net](mailto:security@alliedmods.net) rather than to this public issue tracker.
#### We're only human
Please keep in mind that we maintain this project in our spare time, at no cost. There is no SLA, and you are not owed a response or a fix.
#### Conduct
Please refer to the [AlliedModders forum rules.](https://forums.alliedmods.net/misc.php?do=showrules)
## Pull Requests
Firstly, thank you for considering contributing changes to the project!
However, if this is anything more than a small fix such as a gamedata update, a glaring code flaw, or a simple typo in a file like this one, please file an issue first so that it can be discussed, unless you have already spoken to multiple members of the development team about it on IRC or the AlliedModders forums.
We don't like to have to reject pull requests, so we want to avoid those scenarios. We wouldn't want you to feel like you wasted your time writing something only for us to shoot it down.
#### Rejection
*Copied from Phabricator's [Contributing Code guidelines](https://secure.phabricator.com/book/phabcontrib/article/contributing_code/#rejecting-patches), as we largely feel the same way about this.*
> If you send us a patch without coordinating it with us first, it will probably be immediately rejected, or sit in limbo for a long time and eventually be rejected. The reasons we do this vary from patch to patch, but some of the most common reasons are:
>
> **Unjustifiable Costs**: We support code in the upstream forever. Support is enormously expensive and takes up a huge amount of our time. The cost to support a change over its lifetime is often 10x or 100x or 1000x greater than the cost to write the first version of it. Many uncoordinated patches we receive are "white elephants", which would cost much more to maintain than the value they provide.
>
> As an author, it may look like you're giving us free work and we're rejecting it as too expensive, but this viewpoint doesn't align with the reality of a large project which is actively supported by a small, experienced team. Writing code is cheap; maintaining it is expensive.
>
> By coordinating with us first, you can make sure the patch is something we consider valuable enough to put long-term support resources behind, and that you're building it in a way that we're comfortable taking over.
>
> **Not a Good Fit**: Many patches aren't good fits for the upstream: they implement features we simply don't want. You can find more information in Contributing Feature Requests. Coordinating with us first helps make sure we're on the same page and interested in a feature.
>
> The most common type of patch along these lines is a patch which adds new configuration options. We consider additional configuration options to have an exceptionally high lifetime support cost and are very unlikely to accept them. Coordinate with us first.
>
> **Not a Priority**: If you send us a patch against something which isn't a priority, we probably won't have time to look at it. We don't give special treatment to low-priority issues just because there's code written: we'd still be spending time on something lower-priority when we could be spending it on something higher-priority instead.
>
> If you coordinate with us first, you can make sure your patch is in an area of the codebase that we can prioritize.
>
> **Overly Ambitious Patches**: Sometimes we'll get huge patches from new contributors. These can have a lot of fundamental problems and require a huge amount of our time to review and correct. If you're interested in contributing, you'll have more success if you start small and learn as you go.
>
> We can help you break a large change into smaller pieces and learn how the codebase works as you proceed through the implementation, but only if you coordinate with us first.
>
> **Generality**: We often receive several feature requests which ask for similar features, and can come up with a general approach which covers all of the use cases. If you send us a patch for your use case only, the approach may be too specific. When a cleaner and more general approach is available, we usually prefer to pursue it.
>
> By coordinating with us first, we can make you aware of similar use cases and opportunities to generalize an approach. These changes are often small, but can have a big impact on how useful a piece of code is.
>
> **Infrastructure and Sequencing**: Sometimes patches are written against a piece of infrastructure with major planned changes. We don't want to accept these because they'll make the infrastructure changes more difficult to implement.
>
> Coordinate with us first to make sure a change doesn't need to wait on other pieces of infrastructure. We can help you identify technical blockers and possibly guide you through resolving them if you're interested.

12
.github/FUNDING.yml vendored
View File

@ -1,12 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://www.sourcemod.net/donate.php

View File

@ -1,25 +0,0 @@
# Help us help you
- [ ] I have checked that my issue [doesn't exist yet](https://github.com/alliedmodders/amxmodx/issues).
- [ ] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
- [ ] I can always reproduce the issue with the provided description below.
# Environment
* Operating System version:
* Game/AppID (with version if applicable):
* Current AMX Mod X version:
* Current Metamod version:
- [ ] I have updated AMX Mod X to the [latest version](https://www.amxmodx.org/downloads.php) and it still happens.
- [ ] I have updated AMX Mod X to the [latest snapshot](https://www.amxmodx.org/snapshots.php) and it still happens.
- [ ] I have updated Metamod to the [latest version](https://www.amxmodx.org/downloads.php) and it still happens.
# Description
# Problematic Code (or Steps to Reproduce)
```PAWN
// TODO(you): code here to reproduce the problem
```
# Logs
* Please attach in separate files: game output, library logs, kernel logs, and any other supporting information.
* In case of a crash, please attach minidump or dump analyze output.

View File

@ -1,137 +0,0 @@
name: Continuous Integration
on:
workflow_dispatch:
push:
branches:
- master
- 1.9-dev
pull_request:
branches:
- master
- 1.9-dev
jobs:
test:
strategy:
matrix:
include:
- os: ubuntu-latest
os_short: linux
compiler_cc: gcc
compiler_cxx: g++
- os: ubuntu-latest
os_short: linux
compiler_cc: clang
compiler_cxx: clang++
- os: ubuntu-18.04
os_short: linux
compiler_cc: clang-3.9
compiler_cxx: clang++-3.9
- os: ubuntu-18.04
os_short: linux
compiler_cc: gcc-6
compiler_cxx: g++-6
compiler_install: 'g++6 g++-6-multilib'
- os: windows-latest
os_short: windows
compiler_cc: msvc
- os: windows-2016
os_short: windows
compiler_cc: msvc++14.16-vs2017-cl
# MacOS 32 Bins seem not supported
# - os: macos-latest
# os_short: mac
# compiler_cc: clang
# compiler_cxx: clang++
fail-fast: false
runs-on: ${{ matrix.os }}
name: ${{ matrix.os_short }}-${{ matrix.os }}-${{ matrix.compiler_cc }}
env:
DEPENDENCIES_FOLDER: dependencies
DEPENDENCIES_ROOT: ${{ github.workspace }}/dependencies
DEPENDENCIES_ROOT_WIN: ${{ github.workspace }}\dependencies
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
path: amxmodx
# Setup Python for AMBuild
- uses: actions/setup-python@v2
name: Setup Python 3.8
with:
python-version: 3.8
- name: Install Python dependencies
run: |
python3 -m pip install --upgrade pip setuptools wheel
python3 --version
- name: Install AMXModX dependencies (Linux)
if: startsWith(runner.os, 'Linux') || startsWith(runner.os, 'macOS')
shell: bash
run: |
mkdir -p ${{ env.DEPENDENCIES_FOLDER }}
cd ${{ env.DEPENDENCIES_FOLDER }}
# Satisfy checkout-deps requirement for a "amxmodx" folder.
mkdir -p amxmodx
../amxmodx/support/checkout-deps.sh
- name: Install AMXModX dependencies (Windows)
if: startsWith(runner.os, 'Windows')
shell: cmd
run: |
mkdir %DEPENDENCIES_ROOT_WIN%\nasm
curl -L -o "%DEPENDENCIES_ROOT_WIN%\nasm\nasm.zip" https://www.nasm.us/pub/nasm/releasebuilds/2.13.03/win32/nasm-2.13.03-win32.zip
chdir %DEPENDENCIES_ROOT_WIN%\nasm
7z x nasm.zip
chdir %DEPENDENCIES_ROOT_WIN%
git clone https://github.com/alliedmodders/ambuild
git clone https://github.com/alliedmodders/metamod-hl1 metamod-am
git clone https://github.com/alliedmodders/hlsdk
curl -L -o "mysql-connector-c-6.1.1-win32.zip" https://downloads.mysql.com/archives/get/p/19/file/mysql-connector-c-6.1.1-win32.zip
7z x mysql-connector-c-6.1.1-win32.zip -o"mysql"
cd mysql
dir
ren mysql-connector-c-6.1.1-win32 mysql-5.5
move /Y mysql-5.5 ..\
cd ..\ambuild
python3 setup.py install
- 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 nasm ${{ matrix.compiler_cc }} ${{ matrix.compiler_install }}
- name: Select 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
- uses: ilammy/setup-nasm@v1
- name: Build Linux/macOS
if: startsWith(runner.os, 'Linux') || startsWith(runner.os, 'macOS')
working-directory: amxmodx
run: |
mkdir build
cd build
python3 ../configure.py --enable-optimize --metamod=${{ env.DEPENDENCIES_ROOT }}/metamod-am --hlsdk=${{ env.DEPENDENCIES_ROOT }}/hlsdk --mysql=${{ env.DEPENDENCIES_ROOT }}/mysql-5.5
ambuild
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: x86
- name: Build Windows
if: startsWith(runner.os, 'Windows')
working-directory: amxmodx
shell: cmd
run: |
cl.exe
mkdir build
cd build
python3 ../configure.py --enable-optimize --metamod=${{ env.DEPENDENCIES_ROOT_WIN }}\metamod-am --hlsdk=${{ env.DEPENDENCIES_ROOT_WIN }}\hlsdk --mysql=${{ env.DEPENDENCIES_ROOT_WIN }}\mysql-5.5
ambuild

90
.gitignore vendored
View File

@ -1,90 +0,0 @@
# Binaries
*.dll
*.exe
*.so
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
JITDebug/
JITRelease/
JITDebugBinLog/
JITReleaseBinLog/
x64/
build/
[Bb]in/
[Oo]bj/
build/
obj-*/
# Visual Studio 2015 cache/options directory
.vs/
.vscode/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# Files generated by Mac OS X Finder
.DS_Store
# Files generated by Windows Explorer
Desktop.ini
Thumbs.db
# AMXX plugin build related files
plugins/compile.dat
plugins/compiled/
*.amx
*.amxx
build_deps/

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "public/amtl"]
path = public/amtl
url = https://github.com/alliedmodders/amtl

View File

@ -1,30 +0,0 @@
addons:
apt:
packages:
- clang-3.7
- lib32stdc++6
- lib32z1-dev
- libc6-dev-i386
- linux-libc-dev
- gcc-multilib
- g++-multilib
- nasm
sources:
- llvm-toolchain-precise-3.7
- ubuntu-toolchain-r-test
language: cpp
sudo: false
compiler:
- clang
install:
- pyenv install 3.6.3
- pyenv global 3.6.3
before_script:
- CHECKOUT_DIR=$PWD && cd ..
- chmod a+x $CHECKOUT_DIR/support/checkout-deps.sh
- $CHECKOUT_DIR/support/checkout-deps.sh && cd $CHECKOUT_DIR
script:
- mkdir build && cd build
- PATH="~/.local/bin:$PATH"
- CC=clang-3.7 CXX=clang-3.7 python3 ../configure.py --enable-optimize
- ambuild

View File

@ -1,514 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python :
import os
import subprocess
import locale
class AMXXConfig(object):
def __init__(self):
self.binaries = []
self.modules = []
self.plugins = {}
self.libpc300 = None
self.amxxpc = None
self.metamod_path = None
self.hlsdk_path = None
self.mysql_path = None
self.generated_headers = []
self.versionlib = None
self.zlib = None
self.hashing = None
self.utf8rewind = None
self.csx_app = None
self.stdcxx_path = None
self.nasm_path = None
def use_auto_versioning(self):
if builder.backend != 'amb2':
return False
return not getattr(builder.options, 'disable_auto_versioning', False)
def detectProductVersion(self):
builder.AddConfigureFile('product.version')
# For OS X dylib versioning
import re
with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
productContents = fp.read()
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
if m == None:
self.productVersion = '1.0.0'
else:
major, minor, release = m.groups()
self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
def detectMetamod(self):
metamod_path = builder.options.metamod_path
if not len(metamod_path):
metamod_path = os.getenv('METAMOD', '')
if len(metamod_path):
self.metamod_path = os.path.join(builder.originalCwd, metamod_path)
if not os.path.exists(os.path.join(self.metamod_path, 'metamod')):
raise Exception('Metamod path does not exist: {0}'.format(metamod_path))
else:
try_paths = [
os.path.join(builder.sourcePath, '..', 'metamod'),
os.path.join(builder.sourcePath, '..', 'metamod-am'),
os.path.join(builder.sourcePath, '..', 'metamod-hl1'),
]
for try_path in try_paths:
if os.path.exists(os.path.join(try_path, 'metamod')):
self.metamod_path = os.path.normpath(try_path)
break
if not self.metamod_path:
raise Exception('Could not find the source code to Metamod! Try passing --metamod to configure.py.')
def detectHlsdk(self):
hlsdk_path = builder.options.hlsdk_path
if not len(hlsdk_path):
hlsdk_path = os.getenv('HLSDK', '')
if len(hlsdk_path):
self.hlsdk_path = os.path.join(builder.originalCwd, hlsdk_path)
if not os.path.exists(self.hlsdk_path):
raise Exception('HLSDK path does not exist: {0}'.format(hlsdk_path))
else:
try_paths = [
os.path.join(builder.sourcePath, '..', 'hlsdk'),
]
for try_path in try_paths:
if os.path.exists(try_path):
self.hlsdk_path = os.path.normpath(try_path)
break
if not self.hlsdk_path:
raise Exception('Could not find the HLSDK! Try passing --hlsdk to configure.py.')
def detectMysql(self):
if builder.options.disable_mysql:
return
mysql_path = builder.options.mysql_path
if not len(mysql_path):
mysql_path = os.getenv('MYSQL55', '')
if len(mysql_path):
self.mysql_path = os.path.join(builder.originalCwd, mysql_path)
if not os.path.exists(self.mysql_path):
raise Exception('MySQL path does not exist: {0}'.format(mysql_path))
else:
try_paths = [
os.path.join(builder.sourcePath, '..', 'mysql-5.5'),
]
for try_path in try_paths:
if os.path.exists(try_path):
self.mysql_path = os.path.normpath(try_path)
break
if not self.mysql_path:
raise Exception('Could not find MySQL! Try passing --mysql to configure.py.')
def detectNASM(self):
import subprocess
nasm_paths = [
getattr(builder.options, 'nasm_path', 'nasm'),
]
if builder.target_platform == 'windows':
nasm_paths += [os.path.join(
builder.sourcePath,
'build_deps',
'nasm',
'nasm.exe')
]
for nasm_path in nasm_paths:
try:
subprocess.check_output([nasm_path, '-v'])
self.nasm_path = nasm_path
break
except:
pass
if self.nasm_path is None:
raise Exception('Could not find a suitable path for nasm')
# Returns list of lines of output from the compiler
@staticmethod
def invokeCompiler(args):
if builder.compiler:
p = subprocess.Popen(builder.compiler.argv + args, stdout=subprocess.PIPE)
output = p.communicate()[0]
if hasattr(output,'encoding') and output.encoding is not None:
encoding = output.encoding
else:
encoding = locale.getpreferredencoding()
return output.decode(encoding, 'replace').split('\n')
return None
def configure(self):
builder.AddConfigureFile('pushbuild.txt')
cxx = builder.DetectCompilers()
if cxx.like('gcc'):
self.configure_gcc(cxx)
elif cxx.like('msvc'):
self.configure_msvc(cxx)
# Optimization
if builder.options.opt == '1':
cxx.defines += ['NDEBUG']
# Debugging
if builder.options.debug == '1':
cxx.defines += ['DEBUG', '_DEBUG']
# Platform-specifics
if builder.target_platform == 'linux':
self.configure_linux(cxx)
elif builder.target_platform == 'mac':
self.configure_mac(cxx)
elif builder.target_platform == 'windows':
self.configure_windows(cxx)
# Finish up.
cxx.defines += [
'AMX_NOPROPLIST',
'PAWN_CELL_SIZE=32',
'AMXMODX_BUILD',
'AMXX_USE_VERSIONLIB',
]
if self.use_auto_versioning():
cxx.defines += ['AMXX_GENERATED_BUILD']
cxx.includes += [os.path.join(builder.buildPath, 'includes')]
cxx.includes += [os.path.join(builder.sourcePath, 'support', 'versionlib')]
cxx.includes += [os.path.join(builder.sourcePath, 'public')]
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'sdk')]
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'amtl')]
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl')]
cxx.includes += [os.path.join(builder.sourcePath, 'public', 'memtools')]
cxx.includes += [os.path.join(builder.sourcePath, 'third_party')]
cxx.includes += [os.path.join(builder.sourcePath, 'third_party', 'hashing')]
cxx.includes += [os.path.join(builder.sourcePath, 'third_party', 'zlib')]
cxx.includes += [os.path.join(builder.sourcePath, 'third_party', 'utf8rewind')]
def configure_gcc(self, cxx):
cxx.cflags += [
'-pipe',
'-fno-strict-aliasing',
'-Wall',
'-Werror',
'-Wno-uninitialized',
'-Wno-unused',
'-Wno-switch',
'-Wno-format',
'-Wno-format-security',
'-m32',
]
cxx.cxxflags += [
'-Wno-invalid-offsetof',
'-std=c++11',
]
cxx.linkflags += ['-m32']
have_gcc = cxx.vendor == 'gcc'
have_clang = cxx.vendor == 'clang'
if have_clang or (have_gcc and cxx.version >= '4'):
cxx.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.version >= '4.6'):
cxx.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if have_gcc and cxx.version >= '4.8':
cxx.cflags += ['-Wno-unused-result', '-Wno-error=sign-compare']
if have_gcc and cxx.version >= '8.0':
cxx.cflags += ['-Wno-stringop-truncation']
if have_gcc and cxx.version >= '9.0':
cxx.cflags += ['-Wno-address-of-packed-member']
if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= '10.0':
cxx.cxxflags += ['-Wno-tautological-compare']
if cxx.version >= 'apple-clang-10.0':
cxx.cxxflags += [
'-Wno-inconsistent-missing-override',
'-Wno-varargs',
]
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
if builder.target_platform == 'linux' and cxx.version >= '3.6':
cxx.cxxflags += ['-Wno-inconsistent-missing-override']
if builder.target_platform == 'linux' and cxx.version >= '3.9':
cxx.cxxflags += ['-Wno-varargs']
if builder.target_platform == 'linux' and cxx.version >= '4.0':
cxx.cxxflags += ['-Wno-address-of-packed-member']
if have_gcc:
cxx.cflags += ['-Wno-parentheses']
cxx.c_only_flags += ['-std=c99']
elif have_clang:
cxx.cflags += ['-Wno-logical-op-parentheses']
cxx.cxxflags += [
'-fno-exceptions',
'-fno-rtti',
]
if builder.options.opt == '1':
cxx.cflags += ['-O2']
def configure_msvc(self, cxx):
if builder.options.debug == '1':
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
else:
cxx.cflags += ['/MT']
cxx.defines += [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
'_ITERATOR_DEBUG_LEVEL=0',
]
cxx.cflags += [
'/W3',
]
cxx.cxxflags += [
'/EHsc',
'/GR-',
'/TP',
]
cxx.linkflags += [
'/MACHINE:X86',
'/SUBSYSTEM:WINDOWS',
'kernel32.lib',
'user32.lib',
'gdi32.lib',
'winspool.lib',
'comdlg32.lib',
'advapi32.lib',
'shell32.lib',
'ole32.lib',
'oleaut32.lib',
'uuid.lib',
'odbc32.lib',
'odbccp32.lib',
]
if cxx.version >= 1900:
cxx.linkflags += ['legacy_stdio_definitions.lib', 'legacy_stdio_wide_specifiers.lib']
if builder.options.opt == '1':
cxx.cflags += ['/Ox']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
if builder.options.debug == '1':
cxx.cflags += ['/Od', '/RTC1']
# This needs to be after our optimization flags which could otherwise disable it.
# Don't omit the frame pointer.
cxx.cflags += ['/Oy-']
def configure_linux(self, cxx):
cxx.defines += ['_LINUX', 'POSIX', 'LINUX']
cxx.linkflags += ['-ldl', '-lm']
if cxx.vendor == 'gcc':
cxx.linkflags += ['-static-libgcc']
elif cxx.vendor == 'clang':
cxx.linkflags += ['-lgcc_eh']
if cxx.like('gcc'):
self.stdcxx_path = self.invokeCompiler(['-m32', '-print-file-name=' + 'libstdc++.a'])[0]
def configure_mac(self, cxx):
cxx.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += [
'-mmacosx-version-min=10.7',
'-Wno-address-of-packed-member',
]
cxx.linkflags += [
'-mmacosx-version-min=10.7',
'-arch', 'i386',
'-lstdc++',
'-stdlib=libc++',
'-framework', 'CoreServices',
]
cxx.cxxflags += ['-stdlib=libc++']
def configure_windows(self, cxx):
cxx.defines += ['WIN32', '_WINDOWS']
#
# Low-level compiler and binary construction.
#
def ConfigureForModule(self, context, compiler):
compiler.cxxincludes += [
os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sdk'),
os.path.join(self.metamod_path, 'metamod'),
os.path.join(self.hlsdk_path, 'common'),
os.path.join(self.hlsdk_path, 'dlls'),
os.path.join(self.hlsdk_path, 'engine'),
os.path.join(self.hlsdk_path, 'game_shared'),
os.path.join(self.hlsdk_path, 'public'),
os.path.join(self.hlsdk_path, 'pm_shared'),
]
return compiler
def AddVersioning(self, binary):
if builder.target_platform == 'windows':
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'RC_COMPILE',
]
if self.use_auto_versioning():
binary.compiler.rcdefines += ['AMXX_GENERATED_BUILD']
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.linkflags += [self.versionlib]
binary.compiler.sourcedeps += AMXX.generated_headers
return binary
#
# High level job construction for libraries, metamod plugins, modules, and
# executables.
#
def Library(self, context, name):
binary = context.compiler.Library(name)
return self.AddVersioning(binary)
def MetaPlugin(self, context, name):
if builder.target_platform == 'mac' or builder.target_platform == 'windows':
name = name + '_mm'
elif builder.target_platform == 'linux':
name = name + '_mm_i386'
binary = context.compiler.Library(name)
self.ConfigureForModule(context, binary.compiler)
return self.AddVersioning(binary)
def MetaModule(self, context, name):
if builder.target_platform == 'mac' or builder.target_platform == 'windows':
name = name + '_amxx'
elif builder.target_platform == 'linux':
name = name + '_amxx_i386'
binary = context.compiler.Library(name)
self.ConfigureForModule(context, binary.compiler)
return self.AddVersioning(binary)
def Program(self, context, name):
binary = context.compiler.Program(name)
return self.AddVersioning(binary)
def AddAssembly(self, context, binary, input_file, output_file, includes=[], extra_argv=[]):
if builder.target_platform == 'windows':
obj_type = 'win32'
elif builder.target_platform == 'linux':
obj_type = 'elf32'
elif builder.target_platform == 'mac':
obj_type = 'macho32'
input_path = os.path.join(context.currentSourcePath, input_file)
output_path = output_file
argv = [
self.nasm_path,
'-I{0}{1}'.format(context.currentSourcePath, os.sep),
input_path,
'-f', obj_type,
'-o', output_path,
] + extra_argv
extra_includes = []
for include_file in includes:
extra_includes.append(os.path.join(context.currentSourcePath, include_file))
cmd_node, output_nodes = context.AddCommand(
inputs = [input_path] + extra_includes,
argv = argv,
outputs = [output_path])
binary.compiler.linkflags += [output_nodes[0]]
AMXX = AMXXConfig()
AMXX.detectProductVersion()
AMXX.detectMetamod()
AMXX.detectHlsdk()
AMXX.detectMysql()
AMXX.detectNASM()
AMXX.configure()
if AMXX.use_auto_versioning():
AMXX.generated_headers = builder.RunScript(
'support/Versioning',
{ 'AMXX': AMXX }
)
AMXX.versionlib = builder.RunScript(
'support/versionlib/AMBuilder',
{ 'AMXX': AMXX }
)
AMXX.zlib = builder.RunScript(
'third_party/zlib/AMBuilder'
)
AMXX.hashing = builder.RunScript(
'third_party/hashing/AMBuilder'
)
AMXX.utf8rewind = builder.RunScript(
'third_party/utf8rewind/AMBuilder'
)
builder.RunBuildScripts(
[
'amxmodx/AMBuilder',
'compiler/amxxpc/AMBuilder',
'compiler/libpc300/AMBuilder',
'modules/cstrike/cstrike/AMBuilder',
'modules/cstrike/csx/AMBuilder',
'modules/dod/dodfun/AMBuilder',
'modules/dod/dodx/AMBuilder',
'modules/engine/AMBuilder',
'modules/fakemeta/AMBuilder',
'modules/fun/AMBuilder',
'modules/geoip/AMBuilder',
'modules/hamsandwich/AMBuilder',
'modules/json/AMBuilder',
'modules/mysqlx/AMBuilder',
'modules/ns/AMBuilder',
'modules/nvault/AMBuilder',
'modules/regex/AMBuilder',
'modules/sockets/AMBuilder',
'modules/sqlite/AMBuilder',
'modules/tfcx/AMBuilder',
'modules/ts/tsfun/AMBuilder',
'modules/ts/tsx/AMBuilder',
],
{ 'AMXX': AMXX }
)
# The csstats.dat reader is Windows-only.
if builder.target_platform == 'windows':
builder.RunScript('modules/cstrike/csx/WinCSX/AMBuilder', { 'AMXX': AMXX })
if builder.backend == 'amb2':
builder.RunBuildScripts([
'plugins/AMBuilder',
'support/PackageScript',
],
{ 'AMXX': AMXX }
)

View File

@ -1,22 +0,0 @@
<p align="center">
<img src="https://github.com/alliedmodders/amxmodx/blob/master/editor/studio/AMXXLarge.bmp"/>
</p>
**AMX Mod X** is a [Metamod](https://github.com/jkivilin/metamod-p) plugin for [Half-Life 1](https://github.com/ValveSoftware/halflife). It provides comprehensive scripting for the game engine and its mods. Scripts can intercept network messages, log events, commands, client commands, set cvars, modify entities, and more. AMX Mod X also has a system for extending native scripting through modules, leading to outside support for things like MySQL and Sockets.
General
-------
- [AMXX website](https://amxmodx.org/)
- [Forum](https://forums.alliedmods.net/forumdisplay.php?f=3): Discussion forum including plugin/extension development
- [General documentation](https://wiki.alliedmods.net/Category:Documentation_%28AMX_Mod_X%29): Miscellaneous information about AMXX
- [Latest release](https://amxmodx.org/downloads.php): The latest stable AMXX release
- [Build snapshots](https://www.amxmodx.org/downloads-new.php): Builds of recent development versions
Development
-----------
- [Issue tracker](https://github.com/alliedmodders/amxmodx/issues): Issues that require back and forth communication
- [Issue archive](https://bugs.alliedmods.net/describecomponents.cgi?product=AMX%20Mod%20X): Old issue tracker (read-only)
- [Building AMXX](https://wiki.alliedmods.net/Building_AMX_Mod_X): Instructions on how to build AMXX itself using [AMBuild](https://github.com/alliedmodders/ambuild)
- [AMX Mod X API](https://amxmodx.org/api/): AMX Mod X API reference generated from include files
- [AMXX scripting](https://wiki.alliedmods.net/Category:Scripting_(AMX_Mod_X)): Pawn examples and introduction to the language

View File

@ -1,101 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os.path
binary = AMXX.MetaPlugin(builder, 'amxmodx')
binary.compiler.defines += [
'JIT',
'ASM32',
'HAVE_STDINT_H',
]
AMXX.AddAssembly(builder, binary, 'helpers-x86.asm', 'helpers-asm.obj')
AMXX.AddAssembly(builder, binary, 'natives-x86.asm', 'natives-asm.obj')
AMXX.AddAssembly(builder, binary, 'amxexecn.asm', 'amxexecn-asm.obj',
includes=['amxdefn.asm'])
AMXX.AddAssembly(builder, binary, 'amxjitsn.asm', 'amxjitsn-asm.obj',
includes=['amxdefn.asm'],
# Opcode sizes must be maximum width for patching to work.
extra_argv=['-O0'])
if builder.target_platform == 'mac':
binary.compiler.postlink += [
'-Wl,-read_only_relocs,suppress'
]
elif builder.target_platform == 'windows':
binary.compiler.linkflags += [
'/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1',
'/SECTION:.data,RW',
]
elif builder.target_platform == 'linux':
binary.compiler.postlink += [
binary.Dep(AMXX.stdcxx_path),
]
binary.compiler.linkflags += [AMXX.zlib.binary, AMXX.hashing.binary, AMXX.utf8rewind.binary]
binary.sources = [
'meta_api.cpp',
'CVault.cpp',
'vault.cpp',
'float.cpp',
'file.cpp',
'modules.cpp',
'CMisc.cpp',
'CTask.cpp',
'string.cpp',
'amxmodx.cpp',
'CEvent.cpp',
'CCmd.cpp',
'CLogEvent.cpp',
'srvcmd.cpp',
'strptime.cpp',
'amxcore.cpp',
'amxtime.cpp',
'power.cpp',
'amxxlog.cpp',
'fakemeta.cpp',
'amxxfile.cpp',
'CLang.cpp',
'emsg.cpp',
'CForward.cpp',
'CPlugin.cpp',
'CModule.cpp',
'CMenu.cpp',
'util.cpp',
'amx.cpp',
'amxdbg.cpp',
'natives.cpp',
'newmenus.cpp',
'debugger.cpp',
'optimizer.cpp',
'format.cpp',
'messages.cpp',
'libraries.cpp',
'vector.cpp',
'sorting.cpp',
'nongpl_matches.cpp',
'CFlagManager.cpp',
'datastructs.cpp',
'trie_natives.cpp',
'CDataPack.cpp',
'datapacks.cpp',
'stackstructs.cpp',
'CTextParsers.cpp',
'textparse.cpp',
'CvarManager.cpp',
'cvars.cpp',
'../public/memtools/MemoryUtils.cpp',
'../public/memtools/CDetour/detours.cpp',
'../public/memtools/CDetour/asm/asm.c',
'../public/resdk/mod_rehlds_api.cpp',
'CLibrarySys.cpp',
'CGameConfigs.cpp',
'gameconfigs.cpp',
'CoreConfig.cpp',
]
if builder.target_platform == 'windows':
binary.sources += ['version.rc']
AMXX.binaries += [builder.Add(binary)]

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "CCmd.h" #include "CCmd.h"
@ -30,20 +52,19 @@ CmdMngr::CmdMngr()
} }
CmdMngr::Command::Command(CPluginMngr::CPlugin* pplugin, const char* pcmd, const char* pinfo, int pflags, CmdMngr::Command::Command(CPluginMngr::CPlugin* pplugin, const char* pcmd, const char* pinfo, int pflags,
int pfunc, bool pviewable, bool pinfo_ml, CmdMngr* pparent) : commandline(pcmd), info(pinfo) int pfunc, bool pviewable, CmdMngr* pparent) : commandline(pcmd), info(pinfo)
{ {
char szCmd[64], szArg[64]; char szCmd[64], szArg[64];
*szCmd = 0; *szArg = 0; *szCmd = 0; *szArg = 0;
sscanf(pcmd, "%s %s", szCmd, szArg); sscanf(pcmd, "%s %s", szCmd, szArg);
command = szCmd; command.assign(szCmd);
argument = szArg; argument.assign(szArg);
plugin = pplugin; plugin = pplugin;
flags = pflags; flags = pflags;
cmdtype = 0; cmdtype = 0;
prefix = 0; prefix = 0;
function = pfunc; function = pfunc;
listable = pviewable; listable = pviewable;
info_ml = pinfo_ml;
parent = pparent; parent = pparent;
id = --uniqueid; id = --uniqueid;
} }
@ -53,9 +74,9 @@ CmdMngr::Command::~Command()
++uniqueid; ++uniqueid;
} }
CmdMngr::Command* CmdMngr::registerCommand(CPluginMngr::CPlugin* plugin, int func, const char* cmd, const char* info, int level, bool listable, bool info_ml) CmdMngr::Command* CmdMngr::registerCommand(CPluginMngr::CPlugin* plugin, int func, char* cmd, char* info, int level, bool listable)
{ {
Command* b = new Command(plugin, cmd, info, level, func, listable, info_ml, this); Command* b = new Command(plugin, cmd, info, level, func, listable, this);
if (b == 0) return 0; if (b == 0) return 0;
setCmdLink(&sortedlists[0], b); setCmdLink(&sortedlists[0], b);
@ -103,6 +124,8 @@ CmdMngr::Command* CmdMngr::getCmd(long int id, int type, int access)
int CmdMngr::getCmdNum(int type, int access) int CmdMngr::getCmdNum(int type, int access)
{ {
if ((access == buf_access) && (type == buf_type))
return buf_num; // once calculated don't have to be done again
buf_access = access; buf_access = access;
buf_type = type; buf_type = type;
@ -132,7 +155,7 @@ void CmdMngr::setCmdLink(CmdLink** a, Command* c, bool sorted)
{ {
int i = strcmp(c->getCommand(), (*a)->cmd->getCommand()); int i = strcmp(c->getCommand(), (*a)->cmd->getCommand());
if ((i < 0) || ((i == 0) && (strcmp(c->getArgument(), (*a)->cmd->getArgument()) < 0))) if ((i < 0) || (i == 0) && (strcmp(c->getArgument(), (*a)->cmd->getArgument()) < 0))
break; break;
a = &(*a)->next; a = &(*a)->next;
@ -201,7 +224,7 @@ bool CmdMngr::registerCmdPrefix(Command* cc)
if (*b) if (*b)
{ {
setCmdLink(&(*b)->list, cc, false); setCmdLink(&(*b)->list, cc, false);
cc->prefix = (*b)->name.length(); cc->prefix = (*b)->name.size();
return true; return true;
} }
@ -223,7 +246,7 @@ CmdMngr::CmdPrefix** CmdMngr::findPrefix(const char* nn)
while (*aa) while (*aa)
{ {
if (!strncmp((*aa)->name.chars(), nn, (*aa)->name.length())) if (!strncmp((*aa)->name.c_str(), nn, (*aa)->name.size()))
break; break;
aa = &(*aa)->next; aa = &(*aa)->next;
} }

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef COMMANDS_H #ifndef COMMANDS_H
#define COMMANDS_H #define COMMANDS_H
@ -33,12 +55,11 @@ public:
CPluginMngr::CPlugin* plugin; CPluginMngr::CPlugin* plugin;
CmdMngr* parent; CmdMngr* parent;
ke::AString command; String command;
ke::AString argument; String argument;
ke::AString commandline; String commandline;
ke::AString info; String info;
bool info_ml;
bool listable; bool listable;
int function; int function;
int flags; int flags;
@ -47,20 +68,19 @@ public:
int prefix; int prefix;
static int uniqueid; static int uniqueid;
Command(CPluginMngr::CPlugin* pplugin, const char* pcmd, const char* pinfo, int pflags, int pfunc, bool pviewable, bool pinfo_ml, CmdMngr* pparent); Command(CPluginMngr::CPlugin* pplugin, const char* pcmd, const char* pinfo, int pflags, int pfunc, bool pviewable, CmdMngr* pparent);
~Command(); ~Command();
public: public:
inline const char* getCommand() { return command.chars(); } inline const char* getCommand() { return command.c_str(); }
inline const char* getArgument() { return argument.chars(); } inline const char* getArgument() { return argument.c_str(); }
inline const char* getCmdInfo() { return info.chars(); } inline const char* getCmdInfo() { return info.c_str(); }
inline const char* getCmdLine() { return commandline.chars(); } inline const char* getCmdLine() { return commandline.c_str(); }
inline bool matchCommandLine(const char* cmd, const char* arg) {return (!stricmp(command.chars() + prefix, cmd + prefix) && (!argument.length() || !stricmp(argument.chars(), arg)));} inline bool matchCommandLine(const char* cmd, const char* arg) { return (!stricmp(command.c_str() + prefix, cmd + prefix) && (argument.empty() || !stricmp(argument.c_str(), arg))); }
inline bool matchCommand(const char* cmd) { return (!stricmp(command.chars(), cmd)); } inline bool matchCommand(const char* cmd) { return (!strcmp(command.c_str(), cmd)); }
inline int getFunction() const { return function; } inline int getFunction() const { return function; }
inline bool gotAccess(int f) const { return (!flags || ((flags & f) != 0)); } inline bool gotAccess(int f) const { return (!flags || ((flags & f) == flags)); }
inline CPluginMngr::CPlugin* getPlugin() { return plugin; } inline CPluginMngr::CPlugin* getPlugin() { return plugin; }
inline bool isViewable() const { return listable; } inline bool isViewable() const { return listable; }
inline bool isInfoML() const { return info_ml; }
inline int getFlags() const { return flags; } inline int getFlags() const { return flags; }
inline long int getId() const { return (long int)id; } inline long int getId() const { return (long int)id; }
@ -85,7 +105,7 @@ private:
struct CmdPrefix struct CmdPrefix
{ {
ke::AString name; String name;
CmdMngr* parent; CmdMngr* parent;
CmdLink* list; CmdLink* list;
CmdPrefix* next; CmdPrefix* next;
@ -108,7 +128,7 @@ public:
void registerPrefix(const char* nn); void registerPrefix(const char* nn);
Command* registerCommand(CPluginMngr::CPlugin* plugin, int func, const char* cmd, const char* info, int level, bool listable, bool info_ml); Command* registerCommand(CPluginMngr::CPlugin* plugin, int func, char* cmd, char* info, int level, bool listable);
Command* getCmd(long int id, int type, int access); Command* getCmd(long int id, int type, int access);
int getCmdNum(int type, int access); int getCmdNum(int type, int access);

View File

@ -1,340 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*/
#include "CDataPack.h"
#define DATAPACK_INITIAL_SIZE 64
CDataPack::CDataPack()
{
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
m_capacity = DATAPACK_INITIAL_SIZE;
Initialize();
}
CDataPack::~CDataPack()
{
free(m_pBase);
}
void CDataPack::Initialize()
{
m_curptr = m_pBase;
m_size = 0;
}
void CDataPack::CheckSize(size_t typesize)
{
if (m_curptr - m_pBase + typesize <= m_capacity)
{
return;
}
size_t pos = m_curptr - m_pBase;
do
{
m_capacity *= 2;
} while (pos + typesize > m_capacity);
m_pBase = (char *)realloc(m_pBase, m_capacity);
m_curptr = m_pBase + pos;
}
void CDataPack::ResetSize()
{
m_size = 0;
}
size_t CDataPack::CreateMemory(size_t size, void **addr)
{
CheckSize(sizeof(char) + sizeof(size_t) + size);
size_t pos = m_curptr - m_pBase;
*(char *)m_curptr = Raw;
m_curptr += sizeof(char);
*(size_t *)m_curptr = size;
m_curptr += sizeof(size_t);
if (addr)
{
*addr = m_curptr;
}
m_curptr += size;
m_size += sizeof(char) + sizeof(size_t) + size;
return pos;
}
void CDataPack::PackCell(cell cells)
{
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell));
*(char *)m_curptr = DataPackType::Cell;
m_curptr += sizeof(char);
*(size_t *)m_curptr = sizeof(cell);
m_curptr += sizeof(size_t);
*(cell *)m_curptr = cells;
m_curptr += sizeof(cell);
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell);
}
void CDataPack::PackFloat(float val)
{
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
*(char *)m_curptr = DataPackType::Float;
m_curptr += sizeof(char);
*(size_t *)m_curptr = sizeof(float);
m_curptr += sizeof(size_t);
*(float *)m_curptr = val;
m_curptr += sizeof(float);
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
}
void CDataPack::PackString(const char *string)
{
size_t len = strlen(string);
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
CheckSize(maxsize);
*(char *)m_curptr = DataPackType::String;
m_curptr += sizeof(char);
// Pack the string length first for buffer overrun checking.
*(size_t *)m_curptr = len;
m_curptr += sizeof(size_t);
// Now pack the string.
memcpy(m_curptr, string, len);
m_curptr[len] = '\0';
m_curptr += len + 1;
m_size += maxsize;
}
void CDataPack::Reset() const
{
m_curptr = m_pBase;
}
size_t CDataPack::GetPosition() const
{
return static_cast<size_t>(m_curptr - m_pBase);
}
bool CDataPack::SetPosition(size_t pos) const
{
if (pos > m_size-1)
{
return false;
}
m_curptr = m_pBase + pos;
return true;
}
bool CDataPack::CanReadCell() const
{
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell)))
{
return false;
}
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::Cell)
{
return false;
}
if (*reinterpret_cast<size_t *>(m_curptr + sizeof(char)) != sizeof(cell))
{
return false;
}
return true;
}
cell CDataPack::ReadCell() const
{
if (!CanReadCell())
{
return 0;
}
m_curptr += sizeof(char);
m_curptr += sizeof(size_t);
cell val = *reinterpret_cast<cell *>(m_curptr);
m_curptr += sizeof(cell);
return val;
}
bool CDataPack::CanReadFloat() const
{
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
{
return false;
}
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::Float)
{
return false;
}
if (*reinterpret_cast<size_t *>(m_curptr + sizeof(char)) != sizeof(float))
{
return false;
}
return true;
}
float CDataPack::ReadFloat() const
{
if (!CanReadFloat())
{
return 0;
}
m_curptr += sizeof(char);
m_curptr += sizeof(size_t);
float val = *reinterpret_cast<float *>(m_curptr);
m_curptr += sizeof(float);
return val;
}
bool CDataPack::IsReadable(size_t bytes) const
{
return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
}
bool CDataPack::CanReadString(size_t *len) const
{
if (!IsReadable(sizeof(char) + sizeof(size_t)))
{
return false;
}
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::String)
{
return false;
}
size_t real_len = *(size_t *)(m_curptr + sizeof(char));
char *str = (char *)(m_curptr + sizeof(char) + sizeof(size_t));
if ((strlen(str) != real_len) || !(IsReadable(sizeof(char) + sizeof(size_t) + real_len + 1)))
{
return false;
}
if (len)
{
*len = real_len;
}
return true;
}
const char *CDataPack::ReadString(size_t *len) const
{
size_t real_len;
if (!CanReadString(&real_len))
{
return NULL;
}
m_curptr += sizeof(char);
m_curptr += sizeof(size_t);
char *str = (char *)m_curptr;
m_curptr += real_len + 1;
if (len)
{
*len = real_len;
}
return str;
}
void *CDataPack::GetMemory() const
{
return m_curptr;
}
bool CDataPack::CanReadMemory(size_t *size) const
{
if (!IsReadable(sizeof(char) + sizeof(size_t)))
{
return false;
}
if (*reinterpret_cast<char *>(m_curptr) != DataPackType::Raw)
{
return false;
}
size_t bytecount = *(size_t *)(m_curptr + sizeof(char));
if (!IsReadable(sizeof(char) + sizeof(size_t) + bytecount))
{
return false;
}
if (size)
{
*size = bytecount;
}
return true;
}
void *CDataPack::ReadMemory(size_t *size) const
{
size_t bytecount;
if (!CanReadMemory(&bytecount))
{
return NULL;
}
m_curptr += sizeof(char);
m_curptr += sizeof(size_t);
void *ptr = m_curptr;
m_curptr += bytecount;
if (size)
{
*size = bytecount;
}
return ptr;
}

View File

@ -1,181 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*/
#ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_
#include "amxmodx.h"
#include "natives_handles.h"
/**
* @brief Contains functions for packing data abstractly to/from plugins.
*/
class CDataPack
{
public:
CDataPack();
~CDataPack();
public:
/**
* @brief Resets the position in the data stream to the beginning.
*/
void Reset() const;
/**
* @brief Retrieves the current stream position.
*
* @return Index into the stream.
*/
size_t GetPosition() const;
/**
* @brief Sets the current stream position.
*
* @param pos Index to set the stream at.
* @return True if succeeded, false if out of bounds.
*/
bool SetPosition(size_t pos) const;
/**
* @brief Reads one cell from the data stream.
*
* @return A cell read from the current position.
*/
cell ReadCell() const;
/**
* @brief Reads one float from the data stream.
*
* @return A float read from the current position.
*/
float ReadFloat() const;
/**
* @brief Returns whether or not a specified number of bytes from the current stream
* position to the end can be read.
*
* @param bytes Number of bytes to simulate reading.
* @return True if can be read, false otherwise.
*/
bool IsReadable(size_t bytes) const;
/**
* @brief Reads a string from the data stream.
*
* @param len Optional pointer to store the string length.
* @return Pointer to the string, or NULL if out of bounds.
*/
const char *ReadString(size_t *len) const;
/**
* @brief Reads the current position as a generic address.
*
* @return Pointer to the memory.
*/
void *GetMemory() const;
/**
* @brief Reads the current position as a generic data type.
*
* @param size Optional pointer to store the size of the data type.
* @return Pointer to the data, or NULL if out of bounds.
*/
void *ReadMemory(size_t *size) const;
bool CanReadCell() const;
bool CanReadFloat() const;
bool CanReadString(size_t *len) const;
bool CanReadMemory(size_t *size) const;
public:
/**
* @brief Resets the used size of the stream back to zero.
*/
void ResetSize();
/**
* @brief Packs one cell into the data stream.
*
* @param cell Cell value to write.
*/
void PackCell(cell cells);
/**
* @brief Packs one float into the data stream.
*
* @param val Float value to write.
*/
void PackFloat(float val);
/**
* @brief Packs one string into the data stream.
* The length is recorded as well for buffer overrun protection.
*
* @param string String to write.
*/
void PackString(const char *string);
/**
* @brief Creates a generic block of memory in the stream.
*
* Note that the pointer it returns can be invalidated on further
* writing, since the stream size may grow. You may need to double back
* and fetch the pointer again.
*
* @param size Size of the memory to create in the stream.
* @param addr Optional pointer to store the relocated memory address.
* @return Current position of the stream beforehand.
*/
size_t CreateMemory(size_t size, void **addr);
public:
void Initialize();
private:
void CheckSize(size_t sizetype);
private:
char *m_pBase;
mutable char *m_curptr;
size_t m_capacity;
size_t m_size;
enum DataPackType {
Raw,
Cell,
Float,
String,
};
};
extern NativeHandle<CDataPack> DataPackHandles;
extern AMX_NATIVE_INFO g_DatapackNatives[];
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "CEvent.h" #include "CEvent.h"
@ -14,8 +36,6 @@
// class ClEvent // class ClEvent
// ***************************************************** // *****************************************************
NativeHandle<EventHook> EventHandles;
EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags) EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
{ {
m_Plugin = plugin; m_Plugin = plugin;
@ -26,7 +46,7 @@ EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
m_FlagDead = true; m_FlagDead = true;
m_FlagWorld = (flags & 1) ? true : false; // flag a m_FlagWorld = (flags & 1) ? true : false; // flag a
m_FlagClient = (flags & 2) ? true : false; // flag b m_FlagPlayer = (flags & 2) ? true : false; // flag b
m_FlagOnce = (flags & 4) ? true : false; // flag c m_FlagOnce = (flags & 4) ? true : false; // flag c
if (flags & 24) if (flags & 24)
@ -35,21 +55,8 @@ EventsMngr::ClEvent::ClEvent(CPluginMngr::CPlugin* plugin, int func, int flags)
m_FlagDead = (flags & 8) ? true : false; // flag d m_FlagDead = (flags & 8) ? true : false; // flag d
} }
if (m_FlagClient)
{
m_FlagPlayer = true;
m_FlagBot = true;
if (flags & 96)
{
m_FlagPlayer = (flags & 32) ? true : false; // flag f
m_FlagBot = (flags & 64) ? true : false; // flag g
}
}
m_Stamp = 0.0f; m_Stamp = 0.0f;
m_Done = false; m_Done = false;
m_State = FSTATE_ACTIVE;
m_Conditions = NULL; m_Conditions = NULL;
} }
@ -119,11 +126,7 @@ EventsMngr::EventsMngr()
{ {
m_ParseVault = NULL; m_ParseVault = NULL;
m_ParseVaultSize = 0; m_ParseVaultSize = 0;
m_ParseMsgType = -1; m_CurrentMsgType = -1;
m_ReadVault = NULL;
m_ReadVaultSize = 0;
m_ReadPos = -1;
m_ReadMsgType = -1;
clearEvents(); clearEvents();
} }
@ -172,7 +175,7 @@ void EventsMngr::ClEvent::registerFilter(char *filter)
tmpCond->paramId = atoi(filter); tmpCond->paramId = atoi(filter);
// rest of line // rest of line
tmpCond->sValue = value; tmpCond->sValue.assign(value);
tmpCond->fValue = static_cast<float>(atof(value)); tmpCond->fValue = static_cast<float>(atof(value));
tmpCond->iValue = atoi(value); tmpCond->iValue = atoi(value);
@ -191,31 +194,20 @@ void EventsMngr::ClEvent::registerFilter(char *filter)
m_Conditions = tmpCond; m_Conditions = tmpCond;
} }
void EventsMngr::ClEvent::setForwardState(ForwardState state) EventsMngr::ClEvent* EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid)
{
m_State = state;
}
int EventsMngr::registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid)
{ {
// validate parameter
if (msgid < 0 || msgid >= MAX_AMX_REG_MSG) if (msgid < 0 || msgid >= MAX_AMX_REG_MSG)
{ return NULL;
return 0;
}
auto event = ke::AutoPtr<ClEvent>(new ClEvent(plugin, func, flags)); ClEvent *event = new ClEvent(plugin, func, flags);
int handle = EventHandles.create(event.get());
if (!handle) if (!event)
{ return NULL;
return 0;
}
m_Events[msgid].append(ke::Move(event)); m_Events[msgid].put(event);
return handle; return event;
} }
void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index) void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index)
@ -223,43 +215,43 @@ void EventsMngr::parserInit(int msg_type, float* timer, CPlayer* pPlayer, int in
if (msg_type < 0 || msg_type > MAX_AMX_REG_MSG) if (msg_type < 0 || msg_type > MAX_AMX_REG_MSG)
return; return;
m_CurrentMsgType = msg_type;
m_ParseNotDone = false; m_ParseNotDone = false;
// don't parse if nothing to do
if (!m_Events[msg_type].length())
return;
m_ParseMsgType = msg_type;
m_Timer = timer; m_Timer = timer;
for (auto &event : m_Events[msg_type]) // don't parse if nothing to do
if (!m_Events[msg_type].size())
return;
for (ClEventVecIter iter = m_Events[msg_type].begin(); iter; ++iter)
{ {
if (event->m_Done) if ((*iter).m_Done)
continue; continue;
if (!event->m_Plugin->isExecutable(event->m_Func)) if (!(*iter).m_Plugin->isExecutable((*iter).m_Func))
{ {
event->m_Done = true; (*iter).m_Done = true;
continue; continue;
} }
if (pPlayer) if (pPlayer)
{ {
if (!event->m_FlagClient || (pPlayer->IsBot() ? !event->m_FlagBot : !event->m_FlagPlayer) || (pPlayer->IsAlive() ? !event->m_FlagAlive : !event->m_FlagDead)) if (!(*iter).m_FlagPlayer || (pPlayer->IsAlive() ? !(*iter).m_FlagAlive : !(*iter).m_FlagDead))
{ {
event->m_Done = true; (*iter).m_Done = true;
continue; continue;
} }
} }
else if (!event->m_FlagWorld) else if (!(*iter).m_FlagWorld)
{ {
event->m_Done = true; (*iter).m_Done = true;
continue; continue;
} }
if (event->m_FlagOnce && event->m_Stamp == *timer) if ((*iter).m_FlagOnce && (*iter).m_Stamp == (float)(*timer))
{ {
event->m_Done = true; (*iter).m_Done = true;
continue; continue;
} }
@ -292,16 +284,16 @@ void EventsMngr::parseValue(int iValue)
// loop through the registered funcs, and decide whether they have to be called or not // loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true // if they shouldnt, their m_Done is set to true
for (auto &event : *m_ParseFun) for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
{ {
if (event->m_Done) if ((*iter).m_Done)
continue; // already skipped; don't bother with parsing continue; // already skipped; don't bother with parsing
// loop through conditions // loop through conditions
bool execute = false; bool execute = false;
bool anyConditions = false; bool anyConditions = false;
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next) for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
{ {
if (condIter->paramId == m_ParsePos) if (condIter->paramId == m_ParsePos)
{ {
@ -320,7 +312,7 @@ void EventsMngr::parseValue(int iValue)
} }
if (anyConditions && !execute) if (anyConditions && !execute)
event->m_Done = true; // don't execute (*iter).m_Done = true; // don't execute
} }
} }
@ -339,16 +331,16 @@ void EventsMngr::parseValue(float fValue)
// loop through the registered funcs, and decide whether they have to be called or not // loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true // if they shouldnt, their m_Done is set to true
for (auto &event : *m_ParseFun) for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
{ {
if (event->m_Done) if ((*iter).m_Done)
continue; // already skipped; don't bother with parsing continue; // already skipped; don't bother with parsing
// loop through conditions // loop through conditions
bool execute = false; bool execute = false;
bool anyConditions = false; bool anyConditions = false;
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next) for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
{ {
if (condIter->paramId == m_ParsePos) if (condIter->paramId == m_ParsePos)
{ {
@ -367,7 +359,7 @@ void EventsMngr::parseValue(float fValue)
} }
if (anyConditions && !execute) if (anyConditions && !execute)
event->m_Done = true; // don't execute (*iter).m_Done = true; // don't execute
} }
} }
@ -386,25 +378,25 @@ void EventsMngr::parseValue(const char *sz)
// loop through the registered funcs, and decide whether they have to be called or not // loop through the registered funcs, and decide whether they have to be called or not
// if they shouldnt, their m_Done is set to true // if they shouldnt, their m_Done is set to true
for (auto &event : *m_ParseFun) for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
{ {
if (event->m_Done) if ((*iter).m_Done)
continue; // already skipped; don't bother with parsing continue; // already skipped; don't bother with parsing
// loop through conditions // loop through conditions
bool execute = false; bool execute = false;
bool anyConditions = false; bool anyConditions = false;
for (auto condIter = event->m_Conditions; condIter; condIter = condIter->next) for (ClEvent::cond_t *condIter = (*iter).m_Conditions; condIter; condIter = condIter->next)
{ {
if (condIter->paramId == m_ParsePos) if (condIter->paramId == m_ParsePos)
{ {
anyConditions = true; anyConditions = true;
switch (condIter->type) switch (condIter->type)
{ {
case '=': if (!strcmp(sz, condIter->sValue.chars())) execute = true; break; case '=': if (!strcmp(sz, condIter->sValue.c_str())) execute = true; break;
case '!': if (strcmp(sz, condIter->sValue.chars())) execute = true; break; case '!': if (strcmp(sz, condIter->sValue.c_str())) execute = true; break;
case '&': if (strstr(sz, condIter->sValue.chars())) execute = true; break; case '&': if (strstr(sz, condIter->sValue.c_str())) execute = true; break;
} }
if (execute) if (execute)
@ -413,134 +405,87 @@ void EventsMngr::parseValue(const char *sz)
} }
if (anyConditions && !execute) if (anyConditions && !execute)
event->m_Done = true; // don't execute (*iter).m_Done = true; // don't execute
} }
} }
void EventsMngr::executeEvents() void EventsMngr::executeEvents()
{ {
static unsigned int reentrant = 0;
if (!m_ParseFun) if (!m_ParseFun)
{ {
return; return;
} }
// Store old read data, which are either default values or previous event data for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
int oldMsgType = m_ReadMsgType, oldReadPos = m_ReadPos;
MsgDataEntry *oldReadVault = m_ReadVault, *readVault = NULL;
// We have a re-entrant call
if (reentrant++)
{ {
// Create temporary read vault if ((*iter).m_Done)
readVault = new MsgDataEntry[m_ParsePos + 1];
m_ReadVault = readVault;
} else if (m_ReadVaultSize != m_ParseVaultSize) {
// Extend read vault size if necessary
delete [] m_ReadVault;
m_ReadVault = new MsgDataEntry[m_ParseVaultSize];
m_ReadVaultSize = m_ParseVaultSize;
// Update old read vault so we don't restore to a wrong pointer
oldReadVault = m_ReadVault;
}
// Copy data over to readvault
m_ReadPos = m_ParsePos;
m_ReadMsgType = m_ParseMsgType;
if (m_ParseVault)
{
memcpy(m_ReadVault, m_ParseVault, (m_ParsePos + 1) * sizeof(MsgDataEntry));
}
// Reset this here so we don't trigger re-entrancy for unregistered messages
auto parseFun = m_ParseFun;
m_ParseFun = nullptr;
auto lastSize = parseFun->length();
for(auto i = 0u; i < lastSize; i++)
{
auto &event = parseFun->at(i);
if (event->m_Done)
{ {
event->m_Done = false; (*iter).m_Done = false;
continue; continue;
} }
event->m_Stamp = *m_Timer; (*iter).m_Stamp = (float)*m_Timer;
executeForwards((*iter).m_Func, static_cast<cell>(m_ParseVault ? m_ParseVault[0].iValue : 0));
if (event->m_State == FSTATE_ACTIVE)
{
executeForwards(event->m_Func, static_cast<cell>(m_ReadVault ? m_ReadVault[0].iValue : 0));
}
} }
// Restore old read data, either resetting to default or to previous event data
m_ReadMsgType = oldMsgType;
m_ReadPos = oldReadPos;
m_ReadVault = oldReadVault;
delete [] readVault;
--reentrant; m_CurrentMsgType = -1;
m_ParseFun = NULL;
} }
int EventsMngr::getArgNum() const int EventsMngr::getArgNum() const
{ {
return m_ReadPos + 1; return m_ParsePos + 1;
} }
const char* EventsMngr::getArgString(int a) const const char* EventsMngr::getArgString(int a) const
{ {
if (a < 0 || a > m_ReadPos) if (a < 0 || a > m_ParsePos)
return ""; return "";
static char var[32]; static char var[32];
switch (m_ReadVault[a].type) switch (m_ParseVault[a].type)
{ {
case MSG_INTEGER: case MSG_INTEGER:
sprintf(var, "%d", m_ReadVault[a].iValue); sprintf(var, "%d", m_ParseVault[a].iValue);
return var; return var;
case MSG_STRING: case MSG_STRING:
return m_ReadVault[a].sValue; return m_ParseVault[a].sValue;
default: default:
sprintf(var, "%g", m_ReadVault[a].fValue); sprintf(var, "%g", m_ParseVault[a].fValue);
return var; return var;
} }
} }
int EventsMngr::getArgInteger(int a) const int EventsMngr::getArgInteger(int a) const
{ {
if (a < 0 || a > m_ReadPos) if (a < 0 || a > m_ParsePos)
return 0; return 0;
switch (m_ReadVault[a].type) switch (m_ParseVault[a].type)
{ {
case MSG_INTEGER: case MSG_INTEGER:
return m_ReadVault[a].iValue; return m_ParseVault[a].iValue;
case MSG_STRING: case MSG_STRING:
return atoi(m_ReadVault[a].sValue); return atoi(m_ParseVault[a].sValue);
default: default:
return (int)m_ReadVault[a].fValue; return (int)m_ParseVault[a].fValue;
} }
} }
float EventsMngr::getArgFloat(int a) const float EventsMngr::getArgFloat(int a) const
{ {
if (a < 0 || a > m_ReadPos) if (a < 0 || a > m_ParsePos)
return 0.0f; return 0.0f;
switch (m_ReadVault[a].type) switch (m_ParseVault[a].type)
{ {
case MSG_INTEGER: case MSG_INTEGER:
return static_cast<float>(m_ReadVault[a].iValue); return static_cast<float>(m_ParseVault[a].iValue);
case MSG_STRING: case MSG_STRING:
return static_cast<float>(atof(m_ReadVault[a].sValue)); return static_cast<float>(atof(m_ParseVault[a].sValue));
default: default:
return m_ReadVault[a].fValue; return m_ParseVault[a].fValue;
} }
} }
@ -550,9 +495,7 @@ void EventsMngr::clearEvents(void)
{ {
m_Events[i].clear(); m_Events[i].clear();
} }
EventHandles.clear();
// delete parsevault // delete parsevault
if (m_ParseVault) if (m_ParseVault)
{ {
@ -560,14 +503,6 @@ void EventsMngr::clearEvents(void)
m_ParseVault = NULL; m_ParseVault = NULL;
m_ParseVaultSize = 0; m_ParseVaultSize = 0;
} }
if (m_ReadVault)
{
delete [] m_ReadVault;
m_ReadVault = NULL;
m_ReadVaultSize = 0;
m_ReadPos = -1;
}
} }
int EventsMngr::getEventId(const char* msg) int EventsMngr::getEventId(const char* msg)
@ -603,5 +538,5 @@ int EventsMngr::getEventId(const char* msg)
int EventsMngr::getCurrentMsgType() int EventsMngr::getCurrentMsgType()
{ {
return m_ReadMsgType; return m_CurrentMsgType;
} }

View File

@ -1,17 +1,37 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef __CEVENTS_H__ #ifndef __CEVENTS_H__
#define __CEVENTS_H__ #define __CEVENTS_H__
#include "natives_handles.h"
#define MAX_AMX_REG_MSG MAX_REG_MSGS + 16 #define MAX_AMX_REG_MSG MAX_REG_MSGS + 16
enum enum
@ -54,25 +74,22 @@ public:
CPluginMngr::CPlugin *m_Plugin; // the plugin this ClEvent class is assigned to CPluginMngr::CPlugin *m_Plugin; // the plugin this ClEvent class is assigned to
// flags // flags
bool m_FlagClient; bool m_FlagPlayer;
bool m_FlagWorld; bool m_FlagWorld;
bool m_FlagOnce; bool m_FlagOnce;
bool m_FlagDead; bool m_FlagDead;
bool m_FlagAlive; bool m_FlagAlive;
bool m_FlagPlayer;
bool m_FlagBot;
float m_Stamp; // for 'once' flag float m_Stamp; // for 'once' flag
bool m_Done; bool m_Done;
ForwardState m_State;
// conditions // conditions
struct cond_t struct cond_t
{ {
int paramId; // the message parameter id int paramId; // the message parameter id
ke::AString sValue; // value (string) String sValue; // value (string)
float fValue; // value (float) float fValue; // value (float)
int iValue; // value (int) int iValue; // value (int)
int type; // type (can be int, float, string) int type; // type (can be int, float, string)
@ -90,7 +107,6 @@ public:
inline CPluginMngr::CPlugin* getPlugin(); inline CPluginMngr::CPlugin* getPlugin();
inline int getFunction(); inline int getFunction();
void registerFilter(char* filter); // add a condition void registerFilter(char* filter); // add a condition
void setForwardState(ForwardState value);
}; };
private: private:
@ -103,31 +119,30 @@ private:
}; };
MsgDataEntry *m_ParseVault; MsgDataEntry *m_ParseVault;
MsgDataEntry *m_ReadVault;
int m_ParseVaultSize; int m_ParseVaultSize;
int m_ReadVaultSize;
void NextParam(); // make sure a new parameter can be added void NextParam(); // make sure a new parameter can be added
ke::Vector<ke::AutoPtr<ClEvent>> m_Events[MAX_AMX_REG_MSG]; typedef CList<ClEvent> ClEventVec;
ke::Vector<ke::AutoPtr<ClEvent>> *m_ParseFun; // current Event vector typedef ClEventVec::iterator ClEventVecIter;
ClEventVec m_Events[MAX_AMX_REG_MSG];
ClEventVec *m_ParseFun; // current Event vector
bool m_ParseNotDone; bool m_ParseNotDone;
int m_ParsePos; // is args. num. - 1 int m_ParsePos; // is args. num. - 1
int m_ReadPos;
float* m_Timer; float* m_Timer;
ClEvent* getValidEvent(ClEvent* a); ClEvent* getValidEvent(ClEvent* a);
int m_ParseMsgType; int m_CurrentMsgType;
int m_ReadMsgType;
public: public:
EventsMngr(); EventsMngr();
~EventsMngr(); ~EventsMngr();
// Interface // Interface
int registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid); ClEvent* registerEvent(CPluginMngr::CPlugin* plugin, int func, int flags, int msgid);
void parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index); void parserInit(int msg_type, float* timer, CPlayer* pPlayer, int index);
void parseValue(int iValue); void parseValue(int iValue);
void parseValue(float fValue); void parseValue(float fValue);
@ -143,12 +158,4 @@ public:
int getCurrentMsgType(); int getCurrentMsgType();
}; };
struct EventHook
{
explicit EventHook(EventsMngr::ClEvent *event) : m_event(event) {}
EventsMngr::ClEvent *m_event;
};
extern NativeHandle<EventHook> EventHandles;
#endif //__CEVENTS_H__ #endif //__CEVENTS_H__

126
amxmodx/CFile.cpp Executable file
View File

@ -0,0 +1,126 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include <ctype.h>
#include "amxmodx.h"
#include "CFile.h"
// *****************************************************
// class File
// *****************************************************
File::File(const char* n, const char* m)
{
fp = fopen(n, m);
}
File::~File()
{
if (fp)
fclose(fp);
}
File::operator bool () const
{
return fp && !feof(fp);
}
File& operator<<(File& f, const String& n)
{
if (f) fputs(n.c_str(), f.fp);
return f;
}
File& operator<<(File& f, const char* n)
{
if (f) fputs(n, f.fp);
return f;
}
File& operator<<(File& f, int n)
{
if (f) fprintf(f.fp, "%d", n);
return f;
}
File& operator<<(File& f, const char& c)
{
if (f) fputc(c, f.fp);
return f;
}
File& operator>>(File& f, String& n)
{
if (!f) return f;
char temp[1024];
fscanf(f.fp, "%s", temp);
n.assign(temp);
return f;
}
File& operator>>(File& f, char* n)
{
if (f) fscanf(f.fp, "%s", n);
return f;
}
int File::getline(char* buf, int sz)
{
int a = sz;
char *origBuf = buf;
if (*this)
{
int c;
while (sz-- && (c = getc((*this).fp)) && c != EOF && c != '\n')
*buf++ = c;
*buf = 0;
}
// trim 0x0a and 0x0d characters at the end
while (buf != origBuf)
{
if (*buf == 0x0a || *buf == 0x0d)
*buf = 0;
--buf;
}
return a - sz;
}
File& File::skipWs()
{
if (!*this) return *this;
int c;
while (isspace(c = getc(fp))) {};
ungetc(c, fp);
return *this;
}

59
amxmodx/CFile.h Executable file
View File

@ -0,0 +1,59 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include <stdio.h>
#include "CString.h"
// *****************************************************
// class File
// *****************************************************
class File
{
FILE* fp;
public:
File(const char* n, const char* m);
~File();
operator bool () const;
friend File& operator<<(File& f, const String& n);
friend File& operator<<(File& f, const char* n);
friend File& operator<<(File& f, const char& c);
friend File& operator<<(File& f, int n);
friend File& operator>>(File& f, String& n);
friend File& operator>>(File& f, char* n);
int getline(char* buf, int sz);
File& skipWs();
};

View File

@ -1,255 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _INCLUDE_CFILESYSTEM_H_
#define _INCLUDE_CFILESYSTEM_H_
#include <FileSystem.h> // IFileSystem, FileSystemSeek_t, FileHandle_t (HLSDK)
#include <stdio.h> // FILE*
extern IFileSystem* g_FileSystem;
class ValveFile;
class SystemFile;
class FileObject
{
public:
virtual ~FileObject() {};
virtual size_t Read(void* pOut, size_t size) = 0;
virtual char* ReadLine(char* pOut, size_t size) = 0;
virtual size_t Write(const void* pData, size_t size) = 0;
virtual bool Seek(int pos, int seek_type) = 0;
virtual int Tell() = 0;
virtual int Flush() = 0;
virtual bool HasError() = 0;
virtual bool EndOfFile() = 0;
virtual void Close() = 0;
virtual ValveFile *AsValveFile()
{
return nullptr;
}
virtual SystemFile *AsSystemFile()
{
return nullptr;
}
};
class ValveFile : public FileObject
{
public:
ValveFile(FileHandle_t handle) : handle_(handle) {}
~ValveFile()
{
Close();
}
static bool Exists(const char* file)
{
return g_FileSystem->FileExists(file);
}
static ValveFile* Open(const char* filename, const char* mode, const char* pathID)
{
FileHandle_t handle = g_FileSystem->OpenFromCacheForRead(filename, mode, pathID);
if (!handle)
{
return nullptr;
}
return new ValveFile(handle);
}
static bool Delete(const char* filename, const char* pathID)
{
if (!Exists(filename))
{
return false;
}
g_FileSystem->RemoveFile(filename, pathID);
if (Exists(filename))
{
return false;
}
return true;
}
size_t Read(void* pOut, size_t size) override
{
return static_cast<size_t>(g_FileSystem->Read(pOut, size, handle_));
}
char* ReadLine(char* pOut, size_t size) override
{
return g_FileSystem->ReadLine(pOut, size, handle_);
}
size_t Write(const void* pData, size_t size) override
{
return static_cast<size_t>(g_FileSystem->Write(pData, size, handle_));
}
bool Seek(int pos, int seek_type) override
{
g_FileSystem->Seek(handle_, pos, static_cast<FileSystemSeek_t>(seek_type));
return !HasError();
}
int Tell() override
{
return g_FileSystem->Tell(handle_);
}
bool HasError() override
{
return !handle_ || !g_FileSystem->IsOk(handle_);
}
int Flush() override
{
g_FileSystem->Flush(handle_);
return 0;
}
bool EndOfFile() override
{
return g_FileSystem->EndOfFile(handle_);
}
void Close() override
{
if (handle_)
{
g_FileSystem->Close(handle_);
handle_ = nullptr;;
}
}
virtual ValveFile* AsValveFile()
{
return this;
}
FileHandle_t handle() const
{
return handle_;
}
private:
FileHandle_t handle_;
};
class SystemFile : public FileObject
{
public:
SystemFile(FILE* fp) : fp_(fp) {}
~SystemFile()
{
Close();
}
static SystemFile* Open(const char* path, const char* mode)
{
FILE* fp = fopen(path, mode);
if (!fp)
{
return nullptr;
}
return new SystemFile(fp);
}
static bool Delete(const char* path)
{
return unlink(path) == 0;
}
size_t Read(void* pOut, size_t size) override
{
return fread(pOut, 1, size, fp_);
}
char* ReadLine(char* pOut, size_t size) override
{
return fgets(pOut, size, fp_);
}
size_t Write(const void* pData, size_t size) override
{
return fwrite(pData, 1, size, fp_);
}
bool Seek(int pos, int seek_type) override
{
return fseek(fp_, pos, seek_type) == 0;
}
int Tell() override
{
return ftell(fp_);
}
bool HasError() override
{
return ferror(fp_) != 0;
}
int Flush() override
{
return fflush(fp_);
}
bool EndOfFile() override
{
return feof(fp_) != 0;
}
void Close() override
{
if (fp_)
{
fclose(fp_);
fp_ = nullptr;
}
}
virtual SystemFile* AsSystemFile()
{
return this;
}
FILE* handle() const
{
return fp_;
}
private:
FILE* fp_;
};
#endif // _INCLUDE_CFILESYSTEM_H_

View File

@ -1,410 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "sh_list.h"
#include "amxmodx.h"
#include "CFlagManager.h"
void CFlagManager::SetFile(const char *Filename)
{
m_strConfigFile = build_pathname("%s/%s", get_localinfo("amxx_configsdir", "addons/amxmodx/configs"), Filename);
CreateIfNotExist();
}
const int CFlagManager::LoadFile(const int force)
{
CheckIfDisabled();
// If we're disabled get the hell out. now.
if (m_iDisabled)
{
return 0;
}
// if we're not forcing this, and NeedToLoad says we dont have to
// then just stop
if (!force && !NeedToLoad())
{
return 0;
}
this->Clear();
// We need to load the file
FILE *File;
File=fopen(GetFile(),"r");
if (!File)
{
AMXXLOG_Log("[AMXX] FlagManager: Cannot open file \"%s\" (FILE pointer null!)", GetFile());
return -1;
}
// Trying to copy this almost exactly as other configs are read...
char Line[512];
char TempLine[512];
char Command[256];
char Flags[256];
while (!feof(File) && fgets(Line, sizeof(Line), File))
{
char *nonconst= Line;
// Strip out comments
while (*nonconst)
{
if (*nonconst==';') // End the line at comments
{
*nonconst='\0';
}
else
{
nonconst++;
}
}
Command[0]='\0';
Flags[0]='\0';
// Extract the command
strncopy(TempLine, Line, sizeof(TempLine));
nonconst = TempLine;
char *start=NULL;
char *end=NULL;
// move up line until the first ", mark this down as the start
// then find the second " and mark it down as the end
while (*nonconst!='\0')
{
if (*nonconst=='"')
{
if (start==NULL)
{
start=nonconst+1;
}
else
{
end=nonconst;
goto done_with_command;
}
}
nonconst++;
}
done_with_command:
// invalid line?
if (start==NULL || end==NULL)
{
// TODO: maybe warn for an invalid non-commented line?
continue;
}
*end='\0';
strncpy(Command,start,sizeof(Command)-1);
// Now do the same thing for the flags
nonconst=++end;
start=NULL;
end=NULL;
// move up line until the first ", mark this down as the start
// then find the second " and mark it down as the end
while (*nonconst!='\0')
{
if (*nonconst=='"')
{
if (start==NULL)
{
start=nonconst+1;
}
else
{
end=nonconst;
goto done_with_flags;
}
}
nonconst++;
}
done_with_flags:
// invalid line?
if (start==NULL || end==NULL)
{
// TODO: maybe warn for an invalid non-commented line?
continue;
}
*end='\0';
strncpy(Flags,start,sizeof(Flags)-1);
//if (!isalnum(*Command))
if (*Command == '"' || *Command == '\0')
{
continue;
}
// Done sucking the command and flags out of the line
// now insert this command into the linked list
AddFromFile(const_cast<const char*>(&Command[0]),&Flags[0]);
nonconst = Line;
*nonconst = '\0';
}
fclose(File);
return 1;
}
/**
* This gets called from LoadFile
* Do NOT flag the entries as NeedToWrite
* No comment is passed from the file because
* this should never get written
*/
void CFlagManager::AddFromFile(const char *Command, const char *Flags)
{
CFlagEntry *Entry=new CFlagEntry;
Entry->SetName(Command);
Entry->SetFlags(Flags);
// Link it
m_FlagList.push_back(Entry);
}
void CFlagManager::LookupOrAdd(const char *Command, int &Flags, AMX *Plugin)
{
if (m_iDisabled) // if disabled in core.ini stop
{
return;
}
int TempFlags=Flags;
if (TempFlags==-1)
{
TempFlags=0;
}
List<CFlagEntry *>::iterator iter;
List<CFlagEntry *>::iterator end;
iter=m_FlagList.begin();
end=m_FlagList.end();
while (iter!=end)
{
if (strcmp((*iter)->GetName()->chars(),Command)==0)
{
CFlagEntry *Entry=(*iter);
if (Entry->IsHidden()) // "!" flag, exclude this function
{
return;
}
// Found, byref the new flags
Flags=Entry->Flags();
// Move it to the back of the list for faster lookup for the rest
m_FlagList.erase(iter);
m_FlagList.push_back(Entry);
return;
}
iter++;
}
// was not found, add it
CFlagEntry *Entry=new CFlagEntry;
Entry->SetName(Command);
Entry->SetFlags(TempFlags);
if (Plugin)
{
CPluginMngr::CPlugin* a = g_plugins.findPluginFast(Plugin);
if (a)
{
Entry->SetComment(a->getName());
}
}
// This entry was added from a register_* native
// it needs to be written during map change
Entry->SetNeedWritten(1);
// Link it
m_FlagList.push_back(Entry);
}
void CFlagManager::WriteCommands(void)
{
if (m_iDisabled)
{
return;
}
List<CFlagEntry *>::iterator iter;
List<CFlagEntry *>::iterator end;
FILE *File;
int NeedToRead=0;
// First off check the modified time of this file
// if it matches the stored modified time, then update
// after we write so we do not re-read next map
struct stat TempStat;
stat(GetFile(), &TempStat);
if (TempStat.st_mtime != m_Stat.st_mtime)
{
NeedToRead=1;
};
File = fopen(GetFile(), "a");
if (!File)
{
return;
}
iter=m_FlagList.begin();
end=m_FlagList.end();
while (iter!=end)
{
if ((*iter)->NeedWritten())
{
if ((*iter)->GetComment()->length())
{
fprintf(File,"\"%s\" \t\"%s\" ; %s\n",(*iter)->GetName()->chars(),(*iter)->GetFlags()->chars(),(*iter)->GetComment()->chars());
}
else
{
fprintf(File,"\"%s\" \t\"%s\"\n",(*iter)->GetName()->chars(),(*iter)->GetFlags()->chars());
}
(*iter)->SetNeedWritten(0);
}
++iter;
}
fclose(File);
// If NeedToRead was 0, then update the timestamp
// that was saved so we do not re-read this file
// next map
if (!NeedToRead)
{
stat(GetFile(), &TempStat);
m_Stat.st_mtime=TempStat.st_mtime;
}
}
int CFlagManager::ShouldIAddThisCommand(const AMX *amx, const cell *params, const char *cmdname) const
{
// If flagmanager is disabled then ignore this
if (m_iDisabled)
{
return 0;
}
// If 5th param exists it was compiled after this change was made
// if it does not exist, try our logic at the end of this function
// 5th param being > 0 means explicit yes
// < 0 means auto detect (default is -1), treat it like there was no 5th param
// 0 means explicit no
if ((params[0] / sizeof(cell)) >= 5)
{
if (params[5]>0) // This command was explicitly told to be included
{
return 1;
}
else if (params[5]==0) // this command was explicitly told to NOT be used
{
return 0;
}
}
// auto detect if we should use this command
// if command access is -1 (default, not set to ADMIN_ALL or any other access), then no
if (params[3]==-1)
{
return 0;
}
// if command is (or starts with) "say", then no
if (strncmp(cmdname,"say",3)==0)
{
return 0;
}
// else use it
return 1;
}
void CFlagManager::Clear(void)
{
List<CFlagEntry *>::iterator iter;
List<CFlagEntry *>::iterator end;
iter=m_FlagList.begin();
end=m_FlagList.end();
while (iter!=end)
{
delete (*iter);
++iter;
}
m_FlagList.clear();
}
void CFlagManager::CheckIfDisabled(void)
{
if (atoi(get_localinfo("disableflagman","0"))==0)
{
m_iDisabled=0;
}
else
{
m_iDisabled=1;
}
}

View File

@ -1,231 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef CFLAGMANAGER_H
#define CFLAGMANAGER_H
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "sh_list.h"
#include "amxmodx.h"
#include "CLibrarySys.h"
class CFlagEntry
{
private:
ke::AString m_strName; // command name ("amx_slap")
ke::AString m_strFlags; // string flags ("a","b")
ke::AString m_strComment; // comment to write ("; admincmd.amxx")
int m_iFlags; // bitmask flags
int m_iNeedWritten; // write this command on map change?
int m_iHidden; // set to 1 when the command is set to "!" access in
// the .ini file: this means do not process this command
public:
CFlagEntry()
{
m_iNeedWritten=0;
m_iFlags=0;
m_iHidden=0;
};
const int NeedWritten(void) const
{
return m_iNeedWritten;
};
void SetNeedWritten(const int i=1)
{
m_iNeedWritten=i;
};
const ke::AString *GetName(void) const
{
return &m_strName;
};
const ke::AString *GetFlags(void) const
{
return &m_strFlags;
};
const ke::AString *GetComment(void) const
{
return &m_strComment;
};
const int Flags(void) const
{
return m_iFlags;
};
void SetName(const char *data)
{
m_strName = data;
};
void SetFlags(const char *flags)
{
// If this is a "!" entry then stop
if (flags && flags[0]=='!')
{
SetHidden(1);
return;
}
m_strFlags = flags;
m_iFlags=UTIL_ReadFlags(flags);
};
void SetFlags(const int flags)
{
m_iFlags=flags;
char FlagsString[32];
UTIL_GetFlags(FlagsString, flags);
m_strFlags = FlagsString;
};
void SetComment(const char *comment)
{
m_strComment = comment;
};
void SetHidden(int i=1)
{
m_iHidden=i;
};
int IsHidden(void) const
{
return m_iHidden;
};
};
class CFlagManager
{
private:
List<CFlagEntry *> m_FlagList;
ke::AString m_strConfigFile;
struct stat m_Stat;
int m_iForceRead;
int m_iDisabled;
void CreateIfNotExist(void) const
{
FILE *fp;
fp = fopen(GetFile(), "r");
if (!fp)
{
// File does not exist, create the header
fp = fopen(GetFile(), "a");
if (fp)
{
fprintf(fp,"; This file will store the commands used by plugins, and their access level\n");
fprintf(fp,"; To change the access of a command, edit the flags beside it and then\n");
fprintf(fp,"; change the server's map.\n;\n");
fprintf(fp,"; Example: If I wanted to change the amx_slap access to require\n");
fprintf(fp,"; RCON access (flag \"l\") I would change this:\n");
fprintf(fp,"; \"amx_slap\" \"e\" ; admincmd.amxx\n");
fprintf(fp,"; To this:\n");
fprintf(fp,"; \"amx_slap\" \"l\" ; admincmd.amxx\n;\n");
fprintf(fp,"; To disable a specific command from being used with the command manager\n");
fprintf(fp,"; and to only use the plugin-specified access set the flag to \"!\"\n;\n");
fprintf(fp,"; NOTE: The plugin name at the end is just for reference to what plugin\n");
fprintf(fp,"; uses what commands. It is ignored.\n\n");
fclose(fp);
};
}
else
{
fclose(fp);
}
};
/**
* Returns 1 if the timestamp for the file is different than the one we have loaded
* 0 otherwise
*/
inline int NeedToLoad(void)
{
struct stat TempStat;
stat(GetFile(), &TempStat);
// If the modified timestamp does not match the stored
// timestamp than we need to re-read this file.
// Otherwise, ignore the file.
if (TempStat.st_mtime != m_Stat.st_mtime)
{
// Save down the modified timestamp
m_Stat.st_mtime=TempStat.st_mtime;
return 1;
};
return 0;
};
public:
CFlagManager()
{
memset(&m_Stat,0x0,sizeof(struct stat));
m_iDisabled=0;
m_iForceRead=0;
};
~CFlagManager()
{
};
/**
* Sets the filename in relation to amxmodx/configs
*/
void SetFile(const char *Filename="cmdaccess.ini");
const char *GetFile(void) const { return m_strConfigFile.chars(); };
/**
* Parse the file, and load all entries
* Returns 1 on success, 0 on refusal (no need to), and -1 on error
*/
const int LoadFile(const int force=0);
/**
* Checks if the command exists in the list
* If it does, it byrefs the flags for it
* If it does not, it adds it to the list
* These are added from register_*cmd calls
*/
void LookupOrAdd(const char *Command, int &Flags, AMX *Plugin);
/**
* Write the commands back to the file
*/
void WriteCommands(void);
/**
* Add this straight from the cmdaccess.ini file
*/
void AddFromFile(const char *Command, const char *Flags);
/**
* Checks if this command should be added to flagman or not
* This is only checked when adding commands from the register_* natives
* If an admin manually adds a command to cmdaccess.ini it will be used
* regardless of whatever this function would say should be done with it
*/
int ShouldIAddThisCommand(const AMX *amx, const cell *params, const char *cmdname) const;
void Clear(void);
void CheckIfDisabled(void);
};
#endif // CFLAGMANAGER_H

View File

@ -1,15 +1,36 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "debugger.h" #include "debugger.h"
#include "binlog.h"
CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes) CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes)
{ {
@ -21,6 +42,7 @@ CForward::CForward(const char *name, ForwardExecType et, int numParams, const Fo
// find funcs // find funcs
int func; int func;
AMXForward *tmp = NULL;
m_Funcs.clear(); m_Funcs.clear();
for (CPluginMngr::iterator iter = g_plugins.begin(); iter; ++iter) for (CPluginMngr::iterator iter = g_plugins.begin(); iter; ++iter)
@ -30,11 +52,9 @@ CForward::CForward(const char *name, ForwardExecType et, int numParams, const Fo
AMXForward tmp; AMXForward tmp;
tmp.pPlugin = &(*iter); tmp.pPlugin = &(*iter);
tmp.func = func; tmp.func = func;
m_Funcs.append(tmp); m_Funcs.push_back(tmp);
} }
} }
m_Name = name;
} }
cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
@ -46,21 +66,23 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
cell globRetVal = 0; cell globRetVal = 0;
for (size_t i = 0; i < m_Funcs.length(); ++i) unsigned int id = 0;
{
auto iter = &m_Funcs[i];
AMXForwardList::iterator iter;
for (iter = m_Funcs.begin(); iter != m_Funcs.end(); iter++)
{
if (iter->pPlugin->isExecutable(iter->func)) if (iter->pPlugin->isExecutable(iter->func))
{ {
// Get debug info // Get debug info
AMX *amx = iter->pPlugin->getAMX(); AMX *amx = (*iter).pPlugin->getAMX();
Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER]; Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER];
if (pDebugger) if (pDebugger)
pDebugger->BeginExec(); pDebugger->BeginExec();
// handle strings & arrays & values by reference // handle strings & arrays
int i; int i, ax = 0;
for (i = 0; i < m_NumParams; ++i) for (i = 0; i < m_NumParams; ++i)
{ {
@ -70,7 +92,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
cell *tmp; cell *tmp;
if (!str) if (!str)
str = ""; str = "";
amx_Allot(amx, (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); amx_Allot(iter->pPlugin->getAMX(), (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp);
amx_SetStringOld(tmp, str, 0, 0); amx_SetStringOld(tmp, str, 0, 0);
physAddrs[i] = tmp; physAddrs[i] = tmp;
} }
@ -89,24 +111,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
*tmp++ = (static_cast<cell>(*data++)) & 0xFF; *tmp++ = (static_cast<cell>(*data++)) & 0xFF;
} }
} } else {
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
cell *tmp;
amx_Allot(amx, 1, &realParams[i], &tmp);
physAddrs[i] = tmp;
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(tmp, reinterpret_cast<cell *>(params[i]), sizeof(cell));
}
else
{
memcpy(tmp, reinterpret_cast<REAL *>(params[i]), sizeof(REAL));
}
}
else
{
realParams[i] = params[i]; realParams[i] = params[i];
} }
} }
@ -118,12 +123,9 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
} }
// exec // exec
cell retVal = 0; cell retVal;
#if defined BINLOG_ENABLED int err = amx_Exec(amx, &retVal, iter->func);
g_BinLog.WriteOp(BinLog_CallPubFunc, iter->pPlugin->getId(), iter->func);
#endif
int err = amx_ExecPerf(amx, &retVal, iter->func);
// log runtime error, if any // log runtime error, if any
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
{ {
@ -144,18 +146,18 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
if (pDebugger) if (pDebugger)
pDebugger->EndExec(); pDebugger->EndExec();
// cleanup strings & arrays & values by reference // cleanup strings & arrays
for (i = 0; i < m_NumParams; ++i) for (i = 0; i < m_NumParams; ++i)
{ {
if (m_ParamTypes[i] == FP_STRING) if (m_ParamTypes[i] == FP_STRING)
{ {
amx_Release(amx, realParams[i]); amx_Release(iter->pPlugin->getAMX(), realParams[i]);
} }
else if (m_ParamTypes[i] == FP_STRINGEX) else if (m_ParamTypes[i] == FP_STRINGEX)
{ {
// copy back // copy back
amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0);
amx_Release(amx, realParams[i]); amx_Release(iter->pPlugin->getAMX(), realParams[i]);
} }
else if (m_ParamTypes[i] == FP_ARRAY) else if (m_ParamTypes[i] == FP_ARRAY)
{ {
@ -173,21 +175,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
*data++ = static_cast<char>(*tmp++ & 0xFF); *data++ = static_cast<char>(*tmp++ & 0xFF);
} }
} }
amx_Release(amx, realParams[i]); amx_Release(iter->pPlugin->getAMX(), realParams[i]);
}
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
//copy back
cell *tmp = physAddrs[i];
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(reinterpret_cast<cell *>(params[i]), tmp, sizeof(cell));
}
else
{
memcpy(reinterpret_cast<REAL *>(params[i]), tmp, sizeof(REAL));
}
amx_Release(amx, realParams[i]);
} }
} }
@ -218,18 +206,12 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
void CSPForward::Set(int func, AMX *amx, int numParams, const ForwardParam *paramTypes) void CSPForward::Set(int func, AMX *amx, int numParams, const ForwardParam *paramTypes)
{ {
char name[sNAMEMAX];
m_Func = func; m_Func = func;
m_Amx = amx; m_Amx = amx;
m_NumParams = numParams; m_NumParams = numParams;
memcpy((void *)m_ParamTypes, paramTypes, numParams * sizeof(ForwardParam)); memcpy((void *)m_ParamTypes, paramTypes, numParams * sizeof(ForwardParam));
m_HasFunc = true; m_HasFunc = true;
isFree = false; isFree = false;
name[0] = '\0';
amx_GetPublic(amx, func, name);
m_Name = name;
m_ToDelete = false;
m_InExec = false;
} }
void CSPForward::Set(const char *funcName, AMX *amx, int numParams, const ForwardParam *paramTypes) void CSPForward::Set(const char *funcName, AMX *amx, int numParams, const ForwardParam *paramTypes)
@ -239,9 +221,6 @@ void CSPForward::Set(const char *funcName, AMX *amx, int numParams, const Forwar
memcpy((void *)m_ParamTypes, paramTypes, numParams * sizeof(ForwardParam)); memcpy((void *)m_ParamTypes, paramTypes, numParams * sizeof(ForwardParam));
m_HasFunc = (amx_FindPublic(amx, funcName, &m_Func) == AMX_ERR_NONE); m_HasFunc = (amx_FindPublic(amx, funcName, &m_Func) == AMX_ERR_NONE);
isFree = false; isFree = false;
m_Name = funcName;
m_ToDelete = false;
m_InExec = false;
} }
cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays) cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
@ -254,20 +233,18 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
cell realParams[FORWARD_MAX_PARAMS]; cell realParams[FORWARD_MAX_PARAMS];
cell *physAddrs[FORWARD_MAX_PARAMS]; cell *physAddrs[FORWARD_MAX_PARAMS];
if (!m_HasFunc || m_ToDelete) if (!m_HasFunc)
return 0; return 0;
CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(m_Amx); CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(m_Amx);
if (!pPlugin->isExecutable(m_Func)) if (!pPlugin->isExecutable(m_Func))
return 0; return 0;
m_InExec = true;
Debugger *pDebugger = (Debugger *)m_Amx->userdata[UD_DEBUGGER]; Debugger *pDebugger = (Debugger *)m_Amx->userdata[UD_DEBUGGER];
if (pDebugger) if (pDebugger)
pDebugger->BeginExec(); pDebugger->BeginExec();
// handle strings & arrays & values by reference // handle strings & arrays
int i; int i;
for (i = 0; i < m_NumParams; ++i) for (i = 0; i < m_NumParams; ++i)
@ -297,24 +274,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
*tmp++ = (static_cast<cell>(*data++)) & 0xFF; *tmp++ = (static_cast<cell>(*data++)) & 0xFF;
} }
} } else {
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
cell *tmp;
amx_Allot(m_Amx, 1, &realParams[i], &tmp);
physAddrs[i] = tmp;
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(tmp, reinterpret_cast<cell *>(params[i]), sizeof(cell));
}
else
{
memcpy(tmp, reinterpret_cast<REAL *>(params[i]), sizeof(REAL));
}
}
else
{
realParams[i] = params[i]; realParams[i] = params[i];
} }
} }
@ -323,11 +283,9 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
amx_Push(m_Amx, realParams[i]); amx_Push(m_Amx, realParams[i]);
// exec // exec
cell retVal = 0; cell retVal;
#if defined BINLOG_ENABLED int err = amx_Exec(m_Amx, &retVal, m_Func);
g_BinLog.WriteOp(BinLog_CallPubFunc, pPlugin->getId(), m_Func);
#endif
int err = amx_ExecPerf(m_Amx, &retVal, m_Func);
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
{ {
//Did something else set an error? //Did something else set an error?
@ -347,7 +305,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
m_Amx->error = AMX_ERR_NONE; m_Amx->error = AMX_ERR_NONE;
// cleanup strings & arrays & values by reference // cleanup strings & arrays
for (i = 0; i < m_NumParams; ++i) for (i = 0; i < m_NumParams; ++i)
{ {
if (m_ParamTypes[i] == FP_STRING) if (m_ParamTypes[i] == FP_STRING)
@ -378,38 +336,20 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
} }
amx_Release(m_Amx, realParams[i]); amx_Release(m_Amx, realParams[i]);
} }
else if (m_ParamTypes[i] == FP_CELL_BYREF || m_ParamTypes[i] == FP_FLOAT_BYREF)
{
//copy back
cell *tmp = physAddrs[i];
if (m_ParamTypes[i] == FP_CELL_BYREF)
{
memcpy(reinterpret_cast<cell *>(params[i]), tmp, sizeof(cell));
}
else
{
memcpy(reinterpret_cast<REAL *>(params[i]), tmp, sizeof(REAL));
}
amx_Release(m_Amx, realParams[i]);
}
} }
m_InExec = false;
return retVal; return retVal;
} }
int CForwardMngr::registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam * paramTypes) int CForwardMngr::registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam * paramTypes)
{ {
int retVal = m_Forwards.length() << 1; int retVal = m_Forwards.size() << 1;
CForward *tmp = new CForward(funcName, et, numParams, paramTypes); CForward *tmp = new CForward(funcName, et, numParams, paramTypes);
if (!tmp) if (!tmp)
{
return -1; // should be invalid return -1; // should be invalid
}
m_Forwards.append(tmp); m_Forwards.push_back(tmp);
return retVal; return retVal;
} }
@ -430,7 +370,7 @@ int CForwardMngr::registerSPForward(int func, AMX *amx, int numParams, const For
m_FreeSPForwards.pop(); m_FreeSPForwards.pop();
} else { } else {
retVal = (m_SPForwards.length() << 1) | 1; retVal = (m_SPForwards.size() << 1) | 1;
pForward = new CSPForward(); pForward = new CSPForward();
if (!pForward) if (!pForward)
@ -440,11 +380,11 @@ int CForwardMngr::registerSPForward(int func, AMX *amx, int numParams, const For
if (pForward->getFuncsNum() == 0) if (pForward->getFuncsNum() == 0)
{ {
delete pForward;
return -1; return -1;
delete pForward;
} }
m_SPForwards.append(pForward); m_SPForwards.push_back(pForward);
} }
return retVal; return retVal;
@ -452,7 +392,7 @@ int CForwardMngr::registerSPForward(int func, AMX *amx, int numParams, const For
int CForwardMngr::registerSPForward(const char *funcName, AMX *amx, int numParams, const ForwardParam *paramTypes) int CForwardMngr::registerSPForward(const char *funcName, AMX *amx, int numParams, const ForwardParam *paramTypes)
{ {
int retVal = (m_SPForwards.length() << 1) | 1; int retVal = (m_SPForwards.size() << 1) | 1;
CSPForward *pForward; CSPForward *pForward;
if (!m_FreeSPForwards.empty()) if (!m_FreeSPForwards.empty())
@ -479,7 +419,7 @@ int CForwardMngr::registerSPForward(const char *funcName, AMX *amx, int numParam
return -1; return -1;
} }
m_SPForwards.append(pForward); m_SPForwards.push_back(pForward);
} }
return retVal; return retVal;
@ -487,48 +427,17 @@ int CForwardMngr::registerSPForward(const char *funcName, AMX *amx, int numParam
bool CForwardMngr::isIdValid(int id) const bool CForwardMngr::isIdValid(int id) const
{ {
return (id >= 0) && ((id & 1) ? (static_cast<size_t>(id >> 1) < m_SPForwards.length()) : (static_cast<size_t>(id >> 1) < m_Forwards.length())); return (id >= 0) && ((id & 1) ? (static_cast<size_t>(id >> 1) < m_SPForwards.size()) : (static_cast<size_t>(id >> 1) < m_Forwards.size()));
} }
cell CForwardMngr::executeForwards(int id, cell *params) cell CForwardMngr::executeForwards(int id, cell *params)
{ {
int retVal; int retVal = (id & 1) ? m_SPForwards[id >> 1]->execute(params, m_TmpArrays) : m_Forwards[id >> 1]->execute(params, m_TmpArrays);
if (id & 1)
{
CSPForward *fwd = m_SPForwards[id >> 1];
retVal = fwd->execute(params, m_TmpArrays);
if (fwd->m_ToDelete)
{
fwd->m_ToDelete = false;
unregisterSPForward(id);
}
} else {
retVal = m_Forwards[id >> 1]->execute(params, m_TmpArrays);
}
m_TmpArraysNum = 0; m_TmpArraysNum = 0;
return retVal; return retVal;
} }
const char *CForwardMngr::getFuncName(int id) const
{
if (!isIdValid(id))
{
return "";
}
return (id & 1) ? m_SPForwards[id >> 1]->getFuncName() : m_Forwards[id >> 1]->getFuncName();
}
int CForwardMngr::getFuncsNum(int id) const
{
if (!isIdValid(id))
{
return 0;
}
return (id & 1) ? m_SPForwards[id >> 1]->getFuncsNum() : m_Forwards[id >> 1]->getFuncsNum();
}
int CForwardMngr::getParamsNum(int id) const int CForwardMngr::getParamsNum(int id) const
{ {
return (id & 1) ? m_SPForwards[id >> 1]->getParamsNum() : m_Forwards[id >> 1]->getParamsNum(); return (id & 1) ? m_SPForwards[id >> 1]->getParamsNum() : m_Forwards[id >> 1]->getParamsNum();
@ -536,35 +445,29 @@ int CForwardMngr::getParamsNum(int id) const
ForwardParam CForwardMngr::getParamType(int id, int paramNum) const ForwardParam CForwardMngr::getParamType(int id, int paramNum) const
{ {
if (!isIdValid(id))
{
return FP_DONE;
}
return (id & 1) ? m_SPForwards[id >> 1]->getParamType(paramNum) : m_Forwards[id >> 1]->getParamType(paramNum); return (id & 1) ? m_SPForwards[id >> 1]->getParamType(paramNum) : m_Forwards[id >> 1]->getParamType(paramNum);
} }
void CForwardMngr::clear() void CForwardMngr::clear()
{ {
size_t i; for (ForwardVec::iterator iter = m_Forwards.begin(); iter != m_Forwards.end(); ++iter)
for (i = 0; i < m_Forwards.length(); ++i)
{ {
delete m_Forwards[i]; delete *iter;
} }
for (i = 0; i < m_SPForwards.length(); ++i) SPForwardVec::iterator spIter;
for (spIter = m_SPForwards.begin(); spIter != m_SPForwards.end(); ++spIter)
{ {
delete m_SPForwards[i]; delete (*spIter);
} }
m_Forwards.clear(); m_Forwards.clear();
m_SPForwards.clear(); m_SPForwards.clear();
while (!m_FreeSPForwards.empty()) while (!m_FreeSPForwards.empty())
{
m_FreeSPForwards.pop(); m_FreeSPForwards.pop();
}
m_TmpArraysNum = 0; m_TmpArraysNum = 0;
} }
@ -577,51 +480,10 @@ void CForwardMngr::unregisterSPForward(int id)
{ {
//make sure the id is valid //make sure the id is valid
if (!isIdValid(id) || m_SPForwards.at(id >> 1)->isFree) if (!isIdValid(id) || m_SPForwards.at(id >> 1)->isFree)
{
return; return;
}
CSPForward *fwd = m_SPForwards.at(id >> 1); m_SPForwards.at(id >> 1)->isFree = true;
m_FreeSPForwards.push(id);
if (fwd->m_InExec)
{
fwd->m_ToDelete = true;
} else {
fwd->isFree = true;
m_FreeSPForwards.push(id);
}
}
int CForwardMngr::duplicateSPForward(int id)
{
if (!isIdValid(id) || m_SPForwards.at(id >> 1)->isFree)
{
return -1;
}
CSPForward *fwd = m_SPForwards.at(id >> 1);
return registerSPForward(fwd->m_Func, fwd->m_Amx, fwd->m_NumParams, fwd->m_ParamTypes);
}
int CForwardMngr::isSameSPForward(int id1, int id2)
{
if (!isIdValid(id1) || !isIdValid(id2))
{
return false;
}
CSPForward *fwd1 = m_SPForwards.at(id1 >> 1);
CSPForward *fwd2 = m_SPForwards.at(id2 >> 1);
if (fwd1->isFree || fwd2->isFree)
{
return false;
}
return ((fwd1->m_Amx == fwd2->m_Amx)
&& (fwd1->m_Func == fwd2->m_Func)
&& (fwd1->m_NumParams == fwd2->m_NumParams));
} }
int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num) int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_t num)
@ -629,9 +491,7 @@ int registerForwardC(const char *funcName, ForwardExecType et, cell *list, size_
ForwardParam params[FORWARD_MAX_PARAMS]; ForwardParam params[FORWARD_MAX_PARAMS];
for (size_t i=0; i<num; i++) for (size_t i=0; i<num; i++)
{
params[i] = static_cast<ForwardParam>(list[i]); params[i] = static_cast<ForwardParam>(list[i]);
}
return g_forwards.registerForward(funcName, et, num, params); return g_forwards.registerForward(funcName, et, num, params);
} }
@ -744,26 +604,13 @@ cell executeForwards(int id, ...)
va_list argptr; va_list argptr;
va_start(argptr, id); va_start(argptr, id);
ForwardParam param_type;
for (int i = 0; i < paramsNum && i < FORWARD_MAX_PARAMS; ++i) for (int i = 0; i < paramsNum && i < FORWARD_MAX_PARAMS; ++i)
{ {
param_type = g_forwards.getParamType(id, i); if (g_forwards.getParamType(id, i) == FP_FLOAT)
if (param_type == FP_FLOAT)
{ {
REAL tmp = (REAL)va_arg(argptr, double); // floats get converted to doubles REAL tmp = (REAL)va_arg(argptr, double); // floats get converted to doubles
params[i] = amx_ftoc(tmp); params[i] = *(cell*)&tmp;
}
else if(param_type == FP_FLOAT_BYREF)
{
REAL *tmp = reinterpret_cast<REAL *>(va_arg(argptr, double*));
params[i] = reinterpret_cast<cell>(tmp);
}
else if(param_type == FP_CELL_BYREF)
{
cell *tmp = reinterpret_cast<cell *>(va_arg(argptr, cell*));
params[i] = reinterpret_cast<cell>(tmp);
} }
else else
params[i] = (cell)va_arg(argptr, cell); params[i] = (cell)va_arg(argptr, cell);

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
/* /*
CForward.h CForward.h
@ -46,8 +68,6 @@ enum ForwardParam
FP_STRING, // string FP_STRING, // string
FP_STRINGEX, // string; will be updated to the last function's value FP_STRINGEX, // string; will be updated to the last function's value
FP_ARRAY, // array; use the return value of prepareArray. FP_ARRAY, // array; use the return value of prepareArray.
FP_CELL_BYREF, // cell; pass by reference
FP_FLOAT_BYREF, // float; pass by reference
}; };
// for prepareArray // for prepareArray
@ -73,7 +93,6 @@ class CForward
const char *m_FuncName; const char *m_FuncName;
ForwardExecType m_ExecType; ForwardExecType m_ExecType;
int m_NumParams; int m_NumParams;
ke::AString m_Name;
struct AMXForward struct AMXForward
{ {
@ -81,7 +100,7 @@ class CForward
int func; int func;
}; };
typedef ke::Vector<AMXForward> AMXForwardList; typedef CVector<AMXForward> AMXForwardList;
AMXForwardList m_Funcs; AMXForwardList m_Funcs;
ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS]; ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS];
@ -99,12 +118,7 @@ public:
int getFuncsNum() const int getFuncsNum() const
{ {
return m_Funcs.length(); return m_Funcs.size();
}
const char *getFuncName() const
{
return m_Name.chars();
} }
ForwardParam getParamType(int paramId) const ForwardParam getParamType(int paramId) const
@ -119,7 +133,7 @@ public:
// Single plugin forward // Single plugin forward
class CSPForward class CSPForward
{ {
friend class CForwardMngr; const char *m_FuncName;
int m_NumParams; int m_NumParams;
ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS]; ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS];
@ -127,9 +141,6 @@ class CSPForward
int m_Func; int m_Func;
bool m_HasFunc; bool m_HasFunc;
ke::AString m_Name;
bool m_InExec;
bool m_ToDelete;
public: public:
bool isFree; bool isFree;
@ -149,11 +160,6 @@ public:
{ {
return (m_HasFunc) ? 1 : 0; return (m_HasFunc) ? 1 : 0;
} }
const char *getFuncName() const
{
return m_Name.chars();
}
ForwardParam getParamType(int paramId) const ForwardParam getParamType(int paramId) const
{ {
@ -166,8 +172,8 @@ public:
class CForwardMngr class CForwardMngr
{ {
typedef ke::Vector<CForward*> ForwardVec; typedef CVector<CForward*> ForwardVec;
typedef ke::Vector<CSPForward*> SPForwardVec; typedef CVector<CSPForward*> SPForwardVec;
typedef CStack<int> FreeSPVec; // Free SP Forwards typedef CStack<int> FreeSPVec; // Free SP Forwards
ForwardVec m_Forwards; ForwardVec m_Forwards;
@ -192,8 +198,6 @@ public:
// Unregister single plugin forward // Unregister single plugin forward
void unregisterSPForward(int id); void unregisterSPForward(int id);
int duplicateSPForward(int id);
int isSameSPForward(int id1, int id2);
// execute forward // execute forward
cell executeForwards(int id, cell *params); cell executeForwards(int id, cell *params);
@ -203,7 +207,6 @@ public:
bool isSPForward(int id) const; // check whether forward is single plugin bool isSPForward(int id) const; // check whether forward is single plugin
int getParamsNum(int id) const; // get num of params of a forward int getParamsNum(int id) const; // get num of params of a forward
int getFuncsNum(int id) const; // get num of found functions of a forward int getFuncsNum(int id) const; // get num of found functions of a forward
const char *getFuncName(int id) const; // get the function name
ForwardParam getParamType(int id, int paramId) const; ForwardParam getParamType(int id, int paramId) const;
cell prepareArray(void *ptr, unsigned int size, ForwardArrayElemType type, bool copyBack); // prepare array cell prepareArray(void *ptr, unsigned int size, ForwardArrayElemType type, bool copyBack); // prepare array

View File

@ -1,61 +0,0 @@
#ifndef FRAMEACTION_H
#define FRAMEACTION_H
#include "amxmodx.h"
#include <amtl/am-deque.h>
#include <amtl/am-autoptr.h>
class CFrameActionMngr
{
public:
class CFrameAction
{
public:
CFrameAction(int callbackForward, cell callbackData) :
m_callbackForward(callbackForward),
m_callbackData(callbackData)
{
}
~CFrameAction()
{
unregisterSPForward(m_callbackForward);
}
void Execute()
{
executeForwards(m_callbackForward, m_callbackData);
}
public:
int m_callbackForward;
cell m_callbackData;
};
public:
void AddFrameAction(int callbackForward, cell callbackData)
{
m_requestedFrames.append(new CFrameAction(callbackForward, callbackData));
}
void ExecuteFrameCallbacks()
{
// In case a frame callback requests another frame, newly added frames won't be executed this way
int callbacksToRun = m_requestedFrames.length();
while (callbacksToRun--)
{
ke::AutoPtr<CFrameAction> action = ke::Move(m_requestedFrames.front());
m_requestedFrames.popFront();
action->Execute();
}
}
private:
ke::Deque<ke::AutoPtr<CFrameAction>> m_requestedFrames;
};
#endif // FRAMEACTION_H

File diff suppressed because it is too large Load Diff

View File

@ -1,198 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _INCLUDE_GAMECONFIG_H_
#define _INCLUDE_GAMECONFIG_H_
#include <IGameConfigs.h>
#include "CLibrarySys.h"
#include <amtl/am-autoptr.h>
#include <amtl/am-vector.h>
#include <amtl/am-string.h>
#include <amtl/am-refcounting.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
class CGameConfig
:
public ITextListener_SMC,
public IGameConfig,
public ke::Refcounted <CGameConfig>
{
friend class CGameConfigManager;
public:
CGameConfig(const char *file);
~CGameConfig();
public:
bool Reparse(char *error, size_t maxlength);
bool EnterFile(const char *file, char *error, size_t maxlength);
public: // ITextListener_SMC
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
public: // IGameConfig
const char* GetKeyValue(const char *key);
bool GetOffset(const char *key, TypeDescription *value);
bool GetOffsetByClass(const char *classname, const char *key, TypeDescription *value);
bool GetMemSig(const char *key, void **addr);
bool GetAddress(const char *key, void **addr);
public: // NameHashSet
static inline bool matches(const char *key, const CGameConfig *value)
{
return strcmp(key, value->m_File) == 0;
}
private:
struct OffsetClass
{
StringHashMap<TypeDescription> list;
};
typedef StringHashMap<ke::AutoPtr<OffsetClass>> OffsetClassMap;
typedef StringHashMap<TypeDescription> OffsetMap;
char m_File[PLATFORM_MAX_PATH];
char m_CurrentPath[PLATFORM_MAX_PATH];
OffsetMap m_Offsets;
OffsetClassMap m_OffsetsByClass;
StringHashMap<ke::AString> m_Keys;
StringHashMap<void*> m_Sigs;
int m_ParseState;
unsigned int m_IgnoreLevel;
char m_Class[64];
char m_Offset[64];
char m_Game[256];
bool m_FoundOffset;
bool m_MatchedClasses;
bool m_ShouldBeReadingDefault;
bool m_HadGame;
bool m_MatchedGame;
bool m_HadEngine;
bool m_MatchedEngine;
bool m_MatchedPlatform;
unsigned int m_CustomLevel;
ITextListener_SMC* m_CustomHandler;
struct AddressConf
{
char m_SignatureName[64];
size_t m_ReadCount;
int m_ReadBytes[8];
AddressConf(const char *sigName, size_t sigLength, size_t readCount, int *read);
AddressConf() {}
};
char m_Address[64];
char m_AddressSignature[64];
int m_AddressReadCount;
int m_AddressRead[8];
StringHashMap<AddressConf> m_Addresses;
char m_pEngine[64];
};
class CGameMasterReader : public ITextListener_SMC
{
public:
void ReadSMC_ParseStart();
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
public:
ke::Vector<ke::AString>* m_FileList;
unsigned int m_State;
unsigned int m_IgnoreLevel;
char m_CurrentPath[PLATFORM_MAX_PATH];
bool m_HadEngine;
bool m_MatchedEngine;
bool m_HadGame;
bool m_MatchedGame;
};
class CGameConfigManager : public IGameConfigManager
{
public:
CGameConfigManager();
~CGameConfigManager();
public: // IGameConfigManager
bool LoadGameConfigFile(const char *file, IGameConfig **pConfig, char *error, size_t maxlength);
void CloseGameConfigFile(IGameConfig *cfg);
void AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
public:
void OnAmxxStartup();
void RemoveCachedConfig(CGameConfig *config);
private:
NameHashSet<CGameConfig*> m_Lookup;
public:
StringHashMap<ITextListener_SMC*> m_customHandlers;
};
#define GET_OFFSET(classname, member) \
static int member = -1; \
if (member == -1) \
{ \
TypeDescription type; \
if (!CommonConfig->GetOffsetByClass(classname, #member, &type) || type.fieldOffset < 0)\
{ \
LogError(amx, AMX_ERR_NATIVE, "Invalid %s offset. Native %s is disabled", #member, __FUNCTION__);\
return 0; \
} \
member = type.fieldOffset; \
}
#define GET_OFFSET_NO_ERROR(classname, member) \
static int member = -1; \
if (member == -1) \
{ \
TypeDescription type; \
if (!CommonConfig->GetOffsetByClass(classname, #member, &type) || type.fieldOffset < 0)\
{ \
return; \
} \
member = type.fieldOffset; \
}
extern CGameConfigManager ConfigManager;
extern IGameConfig *CommonConfig;
#endif // _INCLUDE_GAMECONFIG_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,38 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef _INCLUDE_CLANG_H #ifndef _INCLUDE_CLANG_H
#define _INCLUDE_CLANG_H #define _INCLUDE_CLANG_H
#include "sh_tinyhash.h" #include "sh_tinyhash.h"
#include "sm_stringhashmap.h"
#include <ITextParsers.h>
#define LANG_SERVER 0 #define LANG_SERVER 0
#define LANG_PLAYER -1 #define LANG_PLAYER -1
@ -20,9 +40,15 @@
#define ERR_BADKEY 1 // Lang key not found #define ERR_BADKEY 1 // Lang key not found
#define ERR_BADLANG 2 // Invalid lang #define ERR_BADLANG 2 // Invalid lang
struct md5Pair
{
String file;
String val;
};
struct sKeyDef struct sKeyDef
{ {
ke::AutoString* definition; String *definition;
int key; int key;
}; };
@ -47,7 +73,7 @@ public:
~defentry() ~defentry()
{ {
} }
ke::AString *definition; String *definition;
}; };
struct keytbl_val struct keytbl_val
@ -58,7 +84,7 @@ struct keytbl_val
int index; int index;
}; };
class CLangMngr : public ITextListener_INI class CLangMngr
{ {
class CLang class CLang
{ {
@ -73,7 +99,7 @@ class CLangMngr : public ITextListener_INI
// Get the definition // Get the definition
const char *GetDef(int key, int &status); const char *GetDef(int key, int &status);
// Add definitions to this language // Add definitions to this language
void MergeDefinitions(ke::Vector <sKeyDef> & vec); void MergeDefinitions(CQueue <sKeyDef> & vec);
// Reset this language // Reset this language
void Clear(); void Clear();
@ -85,6 +111,11 @@ class CLangMngr : public ITextListener_INI
// Get language name // Get language name
const char *GetName() { return m_LanguageName; } const char *GetName() { return m_LanguageName; }
// Save to file
bool Save(FILE *fp, int &defOffset, uint32_t &curOffset);
bool SaveDefinitions(FILE *fp, uint32_t &curOffset);
// Load
bool Load(FILE *fp);
void SetMngr(CLangMngr *l) { m_LMan = l; } void SetMngr(CLangMngr *l) { m_LMan = l; }
// Get number of entries // Get number of entries
int Entries(); int Entries();
@ -101,27 +132,20 @@ class CLangMngr : public ITextListener_INI
public: public:
void AddEntry(int key, const char *definition); void AddEntry(int key, const char *definition);
}; };
public:
// Merge definitions into a language // Merge definitions into a language
void MergeDefinitions(const char *lang, ke::Vector <sKeyDef> &tmpVec); void MergeDefinitions(const char *lang, CQueue <sKeyDef> &tmpVec);
public: // ITextListener_INI
void ReadINI_ParseStart();
void ReadINI_ParseEnd(bool halted);
bool ReadINI_NewSection(const char *section, bool invalid_tokens, bool close_bracket, bool extra_tokens, unsigned int *curtok);
bool ReadINI_KeyValue(const char *key, const char *value, bool invalid_tokens, bool equal_token, bool quotes, unsigned int *curtok);
private:
// strip lowercase; make lower if needed // strip lowercase; make lower if needed
static size_t strip(char *str, char *newstr, bool makelower = false); static size_t strip(char *str, char *newstr, bool makelower = false);
typedef ke::Vector<CLang*> LangVec; typedef CVector<CLang*> LangVec;
typedef CVector<CLang*>::iterator LangVecIter;
LangVec m_Languages; LangVec m_Languages;
StringHashMap<time_t> FileList; CVector<md5Pair *> FileList;
ke::Vector<ke::AString *> KeyList; CVector<String *> KeyList;
THash<ke::AString, keytbl_val> KeyTable; THash<String, keytbl_val> KeyTable;
// Get a lang object (construct if needed) // Get a lang object (construct if needed)
CLang * GetLang(const char *name); CLang * GetLang(const char *name);
@ -135,17 +159,27 @@ public:
int MergeDefinitionFile(const char *file); int MergeDefinitionFile(const char *file);
// Get a definition from a lang name and a key // Get a definition from a lang name and a key
const char *GetDef(const char *langName, const char *key, int &status); const char *GetDef(const char *langName, const char *key, int &status);
// Format a string
const char *Format(const char *src, ...);
// Format a string for an AMX plugin // Format a string for an AMX plugin
char *FormatAmxString(AMX *amx, cell *params, int parm, int &len); char *FormatAmxString(AMX *amx, cell *params, int parm, int &len);
char *FormatString(const char *fmt, va_list &ap);
// Save
bool Save(const char *filename);
// Load
bool Load(const char *filename);
// Cache
bool LoadCache(const char *filename);
bool SaveCache(const char *filename);
void InvalidateCache(); void InvalidateCache();
// Get index // Get index
int GetKeyEntry(ke::AString &key); int GetKeyEntry(String &key);
int GetKeyEntry(const char *key); int GetKeyEntry(const char *key);
int GetKeyIndex(const char *key);
// Get key from index // Get key from index
const char *GetKey(int key); const char *GetKey(int key);
// Add key // Add key
int AddKeyEntry(ke::AString &key); int AddKeyEntry(String &key);
int AddKeyEntry(const char *key);
// Get the number of languages // Get the number of languages
int GetLangsNum(); int GetLangsNum();

View File

@ -1,388 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "CLibrarySys.h"
#include <amxmodx.h>
#include <amtl/os/am-fsutil.h>
#include <amtl/os/am-path.h>
#include <amtl/os/am-system-errors.h>
LibrarySystem g_LibSys;
/******************/
/* Directory Code */
/******************/
CDirectory::CDirectory(const char *path)
{
#if defined PLATFORM_WINDOWS
char newpath[PLATFORM_MAX_PATH];
ke::SafeSprintf(newpath, sizeof(newpath), "%s\\*.*", path);
m_dir = FindFirstFile(newpath, &m_fd);
if (!IsValid())
{
m_fd.cFileName[0] = '\0';
}
#elif defined PLATFORM_POSIX
m_dir = opendir(path);
if (IsValid())
{
m_ep = readdir(m_dir); // TODO: we need to read past "." and ".."!
ke::SafeSprintf(m_origpath, sizeof(m_origpath), "%s", path);
}
else
{
m_ep = nullptr;
}
#endif
}
CDirectory::~CDirectory()
{
if (IsValid())
{
#if defined PLATFORM_WINDOWS
FindClose(m_dir);
#elif defined PLATFORM_POSIX
closedir(m_dir);
#endif
}
}
DirHandle CDirectory::GetHandle()
{
return m_dir;
}
void CDirectory::NextEntry()
{
#if defined PLATFORM_WINDOWS
if (FindNextFile(m_dir, &m_fd) == 0)
{
FindClose(m_dir);
m_dir = INVALID_HANDLE_VALUE;
}
#elif defined PLATFORM_POSIX
if (!(m_ep = readdir(m_dir)))
{
closedir(m_dir);
m_dir = nullptr;
}
#endif
}
bool CDirectory::IsEntryValid()
{
return IsValid();
}
bool CDirectory::IsEntryDirectory()
{
#if defined PLATFORM_WINDOWS
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
#elif defined PLATFORM_POSIX
char temppath[PLATFORM_MAX_PATH];
ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
return ke::file::IsDirectory(temppath);
#endif
}
bool CDirectory::IsEntryFile()
{
#if defined PLATFORM_WINDOWS
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));
#elif defined PLATFORM_POSIX
char temppath[PLATFORM_MAX_PATH];
ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
return ke::file::IsFile(temppath);
#endif
}
const char* CDirectory::GetEntryName()
{
#if defined PLATFORM_WINDOWS
return m_fd.cFileName;
#elif defined PLATFORM_POSIX
return m_ep ? m_ep->d_name : "";
#endif
}
bool CDirectory::MoreFiles()
{
return IsValid();
}
bool CDirectory::IsValid()
{
#if defined PLATFORM_WINDOWS
return (m_dir != INVALID_HANDLE_VALUE);
#elif defined PLATFORM_POSIX
return (m_dir != nullptr);
#endif
}
/****************/
/* Library Code */
/****************/
CLibrary::CLibrary(ke::RefPtr<ke::SharedLib> lib) : lib_(lib)
{}
void CLibrary::CloseLibrary()
{
delete this;
}
void *CLibrary::GetSymbolAddress(const char* symname)
{
return lib_->lookup(symname);
}
/***********************/
/* Library System Code */
/***********************/
bool LibrarySystem::PathExists(const char *path)
{
return ke::file::PathExists(path);
}
bool LibrarySystem::IsPathFile(const char* path)
{
return ke::file::IsFile(path);
}
bool LibrarySystem::IsPathDirectory(const char* path)
{
return ke::file::IsDirectory(path);
}
CDirectory *LibrarySystem::OpenDirectory(const char* path)
{
CDirectory* dir = new CDirectory(path);
if (!dir->IsValid())
{
delete dir;
return nullptr;
}
return dir;
}
CLibrary* LibrarySystem::OpenLibrary(const char* path, char* error, size_t maxlength)
{
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(path, error, maxlength);
if (!lib)
{
return nullptr;
}
return new CLibrary(lib);
}
void LibrarySystem::GetPlatformError(char* error, size_t maxlength)
{
#if defined PLATFORM_WINDOWS
return GetPlatformErrorEx(GetLastError(), error, maxlength);
#elif defined PLATFORM_POSIX
return GetPlatformErrorEx(errno, error, maxlength);
#endif
}
void LibrarySystem::GetPlatformErrorEx(int code, char* error, size_t maxlength)
{
if (error && maxlength)
{
ke::FormatSystemErrorCode(code, error, maxlength);
}
}
void LibrarySystem::GetLoaderError(char* buffer, size_t maxlength)
{
ke::FormatSystemError(buffer, maxlength);
}
void LibrarySystem::CloseDirectory(CDirectory *dir)
{
delete dir;
}
size_t LibrarySystem::PathFormat(char* buffer, size_t len, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t mylen = ke::path::FormatVa(buffer, len, fmt, ap);
va_end(ap);
return mylen;
}
char* LibrarySystem::PathFormat(const char* fmt, ...)
{
static char buffer[PLATFORM_MAX_PATH];
va_list ap;
va_start(ap, fmt);
ke::path::FormatVa(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
return buffer;
}
const char* LibrarySystem::GetFileExtension(const char* filename)
{
size_t len, end;
len = strlen(filename);
/* Minimum string length for filename with ext would be 3; example: a.a */
if (len < 3)
{
return nullptr;
}
end = len - 1;
for (size_t i = end; i <= end; i--)
{
if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR)
{
break;
}
if (filename[i] == '.' && i != end && i != 0)
{
return &filename[++i];
}
}
return nullptr;
}
bool LibrarySystem::CreateFolder(const char* path)
{
return ke::file::CreateDirectory(path, 0775);
}
size_t LibrarySystem::GetFileFromPath(char* buffer, size_t maxlength, const char* path)
{
size_t length = strlen(path);
for (size_t i = length - 1; i <= length - 1; i--)
{
if (path[i] == '/'
#if defined PLATFORM_WINDOWS
|| path[i] == '\\'
#endif
)
{
return ke::SafeSprintf(buffer, maxlength, "%s", &path[i + 1]);
}
}
/* We scanned and found no path separator */
return ke::SafeSprintf(buffer, maxlength, "%s", path);
}
bool LibrarySystem::FileTime(const char* path, FileTimeType type, time_t* pTime)
{
struct stat s;
if (stat(path, &s) != 0)
{
return false;
}
switch (type)
{
case FileTime_LastAccess:
{
*pTime = s.st_atime;
break;
}
case FileTime_Created:
{
*pTime = s.st_ctime;
break;
}
case FileTime_LastChange:
{
*pTime = s.st_mtime;
break;
}
default:
{
return false;
}
}
return true;
}
bool LibrarySystem::DoesPlatformMatch(const char *platform)
{
return strcmp(platform, PLATFORM_NAME) == 0;
}
bool LibrarySystem::IsPlatformCompatible(const char *platform, bool *hadPrimaryMatch)
{
if (DoesPlatformMatch(platform))
{
#if defined PLATFORM_COMPAT_ALT
*hadPrimaryMatch = true;
#endif
return true;
}
#if defined PLATFORM_COMPAT_ALT
/* If entry hasn't been found for the primary platform name, check for compatible alternate */
if (!*hadPrimaryMatch)
{
return strcmp(platform, PLATFORM_COMPAT_ALT) == 0;
}
#endif
return false;
}

View File

@ -1,107 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _INCLUDE_LIBRARY_SYS_H_
#define _INCLUDE_LIBRARY_SYS_H_
#include "amx.h" // cell
#include <platform_helpers.h>
#include <amtl/os/am-shared-library.h>
enum FileTimeType
{
FileTime_LastAccess = 0, /* Last access (not available on FAT) */
FileTime_Created = 1, /* Creation (not available on FAT) */
FileTime_LastChange = 2, /* Last modification */
};
class CDirectory
{
public:
CDirectory(const char* path);
~CDirectory();
public:
bool MoreFiles();
void NextEntry();
const char* GetEntryName();
bool IsEntryDirectory();
bool IsEntryFile();
bool IsEntryValid();
public:
bool IsValid();
DirHandle GetHandle();
private:
#if defined PLATFORM_WINDOWS
HANDLE m_dir;
WIN32_FIND_DATAA m_fd;
#elif defined PLATFORM_POSIX
DIR* m_dir;
struct dirent* m_ep;
char m_origpath[PLATFORM_MAX_PATH];
#endif
};
class CLibrary
{
public:
CLibrary(ke::RefPtr<ke::SharedLib> lib);
public:
void CloseLibrary();
void *GetSymbolAddress(const char* symname);
private:
ke::RefPtr<ke::SharedLib> lib_;
};
class LibrarySystem
{
public:
CLibrary* OpenLibrary(const char* path, char* error = nullptr, size_t maxlength = 0);
CDirectory* OpenDirectory(const char* path);
void CloseDirectory(CDirectory *dir);
bool PathExists(const char* path);
bool IsPathFile(const char* path);
bool IsPathDirectory(const char* path);
void GetPlatformError(char* error, size_t maxlength);
void GetPlatformErrorEx(int code, char* error, size_t maxlength);
size_t PathFormat(char* buffer, size_t len, const char* fmt, ...);
char* PathFormat(const char* fmt, ...);
const char* GetFileExtension(const char* filename);
bool CreateFolder(const char* path);
size_t GetFileFromPath(char* buffer, size_t maxlength, const char* path);
bool FileTime(const char* path, FileTimeType type, time_t* pTime);
void GetLoaderError(char* buffer, size_t maxlength);
bool DoesPlatformMatch(const char* platform);
bool IsPlatformCompatible(const char *platform, bool *hadPrimaryMatch);
};
extern LibrarySystem g_LibSys;
#endif // _INCLUDE_LIBRARY_SYS_H_

329
amxmodx/CList.h Executable file
View File

@ -0,0 +1,329 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef CLIST_H
#define CLIST_H
// *****************************************************
// class CList
// *****************************************************
// Linked list
template <typename T, typename F = char* >
class CList
{
private:
// One list element
class CElement
{
T *m_pObject; // pointer to the object
CElement *m_pNext; // pointer to the next element
CElement *m_pPrev; // pointer to the previous element
public:
// dereference operator
T& operator* ()
{
return *m_pObject;
}
// constructor
CElement(T *pObj)
{
m_pObject = pObj;
m_pNext = NULL;
m_pPrev = NULL;
}
// destructor
~CElement()
{
delete m_pObject;
if (m_pNext)
m_pNext->m_pPrev = m_pPrev;
if (m_pPrev)
m_pPrev->m_pNext = m_pNext;
}
// returns object pointer
T *GetObj()
{
return m_pObject;
}
// returns next element pointer
CElement *GetNext()
{
return m_pNext;
}
// sets next element
void SetNext(CElement *newNext)
{
m_pNext = newNext;
}
// returns previous element pointer
CElement *GetPrev()
{
return m_pPrev;
}
// sets previous element
void SetPrev(CElement *newPrev)
{
m_pPrev = newPrev;
}
};
// CList<T, F> class
CElement *m_pHead; // head of the linked list
CElement *m_pTail; // tail of the linked list
public:
// iterator class
class iterator
{
friend class CList<T, F>;
CList<T, F> *m_pList; // The list that created this iterator
CElement *m_CurPos; // Current position in the list
public:
iterator()
{
m_pList = NULL;
m_CurPos = NULL;
}
// constructor based on list, element
iterator(CList<T, F> *pList, CElement *startPos)
{
m_pList = pList;
m_CurPos = startPos;
}
// constructor based on other iterator
iterator(const iterator &other)
{
m_pList = other.m_pList;
m_CurPos = other.m_CurPos;
}
// dereference operator
T & operator* () const
{
return *m_CurPos->GetObj();
}
T * operator-> () const
{
return m_CurPos->GetObj();
}
// validity check operator
inline operator bool () const
{
return m_pList != NULL && m_CurPos != NULL && m_CurPos->GetObj() != NULL;
}
// pre increment operator
inline iterator& operator ++ ()
{
m_CurPos = m_CurPos->GetNext();
return *this;
}
// post increment operator
inline iterator operator++(int)
{
iterator tmp(*this);
m_CurPos = m_CurPos->next;
return tmp;
}
// returns iterator that points to next element
iterator GetNext()
{
iterator tmp(*this);
return ++tmp;
}
iterator remove()
{
return m_pList->remove(*this);
}
iterator put(T *obj)
{
return m_pList->put(obj, *this);
}
};
CList<T, F>()
{
m_pHead = NULL;
m_pTail = NULL;
}
~CList<T, F>()
{
clear();
}
// removes the object referenced by where
// sets where to the next object
// returns an iterator pointing to the next object
iterator remove(iterator &where)
{
iterator tmp(where.GetNext());
if (where.m_CurPos == m_pHead)
m_pHead = where.m_CurPos->GetNext();
if (where.m_CurPos == m_pTail)
m_pTail = where.m_CurPos->GetPrev();
delete where.m_CurPos;
where = tmp;
return tmp;
}
// puts an element to the end of the list
// returns an iterator pointing to it
iterator put_back(T *pObj)
{
CElement *pTmp = new CElement(pObj);
if (!m_pHead)
{
m_pHead = pTmp;
m_pTail = pTmp;
} else {
pTmp->SetNext(NULL);
pTmp->SetPrev(m_pTail);
m_pTail->SetNext(pTmp);
m_pTail = pTmp;
}
return iterator(this, pTmp);
}
iterator put_front(T *pObj)
{
CElement *pTmp = new CElement(pObj);
if (!m_pHead)
{
m_pHead = pTmp;
m_pTail = pTmp;
} else {
pTmp->SetNext(m_pHead);
pTmp->SetPrev(NULL);
m_pHead->SetPrev(pTmp);
m_pHead = pTmp;
}
return iterator(this, pTmp);
}
// alias for put_back
iterator put(T *pObj)
{
return put_back(pObj);
}
// puts an element after where
// alters where to point to the new element
// returns an iterator pointing to the new element
iterator put(T *pObj, iterator &where)
{
CElement *pTmp = new CElement(pObj);
if (where.m_CurPos->GetNext())
where.m_CurPos->GetNext()->SetPrev(pTmp);
else // where = tail
m_pTail = pTmp;
pTmp->SetPrev(where.m_CurPos);
pTmp->SetNext(where.m_CurPos->GetNext());
where.m_CurPos->SetNext(pTmp);
return ++where;
}
iterator begin()
{
return iterator(this, m_pHead);
}
void clear()
{
iterator iter = begin();
while (iter) iter.remove();
}
iterator find(iterator startOn, const F &desc)
{
iterator iter = startOn;
while (iter)
{
if (*iter == desc)
break;
++iter;
}
return iter;
}
iterator find(const F &desc)
{
return find(begin(), desc);
}
int size()
{
iterator iter = begin();
int i = 0;
while (iter)
{
++i;
++iter;
}
return i;
}
};
#endif //CLIST_H

View File

@ -1,17 +1,37 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "CLogEvent.h" #include "CLogEvent.h"
NativeHandle<LogEventHook> LogEventHandles;
// ***************************************************** // *****************************************************
// class LogEventsMngr // class LogEventsMngr
// ***************************************************** // *****************************************************
@ -37,9 +57,9 @@ int LogEventsMngr::CLogCmp::compareCondition(const char* string)
logid = parent->logCounter; logid = parent->logCounter;
if (in) if (in)
return result = strstr(string, text.chars()) ? 0 : 1; return result = strstr(string, text.c_str()) ? 0 : 1;
return result = strcmp(string,text.chars()); return result = strcmp(string,text.c_str());
} }
LogEventsMngr::CLogCmp* LogEventsMngr::registerCondition(char* filter) LogEventsMngr::CLogCmp* LogEventsMngr::registerCondition(char* filter)
@ -61,7 +81,7 @@ LogEventsMngr::CLogCmp* LogEventsMngr::registerCondition(char* filter)
while (c) while (c)
{ {
if ((c->pos == pos) && (c->in == in) && !strcmp(c->text.chars(), filter)) if ((c->pos == pos) && (c->in == in) && !strcmp(c->text.c_str(), filter))
return c; return c;
c = c->next; c = c->next;
} }
@ -91,7 +111,7 @@ void LogEventsMngr::CLogEvent::registerFilter(char* filter)
filters = new LogCond(cmp->pos, aa, filters); filters = new LogCond(cmp->pos, aa, filters);
} }
void LogEventsMngr::setLogString(const char* frmt, va_list& vaptr) void LogEventsMngr::setLogString(char* frmt, va_list& vaptr)
{ {
++logCounter; ++logCounter;
int len = vsnprintf(logString, 255, frmt, vaptr); int len = vsnprintf(logString, 255, frmt, vaptr);
@ -108,7 +128,7 @@ void LogEventsMngr::setLogString(const char* frmt, va_list& vaptr)
logArgc = 0; logArgc = 0;
} }
void LogEventsMngr::setLogString(const char* frmt, ...) void LogEventsMngr::setLogString(char* frmt, ...)
{ {
++logCounter; ++logCounter;
va_list logArgPtr; va_list logArgPtr;
@ -166,37 +186,18 @@ void LogEventsMngr::parseLogString()
} }
} }
void LogEventsMngr::CLogEvent::setForwardState(ForwardState state) LogEventsMngr::CLogEvent* LogEventsMngr::registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos)
{
m_State = state;
}
int LogEventsMngr::registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos)
{ {
if (pos < 1 || pos > MAX_LOGARGS) if (pos < 1 || pos > MAX_LOGARGS)
{
return 0; return 0;
}
arelogevents = true; arelogevents = true;
auto d = &logevents[pos]; CLogEvent** d = &logevents[pos];
while (*d) while (*d)
{
d = &(*d)->next; d = &(*d)->next;
}
return *d = new CLogEvent(plugin, func, this);
auto logevent = new CLogEvent(plugin, func, this);
auto handle = LogEventHandles.create(logevent);
if (!handle)
{
return 0;
}
*d = logevent;
return handle;
} }
void LogEventsMngr::executeLogEvents() void LogEventsMngr::executeLogEvents()
@ -205,13 +206,8 @@ void LogEventsMngr::executeLogEvents()
for (CLogEvent* a = logevents[logArgc]; a; a = a->next) for (CLogEvent* a = logevents[logArgc]; a; a = a->next)
{ {
if (a->m_State != FSTATE_ACTIVE)
{
continue;
}
valid = true; valid = true;
for (CLogEvent::LogCond* b = a->filters; b; b = b->next) for (CLogEvent::LogCond* b = a->filters; b; b = b->next)
{ {
valid = false; valid = false;
@ -224,11 +220,11 @@ void LogEventsMngr::executeLogEvents()
break; break;
} }
} }
if (!valid) if (!valid)
break; break;
} }
if (valid) if (valid)
{ {
executeForwards(a->func); executeForwards(a->func);
@ -253,8 +249,6 @@ void LogEventsMngr::clearLogEvents()
} }
clearConditions(); clearConditions();
LogEventHandles.clear();
} }
void LogEventsMngr::clearConditions() void LogEventsMngr::clearConditions()

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef LOGEVENTS_H #ifndef LOGEVENTS_H
#define LOGEVENTS_H #define LOGEVENTS_H
@ -13,7 +35,6 @@
#define MAX_LOGARGS 12 #define MAX_LOGARGS 12
#include <stdarg.h> #include <stdarg.h>
#include "natives_handles.h"
// ***************************************************** // *****************************************************
// class LogEventsMngr // class LogEventsMngr
@ -42,7 +63,7 @@ public:
friend class CLogEvent; friend class CLogEvent;
LogEventsMngr* parent; LogEventsMngr* parent;
ke::AString text; String text;
int logid; int logid;
int pos; int pos;
@ -96,16 +117,13 @@ public:
LogCond *filters; LogCond *filters;
LogEventsMngr* parent; LogEventsMngr* parent;
ForwardState m_State;
CLogEvent *next; CLogEvent *next;
CLogEvent(CPluginMngr::CPlugin *p, int f, LogEventsMngr* ppp) : plugin(p), func(f), filters(nullptr), parent(ppp), m_State(FSTATE_ACTIVE), next(nullptr) {} CLogEvent(CPluginMngr::CPlugin *p, int f, LogEventsMngr* ppp) : plugin(p), func(f), filters(0), parent(ppp), next(0) {}
~CLogEvent(); ~CLogEvent();
public: public:
inline CPluginMngr::CPlugin *getPlugin() { return plugin; } inline CPluginMngr::CPlugin *getPlugin() { return plugin; }
void registerFilter(char* filter); void registerFilter(char* filter);
void setForwardState(ForwardState value);
inline int getFunction() { return func; } inline int getFunction() { return func; }
}; };
@ -120,11 +138,11 @@ public:
~LogEventsMngr(); ~LogEventsMngr();
// Interface // Interface
int registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos); CLogEvent* registerLogEvent(CPluginMngr::CPlugin* plugin, int func, int pos);
inline bool logEventsExist() { return arelogevents; } inline bool logEventsExist() { return arelogevents; }
void setLogString(const char* frmt, va_list& vaptr); void setLogString(char* frmt, va_list& vaptr);
void setLogString(const char* frmt, ...); void setLogString(char* frmt, ...);
void parseLogString(); void parseLogString();
void executeLogEvents(); void executeLogEvents();
@ -157,12 +175,4 @@ public:
inline iterator end() { return iterator(0, this); } inline iterator end() { return iterator(0, this); }
}; };
struct LogEventHook
{
explicit LogEventHook(LogEventsMngr::CLogEvent *logevent) : m_logevent(logevent) {}
LogEventsMngr::CLogEvent *m_logevent;
};
extern NativeHandle<LogEventHook> LogEventHandles;
#endif //LOGEVENTS_H #endif //LOGEVENTS_H

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "CMenu.h" #include "CMenu.h"
@ -13,15 +35,13 @@
// ***************************************************** // *****************************************************
// class MenuMngr // class MenuMngr
// ***************************************************** // *****************************************************
MenuMngr::MenuCommand::MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f, bool new_menu) MenuMngr::MenuCommand::MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f)
{ {
plugin = a; plugin = a;
keys = k; keys = k;
menuid = mi; menuid = mi;
next = 0;
is_new_menu = new_menu;
function = f; function = f;
next = 0;
} }
MenuMngr::~MenuMngr() MenuMngr::~MenuMngr()
@ -34,54 +54,73 @@ int MenuMngr::findMenuId(const char* name, AMX* amx)
{ {
for (MenuIdEle* b = headid; b; b = b->next) for (MenuIdEle* b = headid; b; b = b->next)
{ {
if ((!amx || !b->amx || amx == b->amx) && strstr(name,b->name.chars())) if ((!amx || !b->amx || amx == b->amx) && strstr(name,b->name.c_str()))
return b->id; return b->id;
} }
return 0; return 0;
} }
void MenuMngr::removeMenuId(int id)
{
MenuIdEle *n = headid;
MenuIdEle *l = NULL;
while (n)
{
if (n->id == id)
{
if (l)
l->next = n->next;
else
headid = n->next;
delete n;
break;
}
l = n;
n = n->next;
}
MenuCommand *c = headcmd;
MenuCommand *lc = NULL;
MenuCommand *tmp;
while (c)
{
if (c->menuid == id)
{
if (lc)
lc->next = c->next;
else
headcmd = c->next;
tmp = c->next;
delete c;
c = tmp;
} else {
lc = c;
c = c->next;
}
}
}
int MenuMngr::registerMenuId(const char* n, AMX* a) int MenuMngr::registerMenuId(const char* n, AMX* a)
{ {
int id = findMenuId(n, a); int id = findMenuId(n, a);
if (id) if (id)
{
return id; return id;
}
headid = new MenuIdEle(n, a, headid); headid = new MenuIdEle(n, a, headid);
if (!headid)
return 0; // :TODO: Better error report
return headid->id; return headid->id;
} }
void MenuMngr::registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f, bool from_new_menu) void MenuMngr::registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f)
{ {
MenuCommand **temp = &headcmd; MenuCommand** temp = &headcmd;
if (from_new_menu) while (*temp) temp = &(*temp)->next;
{ *temp = new MenuCommand(a, mi, k, f);
MenuCommand *ptr;
while (*temp)
{
ptr = *temp;
if (ptr->is_new_menu
&& ptr->plugin == a
&& ptr->menuid == mi)
{
if (g_forwards.isSameSPForward(ptr->function, f))
{
return;
}
}
temp = &(*temp)->next;
}
} else {
while (*temp)
{
temp = &(*temp)->next;
}
}
*temp = new MenuCommand(a, mi, k, f, from_new_menu);
} }
void MenuMngr::clear() void MenuMngr::clear()
@ -101,13 +140,4 @@ void MenuMngr::clear()
} }
} }
MenuMngr::iterator MenuMngr::SetWatchIter(MenuMngr::iterator iter)
{
MenuMngr::iterator old = m_watch_iter;
m_watch_iter = iter;
return old;
}
int MenuMngr::MenuIdEle::uniqueid = 0; int MenuMngr::MenuIdEle::uniqueid = 0;

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef MENUS_H #ifndef MENUS_H
#define MENUS_H #define MENUS_H
@ -18,7 +40,7 @@ class MenuMngr
{ {
struct MenuIdEle struct MenuIdEle
{ {
ke::AString name; String name;
AMX* amx; AMX* amx;
MenuIdEle* next; MenuIdEle* next;
@ -44,34 +66,29 @@ private:
int menuid; int menuid;
int keys; int keys;
int function; int function;
int is_new_menu;
MenuCommand* next; MenuCommand* next;
MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f, bool new_menu=false); MenuCommand(CPluginMngr::CPlugin *a, int mi, int k, int f);
public: public:
inline int getFunction() { return function; } inline int getFunction() { return function; }
inline CPluginMngr::CPlugin* getPlugin() { return plugin; } inline CPluginMngr::CPlugin* getPlugin() { return plugin; }
inline bool matchCommand(int m, int k) inline bool matchCommand(int m, int k) { return ((m == menuid) && (keys & k)); }
{
return ((m == menuid) && (keys & k));
}
} *headcmd; } *headcmd;
public: public:
MenuMngr() : m_watch_iter(end()) MenuMngr() { headid = 0; headcmd = 0; }
{ headid = NULL; headcmd = NULL; }
~MenuMngr(); ~MenuMngr();
// Interface // Interface
int findMenuId(const char* name, AMX* a = 0); int findMenuId(const char* name, AMX* a = 0);
int registerMenuId(const char* n, AMX* a); int registerMenuId(const char* n, AMX* a);
void registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f, bool from_new_menu=false); void removeMenuId(int id);
void registerMenuCmd(CPluginMngr::CPlugin *a, int mi, int k, int f);
void clear(); void clear();
class iterator class iterator
{ {
friend class MenuMngr;
MenuCommand* a; MenuCommand* a;
public: public:
iterator(MenuCommand*aa) : a(aa) {} iterator(MenuCommand*aa) : a(aa) {}
@ -84,13 +101,6 @@ public:
inline iterator begin() const { return iterator(headcmd); } inline iterator begin() const { return iterator(headcmd); }
inline iterator end() const { return iterator(0); } inline iterator end() const { return iterator(0); }
MenuMngr::iterator SetWatchIter(MenuMngr::iterator iter);
inline MenuMngr::iterator GetWatchIter() { return m_watch_iter; }
private:
MenuMngr::iterator m_watch_iter;
}; };
extern MenuMngr g_menucmds;
#endif //MENUS_H #endif //MENUS_H

View File

@ -1,12 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "newmenus.h" #include "newmenus.h"
// ***************************************************** // *****************************************************
@ -19,9 +40,8 @@ void CPlayer::Init(edict_t* e, int i)
pEdict = e; pEdict = e;
initialized = false; initialized = false;
ingame = false; ingame = false;
bot = false;
authorized = false; authorized = false;
disconnecting = false;
teamIdsInitialized = false;
current = 0; current = 0;
teamId = -1; teamId = -1;
@ -32,10 +52,10 @@ void CPlayer::Init(edict_t* e, int i)
menuexpire = 0.0; menuexpire = 0.0;
newmenu = -1; newmenu = -1;
death_weapon = nullptr; death_weapon.clear();
name = nullptr; name.clear();
ip = nullptr; ip.clear();
team = nullptr; team.clear();
} }
void CPlayer::Disconnect() void CPlayer::Disconnect()
@ -43,11 +63,21 @@ void CPlayer::Disconnect()
ingame = false; ingame = false;
initialized = false; initialized = false;
authorized = false; authorized = false;
disconnecting = false;
teamIdsInitialized = false;
if (Menu *pMenu = get_menu_by_id(newmenu)) if (newmenu != -1)
pMenu->Close(index); {
Menu *pMenu = g_NewMenus[newmenu];
if (pMenu)
{
//prevent recursion
newmenu = -1;
menu = 0;
executeForwards(pMenu->func,
static_cast<cell>(ENTINDEX(pEdict)),
static_cast<cell>(pMenu->thisId),
static_cast<cell>(MENU_EXIT));
}
}
List<ClientCvarQuery_Info *>::iterator iter, end=queries.end(); List<ClientCvarQuery_Info *>::iterator iter, end=queries.end();
for (iter=queries.begin(); iter!=end; iter++) for (iter=queries.begin(); iter!=end; iter++)
@ -58,6 +88,7 @@ void CPlayer::Disconnect()
} }
queries.clear(); queries.clear();
bot = 0;
menu = 0; menu = 0;
newmenu = -1; newmenu = -1;
} }
@ -83,9 +114,10 @@ int CPlayer::NextHUDChannel()
bool CPlayer::Connect(const char* connectname, const char* ipaddress) bool CPlayer::Connect(const char* connectname, const char* ipaddress)
{ {
name = connectname; name.assign(connectname);
ip = ipaddress; ip.assign(ipaddress);
time = gpGlobals->time; time = gpGlobals->time;
bot = IsBot();
death_killer = 0; death_killer = 0;
menu = 0; menu = 0;
newmenu = -1; newmenu = -1;
@ -241,7 +273,7 @@ void TeamIds::registerTeam(const char* n, int s)
while (*a) while (*a)
{ {
if (strcmp((*a)->name.chars(),n) == 0) if (strcmp((*a)->name.c_str(),n) == 0)
{ {
if (s != -1) if (s != -1)
{ {
@ -268,7 +300,7 @@ int TeamIds::findTeamId(const char* n)
while (a) while (a)
{ {
if (!stricmp(a->name.chars(), n)) if (!stricmp(a->name.c_str(), n))
return a->id; return a->id;
a = a->next; a = a->next;
} }
@ -282,7 +314,7 @@ int TeamIds::findTeamIdCase(const char* n)
while (a) while (a)
{ {
if (!strcmp(a->name.chars(), n)) if (!strcmp(a->name.c_str(), n))
return a->id; return a->id;
a = a->next; a = a->next;
} }

View File

@ -1,17 +1,65 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef CMISC_H #ifndef CMISC_H
#define CMISC_H #define CMISC_H
#include "CList.h"
#include "sh_list.h" #include "sh_list.h"
// *****************************************************
// class CCVar
// *****************************************************
class CCVar
{
cvar_t cvar;
String name;
String plugin;
public:
CCVar(const char* pname, const char* pplugin, int pflags, float pvalue) : name(pname), plugin(pplugin)
{
cvar.name = (char*)name.c_str();
cvar.flags = pflags;
cvar.string = "";
cvar.value = pvalue;
}
inline cvar_t* getCvar() { return &cvar; }
inline const char* getPluginName() { return plugin.c_str(); }
inline const char* getName() { return name.c_str(); }
inline bool operator == (const char* string) { return (strcmp(name.c_str(), string) == 0); }
};
// ***************************************************** // *****************************************************
// class CPlayer // class CPlayer
// ***************************************************** // *****************************************************
@ -29,16 +77,15 @@ class CPlayer
public: public:
edict_t* pEdict; edict_t* pEdict;
ke::AString name; String name;
ke::AString ip; String ip;
ke::AString team; String team;
bool initialized; bool initialized;
bool ingame; bool ingame;
bool bot;
bool authorized; bool authorized;
bool disconnecting; bool vgui;
bool vgui;
bool teamIdsInitialized;
float time; float time;
float playtime; float playtime;
@ -63,7 +110,7 @@ public:
int death_killer; int death_killer;
int death_victim; int death_victim;
bool death_tk; bool death_tk;
ke::AString death_weapon; String death_weapon;
int newmenu; int newmenu;
int page; int page;
@ -71,6 +118,7 @@ public:
cell hudmap[5]; cell hudmap[5];
Vector lastTrace; Vector lastTrace;
Vector thisTrace;
Vector lastHit; Vector lastHit;
List<ClientCvarQuery_Info *> queries; List<ClientCvarQuery_Info *> queries;
@ -83,8 +131,7 @@ public:
inline bool IsBot() inline bool IsBot()
{ {
const char *auth = GETPLAYERAUTHID(pEdict); return ((pEdict->v.flags & FL_FAKECLIENT) ? true : false);
return auth && !strcmp(auth, "BOT");
} }
inline bool IsAlive() inline bool IsAlive()
@ -128,7 +175,7 @@ public:
class ForceObject class ForceObject
{ {
ke::AString filename; String filename;
FORCE_TYPE type; FORCE_TYPE type;
Vector mins; Vector mins;
Vector maxs; Vector maxs;
@ -136,7 +183,7 @@ class ForceObject
public: public:
ForceObject(const char* n, FORCE_TYPE c, Vector& mi, Vector& ma, AMX* a) : filename(n), type(c), mins(mi), maxs(ma), amx(a) {} ForceObject(const char* n, FORCE_TYPE c, Vector& mi, Vector& ma, AMX* a) : filename(n), type(c), mins(mi), maxs(ma), amx(a) {}
inline const char* getFilename() { return filename.chars(); } inline const char* getFilename() { return filename.c_str(); }
inline AMX* getAMX() { return amx; } inline AMX* getAMX() { return amx; }
Vector& getMin() { return mins; } Vector& getMin() { return mins; }
@ -191,16 +238,17 @@ public:
// class CScript // class CScript
// ***************************************************** // *****************************************************
class CScript : public ke::InlineListNode<CScript> class CScript
{ {
ke::AString filename; String filename;
AMX* amx; AMX* amx;
void* code; void* code;
public: public:
CScript(AMX* aa, void* cc, const char* ff) : filename(ff), amx(aa), code(cc) {} CScript(AMX* aa, void* cc, const char* ff) : filename(ff), amx(aa), code(cc) {}
inline AMX* getAMX() { return amx; } inline AMX* getAMX() { return amx; }
inline const char* getName() { return filename.chars(); } inline const char* getName() { return filename.c_str(); }
inline bool operator==(void* a) { return (amx == (AMX*)a); }
inline void* getCode() { return code; } inline void* getCode() { return code; }
}; };
@ -212,7 +260,7 @@ class TeamIds
{ {
struct TeamEle struct TeamEle
{ {
ke::AString name; String name;
int id; int id;
char tid; char tid;
static char uid; static char uid;
@ -238,87 +286,4 @@ public:
inline bool isNewTeam() { return newTeam ? true : false; } inline bool isNewTeam() { return newTeam ? true : false; }
}; };
class CAdminData
{
private:
cell m_AuthData[44];
cell m_Password[32];
cell m_Flags;
cell m_Access;
public:
CAdminData()
{
m_AuthData[0]=0;
m_Password[0]=0;
m_Flags=0;
m_Access=0;
};
void SetAccess(cell Access)
{
m_Access=Access;
};
cell GetAccess(void) const
{
return m_Access;
};
void SetFlags(cell Flags)
{
m_Flags=Flags;
};
cell GetFlags(void) const
{
return m_Flags;
};
void SetAuthID(const cell *Input)
{
unsigned int i=0;
while (i<sizeof(m_AuthData)-1)
{
if ((m_AuthData[i++]=*Input++)==0)
{
return;
}
}
m_AuthData[arraysize(m_AuthData)-1]=0;
};
const cell *GetAuthID(void) const
{
return &m_AuthData[0];
};
void SetPass(const cell *Input)
{
unsigned int i=0;
while (i<sizeof(m_Password)-1)
{
if ((m_Password[i++]=*Input++)==0)
{
return;
}
}
m_Password[arraysize(m_Password)-1]=0;
};
const cell *GetPass(void) const
{
return &m_Password[0];
};
CAdminData & operator = (const CAdminData &src)
{
this->SetAccess(src.GetAccess());
this->SetFlags(src.GetFlags());
this->SetAuthID(src.GetAuthID());
this->SetPass(src.GetPass());
return *this;
}
};
#endif //CMISC_H #endif //CMISC_H

View File

@ -1,14 +1,35 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "libraries.h"
#ifndef FAR #ifndef FAR
#define FAR #define FAR
@ -17,12 +38,9 @@
// New // New
typedef void* (*PFN_REQ_FNPTR)(const char * /*name*/); typedef void* (*PFN_REQ_FNPTR)(const char * /*name*/);
typedef int (FAR *QUERYMOD_NEW)(int * /*ifvers*/, amxx_module_info_s * /*modInfo*/); typedef int (FAR *QUERYMOD_NEW)(int * /*ifvers*/, amxx_module_info_s * /*modInfo*/);
typedef int (FAR *CHECKGAME_NEW)(const char *);
typedef int (FAR *ATTACHMOD_NEW)(PFN_REQ_FNPTR /*reqFnptrFunc*/); typedef int (FAR *ATTACHMOD_NEW)(PFN_REQ_FNPTR /*reqFnptrFunc*/);
typedef int (FAR *DETACHMOD_NEW)(void); typedef int (FAR *DETACHMOD_NEW)(void);
typedef void (FAR *PLUGINSLOADED_NEW)(void); typedef void (FAR *PLUGINSLOADED_NEW)(void);
typedef void (*PLUGINSUNLOADED_NEW)(void);
typedef void (*PLUGINSUNLOADING_NEW)(void);
// ***************************************************** // *****************************************************
// class CModule // class CModule
@ -30,7 +48,7 @@ typedef void (*PLUGINSUNLOADING_NEW)(void);
CModule::CModule(const char* fname) CModule::CModule(const char* fname)
{ {
m_Filename = fname; m_Filename.assign(fname);
clear(false); clear(false);
} }
@ -49,27 +67,19 @@ void CModule::clear(bool clearFilename)
m_Metamod = false; m_Metamod = false;
m_Handle = NULL; m_Handle = NULL;
m_Status = MODULE_NONE; m_Status = MODULE_NONE;
if (clearFilename) if (clearFilename)
{ m_Filename.assign("unknown");
m_Filename = "unknown";
}
// new // new
m_Amxx = false;
m_InfoNew.author = "unknown"; m_InfoNew.author = "unknown";
m_InfoNew.name = "unknown"; m_InfoNew.name = "unknown";
m_InfoNew.version = "unknown"; m_InfoNew.version = "unknown";
m_InfoNew.reload = 0; m_InfoNew.reload = 0;
m_MissingFunc = NULL; m_MissingFunc = NULL;
for (size_t i=0; i<m_DestroyableIndexes.length(); i++)
{
delete [] m_Natives[m_DestroyableIndexes[i]];
}
m_DestroyableIndexes.clear();
m_Natives.clear(); m_Natives.clear();
m_NewNatives.clear();
} }
bool CModule::attachMetamod(const char *mmfile, PLUG_LOADTIME now) bool CModule::attachMetamod(const char *mmfile, PLUG_LOADTIME now)
@ -92,94 +102,46 @@ bool CModule::attachMetamod(const char *mmfile, PLUG_LOADTIME now)
return true; return true;
} }
//this ugly function is ultimately something like O(n^4).
//sigh. it shouldn't be needed.
void CModule::rewriteNativeLists(AMX_NATIVE_INFO *list)
{
AMX_NATIVE_INFO *curlist;
for (size_t i=0; i<m_Natives.length(); i++)
{
curlist = m_Natives[i];
bool changed = false;
bool found = false;
ke::Vector<size_t> newlist;
for (size_t j=0; curlist[j].func != NULL; j++)
{
found = false;
for (size_t k=0; list[k].func != NULL; k++)
{
if (strcmp(curlist[j].name, list[k].name) == 0)
{
found = true;
break;
}
}
if (found)
{
changed = true;
//don't break, we have to search it all
} else {
newlist.append(j);
}
}
if (changed)
{
//now build the new list
AMX_NATIVE_INFO *rlist = new AMX_NATIVE_INFO[newlist.length()+1];
for (size_t j=0; j<newlist.length(); j++)
{
rlist[j].func = curlist[newlist[j]].func;
rlist[j].name = curlist[newlist[j]].name;
}
rlist[newlist.length()].func = NULL;
rlist[newlist.length()].name = NULL;
m_Natives[i] = rlist;
m_DestroyableIndexes.append(i);
}
}
}
bool CModule::attachModule() bool CModule::attachModule()
{ {
// old & new // old & new
if (m_Status != MODULE_QUERY || !m_Handle) if (m_Status != MODULE_QUERY || !m_Handle)
return false; return false;
ATTACHMOD_NEW AttachFunc_New = (ATTACHMOD_NEW)DLPROC(m_Handle, "AMXX_Attach"); if (m_Amxx)
if (!AttachFunc_New)
return false;
g_ModuleCallReason = ModuleCall_Attach;
g_CurrentlyCalledModule = this;
int retVal = (*AttachFunc_New)(Module_ReqFnptr);
g_CurrentlyCalledModule = NULL;
g_ModuleCallReason = ModuleCall_NotCalled;
switch (retVal)
{ {
case AMXX_OK: // new
m_Status = MODULE_LOADED; ATTACHMOD_NEW AttachFunc_New = (ATTACHMOD_NEW)DLPROC(m_Handle, "AMXX_Attach");
break;
case AMXX_PARAM:
AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") returned \"Invalid parameter\" from Attach func.", m_Filename.chars(), getVersion());
m_Status = MODULE_INTERROR;
return false;
case AMXX_FUNC_NOT_PRESENT:
m_Status = MODULE_FUNCNOTPRESENT;
m_MissingFunc = g_LastRequestedFunc;
return false;
default:
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.chars(), getVersion());
m_Status = MODULE_BADLOAD;
return false;
}
if (m_Status == MODULE_LOADED) if (!AttachFunc_New)
{ return false;
AddLibrariesFromString(m_InfoNew.library, LibType_Library, LibSource_Module, this);
AddLibrariesFromString(m_InfoNew.libclass, LibType_Class, LibSource_Module, this); g_ModuleCallReason = ModuleCall_Attach;
return true; g_CurrentlyCalledModule = this;
int retVal = (*AttachFunc_New)(Module_ReqFnptr);
g_CurrentlyCalledModule = NULL;
g_ModuleCallReason = ModuleCall_NotCalled;
switch (retVal)
{
case AMXX_OK:
m_Status = MODULE_LOADED;
return true;
case AMXX_PARAM:
AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") retured \"Invalid parameter\" from Attach func.", m_Filename.c_str(), getVersion());
m_Status = MODULE_INTERROR;
return false;
case AMXX_FUNC_NOT_PRESENT:
m_Status = MODULE_FUNCNOTPRESENT;
m_MissingFunc = g_LastRequestedFunc;
return false;
default:
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.c_str(), getVersion());
m_Status = MODULE_BADLOAD;
return false;
}
} else {
m_Status = MODULE_BADLOAD;
} }
return false; return false;
@ -190,12 +152,9 @@ bool CModule::queryModule()
if (m_Status != MODULE_NONE) // don't check if already queried if (m_Status != MODULE_NONE) // don't check if already queried
return false; return false;
m_Handle = DLLOAD(m_Filename.chars()); // load file m_Handle = DLLOAD(m_Filename.c_str()); // load file
if (!m_Handle) if (!m_Handle)
{ {
#if defined(__linux__) || defined(__APPLE__)
AMXXLOG_Log("[AMXX] Module \"%s\" failed to load (%s)", m_Filename.chars(), dlerror());
#endif
m_Status = MODULE_BADLOAD; m_Status = MODULE_BADLOAD;
return false; return false;
} }
@ -206,58 +165,33 @@ bool CModule::queryModule()
// Try new interface first // Try new interface first
QUERYMOD_NEW queryFunc_New = (QUERYMOD_NEW)DLPROC(m_Handle, "AMXX_Query"); QUERYMOD_NEW queryFunc_New = (QUERYMOD_NEW)DLPROC(m_Handle, "AMXX_Query");
if (queryFunc_New) if (queryFunc_New)
{ {
m_Amxx = true;
int ifVers = AMXX_INTERFACE_VERSION; int ifVers = AMXX_INTERFACE_VERSION;
g_ModuleCallReason = ModuleCall_Query; g_ModuleCallReason = ModuleCall_Query;
g_CurrentlyCalledModule = this; g_CurrentlyCalledModule = this;
int retVal = (*queryFunc_New)(&ifVers, &m_InfoNew); int retVal = (*queryFunc_New)(&ifVers, &m_InfoNew);
g_CurrentlyCalledModule = NULL; g_CurrentlyCalledModule = NULL;
g_ModuleCallReason = ModuleCall_NotCalled; g_ModuleCallReason = ModuleCall_NotCalled;
switch (retVal) switch (retVal)
{ {
case AMXX_PARAM: case AMXX_PARAM:
AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") returned \"Invalid parameter\" from Attach func.", m_Filename.chars(), getVersion()); AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") retured \"Invalid parameter\" from Attach func.", m_Filename.c_str(), getVersion());
m_Status = MODULE_INTERROR; m_Status = MODULE_INTERROR;
return false; return false;
case AMXX_IFVERS: case AMXX_IFVERS:
if (ifVers < AMXX_INTERFACE_VERSION) if (ifVers < AMXX_INTERFACE_VERSION)
{ m_Status = MODULE_OLD;
//backwards compat for new defs else
if (ifVers == 3)
{
g_ModuleCallReason = ModuleCall_Query;
g_CurrentlyCalledModule = this;
retVal = (*queryFunc_New)(&ifVers, &m_InfoNew);
g_CurrentlyCalledModule = NULL;
g_ModuleCallReason = ModuleCall_NotCalled;
if (retVal == AMXX_OK)
{
m_InfoNew.library = m_InfoNew.logtag;
if (StrCaseStr(m_InfoNew.library, "sql")
|| StrCaseStr(m_InfoNew.library, "dbi"))
{
m_InfoNew.libclass = "DBI";
} else {
m_InfoNew.libclass = "";
}
break;
}
return false;
} else {
m_Status = MODULE_OLD;
return false;
}
} else {
m_Status = MODULE_NEWER; m_Status = MODULE_NEWER;
return false; return false;
}
case AMXX_OK: case AMXX_OK:
break; break;
default: default:
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.chars(), getVersion()); AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an invalid code.", m_Filename.c_str(), getVersion());
m_Status = MODULE_BADLOAD; m_Status = MODULE_BADLOAD;
return false; return false;
} }
@ -269,37 +203,11 @@ bool CModule::queryModule()
return false; return false;
} }
// Lastly, check to see if this module is able to load on this game mod
CHECKGAME_NEW checkGame_New = (CHECKGAME_NEW)DLPROC(m_Handle, "AMXX_CheckGame");
if (checkGame_New)
{
// This is an optional check; do not fail modules that do not have it
int ret = checkGame_New(g_mod_name.chars());
if (ret != AMXX_GAME_OK)
{
switch (ret)
{
case AMXX_GAME_BAD:
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") reported that it cannot load on game \"%s\"", m_Filename.chars(), getVersion(), g_mod_name.chars());
m_Status = MODULE_BADGAME;
break;
default:
AMXXLOG_Log("[AMXX] Module \"%s\" (version \"%s\") returned an unknown CheckGame code (value: %d)", m_Filename.chars(), getVersion(), ret);
m_Status = MODULE_BADLOAD;
break;
}
return false;
}
}
m_Status = MODULE_QUERY; m_Status = MODULE_QUERY;
return true; return true;
} else { } else {
m_Status = MODULE_NOQUERY; m_Status = MODULE_NOQUERY;
m_Amxx = false;
return false; return false;
} }
} }
@ -309,62 +217,33 @@ bool CModule::detachModule()
if (m_Status != MODULE_LOADED) if (m_Status != MODULE_LOADED)
return false; return false;
RemoveLibraries(this); if (m_Amxx)
DETACHMOD_NEW detachFunc_New = (DETACHMOD_NEW)DLPROC(m_Handle, "AMXX_Detach");
if (detachFunc_New)
{ {
g_ModuleCallReason = ModuleCall_Detach; DETACHMOD_NEW detachFunc_New = (DETACHMOD_NEW)DLPROC(m_Handle, "AMXX_Detach");
g_CurrentlyCalledModule = this;
(*detachFunc_New)(); if (detachFunc_New)
g_CurrentlyCalledModule = NULL; {
g_ModuleCallReason = ModuleCall_NotCalled; g_ModuleCallReason = ModuleCall_Detach;
g_CurrentlyCalledModule = this;
(*detachFunc_New)();
g_CurrentlyCalledModule = NULL;
g_ModuleCallReason = ModuleCall_NotCalled;
}
} }
#ifndef FAKEMETA
if (IsMetamod()) if (IsMetamod())
{ {
UnloadMetamodPlugin(m_Handle); UnloadMetamodPlugin(m_Handle);
} }
#endif
DLFREE(m_Handle); DLFREE(m_Handle);
clear(); clear();
return true; return true;
} }
void CModule::CallPluginsUnloaded()
{
if (m_Status != MODULE_LOADED)
return;
if (!m_Handle)
return;
PLUGINSUNLOADED_NEW func = (PLUGINSUNLOADED_NEW)DLPROC(m_Handle, "AMXX_PluginsUnloaded");
if (!func)
return;
func();
}
void CModule::CallPluginsUnloading()
{
if (m_Status != MODULE_LOADED)
return;
if (!m_Handle)
return;
PLUGINSUNLOADING_NEW func = (PLUGINSUNLOADING_NEW)DLPROC(m_Handle, "AMXX_PluginsUnloading");
if (!func)
return;
func();
}
void CModule::CallPluginsLoaded() void CModule::CallPluginsLoaded()
{ {
if (m_Status != MODULE_LOADED) if (m_Status != MODULE_LOADED)
@ -374,10 +253,10 @@ void CModule::CallPluginsLoaded()
return; return;
PLUGINSLOADED_NEW func = (PLUGINSLOADED_NEW)DLPROC(m_Handle, "AMXX_PluginsLoaded"); PLUGINSLOADED_NEW func = (PLUGINSLOADED_NEW)DLPROC(m_Handle, "AMXX_PluginsLoaded");
if (!func) if (!func)
return; return;
func(); func();
} }
@ -397,9 +276,8 @@ const char* CModule::getStatus() const
case MODULE_NEWER: return "newer"; case MODULE_NEWER: return "newer";
case MODULE_INTERROR: return "internal err"; case MODULE_INTERROR: return "internal err";
case MODULE_NOT64BIT: return "not 64bit"; case MODULE_NOT64BIT: return "not 64bit";
case MODULE_BADGAME: return "bad game";
default: break; default: break;
} }
return "unknown"; return "unknown";
} }

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
// ***************************************************** // *****************************************************
// class CModule // class CModule
@ -27,8 +49,7 @@ enum MODULE_STATUS
MODULE_NEWER, // newer interface MODULE_NEWER, // newer interface
MODULE_INTERROR, // Internal error MODULE_INTERROR, // Internal error
MODULE_FUNCNOTPRESENT, // Function not present MODULE_FUNCNOTPRESENT, // Function not present
MODULE_NOT64BIT, // Not 64 bit compatible MODULE_NOT64BIT // Not 64 bit compatible
MODULE_BADGAME, // Module cannot load on the current game mod
}; };
struct amxx_module_info_s struct amxx_module_info_s
@ -38,8 +59,6 @@ struct amxx_module_info_s
const char *version; const char *version;
int reload; // reload on mapchange when nonzero int reload; // reload on mapchange when nonzero
const char *logtag; //added in version 2 const char *logtag; //added in version 2
const char *library; // added in version 4
const char *libclass; // added in version 4
}; };
#define AMXX_OK 0 /* no error */ #define AMXX_OK 0 /* no error */
@ -47,17 +66,15 @@ struct amxx_module_info_s
#define AMXX_PARAM 2 /* Invalid parameter */ #define AMXX_PARAM 2 /* Invalid parameter */
#define AMXX_FUNC_NOT_PRESENT 3 /* Function not present */ #define AMXX_FUNC_NOT_PRESENT 3 /* Function not present */
#define AMXX_GAME_OK 0 /* Module can load on this game. */ #define AMXX_INTERFACE_VERSION 3
#define AMXX_GAME_BAD 1 /* Module cannot load on this game. */
#define AMXX_INTERFACE_VERSION 4 class CModule
class CModule : public ke::InlineListNode<CModule>
{ {
ke::AString m_Filename; // Filename String m_Filename; // Filename
bool m_Metamod; // Using metamod? bool m_Metamod; // Using metamod?
bool m_Amxx; // Using new module interface?
amxx_module_info_s m_InfoNew; // module info (new module interface) amxx_module_info_s m_InfoNew; // module info (new module interface)
DLHANDLE m_Handle; // handle DLHANDLE m_Handle; // handle
MODULE_STATUS m_Status; // status MODULE_STATUS m_Status; // status
@ -69,33 +86,32 @@ public:
~CModule(); ~CModule();
// Interface // Interface
bool attachModule(); bool attachModule();
bool queryModule(); bool queryModule();
bool detachModule(); bool detachModule();
void rewriteNativeLists(AMX_NATIVE_INFO *list);
#ifndef FAKEMETA
bool attachMetamod(const char *mmfile, PLUG_LOADTIME now); bool attachMetamod(const char *mmfile, PLUG_LOADTIME now);
#endif
const char* getStatus() const; const char* getStatus() const;
inline const char* getType() const { return m_Metamod ? "amxx&mm" : "amxx"; } inline const char* getType() const { return m_Amxx ? "amxx" : (m_Metamod ? "amx&mm" : "amx"); }
inline const char* getAuthor() const { return m_InfoNew.author; } inline const char* getAuthor() const { return m_InfoNew.author; }
inline const char* getVersion() const { return m_InfoNew.version; } inline const char* getVersion() const { return m_InfoNew.version; }
inline const char* getName() const { return m_InfoNew.name; } inline const char* getName() const { return m_InfoNew.name; }
inline const amxx_module_info_s* getInfoNew() const { return &m_InfoNew; } // new inline const amxx_module_info_s* getInfoNew() const { return &m_InfoNew; } // new
inline int getStatusValue() { return m_Status; } inline int getStatusValue() { return m_Status; }
inline bool operator==(const char* fname) { return !strcmp(m_Filename.c_str(), fname); }
inline bool isReloadable() { return ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)); } inline bool isReloadable() { return ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)); }
inline bool isAmxx() const { return m_Amxx; }
inline const char *getMissingFunc() const { return m_MissingFunc; } inline const char *getMissingFunc() const { return m_MissingFunc; }
inline const char *getFilename() { return m_Filename.chars(); } inline const char *getFilename() { return m_Filename.c_str(); }
inline bool IsMetamod() { return m_Metamod; } inline bool IsMetamod() { return m_Metamod; }
void CallPluginsLoaded(); void CallPluginsLoaded();
void CallPluginsUnloaded();
void CallPluginsUnloading();
ke::Vector<AMX_NATIVE_INFO*> m_Natives; CList<AMX_NATIVE_INFO*> m_Natives;
ke::Vector<AMX_NATIVE_INFO*> m_NewNatives; // Natives for new (AMXX, not AMX) plugins only
ke::Vector<size_t> m_DestroyableIndexes;
}; };
#endif //CMODULE_H #endif //CMODULE_H

340
amxmodx/COPYING Executable file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -1,33 +1,53 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "CPlugin.h" #include "CPlugin.h"
#include "CForward.h" #include "CForward.h"
#include "CFile.h"
#include "amx.h" #include "amx.h"
#include "natives.h" #include "natives.h"
#include "debugger.h" #include "debugger.h"
#include "libraries.h"
#include <amxmodx_version.h>
#include "engine_strucs.h"
extern const char *no_function; extern const char *no_function;
CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, size_t maxLength, int debug) CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, int debug)
{ {
CPlugin** a = &head; CPlugin** a = &head;
while (*a) while (*a)
a = &(*a)->next; a = &(*a)->next;
*a = new CPlugin(pCounter++, path, name, error, maxLength, debug); *a = new CPlugin(pCounter++, path, name, error, debug);
return (*a); return (*a);
} }
@ -43,10 +63,10 @@ void CPluginMngr::Finalize()
{ {
if (m_Finalized) if (m_Finalized)
return; return;
pNatives = BuildNativeTable(); pNatives = BuildNativeTable();
CPlugin *a = head; CPlugin *a = head;
while (a) while (a)
{ {
if (a->getStatusCode() == ps_running) if (a->getStatusCode() == ps_running)
@ -56,145 +76,55 @@ void CPluginMngr::Finalize()
} }
a = a->next; a = a->next;
} }
m_Finalized = true; m_Finalized = true;
} }
int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn) int CPluginMngr::loadPluginsFromFile(const char* filename)
{ {
char file[PLATFORM_MAX_PATH]; char file[256];
FILE *fp = fopen(build_pathname_r(file, sizeof(file), "%s", filename), "rt"); FILE *fp = fopen(build_pathname_r(file, sizeof(file) - 1, "%s", filename), "rt");
if (!fp) if (!fp)
{ {
if (warn) AMXXLOG_Log("[AMXX] Plugins list not found (file \"%s\")", filename);
{
AMXXLOG_Error("[AMXX] Plugins list not found (file \"%s\")", filename);
}
return 1; return 1;
} }
// Find now folder // Find now folder
char pluginName[256], error[256], debug[256]; char pluginName[256], error[256], debug[256];
int debugFlag = 0; int debugFlag = 0;
const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"); const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins");
String line;
char line[512]; while (!feof(fp))
List<ke::AString *>::iterator block_iter;
while (!feof(fp))
{ {
pluginName[0] = '\0'; pluginName[0] = '\0';
debug[0] = '\0'; debug[0] = '\0';
debugFlag = 0; debugFlag = 0;
line[0] = '\0'; line.clear();
fgets(line, sizeof(line), fp); line._fread(fp);
sscanf(line.c_str(), "%s %s", pluginName, debug);
/** quick hack */
char *ptr = line;
while (*ptr)
{
if (*ptr == ';')
{
*ptr = '\0';
} else {
ptr++;
}
}
sscanf(line, "%s %s", pluginName, debug);
if (!isalnum(*pluginName)) if (!isalnum(*pluginName))
{
continue; continue;
}
if (isalnum(*debug) && !strcmp(debug, "debug")) if (isalnum(*debug) && strcmp(debug, "debug") == 0)
{ {
debugFlag = 1; debugFlag = 1;
} }
bool skip = false; CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, debugFlag);
for (block_iter = m_BlockList.begin();
block_iter != m_BlockList.end();
block_iter++)
{
if ((*block_iter)->compare(pluginName) == 0)
{
skip = true;
break;
}
}
if (skip || !strcmp(debug, "disabled"))
{
continue;
}
if (findPlugin(pluginName) != NULL)
{
continue;
}
CPlugin* plugin = loadPlugin(pluginsDir, pluginName, error, sizeof(error), debugFlag);
if (plugin->getStatusCode() == ps_bad_load) if (plugin->getStatusCode() == ps_bad_load)
{ {
char errorMsg[255]; char errorMsg[255];
sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName); sprintf(errorMsg, "%s (plugin \"%s\")", error, pluginName);
plugin->setError(errorMsg); plugin->setError(errorMsg);
AMXXLOG_Error("[AMXX] %s", plugin->getError()); AMXXLOG_Log("[AMXX] %s", plugin->getError());
}
else
{
cell addr;
if (amx_FindPubVar(plugin->getAMX(), "MaxClients", &addr) != AMX_ERR_NOTFOUND)
{
*get_amxaddr(plugin->getAMX(), addr) = gpGlobals->maxClients;
}
if (amx_FindPubVar(plugin->getAMX(), "MapName", &addr) != AMX_ERR_NOTFOUND)
{
set_amxstring(plugin->getAMX(), addr, STRING(gpGlobals->mapname), MAX_MAPNAME_LENGTH - 1);
}
auto length = 0;
if (amx_FindPubVar(plugin->getAMX(), "PluginName", &addr) != AMX_ERR_NOTFOUND)
{
plugin->setTitle(get_amxstring(plugin->getAMX(), addr, 0, length));
}
if (amx_FindPubVar(plugin->getAMX(), "PluginVersion", &addr) != AMX_ERR_NOTFOUND)
{
plugin->setVersion(get_amxstring(plugin->getAMX(), addr, 0, length));
}
if (amx_FindPubVar(plugin->getAMX(), "PluginAuthor", &addr) != AMX_ERR_NOTFOUND)
{
plugin->setAuthor(get_amxstring(plugin->getAMX(), addr, 0, length));
}
if (amx_FindPubVar(plugin->getAMX(), "PluginURL", &addr) != AMX_ERR_NOTFOUND)
{
plugin->setUrl(get_amxstring(plugin->getAMX(), addr, 0, length));
}
if (amx_FindPubVar(plugin->getAMX(), "PluginDescription", &addr) != AMX_ERR_NOTFOUND)
{
plugin->setDescription(get_amxstring(plugin->getAMX(), addr, 0, length));
}
if (amx_FindPubVar(plugin->getAMX(), "NULL_STRING", &addr) != AMX_ERR_NOTFOUND)
{
plugin->m_pNullStringOfs = get_amxaddr(plugin->getAMX(), addr);
}
if (amx_FindPubVar(plugin->getAMX(), "NULL_VECTOR", &addr) != AMX_ERR_NOTFOUND)
{
plugin->m_pNullVectorOfs = get_amxaddr(plugin->getAMX(), addr);
}
} }
} }
@ -205,82 +135,63 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn)
void CPluginMngr::clear() void CPluginMngr::clear()
{ {
CPlugin**a = &head; CPlugin**a = &head;
while (*a) while (*a)
unloadPlugin(a); unloadPlugin(a);
m_Finalized = false; m_Finalized = false;
if (pNatives) if (pNatives)
{ {
delete [] pNatives; delete [] pNatives;
pNatives = NULL; pNatives = NULL;
} }
List<ke::AString *>::iterator iter = m_BlockList.begin();
while (iter != m_BlockList.end())
{
delete (*iter);
iter = m_BlockList.erase(iter);
}
m_BlockList.clear();
} }
CPluginMngr::CPlugin* CPluginMngr::findPlugin(AMX *amx) CPluginMngr::CPlugin* CPluginMngr::findPlugin(AMX *amx)
{ {
CPlugin*a = head; CPlugin*a = head;
while (a && &a->amx != amx) while (a && &a->amx != amx)
a = a->next; a = a->next;
return a; return a;
} }
CPluginMngr::CPlugin* CPluginMngr::findPlugin(int index) CPluginMngr::CPlugin* CPluginMngr::findPlugin(int index)
{ {
CPlugin*a = head; CPlugin*a = head;
while (a && index--) while (a && index--)
a = a->next; a = a->next;
return a; return a;
} }
CPluginMngr::CPlugin* CPluginMngr::findPlugin(const char* name) CPluginMngr::CPlugin* CPluginMngr::findPlugin(const char* name)
{ {
if (!name) if (!name)
return 0; return 0;
int len = strlen(name); int len = strlen(name);
if (!len) if (!len)
return 0; return 0;
CPlugin*a = head; CPlugin*a = head;
while (a && strncmp(a->name.chars(), name, len)) while (a && strncmp(a->name.c_str(), name, len))
a = a->next; a = a->next;
return a; return a;
} }
void CPluginMngr::CPlugin::AddToFailCounter(unsigned int i)
{
failcounter += i;
if ((failcounter >= 3)
&& (status ))
{
errorMsg = "This plugin is non-GPL which violates AMX Mod X's license.";
status = ps_bad_load;
}
}
const char* CPluginMngr::CPlugin::getStatus() const const char* CPluginMngr::CPlugin::getStatus() const
{ {
switch (status) switch (status)
{ {
case ps_running: case ps_running:
{ {
if (m_Debug) if (m_Debug)
{ {
@ -295,43 +206,41 @@ const char* CPluginMngr::CPlugin::getStatus() const
case ps_stopped: return "stopped"; case ps_stopped: return "stopped";
case ps_locked: return "locked"; case ps_locked: return "locked";
} }
return "error"; return "error";
} }
CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, size_t m, int d) : name(n), title(n), m_pNullStringOfs(nullptr), m_pNullVectorOfs(nullptr) CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, int d) : name(n), title(n)
{ {
const char* unk = "unknown"; const char* unk = "unknown";
failcounter = 0; title.assign(unk);
title = unk; author.assign(unk);
author = unk; version.assign(unk);
version = unk;
url = unk; char file[256];
char* path = build_pathname_r(file, sizeof(file) - 1, "%s/%s", p, n);
char file[PLATFORM_MAX_PATH];
char* path = build_pathname_r(file, sizeof(file), "%s/%s", p, n);
code = 0; code = 0;
memset(&amx, 0, sizeof(AMX)); memset(&amx, 0, sizeof(AMX));
int err = load_amxscript_ex(&amx, &code, path, e, m, d); int err = load_amxscript(&amx, &code, path, e, d);
if (err == AMX_ERR_NONE) if (err == AMX_ERR_NONE)
{ {
status = ps_running; status = ps_running;
} else { } else {
status = ps_bad_load; status = ps_bad_load;
} }
amx.userdata[UD_FINDPLUGIN] = this; amx.userdata[UD_FINDPLUGIN] = this;
paused_fun = 0; paused_fun = 0;
next = 0; next = 0;
id = i; id = i;
if (status == ps_running) if (status == ps_running)
{ {
m_PauseFwd = registerSPForwardByName(&amx, "plugin_pause", FP_DONE); m_PauseFwd = registerSPForwardByName(&amx, "plugin_pause");
m_UnpauseFwd = registerSPForwardByName(&amx, "plugin_unpause", FP_DONE); m_UnpauseFwd = registerSPForwardByName(&amx, "plugin_unpause");
if (amx.flags & AMX_FLAG_DEBUG) if (amx.flags & AMX_FLAG_DEBUG)
{ {
m_Debug = true; m_Debug = true;
@ -401,22 +310,22 @@ void CPluginMngr::CPlugin::Finalize()
{ {
char buffer[128]; char buffer[128];
int old_status = status; int old_status = status;
if (CheckModules(&amx, buffer)) if (CheckModules(&amx, buffer))
{ {
if (amx_Register(&amx, core_Natives, -1) != AMX_ERR_NONE) if (amx_Register(&amx, core_Natives, -1) != AMX_ERR_NONE)
{ {
Handler *pHandler = (Handler *)amx.userdata[UD_HANDLER]; Handler *pHandler = (Handler *)amx.userdata[UD_HANDLER];
int res = 0; int res = 0;
if (pHandler->IsNativeFiltering()) if (pHandler->IsNativeFiltering())
res = amx_CheckNatives(&amx, native_handler); res = amx_CheckNatives(&amx, native_handler);
if (!res) if (!res)
{ {
status = ps_bad_load; status = ps_bad_load;
sprintf(buffer, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function); sprintf(buffer, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function);
errorMsg = buffer; errorMsg.assign(buffer);
amx.error = AMX_ERR_NOTFOUND; amx.error = AMX_ERR_NOTFOUND;
} else { } else {
amx_RegisterToAny(&amx, invalid_native); amx_RegisterToAny(&amx, invalid_native);
@ -424,18 +333,18 @@ void CPluginMngr::CPlugin::Finalize()
} }
} else { } else {
status = ps_bad_load; status = ps_bad_load;
errorMsg = buffer; errorMsg.assign(buffer);
amx.error = AMX_ERR_NOTFOUND; amx.error = AMX_ERR_NOTFOUND;
} }
if (old_status != status) if (old_status != status)
{ {
AMXXLOG_Log("[AMXX] Plugin \"%s\" failed to load: %s", name.chars(), errorMsg.chars()); AMXXLOG_Log("[AMXX] Plugin \"%s\" failed to load: %s", name.c_str(), errorMsg.c_str());
} }
} }
void CPluginMngr::CPlugin::pauseFunction(int id) void CPluginMngr::CPlugin::pauseFunction(int id)
{ {
} }
void CPluginMngr::CPlugin::unpauseFunction(int id) void CPluginMngr::CPlugin::unpauseFunction(int id)
@ -443,8 +352,8 @@ void CPluginMngr::CPlugin::unpauseFunction(int id)
} }
void CPluginMngr::CPlugin::setStatus(int a) void CPluginMngr::CPlugin::setStatus(int a)
{ {
status = a; status = a;
g_commands.clearBufforedInfo(); // ugly way g_commands.clearBufforedInfo(); // ugly way
} }
@ -456,7 +365,7 @@ void CPluginMngr::CPlugin::pausePlugin()
// call plugin_pause if provided // call plugin_pause if provided
if (m_PauseFwd != -1) if (m_PauseFwd != -1)
executeForwards(m_PauseFwd); executeForwards(m_PauseFwd);
setStatus(ps_paused); setStatus(ps_paused);
} }
} }
@ -464,330 +373,13 @@ void CPluginMngr::CPlugin::pausePlugin()
// Unpause a plugin // Unpause a plugin
void CPluginMngr::CPlugin::unpausePlugin() void CPluginMngr::CPlugin::unpausePlugin()
{ {
if (isValid() && (getStatusCode() != ps_stopped)) if (isValid())
{ {
// set status first so the function will be marked executable // set status first so the function will be marked executable
setStatus(ps_running); setStatus(ps_running);
// call plugin_unpause if provided // call plugin_unpause if provided
if (m_UnpauseFwd != -1) if (m_UnpauseFwd != -1)
{
executeForwards(m_UnpauseFwd); executeForwards(m_UnpauseFwd);
}
} }
} }
void CPluginMngr::CPlugin::AddConfig(bool create, const char *name, const char *folder)
{
// Do a check for duplicates to prevent double-execution
for (size_t i = 0; i < m_configs.length(); ++i)
{
AutoConfig *config = m_configs[i];
if (config->autocfg.compare(name) == 0 && config->folder.compare(folder) == 0)
{
if (!config->create)
{
config->create = create;
}
return;
}
}
auto c = new AutoConfig;
c->autocfg = name;
c->folder = folder;
c->create = create;
m_configs.append(c);
}
size_t CPluginMngr::CPlugin::GetConfigCount()
{
return m_configs.length();
}
AutoConfig *CPluginMngr::CPlugin::GetConfig(size_t i)
{
if (i >= GetConfigCount())
{
return nullptr;
}
return m_configs[i];
}
char *CPluginMngr::ReadIntoOrFromCache(const char *file, size_t &bufsize)
{
List<plcache_entry *>::iterator iter;
plcache_entry *pl;
for (iter=m_plcache.begin(); iter!=m_plcache.end(); iter++)
{
pl = (*iter);
if (pl->path.compare(file) == 0)
{
bufsize = pl->bufsize;
return pl->buffer;
}
}
pl = new plcache_entry;
pl->file = new CAmxxReader(file, sizeof(cell));
pl->buffer = NULL;
if (pl->file->GetStatus() != CAmxxReader::Err_None)
{
delete pl->file;
delete pl;
return NULL;
}
pl->bufsize = pl->file->GetBufferSize();
if (pl->bufsize)
{
pl->buffer = new char[pl->bufsize];
pl->file->GetSection(pl->buffer);
}
if (!pl->buffer || pl->file->GetStatus() != CAmxxReader::Err_None)
{
delete [] pl->buffer;
delete pl->file;
delete pl;
return NULL;
}
pl->path = file;
bufsize = pl->bufsize;
m_plcache.push_back(pl);
return pl->buffer;
}
void CPluginMngr::InvalidateCache()
{
List<plcache_entry *>::iterator iter;
plcache_entry *pl;
for (iter=m_plcache.begin(); iter!=m_plcache.end(); iter++)
{
pl = (*iter);
delete [] pl->buffer;
delete pl->file;
delete pl;
}
m_plcache.clear();
}
void CPluginMngr::InvalidateFileInCache(const char *file, bool freebuf)
{
List<plcache_entry *>::iterator iter;
plcache_entry *pl;
for (iter=m_plcache.begin(); iter!=m_plcache.end(); iter++)
{
pl = (*iter);
if (pl->path.compare(file) == 0)
{
if (freebuf)
delete [] pl->buffer;
delete pl->file;
delete pl;
m_plcache.erase(iter);
return;
}
}
}
void CPluginMngr::CacheAndLoadModules(const char *plugin)
{
size_t progsize;
char *prog = ReadIntoOrFromCache(plugin, progsize);
if (!prog)
return;
AMX_HEADER hdr;
memcpy(&hdr, prog, sizeof(AMX_HEADER));
uint16_t magic = hdr.magic;
amx_Align16(&magic);
if (magic != AMX_MAGIC)
{
return;
}
if (hdr.file_version < MIN_FILE_VERSION ||
hdr.file_version > CUR_FILE_VERSION)
{
return;
}
if ((hdr.defsize != sizeof(AMX_FUNCSTUB)) &&
(hdr.defsize != sizeof(AMX_FUNCSTUBNT)))
{
return;
}
amx_Align32((uint32_t*)&hdr.nametable);
uint16_t *namelength=(uint16_t*)((unsigned char*)prog + (unsigned)hdr.nametable);
amx_Align16(namelength);
if (*namelength>sNAMEMAX)
{
return;
}
if (hdr.stp <= 0)
{
return;
}
AMX amx;
memset(&amx, 0, sizeof(AMX));
amx.base = (unsigned char *)prog;
int num;
char name[sNAMEMAX+1];
num = amx_GetLibraries(&amx);
for (int i=0; i<num; i++)
{
amx_GetLibrary(&amx, i, name, sNAMEMAX);
if (stricmp(name, "Float")==0)
continue;
//awful backwards compat hack
if (stricmp(name, "socket")==0)
strcpy(name, "sockets");
//we don't want to report failed modules here...
LoadModule(name, PT_ANYTIME, true, true);
}
cell tag_id;
amx_NumTags(&amx, &num);
ke::Vector<LibDecoder *> expects;
ke::Vector<LibDecoder *> defaults;
CStack<LibDecoder *> delstack;
for (int i=0; i<num; i++)
{
amx_GetTag(&amx, i, name, &tag_id);
if (name[0] == '?')
{
LibDecoder *dc = new LibDecoder;
delstack.push(dc);
if (DecodeLibCmdString(name, dc))
{
if (dc->cmd == LibCmd_ForceLib)
{
RunLibCommand(dc);
} else if ( (dc->cmd == LibCmd_ExpectClass) ||
(dc->cmd == LibCmd_ExpectLib) )
{
expects.append(dc);
} else if (dc->cmd == LibCmd_DefaultLib) {
defaults.append(dc);
}
}
}
}
for (size_t i=0; i<expects.length(); i++)
{
RunLibCommand(expects[i]);
}
for (size_t i=0; i<defaults.length(); i++)
{
RunLibCommand(defaults[i]);
}
expects.clear();
defaults.clear();
while (!delstack.empty())
{
delete delstack.front();
delstack.pop();
}
return;
}
void CPluginMngr::CALMFromFile(const char *file)
{
char filename[PLATFORM_MAX_PATH];
FILE *fp = fopen(build_pathname_r(filename, sizeof(filename), "%s", file), "rt");
if (!fp)
{
return;
}
// Find now folder
char pluginName[256];
char line[256];
char rline[256];
while (!feof(fp))
{
fgets(line, sizeof(line)-1, fp);
if (line[0] == ';' || line[0] == '\n' || line[0] == '\0')
{
continue;
}
/** quick hack */
char *ptr = line;
while (*ptr)
{
if (*ptr == ';')
{
*ptr = '\0';
} else {
ptr++;
}
}
strncopy(rline, line, sizeof(rline));
UTIL_TrimLeft(rline);
UTIL_TrimRight(rline);
pluginName[0] = '\0';
sscanf(rline, "%s", pluginName);
/* HACK: see if there's a 'disabled' coming up
* new block for scopying flexibility
*/
if (1)
{
const char *_ptr = rline + strlen(pluginName);
while (*_ptr != '\0' && isspace(*_ptr))
{
_ptr++;
}
if ((*_ptr != '\0') && !strcmp(_ptr, "disabled"))
{
ke::AString *pString = new ke::AString(pluginName);
m_BlockList.push_back(pString);
continue;
}
}
if (!isalnum(*pluginName))
{
continue;
}
build_pathname_r(filename, sizeof(filename), "%s/%s", get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins"), pluginName);
CacheAndLoadModules(filename);
}
fclose(fp);
}

View File

@ -1,22 +1,37 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef PLUGIN_H #ifndef PLUGIN_H
#define PLUGIN_H #define PLUGIN_H
#include "sh_list.h"
#include "amx.h"
#include "amxxfile.h"
#include <amtl/am-string.h>
#include <amtl/am-vector.h>
#include <amtl/am-autoptr.h>
// ***************************************************** // *****************************************************
// class CPluginMngr // class CPluginMngr
// ***************************************************** // *****************************************************
@ -31,13 +46,6 @@ enum
ps_running, //Plugin is running ps_running, //Plugin is running
}; };
struct AutoConfig
{
ke::AString autocfg;
ke::AString folder;
bool create;
};
class CPluginMngr class CPluginMngr
{ {
public: public:
@ -52,15 +60,12 @@ public:
AMX amx; AMX amx;
void* code; void* code;
ke::AString name; String name;
ke::AString version; String version;
ke::AString title; String title;
ke::AString author; String author;
ke::AString url; String errorMsg;
ke::AString description;
ke::AString errorMsg;
unsigned int failcounter;
int m_PauseFwd; int m_PauseFwd;
int m_UnpauseFwd; int m_UnpauseFwd;
int paused_fun; int paused_fun;
@ -68,38 +73,29 @@ public:
CPlugin* next; CPlugin* next;
int id; int id;
CPlugin(int i, const char* p, const char* n, char* e, size_t m, int d); CPlugin(int i, const char* p, const char* n, char* e, int d);
~CPlugin(); ~CPlugin();
bool m_Debug; bool m_Debug;
cell* m_pNullStringOfs;
cell* m_pNullVectorOfs;
ke::Vector<ke::AutoPtr<AutoConfig>> m_configs;
public: public:
inline const char* getName() { return name.chars();} inline const char* getName() { return name.c_str();}
inline const char* getVersion() { return version.chars();} inline const char* getVersion() { return version.c_str();}
inline const char* getTitle() { return title.chars();} inline const char* getTitle() { return title.c_str();}
inline const char* getAuthor() { return author.chars();} inline const char* getAuthor() { return author.c_str();}
inline const char* getUrl() { return url.chars(); } inline const char* getError() { return errorMsg.c_str();}
inline const char* getDescription() { return description.chars(); }
inline const char* getError() { return errorMsg.chars();}
inline int getStatusCode() { return status; } inline int getStatusCode() { return status; }
inline int getId() const { return id; } inline int getId() const { return id; }
inline AMX* getAMX() { return &amx; } inline AMX* getAMX() { return &amx; }
inline const AMX* getAMX() const { return &amx; } inline const AMX* getAMX() const { return &amx; }
inline void setTitle(const char* n) { title = n; } inline void setTitle(const char* n) { title.assign(n); }
inline void setAuthor(const char* n) { author =n; } inline void setAuthor(const char* n) { author.assign(n); }
inline void setVersion(const char* n) { version = n; } inline void setVersion(const char* n) { version.assign(n); }
inline void setUrl(const char* n) { url = n; } inline void setError(const char* n) { errorMsg.assign(n); }
inline void setDescription(const char* n) { description = n; }
inline void setError(const char* n) { errorMsg = n; }
inline bool isValid() const { return (status >= ps_paused); } inline bool isValid() const { return (status >= ps_paused); }
inline bool isPaused() const { return ((status == ps_paused) || (status == ps_stopped)); } inline bool isPaused() const { return ((status == ps_paused) || (status == ps_stopped)); }
inline bool isStopped() const { return (status == ps_stopped); }
inline bool isExecutable(int id) const { return (isValid() && !isPaused()); } inline bool isExecutable(int id) const { return (isValid() && !isPaused()); }
void Finalize(); void Finalize();
void AddToFailCounter(unsigned int i);
void pausePlugin(); void pausePlugin();
void unpausePlugin(); void unpausePlugin();
void pauseFunction(int id); void pauseFunction(int id);
@ -108,12 +104,6 @@ public:
const char* getStatus() const; const char* getStatus() const;
inline bool isDebug() const { return m_Debug; } inline bool isDebug() const { return m_Debug; }
inline cell* getNullStringOfs() const { return m_pNullStringOfs; }
inline cell* getNullVectorOfs() const { return m_pNullVectorOfs; }
public:
void AddConfig(bool create, const char *name, const char *folder);
size_t GetConfigCount();
AutoConfig *GetConfig(size_t index);
}; };
private: private:
@ -121,16 +111,16 @@ private:
int pCounter; int pCounter;
public: public:
CPluginMngr() { head = 0; pCounter = 0; pNatives = NULL; m_Finalized=false;} CPluginMngr() { head = 0; pCounter = 0; pNatives = NULL; m_Finalized=false;}
~CPluginMngr() { clear(); InvalidateCache(); } ~CPluginMngr() { clear(); }
bool m_Finalized; bool m_Finalized;
AMX_NATIVE_INFO *pNatives; AMX_NATIVE_INFO *pNatives;
// Interface // Interface
CPlugin* loadPlugin(const char* path, const char* name, char* error, size_t maxLength, int debug); CPlugin* loadPlugin(const char* path, const char* name, char* error, int debug);
void unloadPlugin(CPlugin** a); void unloadPlugin(CPlugin** a);
int loadPluginsFromFile(const char* filename, bool warn=true); int loadPluginsFromFile(const char* filename);
inline CPlugin* findPluginFast(AMX *amx) { return (CPlugin*)(amx->userdata[UD_FINDPLUGIN]); } inline CPlugin* findPluginFast(AMX *amx) { return (CPlugin*)(amx->userdata[UD_FINDPLUGIN]); }
CPlugin* findPlugin(AMX *amx); CPlugin* findPlugin(AMX *amx);
@ -155,22 +145,6 @@ public:
inline iterator begin() const { return iterator(head); } inline iterator begin() const { return iterator(head); }
inline iterator end() const { return iterator(0); } inline iterator end() const { return iterator(0); }
public:
struct plcache_entry
{
CAmxxReader *file;
size_t bufsize;
char *buffer;
ke::AString path;
};
char *ReadIntoOrFromCache(const char *file, size_t &bufsize);
void InvalidateCache();
void InvalidateFileInCache(const char *file, bool freebuf);
void CacheAndLoadModules(const char *plugin);
void CALMFromFile(const char *file);
private:
List<plcache_entry *> m_plcache;
List<ke::AString *> m_BlockList;
}; };
#endif //PLUGIN_H #endif //PLUGIN_H

129
amxmodx/CQueue.h Executable file
View File

@ -0,0 +1,129 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
//by David "BAILOPAN" Anderson
#ifndef _INCLUDE_CQUEUE_H
#define _INCLUDE_CQUEUE_H
template <class T>
class CQueue
{
public:
class CQueueItem
{
public:
CQueueItem(const T &i, CQueueItem *n)
{
item = i;
next = n;
}
CQueueItem *GetNext()
{
return next;
}
T & GetItem()
{
return item;
}
void SetNext(CQueueItem *n)
{
next = n;
}
private:
T item;
CQueueItem *next;
};
public:
CQueue()
{
mSize = 0;
mFirst = NULL;
mLast = NULL;
}
bool empty()
{
return ((mSize == 0) ? true : false);
}
void push(const T &v)
{
CQueueItem *p = new CQueueItem(v, NULL);
if (empty())
{
mFirst = p;
} else {
mLast->SetNext(p);
}
mLast = p;
mSize++;
}
void pop()
{
if (mFirst == mLast)
{
delete mFirst;
mFirst = NULL;
mLast = NULL;
} else {
CQueueItem *p = mFirst->GetNext();
delete mFirst;
mFirst = p;
}
mSize--;
}
T & front()
{
return mFirst->GetItem();
}
T & back()
{
return mLast->GetItem();
}
unsigned int size()
{
return mSize;
}
private:
CQueueItem *mFirst;
CQueueItem *mLast;
unsigned int mSize;
};
#endif //_INCLUDE_CQUEUE_H

413
amxmodx/CString.h Executable file
View File

@ -0,0 +1,413 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef _INCLUDE_CSTRING_H
#define _INCLUDE_CSTRING_H
#include <string.h>
#include <stdio.h>
//by David "BAILOPAN" Anderson
class String
{
public:
String()
{
v = NULL;
a_size = 0;
//assign("");
}
~String()
{
if (v)
delete [] v;
}
String(const char *src)
{
v = NULL;
a_size = 0;
assign(src);
}
const char * _fread(FILE *fp)
{
Grow(512, false);
char *ret = fgets(v, 511, fp);
return ret;
}
String(const String &src)
{
v = NULL;
a_size = 0;
assign(src.c_str());
}
const char *c_str() { return v?v:""; }
const char *c_str() const { return v?v:""; }
void append(const char *t)
{
Grow(size() + strlen(t) + 1);
strcat(v, t);
}
void append(const char c)
{
size_t len = size();
Grow(len + 2);
v[len] = c;
v[len + 1] = '\0';
}
void append(String &d)
{
append(d.c_str());
}
void assign(const String &src)
{
assign(src.c_str());
}
void assign(const char *d)
{
if (!d)
{
clear();
} else {
size_t len = strlen(d);
Grow(len + 1, false);
memcpy(v, d, len);
v[len] = '\0';
}
}
void clear()
{
if (v)
v[0] = '\0';
}
int compare (const char *d) const
{
if (!v)
return strcmp("", d);
else
return strcmp(v, d);
}
//Added this for amxx inclusion
bool empty()
{
if (!v)
return true;
if (v[0] == '\0')
return true;
return false;
}
size_t size()
{
if (v)
return strlen(v);
else
return 0;
}
int find(const char c, int index = 0)
{
int len = static_cast<int>(size());
if (len < 1)
return npos;
if (index >= len || index < 0)
return npos;
int i = 0;
for (i=index; i<len; i++)
{
if (v[i] == c)
{
return i;
}
}
return npos;
}
bool is_space(int c)
{
if (c == '\f' || c == '\n' ||
c == '\t' || c == '\r' ||
c == '\v' || c == ' ')
{
return true;
}
return false;
}
void reparse_newlines()
{
size_t len = size();
int offs = 0;
char c;
if (!len)
return;
for (size_t i=0; i<len; i++)
{
c = v[i];
if (c == '^' && (i != len-1))
{
c = v[++i];
if (c == 'n')
c = '\n';
else if (c == 't')
c = '\t';
offs++;
}
v[i-offs] = c;
}
v[len-offs] = '\0';
}
void trim()
{
if (!v)
return;
unsigned int i = 0;
unsigned int j = 0;
size_t len = strlen(v);
if (len == 1)
{
if (is_space(v[i]))
{
clear();
return;
}
}
unsigned char c0 = v[0];
if (is_space(c0))
{
for (i=0; i<len; i++)
{
if (!is_space(v[i]) || (is_space(v[i]) && ((unsigned char)i==len-1)))
{
erase(0, i);
break;
}
}
}
len = strlen(v);
if (len < 1)
{
return;
}
if (is_space(v[len-1]))
{
for (i=len-1; i>=0; i--)
{
if (!is_space(v[i])
|| (is_space(v[i]) && i==0))
{
erase(i+1, j);
break;
}
j++;
}
}
if (len == 1)
{
if (is_space(v[0]))
{
clear();
return;
}
}
}
void erase(unsigned int start, int num = npos)
{
if (!v)
return;
unsigned int i = 0;
size_t len = size();
//check for bounds
if (num == npos || start+num > len-start)
num = len - start;
//do the erasing
bool copyflag = false;
for (i=0; i<len; i++)
{
if (i>=start && i<start+num)
{
if (i+num < len)
{
v[i] = v[i+num];
} else {
v[i] = 0;
}
copyflag = true;
} else if (copyflag) {
if (i+num < len)
{
v[i] = v[i+num];
} else {
v[i] = 0;
}
}
}
len -= num;
v[len] = 0;
}
String substr(unsigned int index, int num = npos)
{
if (!v)
{
String b("");
return b;
}
String ns;
size_t len = size();
if (index >= len || !v)
return ns;
if (num == npos)
{
num = len - index;
} else if (index+num >= len) {
num = len - index;
}
unsigned int i = 0;
unsigned int nslen = num + 2;
ns.Grow(nslen);
for (i=index; i<index+num; i++)
ns.append(v[i]);
return ns;
}
void toLower()
{
if (!v)
return;
unsigned int i = 0;
size_t len = strlen(v);
for (i=0; i<len; i++)
{
if (v[i] >= 65 && v[i] <= 90)
v[i] &= ~(1<<5);
}
}
String & operator = (const String &src)
{
assign(src);
return *this;
}
String & operator = (const char *src)
{
assign(src);
return *this;
}
char operator [] (unsigned int index)
{
if (index > size() || !v)
{
return -1;
} else {
return v[index];
}
}
int at(int a)
{
if (a < 0 || a >= (int)size() || !v)
return -1;
return v[a];
}
bool at(int at, char c)
{
if (at < 0 || at >= (int)size() || !v)
return false;
v[at] = c;
return true;
}
private:
void Grow(unsigned int d, bool copy=true)
{
if (d <= a_size)
return;
char *n = new char[d + 1];
if (copy && v)
strcpy(n, v);
if (v)
delete [] v;
else
strcpy(n, "");
v = n;
a_size = d + 1;
}
char *v;
unsigned int a_size;
public:
static const int npos = -1;
};
#endif //_INCLUDE_CSTRING_H

View File

@ -1,17 +1,49 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "CTask.h" #include "CTask.h"
/*********************** CTask ***********************/ /*********************** CTask ***********************/
int CTaskMngr::CTask::getTaskId() const
{
return m_iId;
}
CPluginMngr::CPlugin *CTaskMngr::CTask::getPlugin() const
{
return m_pPlugin;
}
void CTaskMngr::CTask::set(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, cell iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat, float fCurrentTime) void CTaskMngr::CTask::set(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, cell iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat, float fCurrentTime)
{ {
clear(); clear();
@ -21,7 +53,6 @@ void CTaskMngr::CTask::set(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags,
m_iFunc = iFunc; m_iFunc = iFunc;
m_iId = iId; m_iId = iId;
m_fBase = fBase; m_fBase = fBase;
m_bInExecute = false;
if (iFlags & 2) if (iFlags & 2)
{ {
@ -91,9 +122,7 @@ void CTaskMngr::CTask::changeBase(float fNewBase)
void CTaskMngr::CTask::resetNextExecTime(float fCurrentTime) void CTaskMngr::CTask::resetNextExecTime(float fCurrentTime)
{ {
// If we're here while we're executing we would add m_fBase twice m_fNextExecTime = fCurrentTime + m_fBase;
if (!m_bInExecute)
m_fNextExecTime = fCurrentTime + m_fBase;
} }
void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft) void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft)
@ -121,7 +150,6 @@ void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, f
//only bother calling if we have something to call //only bother calling if we have something to call
if (!(m_bLoop && !m_iRepeat)) if (!(m_bLoop && !m_iRepeat))
{ {
m_bInExecute = true;
if (m_iParamLen) // call with parameters if (m_iParamLen) // call with parameters
{ {
cell arr = prepareCellArray(m_pParams, m_iParamLen); cell arr = prepareCellArray(m_pParams, m_iParamLen);
@ -129,7 +157,6 @@ void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, f
} else { } else {
executeForwards(m_iFunc, m_iId); executeForwards(m_iFunc, m_iId);
} }
m_bInExecute = false;
} }
if (isFree()) if (isFree())
@ -166,7 +193,6 @@ CTaskMngr::CTask::CTask()
m_bLoop = false; m_bLoop = false;
m_bAfterStart = false; m_bAfterStart = false;
m_bBeforeEnd = false; m_bBeforeEnd = false;
m_bInExecute = false;
m_fNextExecTime = 0.0f; m_fNextExecTime = 0.0f;
@ -203,36 +229,35 @@ void CTaskMngr::registerTimers(float *pCurrentTime, float *pTimeLimit, float *pT
void CTaskMngr::registerTask(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, cell iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat) void CTaskMngr::registerTask(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, cell iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat)
{ {
// first, search for free tasks // first, search for free tasks
for (auto &task : m_Tasks) TaskListIter iter = m_Tasks.find(CTaskDescriptor(0, NULL, true));
if (iter)
{ {
if (task->isFree() && !task->inExecute()) // found: reuse it
{ iter->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
// found: reuse it } else {
task->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime); // not found: make a new one
CTask *pTmp = new CTask;
if (!pTmp)
return; return;
}
pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
m_Tasks.put(pTmp);
} }
// not found: make a new one
auto task = ke::AutoPtr<CTask>(new CTask);
if (!task)
return;
task->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
m_Tasks.append(ke::Move(task));
} }
int CTaskMngr::removeTasks(int iId, AMX *pAmx) int CTaskMngr::removeTasks(int iId, AMX *pAmx)
{ {
CTaskDescriptor descriptor(iId, pAmx);
TaskListIter iter = m_Tasks.find(descriptor);
int i = 0; int i = 0;
for (auto &task : m_Tasks) while (iter)
{ {
if (task->match(iId, pAmx)) iter->clear();
{ ++i;
task->clear(); iter = m_Tasks.find(++iter, descriptor);
++i;
}
} }
return i; return i;
@ -240,16 +265,16 @@ int CTaskMngr::removeTasks(int iId, AMX *pAmx)
int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase) int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
{ {
CTaskDescriptor descriptor(iId, pAmx);
TaskListIter iter = m_Tasks.find(descriptor);
int i = 0; int i = 0;
for (auto &task : m_Tasks) while (iter)
{ {
if (task->match(iId, pAmx)) iter->changeBase(fNewBase);
{ iter->resetNextExecTime(*m_pTmr_CurrentTime);
task->changeBase(fNewBase); ++i;
task->resetNextExecTime(*m_pTmr_CurrentTime); iter = m_Tasks.find(++iter, descriptor);
++i;
}
} }
return i; return i;
@ -257,26 +282,16 @@ int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
bool CTaskMngr::taskExists(int iId, AMX *pAmx) bool CTaskMngr::taskExists(int iId, AMX *pAmx)
{ {
for (auto &task : m_Tasks) return m_Tasks.find(CTaskDescriptor(iId, pAmx));
{
if (task->match(iId, pAmx))
{
return true;
}
}
return false;
} }
void CTaskMngr::startFrame() void CTaskMngr::startFrame()
{ {
auto lastSize = m_Tasks.length(); for (TaskListIter iter = m_Tasks.begin(); iter; ++iter)
for(auto i = 0u; i < lastSize; i++)
{ {
auto &task = m_Tasks[i]; if (iter->isFree())
if (task->isFree())
continue; continue;
task->executeIfRequired(*m_pTmr_CurrentTime, *m_pTmr_TimeLimit, *m_pTmr_TimeLeft); iter->executeIfRequired(*m_pTmr_CurrentTime, *m_pTmr_TimeLimit, *m_pTmr_TimeLeft);
} }
} }

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef CTASK_H #ifndef CTASK_H
#define CTASK_H #define CTASK_H
@ -23,7 +45,6 @@ private:
int m_iFunc; int m_iFunc;
int m_iRepeat; int m_iRepeat;
bool m_bInExecute;
bool m_bLoop; bool m_bLoop;
bool m_bAfterStart; bool m_bAfterStart;
bool m_bBeforeEnd; bool m_bBeforeEnd;
@ -40,29 +61,48 @@ private:
void clear(); void clear();
bool isFree() const; bool isFree() const;
inline CPluginMngr::CPlugin *getPlugin() const { return m_pPlugin; } CPluginMngr::CPlugin *getPlugin() const;
inline AMX *getAMX() const { return m_pPlugin->getAMX(); } int getTaskId() const;
inline int getTaskId() const { return m_iId; }
void executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft); // also removes the task if needed void executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft); // also removes the task if needed
void changeBase(float fNewBase); void changeBase(float fNewBase);
void resetNextExecTime(float fCurrentTime); void resetNextExecTime(float fCurrentTime);
inline bool inExecute() const { return m_bInExecute; }
bool shouldRepeat(); bool shouldRepeat();
inline bool match(int id, AMX *amx)
{
return (!m_bFree) && (amx ? getAMX() == amx : true) && (m_iId == id);
}
CTask(); CTask();
~CTask(); ~CTask();
}; };
class CTaskDescriptor
{
public:
cell m_iId;
AMX *m_pAmx;
bool m_bFree;
CTaskDescriptor(int iId, AMX *pAmx, bool bFree = false)
{
m_iId = iId;
m_pAmx = pAmx;
m_bFree = bFree;
}
friend bool operator == (const CTask &left, const CTaskDescriptor &right)
{
if (right.m_bFree)
return left.isFree();
return !left.isFree() && (right.m_pAmx ? left.getPlugin()->getAMX() == right.m_pAmx : true) && left.getTaskId() == right.m_iId;
}
};
/*** CTaskMngr priv members ***/ /*** CTaskMngr priv members ***/
ke::Vector<ke::AutoPtr<CTask>> m_Tasks; typedef CList<CTask, CTaskDescriptor> TaskList;
typedef TaskList::iterator TaskListIter;
TaskList m_Tasks;
float *m_pTmr_CurrentTime; float *m_pTmr_CurrentTime;
float *m_pTmr_TimeLimit; float *m_pTmr_TimeLimit;

File diff suppressed because it is too large Load Diff

View File

@ -1,89 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <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_TEXTPARSERS_H_
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
#include <ITextParsers.h>
#include <amtl/am-vector.h>
/**
* @param void * IN: Stream pointer
* @param char * IN/OUT: Stream buffer
* @param size_t IN: Maximum size of buffer
* @param unsigned int * OUT: Number of bytes read (0 = end of stream)
* @return True on success, false on failure
*/
typedef bool(*STREAMREADER)(void *, char *, size_t, unsigned int *);
class TextParsers : public ITextParsers
{
public:
TextParsers();
public:
bool ParseFile_INI(const char *file,
ITextListener_INI *ini_listener,
unsigned int *line,
unsigned int *col,
bool inline_comment);
SMCError ParseFile_SMC(const char *file,
ITextListener_SMC *smc_listener,
SMCStates *states);
SMCError ParseSMCFile(const char *file,
ITextListener_SMC *smc_listener,
SMCStates *states,
char *buffer,
size_t maxsize);
SMCError ParseSMCStream(const char *stream,
size_t length,
ITextListener_SMC *smc_listener,
SMCStates *states,
char *buffer,
size_t maxsize);
unsigned int GetUTF8CharBytes(const char *stream);
const char *GetSMCErrorString(SMCError err);
bool IsWhitespace(const char *stream);
private:
SMCError ParseStream_SMC(void *stream,
STREAMREADER srdr,
ITextListener_SMC *smc,
SMCStates *states);
};
extern TextParsers g_TextParser;
#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_H_

View File

@ -1,18 +1,40 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "amxmodx.h" #include "amxmodx.h"
#include "CVault.h" #include "CVault.h"
#include "CFileSystem.h" #include "CFile.h"
// ***************************************************** // *****************************************************
// class Vault // class Vault
@ -39,7 +61,7 @@ void Vault::put(const char* k, const char* v)
if (*a) if (*a)
{ {
(*a)->value = v; (*a)->value.assign(v);
(*a)->number = atoi(v); (*a)->number = atoi(v);
} }
else else
@ -57,7 +79,7 @@ Vault::Obj** Vault::find(const char* n)
while (*a) while (*a)
{ {
if (strcmp((*a)->key.chars(), n) == 0) if (strcmp((*a)->key.c_str(), n) == 0)
return a; return a;
a = &(*a)->next; a = &(*a)->next;
@ -86,7 +108,7 @@ const char* Vault::get(const char* n)
if (b == 0) return ""; if (b == 0) return "";
return b->value.chars(); return b->value.c_str();
} }
void Vault::clear() void Vault::clear()
@ -112,74 +134,45 @@ void Vault::remove(const char* n)
void Vault::setSource(const char* n) void Vault::setSource(const char* n)
{ {
path = n; path.assign(n);
} }
bool Vault::loadVault() bool Vault::loadVault()
{ {
if (!path.length()) if (path.empty()) return false;
{
return false;
}
clear(); clear();
FILE *fp = fopen(path.chars(), "r"); File a(path.c_str(), "r");
if (!fp) if (!a) return false;
const int sz = 512;
char value[sz + 1];
char key[sz + 1];
while (a >> key && a.skipWs() && a.getline(value, sz))
{ {
return false;
}
char lineRead[512];
char key[sizeof(lineRead) + 1];
char value[sizeof(lineRead) + 1];
while (fgets(lineRead, sizeof(lineRead), fp))
{
UTIL_TrimLeft(lineRead);
if (!*lineRead || *lineRead == ';')
{
continue;
}
sscanf(lineRead, "%s%*[ \t]%[^\n]", key, value);
if (isalpha(*key)) if (isalpha(*key))
{
put(key, value); put(key, value);
}
} }
fclose(fp);
return true; return true;
} }
bool Vault::saveVault() bool Vault::saveVault()
{ {
if (!path.length()) if (path.empty()) return false;
{
return false;
}
FILE *fp = fopen(path.chars(), "w"); File a(path.c_str(), "w");
if (!fp) if (!a) return false;
{
return false;
}
fputs("; Don't modify!\n", fp); a << "; Don't modify!" << '\n';
for (Obj* b = head; b; b = b->next) for (Obj* b = head; b; b = b->next)
{ a << b->key << '\t' << b->value << '\n';
fprintf(fp, "%s\t%s\n", b->key.chars(), b->value.chars());
}
fclose(fp);
return true; return true;
} }

View File

@ -1,15 +1,40 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef VAULT_CUSTOM_H #ifndef VAULT_CUSTOM_H
#define VAULT_CUSTOM_H #define VAULT_CUSTOM_H
#include "CString.h"
#include "CList.h"
// ***************************************************** // *****************************************************
// class Vault // class Vault
// ***************************************************** // *****************************************************
@ -18,15 +43,15 @@ class Vault
{ {
struct Obj struct Obj
{ {
ke::AString key; String key;
ke::AString value; String value;
int number; int number;
Obj *next; Obj *next;
Obj(const char* k, const char* v); Obj(const char* k, const char* v);
} *head; } *head;
ke::AString path; String path;
Obj** find(const char* n); Obj** find(const char* n);
@ -59,8 +84,8 @@ public:
iterator& operator++() { if (a) a = a->next; return *this; } iterator& operator++() { if (a) a = a->next; return *this; }
bool operator==(const iterator& b) const { return a == b.a; } bool operator==(const iterator& b) const { return a == b.a; }
bool operator!=(const iterator& b) const { return !operator==(b); } bool operator!=(const iterator& b) const { return !operator==(b); }
ke::AString& key() const { return a->key; } String& key() const { return a->key; }
ke::AString& value() const { return a->value; } String& value() const { return a->value; }
}; };
inline iterator begin() const { return iterator(head); } inline iterator begin() const { return iterator(head); }

491
amxmodx/CVector.h Executable file
View File

@ -0,0 +1,491 @@
/* AMX Mod X
*
* by the AMX Mod X Development Team
* originally developed by OLO
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef __CVECTOR_H__
#define __CVECTOR_H__
#include <assert.h>
// Vector
template <class T> class CVector
{
bool Grow()
{
// automatic grow
size_t newSize = m_Size * 2;
if (newSize == 0)
newSize = 8; // a good init value
T *newData = new T[newSize];
if (!newData)
return false;
if (m_Data)
{
for (size_t i=0; i<m_CurrentUsedSize; i++)
newData[i] = m_Data[i];
delete [] m_Data;
}
m_Data = newData;
m_Size = newSize;
return true;
}
bool GrowIfNeeded()
{
if (m_CurrentUsedSize >= m_Size)
return Grow();
else
return true;
}
bool ChangeSize(size_t size)
{
// change size
if (size == m_Size)
return true;
if (!size)
{
if (m_Data)
{
delete [] m_Data;
m_Data = NULL;
m_Size = 0;
}
return true;
}
T *newData = new T[size];
if (!newData)
return false;
if (m_Data)
{
size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
for (size_t i=0; i<end; i++)
newData[i] = m_Data[i];
delete [] m_Data;
}
m_Data = newData;
m_Size = size;
if (m_CurrentUsedSize > m_Size)
m_CurrentUsedSize = m_Size;
return true;
}
void FreeMemIfPossible()
{
if (!m_Data)
return;
if (!m_CurrentUsedSize)
{
ChangeSize(0);
return;
}
size_t newSize = m_Size;
while (m_CurrentUsedSize <= newSize / 2)
newSize /= 2;
if (newSize != m_Size)
ChangeSize(newSize);
}
protected:
T *m_Data;
size_t m_Size;
size_t m_CurrentUsedSize;
public:
class iterator
{
protected:
T *m_Ptr;
public:
// constructors / destructors
iterator()
{
m_Ptr = NULL;
}
iterator(T * ptr)
{
m_Ptr = ptr;
}
// member functions
T * base()
{
return m_Ptr;
}
const T * base() const
{
return m_Ptr;
}
// operators
T & operator*()
{
return *m_Ptr;
}
T * operator->()
{
return m_Ptr;
}
iterator & operator++() // preincrement
{
++m_Ptr;
return (*this);
}
iterator operator++(int) // postincrement
{
iterator tmp = *this;
++m_Ptr;
return tmp;
}
iterator & operator--() // predecrement
{
--m_Ptr;
return (*this);
}
iterator operator--(int) // postdecrememnt
{
iterator tmp = *this;
--m_Ptr;
return tmp;
}
bool operator==(T * right) const
{
return (m_Ptr == right);
}
bool operator==(const iterator & right) const
{
return (m_Ptr == right.m_Ptr);
}
bool operator!=(T * right) const
{
return (m_Ptr != right);
}
bool operator!=(const iterator & right) const
{
return (m_Ptr != right.m_Ptr);
}
iterator & operator+=(size_t offset)
{
m_Ptr += offset;
return (*this);
}
iterator & operator-=(size_t offset)
{
m_Ptr -= offset;
return (*this);
}
iterator operator+(size_t offset) const
{
iterator tmp(*this);
tmp.m_Ptr += offset;
return tmp;
}
iterator operator-(size_t offset) const
{
iterator tmp(*this);
tmp.m_Ptr -= offset;
return tmp;
}
T & operator[](size_t offset)
{
return (*(*this + offset));
}
const T & operator[](size_t offset) const
{
return (*(*this + offset));
}
bool operator<(const iterator & right) const
{
return m_Ptr < right.m_Ptr;
}
bool operator>(const iterator & right) const
{
return m_Ptr > right.m_Ptr;
}
bool operator<=(const iterator & right) const
{
return m_Ptr <= right.m_Ptr;
}
bool operator>=(const iterator & right) const
{
return m_Ptr >= right.m_Ptr;
}
size_t operator-(const iterator & right) const
{
return m_Ptr - right.m_Ptr;
}
};
// constructors / destructors
CVector<T>()
{
m_Size = 0;
m_CurrentUsedSize = 0;
m_Data = NULL;
}
CVector<T>(const CVector<T> & other)
{
// copy data
m_Data = new T [other.m_CurrentUsedSize];
m_Size = other.m_CurrentUsedSize;
m_CurrentUsedSize = other.m_CurrentUsedSize;
for (size_t i=0; i<other.m_CurrentUsedSize; i++)
m_Data[i] = other.m_Data[i];
}
~CVector<T>()
{
clear();
}
// interface
size_t size() const
{
return m_CurrentUsedSize;
}
size_t capacity() const
{
return m_Size;
}
iterator begin() const
{
return iterator(m_Data);
}
iterator end() const
{
return iterator(m_Data + m_CurrentUsedSize);
}
iterator iterAt(size_t pos)
{
if (pos > m_CurrentUsedSize)
assert(0);
return iterator(m_Data + pos);
}
bool reserve(size_t newSize)
{
if (newSize > m_Size)
return ChangeSize(newSize);
return true;
}
bool push_back(const T & elem)
{
++m_CurrentUsedSize;
if (!GrowIfNeeded())
{
--m_CurrentUsedSize;
return false;
}
m_Data[m_CurrentUsedSize - 1] = elem;
return true;
}
void pop_back()
{
--m_CurrentUsedSize;
if (m_CurrentUsedSize < 0)
m_CurrentUsedSize = 0;
FreeMemIfPossible();
}
bool resize(size_t newSize)
{
if (!ChangeSize(newSize))
return false;
m_CurrentUsedSize = newSize;
return true;
}
bool empty() const
{
return (m_CurrentUsedSize == 0);
}
T & at(size_t pos)
{
if (pos > m_CurrentUsedSize)
{
assert(0);
}
return m_Data[pos];
}
const T & at(size_t pos) const
{
if (pos > m_CurrentUsedSize)
{
assert(0);
}
return m_Data[pos];
}
T & operator[](size_t pos)
{
return at(pos);
}
const T & operator[](size_t pos) const
{
return at(pos);
}
T & front()
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[0];
}
const T & front() const
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[0];
}
T & back()
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[m_CurrentUsedSize - 1];
}
const T & back() const
{
if (m_CurrentUsedSize < 1)
{
assert(0);
}
return m_Data[m_CurrentUsedSize - 1];
}
iterator insert(iterator where, const T & value)
{
// validate iter
if (where < m_Data || where > (m_Data + m_CurrentUsedSize))
return iterator(0);
size_t ofs = where - begin();
++m_CurrentUsedSize;
if (!GrowIfNeeded())
{
--m_CurrentUsedSize;
return false;
}
where = begin() + ofs;
// Move subsequent entries
for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr)
*(ptr + 1) = *ptr;
*where.base() = value;
return where;
}
iterator erase(iterator where)
{
// validate iter
if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
return iterator(0);
size_t ofs = where - begin();
if (m_CurrentUsedSize > 1)
{
// move
T *theend = m_Data + m_CurrentUsedSize;
for (T *ptr = where.base() + 1; ptr < theend; ++ptr)
*(ptr - 1) = *ptr;
}
--m_CurrentUsedSize;
FreeMemIfPossible();
return begin() + ofs;
}
void clear()
{
m_Size = 0;
m_CurrentUsedSize = 0;
if (m_Data)
{
delete [] m_Data;
m_Data = NULL;
}
}
};
#endif // __CVECTOR_H__

View File

@ -1,340 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "amxmodx.h"
#include "CoreConfig.h"
#include "CLibrarySys.h"
#include <amxmodx_version.h>
CoreConfig CoreCfg;
const char *MainConfigFile = "amxx.cfg";
const char *AutoConfigDir = "/plugins";
const char *MapConfigDir = "/maps";
const char *CommandFormat = "exec %s\n";
CoreConfig::CoreConfig()
{
Clear();
}
CoreConfig::~CoreConfig()
{
}
void CoreConfig::OnAmxxInitialized()
{
m_ConfigsBufferedForward = registerForward("OnAutoConfigsBuffered", ET_IGNORE, FP_DONE);
m_ConfigsExecutedForward = registerForward("OnConfigsExecuted", ET_IGNORE, FP_DONE);
}
void CoreConfig::Clear()
{
m_ConfigsExecuted = false;
m_PendingForwardPush = false;
m_LegacyMainConfigExecuted = false;
m_LegacyMapConfigsExecuted = false,
m_legacyMapConfigNextTime = 0.0f;
}
void CoreConfig::ExecuteMainConfig()
{
if (m_LegacyMainConfigExecuted)
{
return;
}
char path[PLATFORM_MAX_PATH];
char command[PLATFORM_MAX_PATH + sizeof(CommandFormat)];
ke::SafeSprintf(path, sizeof(path), "%s/%s/%s", g_mod_name.chars(), get_localinfo("amxx_configsdir", "addons/amxmodx/configs"), MainConfigFile);
ke::SafeSprintf(command, sizeof(command), CommandFormat, path);
SERVER_COMMAND(command);
}
void CoreConfig::ExecuteAutoConfigs()
{
for (size_t i = 0; i < static_cast<size_t>(g_plugins.getPluginsNum()); ++i)
{
auto plugin = g_plugins.findPlugin(i);
bool can_create = true;
for (size_t j = 0; j < plugin->GetConfigCount(); ++j)
{
can_create = ExecuteAutoConfig(plugin, plugin->GetConfig(j), can_create);
}
}
executeForwards(m_ConfigsBufferedForward);
}
bool CoreConfig::ExecuteAutoConfig(CPluginMngr::CPlugin *plugin, AutoConfig *config, bool can_create)
{
bool will_create = false;
const char *configsDir = get_localinfo("amxx_configsdir", "addons/amxmodx/configs");
if (can_create && config->create)
{
will_create = true;
const char *folder = config->folder.chars();
char path[PLATFORM_MAX_PATH];
char build[PLATFORM_MAX_PATH];
build_pathname_r(path, sizeof(path), "%s%s/%s", configsDir, AutoConfigDir, folder);
if (!g_LibSys.IsPathDirectory(path))
{
char *cur_ptr = path;
g_LibSys.PathFormat(path, sizeof(path), "%s", folder);
build_pathname_r(build, sizeof(build), "%s%s", configsDir, AutoConfigDir);
size_t length = strlen(build);
do
{
char *next_ptr = cur_ptr;
while (*next_ptr != '\0')
{
if (*next_ptr == PLATFORM_SEP_CHAR)
{
*next_ptr = '\0';
next_ptr++;
break;
}
next_ptr++;
}
if (*next_ptr == '\0')
{
next_ptr = nullptr;
}
length += g_LibSys.PathFormat(&build[length], sizeof(build) - length, "/%s", cur_ptr);
if (!g_LibSys.CreateFolder(build))
{
break;
}
cur_ptr = next_ptr;
} while (cur_ptr);
}
}
char file[PLATFORM_MAX_PATH];
if (config->folder.length())
{
ke::SafeSprintf(file, sizeof(file), "%s/%s%s/%s/%s.cfg", g_mod_name.chars(), configsDir, AutoConfigDir, config->folder.chars(), config->autocfg.chars());
}
else
{
ke::SafeSprintf(file, sizeof(file), "%s/%s%s/%s.cfg", g_mod_name.chars(), configsDir, AutoConfigDir, config->autocfg.chars());
}
bool file_exists = g_LibSys.IsPathFile(file);
if (!file_exists && will_create)
{
auto list = g_CvarManager.GetCvarsList();
if (list->empty())
{
return can_create;
}
FILE *fp = fopen(file, "wt");
if (fp)
{
fprintf(fp, "// This file was auto-generated by AMX Mod X (v%s)\n", AMXX_VERSION);
if (*plugin->getTitle() && *plugin->getAuthor() && *plugin->getVersion())
{
fprintf(fp, "// Cvars for plugin \"%s\" by \"%s\" (%s, v%s)\n", plugin->getTitle(), plugin->getAuthor(), plugin->getName(), plugin->getVersion());
}
else
{
fprintf(fp, "// Cvars for plugin \"%s\"\n", plugin->getName());
}
fprintf(fp, "\n\n");
for (auto iter = list->begin(); iter != list->end(); iter++)
{
auto info = (*iter);
if (info->pluginId == plugin->getId())
{
char description[255];
char *ptr = description;
// Print comments until there is no more
strncopy(description, info->description.chars(), sizeof(description));
while (*ptr != '\0')
{
// Find the next line
char *next_ptr = ptr;
while (*next_ptr != '\0')
{
if (*next_ptr == '\n')
{
*next_ptr = '\0';
next_ptr++;
break;
}
next_ptr++;
}
fprintf(fp, "// %s\n", ptr);
ptr = next_ptr;
}
fprintf(fp, "// -\n");
fprintf(fp, "// Default: \"%s\"\n", info->defaultval.chars());
if (info->bound.hasMin)
{
fprintf(fp, "// Minimum: \"%02f\"\n", info->bound.minVal);
}
if (info->bound.hasMax)
{
fprintf(fp, "// Maximum: \"%02f\"\n", info->bound.maxVal);
}
fprintf(fp, "%s \"%s\"\n", info->var->name, info->defaultval.chars());
fprintf(fp, "\n");
}
}
fprintf(fp, "\n");
file_exists = true;
can_create = false;
fclose(fp);
}
else
{
AMXXLOG_Error("Failed to auto generate config for %s, make sure the directory has write permission.", plugin->getName());
return can_create;
}
}
if (file_exists)
{
char command[PLATFORM_MAX_PATH + sizeof(CommandFormat)];
ke::SafeSprintf(command, sizeof(command), CommandFormat, file);
SERVER_COMMAND(command);
}
return can_create;
}
void CoreConfig::ExecuteMapConfig()
{
const char *configsDir = get_localinfo("amxx_configsdir", "addons/amxmodx/configs");
char cfgPath[PLATFORM_MAX_PATH];
char mapName[PLATFORM_MAX_PATH];
char command[PLATFORM_MAX_PATH + sizeof(CommandFormat)];
strncopy(mapName, STRING(gpGlobals->mapname), sizeof(mapName));
char *mapPrefix;
if ((mapPrefix = strtok(mapName, "_")))
{
ke::SafeSprintf(cfgPath, sizeof(cfgPath), "%s/%s%s/prefix_%s.cfg", g_mod_name.chars(), configsDir, MapConfigDir, mapPrefix);
if (g_LibSys.IsPathFile(cfgPath))
{
ke::SafeSprintf(command, sizeof(command), CommandFormat, cfgPath);
SERVER_COMMAND(command);
}
}
strncopy(mapName, STRING(gpGlobals->mapname), sizeof(mapName));
ke::SafeSprintf(cfgPath, sizeof(cfgPath), "%s/%s%s/%s.cfg", g_mod_name.chars(), configsDir, MapConfigDir, mapName);
if (g_LibSys.IsPathFile(cfgPath))
{
ke::SafeSprintf(command, sizeof(command), CommandFormat, cfgPath);
SERVER_COMMAND(command);
}
// Consider all configs be executed to the next frame.
m_PendingForwardPush = true;
}
void CoreConfig::OnMapConfigTimer()
{
if (m_ConfigsExecuted)
{
return;
}
if (m_legacyMapConfigNextTime <= gpGlobals->time)
{
if (m_PendingForwardPush)
{
m_PendingForwardPush = false;
m_ConfigsExecuted = true;
executeForwards(m_ConfigsExecutedForward);
}
else if (!m_LegacyMapConfigsExecuted)
{
ExecuteMapConfig();
}
}
}
void CoreConfig::CheckLegacyBufferedCommand(char *command)
{
if (m_ConfigsExecuted)
{
return;
}
if (!m_LegacyMainConfigExecuted && strstr(command, MainConfigFile))
{
m_LegacyMainConfigExecuted = true;
}
if (!m_LegacyMapConfigsExecuted && strstr(command, MapConfigDir))
{
m_LegacyMapConfigsExecuted = true;
// Consider all configs be executed to m_legacyMapConfigNextTime time.
m_PendingForwardPush = true;
}
}
void CoreConfig::SetMapConfigTimer(float time)
{
m_legacyMapConfigNextTime = gpGlobals->time + time;
}

View File

@ -1,51 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _CORE_CONFIG_H_
#define _CORE_CONFIG_H_
#include "CPlugin.h"
class CoreConfig
{
public:
CoreConfig();
~CoreConfig();
public:
void Clear();
void ExecuteMainConfig();
void ExecuteAutoConfigs();
bool ExecuteAutoConfig(CPluginMngr::CPlugin *plugin, AutoConfig *config, bool can_create);
void ExecuteMapConfig();
void OnAmxxInitialized();
void OnMapConfigTimer();
void CheckLegacyBufferedCommand(char *command);
void SetMapConfigTimer(float time);
private:
bool m_ConfigsExecuted; // Whether all configs have been executed
bool m_PendingForwardPush; // Whether OnConfigsExecuted forward should be triggered to the next frame
bool m_LegacyMainConfigExecuted; // Whether the old admin.sma is used and amxx.cfg was executed from there
bool m_LegacyMapConfigsExecuted; // Whether the old admin.sma is used and per-map config was executed from there
float m_legacyMapConfigNextTime; // Sets the next time that per-map configs should be executed
int m_ConfigsBufferedForward;
int m_ConfigsExecutedForward;
};
extern CoreConfig CoreCfg;
#endif // _CORE_CONFIG_H_

View File

@ -1,669 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "CvarManager.h"
#include "amxmodx.h"
#include <CDetour/detours.h>
#include <auto-string.h>
#include <resdk/mod_rehlds_api.h>
CvarManager g_CvarManager;
void (*Cvar_DirectSet_Actual)(struct cvar_s* var, const char *value) = nullptr;
void Cvar_DirectSet_Custom(struct cvar_s *var, const char *value, IRehldsHook_Cvar_DirectSet *chain = nullptr)
{
CvarInfo* info = nullptr;
if (!var || !value // Sanity checks against bogus pointers.
|| strcmp(var->string, value) == 0 // Make sure old and new values are different to not trigger callbacks.
|| !g_CvarManager.CacheLookup(var->name, &info)) // No data in cache, nothing to do.
{
chain ? chain->callNext(var, value) : Cvar_DirectSet_Actual(var, value);
return;
}
if (info->bound.hasMin || info->bound.hasMax) // cvar_s doesn't have min/max mechanism, so we check things here.
{
float fvalue = atof(value);
bool oob = false;
if (info->bound.hasMin && fvalue < info->bound.minVal)
{
oob = true;
fvalue = info->bound.minVal;
}
else if (info->bound.hasMax && fvalue > info->bound.maxVal)
{
oob = true;
fvalue = info->bound.maxVal;
}
if (oob) // Found value out of bound, set new value and block original call.
{
CVAR_SET_FLOAT(var->name, fvalue);
return;
}
}
ke::AString oldValue; // We save old value since it will be likely changed after original function called.
if (!info->hooks.empty())
{
oldValue = var->string;
}
chain ? chain->callNext(var, value) : Cvar_DirectSet_Actual(var, value);
if (!info->binds.empty())
{
for (size_t i = 0; i < info->binds.length(); ++i)
{
CvarBind* bind = info->binds[i];
switch (bind->type)
{
case CvarBind::CvarType_Int:
{
*bind->varAddress = atoi(var->string);
break;
}
case CvarBind::CvarType_Float:
{
float fvalue = atof(var->string);
*bind->varAddress = amx_ftoc(fvalue);
break;
}
case CvarBind::CvarType_String:
{
set_amxstring_simple(bind->varAddress, var->string, bind->varLength);
break;
}
}
}
}
if (!info->hooks.empty())
{
for (size_t i = 0; i < info->hooks.length(); ++i)
{
CvarHook* hook = info->hooks[i];
if (hook->forward->state == AutoForward::FSTATE_OK) // Our callback can be enable/disabled by natives.
{
executeForwards(hook->forward->id, reinterpret_cast<cvar_t*>(var), oldValue.chars(), var->string);
}
}
}
}
void Cvar_DirectSet(struct cvar_s *var, const char *value)
{
Cvar_DirectSet_Custom(var, value);
}
void Cvar_DirectSet_RH(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value)
{
Cvar_DirectSet_Custom(var, value, chain);
}
CvarManager::CvarManager() : m_AmxmodxCvars(0), m_HookDetour(nullptr), m_ReHookEnabled(false)
{
}
CvarManager::~CvarManager()
{
OnAmxxShutdown();
}
void CvarManager::CreateCvarHook(void)
{
// void PF_Cvar_DirectSet(struct cvar_s *var, const char *value) // = pfnCvar_DirectSet
// {
// Cvar_DirectSet(var, value); // <- We want to hook this.
// }
if (!RehldsHookchains)
{
void *functionAddress = nullptr;
if (CommonConfig && CommonConfig->GetMemSig("Cvar_DirectSet", &functionAddress) && functionAddress)
{
// Disabled by default.
m_HookDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, functionAddress);
}
else
{
AMXXLOG_Log("Binding/Hooking cvars have been disabled - %s.", RehldsApi ? "update ReHLDS" : "check your gamedata files");
}
}
}
void CvarManager::EnableHook()
{
if (RehldsHookchains)
{
if (!m_ReHookEnabled)
{
RehldsHookchains->Cvar_DirectSet()->registerHook(Cvar_DirectSet_RH);
m_ReHookEnabled = true;
}
}
else if (m_HookDetour)
{
m_HookDetour->EnableDetour();
}
}
void CvarManager::DisableHook()
{
if (RehldsHookchains)
{
if (m_ReHookEnabled)
{
RehldsHookchains->Cvar_DirectSet()->unregisterHook(Cvar_DirectSet_RH);
m_ReHookEnabled = false;
}
}
else if (m_HookDetour)
{
m_HookDetour->DisableDetour();
}
}
void CvarManager::DestroyHook()
{
DisableHook();
if (m_HookDetour)
{
m_HookDetour->Destroy();
}
}
CvarInfo* CvarManager::CreateCvar(const char* name, const char* value, const char* plugin, int pluginId, int flags,
const char* helpText)
{
cvar_t* var = nullptr;
CvarInfo* info = nullptr;
if (!CacheLookup(name, &info))
{
// Not cached - Is cvar already exist?
var = CVAR_GET_POINTER(name);
// Whether it exists, we need to prepare a new entry.
info = new CvarInfo(name, helpText, plugin, pluginId);
if (var)
{
// Cvar already exists. Just copy.
// "string" will be set after. "value" and "next" are automatically set.
info->var = var;
info->defaultval = var->string;
info->amxmodx = false;
}
else
{
// Registers a new cvar.
static cvar_t cvar_reg_helper;
// "string" will be set after. "value" and "next" are automatically set.
cvar_reg_helper.name = info->name.chars();
cvar_reg_helper.string = "";
cvar_reg_helper.flags = flags;
// Adds cvar to global list.
CVAR_REGISTER(&cvar_reg_helper);
// Registering can fail if name is already a registered command.
var = CVAR_GET_POINTER(name);
// If so, we can't go further.
if (!var)
{
delete info;
return nullptr;
}
// If ok, we got a valid pointer, we can copy.
info->var = var;
info->defaultval = value;
info->amxmodx = true;
// Keeps track count of cvars registered by AMXX.
++m_AmxmodxCvars;
}
// Add a new entry in the caches.
m_Cvars.append(info);
m_Cache.insert(name, info);
// Make sure that whether an existing or new cvar is set to the given value.
CVAR_DIRECTSET(var, value);
}
else if (info->pluginId == -1)
{
// In situation where a plugin has been modified/recompiled
// or new added plugins, and a change map occurs. We want to keep data up to date.
info->bound.hasMin = false;
info->bound.minVal = 0;
info->bound.hasMax = false;
info->bound.maxVal = 0;
info->defaultval = value;
info->description = helpText;
info->pluginId = pluginId;
}
// Detour is disabled on map change.
// Don't enable it unless there are things to do.
if ((info->bound.hasMin || info->bound.hasMax))
{
EnableHook();
}
return info;
}
CvarInfo* CvarManager::FindCvar(const char* name)
{
cvar_t* var = nullptr;
CvarInfo* info = nullptr;
// Do we have already cvar in cache?
if (CacheLookup(name, &info))
{
return info;
}
// Cvar doesn't exist.
if (!(var = CVAR_GET_POINTER(name)))
{
return nullptr;
}
// Create a new entry.
info = new CvarInfo(name);
info->var = var;
// Add entry in the caches.
m_Cvars.append(info);
m_Cache.insert(name, info);
return info;
}
CvarInfo* CvarManager::FindCvar(size_t index)
{
// Used by get_plugins_cvar native.
// For compatibility, only cvars registered by AMXX are concerned.
size_t iter_id = 0;
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
{
if (iter->amxmodx && iter_id++ == index)
{
return *(iter);
}
}
return nullptr;
}
bool CvarManager::CacheLookup(const char* name, CvarInfo** info)
{
return m_Cache.retrieve(name, info);
}
AutoForward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback)
{
CvarInfo* info = nullptr;
// A cvar is guaranteed to be in cache if pointer is got from
// get_cvar_pointer and register_cvar natives. Though it might be
// provided by another way. If by any chance we run in such
// situation, we create a new entry right now.
if (!CacheLookup(var->name, &info))
{
// Create a new entry.
info = new CvarInfo(var->name);
info->var = var;
// Add entry in the caches.
m_Cvars.append(info);
m_Cache.insert(info->name.chars(), info);
}
int length;
*callback = get_amxstring(amx, param, 0, length);
int forwardId = registerSPForwardByName(amx, *callback, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
// Invalid callback, it could be: not a public function, wrongly named, or simply missing.
if (forwardId == -1)
{
return nullptr;
}
// Hook is disabled on map change.
EnableHook();
AutoForward* forward = new AutoForward(forwardId, *callback);
info->hooks.append(new CvarHook(g_plugins.findPlugin(amx)->getId(), forward));
return forward;
}
bool CvarManager::BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen)
{
if (varofs > amx->hlw) // If variable address is not inside global area, we can't bind it.
{
LogError(amx, AMX_ERR_NATIVE, "Cvars can only be bound to global variables");
return false;
}
int pluginId = g_plugins.findPluginFast(amx)->getId();
cell* address = get_amxaddr(amx, varofs);
// To avoid unexpected behavior, probably better to error such situations.
for (size_t i = 0; i < info->binds.length(); ++i)
{
CvarBind* bind = info->binds[i];
if (bind->pluginId == pluginId)
{
if (bind->varAddress == address)
{
LogError(amx, AMX_ERR_NATIVE, "A global variable can not be bound to multiple Cvars");
return false;
}
}
}
CvarBind* bind = new CvarBind(pluginId, type, get_amxaddr(amx, varofs), varlen);
info->binds.append(bind);
// Update right away variable with current cvar value.
switch (type)
{
case CvarBind::CvarType_Int:
*bind->varAddress = atoi(info->var->string);
break;
case CvarBind::CvarType_Float:
*bind->varAddress = amx_ftoc(info->var->value);
break;
case CvarBind::CvarType_String:
set_amxstring_simple(bind->varAddress, info->var->string, bind->varLength);
break;
}
// Hook is disabled on map change.
EnableHook();
return true;
}
void CvarManager::SetCvarMin(CvarInfo* info, bool set, float value, int pluginId)
{
info->bound.hasMin = set;
info->bound.minPluginId = pluginId;
if (set)
{
// Hook is disabled on map change.
EnableHook();
info->bound.minVal = value;
// Current value is already in the allowed range.
if (info->var->value >= value)
{
return;
}
// Update if needed.
CVAR_SET_FLOAT(info->var->name, value);
}
}
void CvarManager::SetCvarMax(CvarInfo* info, bool set, float value, int pluginId)
{
info->bound.hasMax = set;
info->bound.maxPluginId = pluginId;
if (set)
{
// Hook is disabled on map change.
EnableHook();
info->bound.maxVal = value;
// Current value is already in the allowed range.
if (info->var->value <= value)
{
return;
}
// Update if needed.
CVAR_SET_FLOAT(info->var->name, value);
}
}
size_t CvarManager::GetRegCvarsCount()
{
return m_AmxmodxCvars;
}
CvarsList* CvarManager::GetCvarsList()
{
return &m_Cvars;
}
ke::AutoString convertFlagsToString(int flags)
{
ke::AutoString flagsName;
if (flags > 0)
{
if (flags & FCVAR_ARCHIVE) flagsName = flagsName + "FCVAR_ARCHIVE ";
if (flags & FCVAR_USERINFO) flagsName = flagsName + "FCVAR_USERINFO ";
if (flags & FCVAR_SERVER) flagsName = flagsName + "FCVAR_SERVER ";
if (flags & FCVAR_EXTDLL) flagsName = flagsName + "FCVAR_EXTDLL ";
if (flags & FCVAR_CLIENTDLL) flagsName = flagsName + "FCVAR_CLIENTDLL ";
if (flags & FCVAR_PROTECTED) flagsName = flagsName + "FCVAR_PROTECTED ";
if (flags & FCVAR_SPONLY) flagsName = flagsName + "FCVAR_SPONLY ";
if (flags & FCVAR_PRINTABLEONLY) flagsName = flagsName + "FCVAR_PRINTABLEONLY ";
if (flags & FCVAR_UNLOGGED) flagsName = flagsName + "FCVAR_UNLOGGED ";
if (flags & FCVAR_NOEXTRAWHITEPACE) flagsName = flagsName + "FCVAR_NOEXTRAWHITEPACE ";
}
if (!flagsName.length())
{
flagsName = "-";
}
return flagsName;
}
void CvarManager::OnConsoleCommand()
{
size_t index = 0;
size_t indexToSearch = 0;
ke::AString partialName;
int argcount = CMD_ARGC();
// amxx cvars [partial plugin name] [index from listing]
// E.g.:
// amxx cvars test <- list all cvars from plugin name starting by "test"
// amxx cvars 2 <- show informations about cvar in position 2 from "amxx cvars" list
// amxx cvars test 2 <- show informations about cvar in position 2 from "amxx cvars test" list
if (argcount > 2)
{
const char* argument = CMD_ARGV(2);
indexToSearch = atoi(argument); // amxx cvars 2
if (!indexToSearch)
{
partialName = argument; // amxx cvars test
if (argcount > 3) // amxx cvars test 2
{
indexToSearch = atoi(CMD_ARGV(3));
}
}
}
if (!indexToSearch)
{
print_srvconsole("\nManaged cvars:\n");
print_srvconsole(" %-24.23s %-24.23s %-18.17s %-8.7s %-8.7s %-8.7s\n", "NAME", "VALUE", "PLUGIN", "HOOKED", "MIN", "MAX");
print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
}
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
{
CvarInfo* ci = (*iter);
// List any cvars having a status either created, hooked or bound by a plugin.
bool in_list = ci->amxmodx || !ci->binds.empty() || !ci->hooks.empty() || ci->bound.hasMin || ci->bound.hasMax;
if (in_list && (!partialName.length() || strncmp(ci->plugin.chars(), partialName.chars(), partialName.length()) == 0))
{
if (!indexToSearch)
{
print_srvconsole(" [%3d] %-24.23s %-24.23s %-18.17s %-8.7s ", ++index, ci->name.chars(), ci->var->string,
ci->plugin.length() ? ci->plugin.chars() : "-",
ci->hooks.empty() ? "no" : "yes");
(ci->bound.hasMin) ? print_srvconsole("%-8.2f ", ci->bound.minVal) : print_srvconsole("%-8.7s ", "-");
(ci->bound.hasMax) ? print_srvconsole("%-8.2f ", ci->bound.maxVal) : print_srvconsole("%-8.7s ", "-");
print_srvconsole("\n");
}
else
{
if (++index != indexToSearch)
{
continue;
}
print_srvconsole("\nCvar details :\n\n");
print_srvconsole(" Cvar name : %s\n", ci->var->name);
print_srvconsole(" Value : %s\n", ci->var->string);
print_srvconsole(" Def. value : %s\n", ci->defaultval.chars());
print_srvconsole(" Description : %s\n", ci->description.chars());
print_srvconsole(" Flags : %s\n\n", convertFlagsToString(ci->var->flags).ptr());
print_srvconsole(" %-12s %-26.25s %s\n", "STATUS", "PLUGIN", "INFOS");
print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
if (ci->amxmodx)
{
print_srvconsole(" Registered %-26.25s %s\n", ci->plugin.chars(), "-");
}
if (ci->bound.hasMin)
{
print_srvconsole(" Min value %-26.25s %f\n", g_plugins.findPlugin(ci->bound.minPluginId)->getName(), ci->bound.minVal);
}
if (ci->bound.hasMax)
{
print_srvconsole(" Max value %-26.25s %f\n", g_plugins.findPlugin(ci->bound.maxPluginId)->getName(), ci->bound.maxVal);
}
if (!ci->binds.empty())
{
for (size_t i = 0; i < ci->binds.length(); ++i)
{
print_srvconsole(" Bound %-26.25s %s\n", g_plugins.findPlugin(ci->binds[i]->pluginId)->getName(), "-");
}
}
if (!ci->hooks.empty())
{
for (size_t i = 0; i < ci->hooks.length(); ++i)
{
CvarHook* hook = ci->hooks[i];
print_srvconsole(" Hooked %-26.25s %s (%s)\n", g_plugins.findPlugin(hook->pluginId)->getName(),
hook->forward->callback.chars(),
hook->forward->state == AutoForward::FSTATE_OK ? "active" : "inactive");
}
}
break;
}
}
}
}
void CvarManager::OnPluginUnloaded()
{
// Clear only plugin hooks list.
for (CvarsList::iterator cvar = m_Cvars.begin(); cvar != m_Cvars.end(); cvar++)
{
for (size_t i = 0; i < (*cvar)->binds.length(); ++i)
{
delete (*cvar)->binds[i];
}
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
{
delete (*cvar)->hooks[i];
}
if ((*cvar)->amxmodx) // Mark registered cvars so we can refresh default datas at next map.
{
(*cvar)->pluginId = -1;
}
(*cvar)->binds.clear();
(*cvar)->hooks.clear();
}
// There is no point to enable hook if at next map change
// no plugins hook cvars.
DisableHook();
}
void CvarManager::OnAmxxShutdown()
{
// Free everything.
CvarsList::iterator iter = m_Cvars.begin();
while (iter != m_Cvars.end())
{
CvarInfo* cvar = (*iter);
for (size_t i = 0; i < cvar->binds.length(); ++i)
{
delete cvar->binds[i];
}
for (size_t i = 0; i < cvar->hooks.length(); ++i)
{
delete cvar->hooks[i];
}
iter = m_Cvars.erase(iter);
delete cvar;
}
m_Cache.clear();
DestroyHook();
}

View File

@ -1,177 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef CVARS_H
#define CVARS_H
#include "amxmodx.h"
#include <amtl/am-vector.h>
#include <amtl/am-inlinelist.h>
#include <sm_namehashset.h>
#include "CGameConfigs.h"
class CDetour;
enum CvarBounds
{
CvarBound_Upper = 0,
CvarBound_Lower
};
struct AutoForward
{
enum fwdstate
{
FSTATE_INVALID = 0,
FSTATE_OK,
FSTATE_STOP,
};
AutoForward(int id_, const char* handler) : id(id_), state(FSTATE_OK), callback(handler) {};
AutoForward() : id(-1) , state(FSTATE_INVALID) {};
~AutoForward()
{
unregisterSPForward(id);
}
int id;
fwdstate state;
ke::AString callback;
};
struct CvarHook
{
CvarHook(int id, AutoForward* fwd) : pluginId(id), forward(fwd) {};
CvarHook(int id) : pluginId(id), forward(new AutoForward()) {};
int pluginId;
ke::AutoPtr<AutoForward> forward;
};
struct CvarBind
{
enum CvarType
{
CvarType_Int,
CvarType_Float,
CvarType_String,
};
CvarBind(int id_, CvarType type_, cell* varAddress_, size_t varLength_)
:
pluginId(id_),
type(type_),
varAddress(varAddress_),
varLength(varLength_) {};
int pluginId;
CvarType type;
cell* varAddress;
size_t varLength;
};
struct CvarBound
{
CvarBound()
:
hasMin(false), minVal(0),
hasMax(false), maxVal(0),
minPluginId(-1),
maxPluginId(-1) {};
bool hasMin;
float minVal;
bool hasMax;
float maxVal;
int minPluginId;
int maxPluginId;
};
typedef ke::Vector<CvarHook*> CvarsHook;
typedef ke::Vector<CvarBind*> CvarsBind;
struct CvarInfo : public ke::InlineListNode<CvarInfo>
{
CvarInfo(const char* name_, const char* helpText, const char* plugin_, int pluginId_)
:
name(name_), description(helpText),
plugin(plugin_), pluginId(pluginId_), bound() {};
CvarInfo(const char* name_)
:
name(name_), defaultval(""), description(""),
plugin(""), pluginId(-1), bound(), amxmodx(false) {};
cvar_t* var;
ke::AString name;
ke::AString defaultval;
ke::AString description;
ke::AString plugin;
int pluginId;
CvarBound bound;
CvarsBind binds;
CvarsHook hooks;
bool amxmodx;
static inline bool matches(const char *name, const CvarInfo* info)
{
return strcmp(name, info->var->name) == 0;
}
};
typedef NameHashSet<CvarInfo*> CvarsCache;
typedef ke::InlineList<CvarInfo> CvarsList;
class CvarManager
{
public:
CvarManager();
~CvarManager();
public:
void CreateCvarHook();
void EnableHook();
void DisableHook();
void DestroyHook();
CvarInfo* CreateCvar(const char* name, const char* value, const char* plugin, int pluginId, int flags = 0, const char* helpText = "");
CvarInfo* FindCvar(const char* name);
CvarInfo* FindCvar(size_t index);
bool CacheLookup(const char* name, CvarInfo** info);
AutoForward* HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback);
bool BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen = 0);
void SetCvarMin(CvarInfo* info, bool set, float value, int pluginId);
void SetCvarMax(CvarInfo* info, bool set, float value, int pluginId);
size_t GetRegCvarsCount();
CvarsList* GetCvarsList();
void OnConsoleCommand();
void OnPluginUnloaded();
void OnAmxxShutdown();
private:
CvarsCache m_Cache;
CvarsList m_Cvars;
size_t m_AmxmodxCvars;
CDetour* m_HookDetour;
bool m_ReHookEnabled;
};
extern CvarManager g_CvarManager;
#endif // CVARS_H

BIN
amxmodx/JIT/amxexecn.o Executable file

Binary file not shown.

BIN
amxmodx/JIT/amxexecn.obj Executable file

Binary file not shown.

BIN
amxmodx/JIT/amxjitsn.o Executable file

Binary file not shown.

BIN
amxmodx/JIT/amxjitsn.obj Executable file

Binary file not shown.

BIN
amxmodx/JIT/natives-amd64.o Executable file

Binary file not shown.

BIN
amxmodx/JIT/natives-x86.o Executable file

Binary file not shown.

BIN
amxmodx/JIT/natives-x86.obj Executable file

Binary file not shown.

96
amxmodx/Makefile Executable file
View File

@ -0,0 +1,96 @@
#(C)2004-2005 AMX Mod X Development Team
# Makefile written by David "BAILOPAN" Anderson
HLSDK = ../hlsdk/SourceCode
MM_ROOT = ../metamod/metamod
### EDIT BELOW FOR OTHER PROJECTS ###
OPT_FLAGS = -O2 -funroll-loops -s -fomit-frame-pointer -pipe
DEBUG_FLAGS = -g -ggdb3
CPP = gcc
NAME = amxmodx_mm
OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules.cpp \
CMisc.cpp CTask.cpp string.cpp amxmodx.cpp CEvent.cpp CCmd.cpp CLogEvent.cpp \
srvcmd.cpp strptime.cpp amxcore.cpp amxtime.cpp power.cpp amxxlog.cpp fakemeta.cpp \
amxxfile.cpp CLang.cpp md5.cpp emsg.cpp CForward.cpp CPlugin.cpp CModule.cpp \
CMenu.cpp util.cpp amx.cpp amxdbg.cpp natives.cpp newmenus.cpp debugger.cpp \
optimizer.cpp format.cpp
LINK = -lz /lib/libstdc++.a
INCLUDE = -I. -I$(HLSDK) -I$(HLSDK)/dlls -I$(HLSDK)/engine -I$(HLSDK)/game_shared -I$(HLSDK)/game_shared \
-I$(MM_ROOT) -Lzlib -I$(HLSDK)/common
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS = $(DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS = $(OPT_FLAGS)
endif
ifeq "$(MMGR)" "true"
OBJECTS += mmgr/mmgr.cpp
CFLAGS += -DMEMORY_TEST
endif
CFLAGS += -DLINUX -DNDEBUG -fPIC -Wno-deprecated -DHAVE_STDINT_H -static-libgcc -fno-rtti -fno-exceptions
ifeq "$(AMD64)" "true"
BINARY = $(NAME)_amd64.so
CFLAGS += -DPAWN_CELL_SIZE=64 -DHAVE_I64 -DAMD64 -m64
OBJECTS += JIT/natives-amd64.o
else
BINARY = $(NAME)_i386.so
OBJECTS += JIT/amxexecn.o JIT/amxjitsn.o JIT/natives-x86.o
CFLAGS += -DPAWN_CELL_SIZE=32 -DJIT -DASM32
OPT_FLAGS += -march=i586
endif
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)
$(MAKE) amxmodx
amd64:
rm -f zlib/libz.a
$(MAKE) all AMD64=true
amd64_mmgr:
rm -f zlib/libz.a
$(MAKE) all AMD64=true MMGR=true
amd64_debug_mmgr:
rm -f zlib/libz.a
$(MAKE) all AMD64=true DEBUG=true MMGR=true
amd64_debug:
rm -f zlib/libz.a
$(MAKE) all AMD64=true DEBUG=true
mmgr:
$(MAKE) all MMGR=true
debug_mmgr:
$(MAKE) all MMGR=true DEBUG=true
amxmodx: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug:
$(MAKE) all DEBUG=true
default: all
clean:
rm -rf Release/*.o
rm -rf Release/$(BINARY)
rm -rf Debug/*.o
rm -rf Debug/$(BINARY)

View File

@ -17,12 +17,14 @@
* 2. Altered source versions must be plainly marked as such, and must not be * 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. * misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/ */
#define AMX_NODYNALOAD #define AMX_NODYNALOAD
#define AMX_ANSIONLY #define AMX_ANSIONLY
#if !defined __linux__ && BUILD_PLATFORM == WINDOWS && BUILD_TYPE == RELEASE && BUILD_COMPILER == MSVC && PAWN_CELL_SIZE == 64 #if BUILD_PLATFORM == WINDOWS && BUILD_TYPE == RELEASE && BUILD_COMPILER == MSVC && PAWN_CELL_SIZE == 64
/* bad bad workaround but we have to prevent a compiler crash :/ */ /* bad bad workaround but we have to prevent a compiler crash :/ */
#pragma optimize("g",off) #pragma optimize("g",off)
#endif #endif
@ -46,7 +48,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "osdefs.h" #include "osdefs.h"
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ #if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
#include <sclinux.h> #include <sclinux.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -66,9 +68,6 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include <chrono>
#include <amxmodx.h>
#include <CPlugin.h>
/* When one or more of the AMX_funcname macris are defined, we want /* When one or more of the AMX_funcname macris are defined, we want
* to compile only those functions. However, when none of these macros * to compile only those functions. However, when none of these macros
@ -437,7 +436,7 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params)
hdr=(AMX_HEADER *)amx->base; hdr=(AMX_HEADER *)amx->base;
assert(hdr->natives<=hdr->libraries); assert(hdr->natives<=hdr->libraries);
#if defined AMX_NATIVETABLE #if defined AMX_NATIVETABLE
if (index<0) { if (index<NULL) {
assert(-(index+1)<(sizeof(AMX_NATIVETABLE)/sizeof(AMX_NATIVETABLE)[0])); assert(-(index+1)<(sizeof(AMX_NATIVETABLE)/sizeof(AMX_NATIVETABLE)[0]));
f=(AMX_NATIVETABLE)[-(index+1)]; f=(AMX_NATIVETABLE)[-(index+1)];
} else { } else {
@ -463,24 +462,8 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params)
amx->error=AMX_ERR_NONE; amx->error=AMX_ERR_NONE;
#if defined BINLOG_ENABLED
binlogfuncs_t *logfuncs = (binlogfuncs_t *)amx->usertags[UT_BINLOGS];
if (logfuncs)
{
logfuncs->pfnLogNative(amx, index, (int)(params[0] / sizeof(cell)));
logfuncs->pfnLogParams(amx, params);
}
#endif //BINLOG_ENABLED
*result = f(amx,params); *result = f(amx,params);
#if defined BINLOG_ENABLED
if (logfuncs)
{
logfuncs->pfnLogReturn(amx, *result);
}
#endif
return amx->error; return amx->error;
} }
#endif /* defined AMX_INIT */ #endif /* defined AMX_INIT */
@ -804,7 +787,7 @@ static void expand(unsigned char *code, long codesize, long memsize)
do { do {
codesize--; codesize--;
/* no input byte should be shifted out completely */ /* no input byte should be shifted out completely */
assert(shift<static_cast<int>(8*sizeof(cell))); assert(shift<8*sizeof(cell));
/* we work from the end of a sequence backwards; the final code in /* we work from the end of a sequence backwards; the final code in
* a sequence may not have the continuation bit set */ * a sequence may not have the continuation bit set */
assert(shift>0 || (code[(size_t)codesize] & 0x80)==0); assert(shift>0 || (code[(size_t)codesize] & 0x80)==0);
@ -845,6 +828,19 @@ int AMXAPI amx_Init(AMX *amx, void *program)
{ {
AMX_HEADER *hdr; AMX_HEADER *hdr;
BROWSEHOOK hook = NULL; BROWSEHOOK hook = NULL;
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
char libname[sNAMEMAX+8]; /* +1 for '\0', +3 for 'amx' prefix, +4 for extension */
#if defined _Windows
typedef int (FAR WINAPI *AMX_ENTRY)(AMX _FAR *amx);
HINSTANCE hlib;
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
typedef int (*AMX_ENTRY)(AMX *amx);
void *hlib;
#endif
int numlibraries,i;
AMX_FUNCSTUB *lib;
AMX_ENTRY libinit;
#endif
if ((amx->flags & AMX_FLAG_RELOC)!=0) if ((amx->flags & AMX_FLAG_RELOC)!=0)
return AMX_ERR_INIT; /* already initialized (may not do so twice) */ return AMX_ERR_INIT; /* already initialized (may not do so twice) */
@ -854,6 +850,22 @@ int AMXAPI amx_Init(AMX *amx, void *program)
* multi-byte words * multi-byte words
*/ */
assert(check_endian()); assert(check_endian());
#if BYTE_ORDER==BIG_ENDIAN
amx_Align32((uint32_t*)&hdr->size);
amx_Align16(&hdr->magic);
amx_Align16((uint16_t*)&hdr->flags);
amx_Align16((uint16_t*)&hdr->defsize);
amx_Align32((uint32_t*)&hdr->cod);
amx_Align32((uint32_t*)&hdr->dat);
amx_Align32((uint32_t*)&hdr->hea);
amx_Align32((uint32_t*)&hdr->stp);
amx_Align32((uint32_t*)&hdr->cip);
amx_Align32((uint32_t*)&hdr->publics);
amx_Align32((uint32_t*)&hdr->natives);
amx_Align32((uint32_t*)&hdr->libraries);
amx_Align32((uint32_t*)&hdr->pubvars);
amx_Align32((uint32_t*)&hdr->tags);
#endif
if (hdr->magic!=AMX_MAGIC) if (hdr->magic!=AMX_MAGIC)
return AMX_ERR_FORMAT; return AMX_ERR_FORMAT;
@ -874,7 +886,13 @@ int AMXAPI amx_Init(AMX *amx, void *program)
} /* if */ } /* if */
if (hdr->stp<=0) if (hdr->stp<=0)
return AMX_ERR_FORMAT; return AMX_ERR_FORMAT;
#if BYTE_ORDER==BIG_ENDIAN
if ((hdr->flags & AMX_FLAG_COMPACT)==0) {
ucell *code=(ucell *)((unsigned char *)program+(int)hdr->cod);
while (code<(ucell *)((unsigned char *)program+(int)hdr->hea))
swapcell(code++);
} /* if */
#endif
assert((hdr->flags & AMX_FLAG_COMPACT)!=0 || hdr->hea == hdr->size); assert((hdr->flags & AMX_FLAG_COMPACT)!=0 || hdr->hea == hdr->size);
if ((hdr->flags & AMX_FLAG_COMPACT)!=0) { if ((hdr->flags & AMX_FLAG_COMPACT)!=0) {
#if AMX_COMPACTMARGIN > 2 #if AMX_COMPACTMARGIN > 2
@ -901,12 +919,108 @@ int AMXAPI amx_Init(AMX *amx, void *program)
amx->callback=amx_Callback; amx->callback=amx_Callback;
amx->data=NULL; amx->data=NULL;
/* also align all addresses in the public function, public variable,
* public tag and native function tables --offsets into the name table
* (if present) must also be swapped.
*/
#if BYTE_ORDER==BIG_ENDIAN
{ /* local */
AMX_FUNCSTUB *fs;
int i,num;
fs=GETENTRY(hdr,natives,0);
num=NUMENTRIES(hdr,natives,libraries);
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address); /* redundant, because it should be zero */
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
fs=GETENTRY(hdr,publics,0);
assert(hdr->publics<=hdr->natives);
num=NUMENTRIES(hdr,publics,natives);
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address);
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
fs=GETENTRY(hdr,pubvars,0);
assert(hdr->pubvars<=hdr->tags);
num=NUMENTRIES(hdr,pubvars,tags);
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address);
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
fs=GETENTRY(hdr,tags,0);
if (hdr->file_version<7) {
assert(hdr->tags<=hdr->cod);
num=NUMENTRIES(hdr,tags,cod);
} else {
assert(hdr->tags<=hdr->nametable);
num=NUMENTRIES(hdr,tags,nametable);
} /* if */
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address);
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
} /* local */
#endif
/* relocate call and jump instructions */ /* relocate call and jump instructions */
hook = (BROWSEHOOK)amx->usertags[UT_BROWSEHOOK]; hook = (BROWSEHOOK)amx->usertags[UT_BROWSEHOOK];
if (hook) if (hook)
hook(amx, NULL, NULL); hook(amx, NULL, NULL);
amx_BrowseRelocate(amx); amx_BrowseRelocate(amx);
/* load any extension modules that the AMX refers to */
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
hdr=(AMX_HEADER *)amx->base;
numlibraries=NUMENTRIES(hdr,libraries,pubvars);
for (i=0; i<numlibraries; i++) {
lib=GETENTRY(hdr,libraries,i);
strcpy(libname,"amx");
strcat(libname,GETENTRYNAME(hdr,lib));
#if defined _Windows
strcat(libname,".dll");
#if defined __WIN32__
hlib=LoadLibraryA(libname);
#else
hlib=LoadLibrary(libname);
if (hlib<=HINSTANCE_ERROR)
hlib=NULL;
#endif
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
strcat(libname,".so");
hlib=dlopen(libname,RTLD_NOW);
#endif
if (hlib!=NULL) {
/* a library that cannot be loaded or that does not have the required
* initialization function is simply ignored
*/
char funcname[sNAMEMAX+9]; /* +1 for '\0', +4 for 'amx_', +4 for 'Init' */
strcpy(funcname,"amx_");
strcat(funcname,GETENTRYNAME(hdr,lib));
strcat(funcname,"Init");
#if defined _Windows
libinit=(AMX_ENTRY)GetProcAddress(hlib,funcname);
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
libinit=(AMX_ENTRY)dlsym(hlib,funcname);
#endif
if (libinit!=NULL)
libinit(amx);
} /* if */
lib->address=(ucell)hlib;
} /* for */
#endif
return AMX_ERR_NONE; return AMX_ERR_NONE;
} }
@ -933,11 +1047,11 @@ int AMXAPI amx_Init(AMX *amx, void *program)
#define ALIGN(addr) (addr) #define ALIGN(addr) (addr)
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
/* Linux already has mprotect() */ /* Linux already has mprotect() */
/* But wants the address aligned! */ /* But wants the address aligned! */
#define ALIGN(addr) ((void *)((intptr_t)addr & ~(sysconf(_SC_PAGESIZE)-1))) #define ALIGN(addr) (char *)(((long)addr + sysconf(_SC_PAGESIZE)-1) & ~(sysconf(_SC_PAGESIZE)-1))
#else #else
@ -974,25 +1088,26 @@ int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code)
memcpy(native_code, amx->base, ((AMX_HEADER *)(amx->base))->cod); memcpy(native_code, amx->base, ((AMX_HEADER *)(amx->base))->cod);
hdr = (AMX_HEADER *)native_code; hdr = (AMX_HEADER *)native_code;
/* JIT rulz! (TM) */ /* JIT rulz! (TM) */
/* MP: added check for correct compilation */ /* MP: added check for correct compilation */
//Fixed bug (thanks T(+)rget) //Fixed bug (thanks T(+)rget)
if ((res = asm_runJIT(amx->base, reloc_table, native_code)) == 0) if ((res = asm_runJIT(amx->base, reloc_table, native_code)) == 0)
{ {
/* update the required memory size (the previous value was a
* conservative estimate, now we know the exact size)
*/
amx->code_size = (hdr->dat + hdr->stp + 3) & ~3;
/* The compiled code is relocatable, since only relative jumps are /* The compiled code is relocatable, since only relative jumps are
* used for destinations within the generated code and absoulute * used for destinations within the generated code and absoulute
* addresses for jumps into the runtime, which is fixed in memory. * addresses for jumps into the runtime, which is fixed in memory.
*/ */
amx->base = (unsigned char*) native_code; amx->base = (unsigned char*) native_code;
amx->cip = hdr->cip; amx->cip = hdr->cip;
/* also put a sentinel for strings at the top the stack */ amx->hea = hdr->hea;
*(cell *)((char*)native_code + hdr->dat + amx->stp - sizeof(cell)) = 0; amx->stp = hdr->stp - sizeof(cell);
/* update the required memory size (the previous value was a /* also put a sentinel for strings at the top the stack */
* conservative estimate, now we know the exact size) *(cell *)((char*)native_code + hdr->dat + hdr->stp - sizeof(cell)) = 0;
*/ amx->stk = amx->stp;
amx->code_size = (hdr->dat + amx->stp + sizeof(cell)) & ~3;
} /* if */ } /* if */
return (res == 0) ? AMX_ERR_NONE : AMX_ERR_INIT_JIT; return (res == 0) ? AMX_ERR_NONE : AMX_ERR_INIT_JIT;
@ -1015,10 +1130,10 @@ int AMXAPI amx_InitJIT(AMX *amx,void *compiled_program,void *reloc_table)
#if defined AMX_CLEANUP #if defined AMX_CLEANUP
int AMXAPI amx_Cleanup(AMX *amx) int AMXAPI amx_Cleanup(AMX *amx)
{ {
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__) && !defined AMX_NODYNALOAD #if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
#if defined _Windows #if defined _Windows
typedef int (FAR WINAPI *AMX_ENTRY)(AMX FAR *amx); typedef int (FAR WINAPI *AMX_ENTRY)(AMX FAR *amx);
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
typedef int (*AMX_ENTRY)(AMX *amx); typedef int (*AMX_ENTRY)(AMX *amx);
#endif #endif
AMX_HEADER *hdr; AMX_HEADER *hdr;
@ -1028,7 +1143,7 @@ int AMXAPI amx_Cleanup(AMX *amx)
#endif #endif
/* unload all extension modules */ /* unload all extension modules */
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__) && !defined AMX_NODYNALOAD #if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
hdr=(AMX_HEADER *)amx->base; hdr=(AMX_HEADER *)amx->base;
assert(hdr->magic==AMX_MAGIC); assert(hdr->magic==AMX_MAGIC);
numlibraries=NUMENTRIES(hdr,libraries,pubvars); numlibraries=NUMENTRIES(hdr,libraries,pubvars);
@ -1041,14 +1156,14 @@ int AMXAPI amx_Cleanup(AMX *amx)
strcat(funcname,"Cleanup"); strcat(funcname,"Cleanup");
#if defined _Windows #if defined _Windows
libcleanup=(AMX_ENTRY)GetProcAddress((HINSTANCE)lib->address,funcname); libcleanup=(AMX_ENTRY)GetProcAddress((HINSTANCE)lib->address,funcname);
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
libcleanup=(AMX_ENTRY)dlsym((void*)lib->address,funcname); libcleanup=(AMX_ENTRY)dlsym((void*)lib->address,funcname);
#endif #endif
if (libcleanup!=NULL) if (libcleanup!=NULL)
libcleanup(amx); libcleanup(amx);
#if defined _Windows #if defined _Windows
FreeLibrary((HINSTANCE)lib->address); FreeLibrary((HINSTANCE)lib->address);
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ #elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
dlclose((void*)lib->address); dlclose((void*)lib->address);
#endif #endif
} /* if */ } /* if */
@ -1176,12 +1291,12 @@ int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname)
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index) int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index)
{ {
int last,mid; int first,last,mid;
char pname[sNAMEMAX+1]; char pname[sNAMEMAX+1];
amx_NumNatives(amx, &last); amx_NumNatives(amx, &last);
last--; /* last valid index is 1 less than the number of functions */ last--; /* last valid index is 1 less than the number of functions */
first=0;
/* normal search */ /* normal search */
for (mid=0; mid<=last; mid++) for (mid=0; mid<=last; mid++)
{ {
@ -1481,36 +1596,6 @@ int AMXAPI amx_RegisterToAny(AMX *amx, AMX_NATIVE f)
return err; return err;
} }
int AMXAPI amx_Reregister(AMX *amx, const AMX_NATIVE_INFO *list, int number)
{
AMX_FUNCSTUB *func;
AMX_HEADER *hdr;
int i,numnatives,count=0;
AMX_NATIVE funcptr;
hdr=(AMX_HEADER *)amx->base;
assert(hdr!=NULL);
assert(hdr->magic==AMX_MAGIC);
assert(hdr->natives<=hdr->libraries);
numnatives=NUMENTRIES(hdr,natives,libraries);
count=0;
func=GETENTRY(hdr,natives,0);
for (i=0; i<numnatives; i++) {
if (func->address!=0) {
/* this function is located */
funcptr=(list!=NULL) ? findfunction(GETENTRYNAME(hdr,func),list,number) : NULL;
if (funcptr!=NULL)
{
func->address=(ucell)funcptr;
count++;
}
} /* if */
func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize);
} /* for */
return count;
}
int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *list, int number) int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *list, int number)
{ {
AMX_FUNCSTUB *func; AMX_FUNCSTUB *func;
@ -1531,12 +1616,12 @@ int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *list, int number)
/* this function is not yet located */ /* this function is not yet located */
funcptr=(list!=NULL) ? findfunction(GETENTRYNAME(hdr,func),list,number) : NULL; funcptr=(list!=NULL) ? findfunction(GETENTRYNAME(hdr,func),list,number) : NULL;
if (funcptr!=NULL) if (funcptr!=NULL)
{ {
func->address=(ucell)funcptr; func->address=(ucell)funcptr;
} else { } else {
no_function = GETENTRYNAME(hdr,func); no_function = GETENTRYNAME(hdr,func);
err=AMX_ERR_NOTFOUND; err=AMX_ERR_NOTFOUND;
} }
} /* if */ } /* if */
func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize); func=(AMX_FUNCSTUB*)((unsigned char*)func+hdr->defsize);
} /* for */ } /* for */
@ -1641,7 +1726,7 @@ int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char
* fast "indirect threaded" interpreter. * fast "indirect threaded" interpreter.
*/ */
#define NEXT(cip) goto *(const void *)*cip++ #define NEXT(cip) goto **cip++
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) int AMXAPI amx_Exec(AMX *amx, cell *retval, int index)
{ {
@ -1825,14 +1910,14 @@ static const void * const amx_opcodelist[] = {
NEXT(cip); NEXT(cip);
op_load_i: op_load_i:
/* verify address */ /* verify address */
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp) if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
pri= * (cell *)(data+(int)pri); pri= * (cell *)(data+(int)pri);
NEXT(cip); NEXT(cip);
op_lodb_i: op_lodb_i:
GETPARAM(offs); GETPARAM(offs);
/* verify address */ /* verify address */
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp) if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
switch (offs) { switch (offs) {
case 1: case 1:
@ -1898,14 +1983,14 @@ static const void * const amx_opcodelist[] = {
NEXT(cip); NEXT(cip);
op_stor_i: op_stor_i:
/* verify address */ /* verify address */
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp) if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
*(cell *)(data+(int)alt)=pri; *(cell *)(data+(int)alt)=pri;
NEXT(cip); NEXT(cip);
op_strb_i: op_strb_i:
GETPARAM(offs); GETPARAM(offs);
/* verify address */ /* verify address */
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp) if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
switch (offs) { switch (offs) {
case 1: case 1:
@ -1922,7 +2007,7 @@ static const void * const amx_opcodelist[] = {
op_lidx: op_lidx:
offs=pri*sizeof(cell)+alt; offs=pri*sizeof(cell)+alt;
/* verify address */ /* verify address */
if ((offs>=hea && offs<stk) || (ucell)offs>=(ucell)amx->stp) if (offs>=hea && offs<stk || (ucell)offs>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
pri= * (cell *)(data+(int)offs); pri= * (cell *)(data+(int)offs);
NEXT(cip); NEXT(cip);
@ -1930,7 +2015,7 @@ static const void * const amx_opcodelist[] = {
GETPARAM(offs); GETPARAM(offs);
offs=(pri << (int)offs)+alt; offs=(pri << (int)offs)+alt;
/* verify address */ /* verify address */
if ((offs>=hea && offs<stk) || (ucell)offs>=(ucell)amx->stp) if (offs>=hea && offs<stk || (ucell)offs>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
pri= * (cell *)(data+(int)offs); pri= * (cell *)(data+(int)offs);
NEXT(cip); NEXT(cip);
@ -2367,13 +2452,13 @@ static const void * const amx_opcodelist[] = {
/* verify top & bottom memory addresses, for both source and destination /* verify top & bottom memory addresses, for both source and destination
* addresses * addresses
*/ */
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp) if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
if (((pri+offs)>hea && (pri+offs)<stk) || (ucell)(pri+offs)>(ucell)amx->stp) if ((pri+offs)>hea && (pri+offs)<stk || (ucell)(pri+offs)>(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp) if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
if (((alt+offs)>hea && (alt+offs)<stk) || (ucell)(alt+offs)>(ucell)amx->stp) if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
memcpy(data+(int)alt, data+(int)pri, (int)offs); memcpy(data+(int)alt, data+(int)pri, (int)offs);
NEXT(cip); NEXT(cip);
@ -2382,22 +2467,22 @@ static const void * const amx_opcodelist[] = {
/* verify top & bottom memory addresses, for both source and destination /* verify top & bottom memory addresses, for both source and destination
* addresses * addresses
*/ */
if ((pri>=hea && pri<stk) || (ucell)pri>=(ucell)amx->stp) if (pri>=hea && pri<stk || (ucell)pri>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
if (((pri+offs)>hea && (pri+offs)<stk) || (ucell)(pri+offs)>(ucell)amx->stp) if ((pri+offs)>hea && (pri+offs)<stk || (ucell)(pri+offs)>(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp) if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
if (((alt+offs)>hea && (alt+offs)<stk) || (ucell)(alt+offs)>(ucell)amx->stp) if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
pri=memcmp(data+(int)alt, data+(int)pri, (int)offs); pri=memcmp(data+(int)alt, data+(int)pri, (int)offs);
NEXT(cip); NEXT(cip);
op_fill: op_fill:
GETPARAM(offs); GETPARAM(offs);
/* verify top & bottom memory addresses */ /* verify top & bottom memory addresses */
if ((alt>=hea && alt<stk) || (ucell)alt>=(ucell)amx->stp) if (alt>=hea && alt<stk || (ucell)alt>=(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
if (((alt+offs)>hea && (alt+offs)<stk) || (ucell)(alt+offs)>(ucell)amx->stp) if ((alt+offs)>hea && (alt+offs)<stk || (ucell)(alt+offs)>(ucell)amx->stp)
ABORT(amx,AMX_ERR_MEMACCESS); ABORT(amx,AMX_ERR_MEMACCESS);
for (i=(int)alt; offs>=(int)sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell)) for (i=(int)alt; offs>=(int)sizeof(cell); i+=sizeof(cell), offs-=sizeof(cell))
*(cell *)(data+i) = pri; *(cell *)(data+i) = pri;
@ -3696,7 +3781,7 @@ int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr)
data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat; data=(amx->data!=NULL) ? amx->data : amx->base+(int)hdr->dat;
assert(phys_addr!=NULL); assert(phys_addr!=NULL);
if ((amx_addr>=amx->hea && amx_addr<amx->stk) || amx_addr<0 || amx_addr>=amx->stp) { if (amx_addr>=amx->hea && amx_addr<amx->stk || amx_addr<0 || amx_addr>=amx->stp) {
*phys_addr=NULL; *phys_addr=NULL;
return AMX_ERR_MEMACCESS; return AMX_ERR_MEMACCESS;
} /* if */ } /* if */
@ -4095,6 +4180,10 @@ int AMXAPI amx_GetLibraries(AMX *amx)
return numLibraries; return numLibraries;
} }
#ifdef __linux__
#define _snprintf snprintf
#endif
const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len) const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len)
{ {
AMX_HEADER *hdr = (AMX_HEADER *)amx->base; AMX_HEADER *hdr = (AMX_HEADER *)amx->base;
@ -4138,7 +4227,7 @@ int AMXAPI amx_SetStringOld(cell *dest,const char *source,int pack,int use_wchar
dest[i]=(cell)(((wchar_t*)source)[i]); dest[i]=(cell)(((wchar_t*)source)[i]);
} else { } else {
for (i=0; i<len; i++) for (i=0; i<len; i++)
dest[i]=(unsigned char)source[i]; dest[i]=(cell)source[i];
} /* if */ } /* if */
dest[len]=0; dest[len]=0;
} /* if */ } /* if */
@ -4176,37 +4265,3 @@ int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar)
dest[len]='\0'; /* store terminator */ dest[len]='\0'; /* store terminator */
return AMX_ERR_NONE; return AMX_ERR_NONE;
} }
int AMXAPI amx_ExecPerf(AMX* amx, cell* retval, int index)
{
CPluginMngr::CPlugin* perf_Plug = g_plugins.findPluginFast(amx);
if (amxmodx_perflog->value > 0.0f && perf_Plug && (perf_Plug->isDebug() || (int)amxmodx_debug->value == 2))
{
char perf_funcname[sNAMEMAX + 1];
perf_funcname[0] = '\0';
amx_GetPublic(perf_Plug->getAMX(), index, perf_funcname);
if (perf_funcname[0] == '\0')
sprintf(perf_funcname, "Unknown_ID%d", index);
const char* perf_plugname = perf_Plug->getName();
if (!perf_plugname || perf_plugname[0] == '\0')
perf_plugname = "Unknown_plugin";
using std::chrono::steady_clock;
using std::chrono::duration_cast;
using std::chrono::duration;
using std::chrono::microseconds;
auto t1 = steady_clock::now();
int err = amx_Exec(amx, retval, index);
auto ms_int = duration_cast<microseconds>(steady_clock::now() - t1);
auto ms_float = (float)(ms_int.count() / 1000.0f);
if (ms_float >= amxmodx_perflog->value)
{
AMXXLOG_Log("[%s] performance issue. Function %s executed more than %.*fms.", perf_plugname, perf_funcname, 1, ms_float);
}
return err;
}
return amx_Exec(amx, retval, index);
}

View File

@ -17,12 +17,14 @@
* 2. Altered source versions must be plainly marked as such, and must not be * 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. * misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/ */
#if defined FREEBSD && !defined __FreeBSD__ #if defined FREEBSD && !defined __FreeBSD__
#define __FreeBSD__ #define __FreeBSD__
#endif #endif
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ #if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
#include <sclinux.h> #include <sclinux.h>
#endif #endif
@ -32,7 +34,7 @@
#if defined HAVE_STDINT_H #if defined HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else #else
#if defined __LCC__ || defined __DMC__ || defined LINUX || defined __APPLE__ #if defined __LCC__ || defined __DMC__ || defined LINUX
#if defined HAVE_INTTYPES_H #if defined HAVE_INTTYPES_H
#include <inttypes.h> #include <inttypes.h>
#else #else
@ -164,14 +166,6 @@ typedef int (AMXAPI *AMX_NATIVE_FILTER)(struct tagAMX *amx, int index);
#pragma warning(disable:4103) /* disable warning message 4103 that complains #pragma warning(disable:4103) /* disable warning message 4103 that complains
* about pragma pack in a header file */ * about pragma pack in a header file */
#pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */ #pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */
#if _MSC_VER >= 1400
// MSVC8 - Replace POSIX stricmp with ISO C++ conformant one as it is deprecated
#define stricmp _stricmp
// Need this because of some stupid bug
#pragma warning (disable : 4996)
#endif
#endif #endif
/* Some compilers do not support the #pragma align, which should be fine. Some /* Some compilers do not support the #pragma align, which should be fine. Some
@ -188,7 +182,7 @@ typedef int (AMXAPI *AMX_NATIVE_FILTER)(struct tagAMX *amx, int index);
#endif #endif
#if !defined AMX_NO_ALIGN #if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__ #if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
#elif defined MACOS && defined __MWERKS__ #elif defined MACOS && defined __MWERKS__
#pragma options align=mac68k #pragma options align=mac68k
@ -208,11 +202,11 @@ typedef struct tagAMX_NATIVE_INFO {
#define AMX_USERNUM 4 #define AMX_USERNUM 4
#define sEXPMAX 19 /* maximum name length for file version <= 6 */ #define sEXPMAX 19 /* maximum name length for file version <= 6 */
#define sNAMEMAX 63 /* maximum name length of symbol name */ #define sNAMEMAX 31 /* maximum name length of symbol name */
typedef struct tagAMX_FUNCSTUB { typedef struct tagAMX_FUNCSTUB {
ucell address PACKED; ucell address PACKED;
char name[sEXPMAX+1]; char name[sEXPMAX+1] PACKED;
} PACKED AMX_FUNCSTUB; } PACKED AMX_FUNCSTUB;
typedef struct tagFUNCSTUBNT { typedef struct tagFUNCSTUBNT {
@ -263,8 +257,8 @@ typedef struct tagAMX {
typedef struct tagAMX_HEADER { typedef struct tagAMX_HEADER {
int32_t size PACKED; /* size of the "file" */ int32_t size PACKED; /* size of the "file" */
uint16_t magic PACKED; /* signature */ uint16_t magic PACKED; /* signature */
char file_version; /* file format version */ char file_version PACKED; /* file format version */
char amx_version; /* required version of the AMX */ char amx_version PACKED; /* required version of the AMX */
int16_t flags PACKED; int16_t flags PACKED;
int16_t defsize PACKED; /* size of a definition record */ int16_t defsize PACKED; /* size of a definition record */
int32_t cod PACKED; /* initial value of COD - code block */ int32_t cod PACKED; /* initial value of COD - code block */
@ -320,7 +314,6 @@ enum {
#define AMX_FLAG_COMPACT 0x04 /* compact encoding */ #define AMX_FLAG_COMPACT 0x04 /* compact encoding */
#define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */ #define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */
#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */ #define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */
/* AMX_FLAG_OLDFILE 0x20 Old AMX Mod plugin */
#define AMX_FLAG_PRENIT 0x100 /* pre-initialized, do not check natives */ #define AMX_FLAG_PRENIT 0x100 /* pre-initialized, do not check natives */
#define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */ #define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */
#define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */ #define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */
@ -343,7 +336,6 @@ enum {
#define UT_NATIVE 3 #define UT_NATIVE 3
#define UT_OPTIMIZER 2 #define UT_OPTIMIZER 2
#define UT_BROWSEHOOK 1 #define UT_BROWSEHOOK 1
#define UT_BINLOGS 0
typedef void (*BROWSEHOOK)(AMX *amx, cell *oplist, cell *cip); typedef void (*BROWSEHOOK)(AMX *amx, cell *oplist, cell *cip);
@ -382,7 +374,6 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
int AMXAPI amx_CheckNatives(AMX *amx, AMX_NATIVE_FILTER nf); int AMXAPI amx_CheckNatives(AMX *amx, AMX_NATIVE_FILTER nf);
int AMXAPI amx_Cleanup(AMX *amx); int AMXAPI amx_Cleanup(AMX *amx);
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data); int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
int AMXAPI amx_ExecPerf(AMX* amx, cell* retval, int index);
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index); int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index); int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index); int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index);
@ -410,7 +401,6 @@ int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell
int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar); int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar);
int AMXAPI amx_RaiseError(AMX *amx, int error); int AMXAPI amx_RaiseError(AMX *amx, int error);
int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number); int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
int AMXAPI amx_Reregister(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
int AMXAPI amx_RegisterToAny(AMX *amx, AMX_NATIVE f); int AMXAPI amx_RegisterToAny(AMX *amx, AMX_NATIVE f);
int AMXAPI amx_Release(AMX *amx, cell amx_addr); int AMXAPI amx_Release(AMX *amx, cell amx_addr);
int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback); int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
@ -441,7 +431,7 @@ int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar);
amx_Register((amx), amx_NativeInfo((name),(func)), 1); amx_Register((amx), amx_NativeInfo((name),(func)), 1);
#if !defined AMX_NO_ALIGN #if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__ #if defined LINUX || defined __FreeBSD__
#pragma pack() /* reset default packing */ #pragma pack() /* reset default packing */
#elif defined MACOS && defined __MWERKS__ #elif defined MACOS && defined __MWERKS__
#pragma options align=reset #pragma options align=reset
@ -450,15 +440,6 @@ int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar);
#endif #endif
#endif #endif
#if defined BINLOG_ENABLED
typedef struct tagBINLOG
{
void (*pfnLogNative)(AMX *amx, int native, int params);
void (*pfnLogReturn)(AMX *amx, cell retval);
void (*pfnLogParams)(AMX *amx, cell *params);
} binlogfuncs_t;
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -17,8 +17,9 @@
* 2. Altered source versions must be plainly marked as such, and must not be * 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. * misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/ */
#if defined _UNICODE || defined __UNICODE__ || defined UNICODE #if defined _UNICODE || defined __UNICODE__ || defined UNICODE
# if !defined UNICODE /* for Windows */ # if !defined UNICODE /* for Windows */
# define UNICODE # define UNICODE
@ -179,7 +180,7 @@ static cell AMX_NATIVE_CALL setarg(AMX *amx, cell *params)
/* adjust the address in "value" in case of an array access */ /* adjust the address in "value" in case of an array access */
value+=params[2]*sizeof(cell); value+=params[2]*sizeof(cell);
/* verify the address */ /* verify the address */
if (value<0 || (value>=amx->hea && value<amx->stk)) if (value<0 || value>=amx->hea && value<amx->stk)
return 0; return 0;
/* set the value indirectly */ /* set the value indirectly */
* (cell *)(data+(int)value) = params[3]; * (cell *)(data+(int)value) = params[3];

View File

@ -19,8 +19,9 @@
* 2. Altered source versions must be plainly marked as such, and must not be * 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. * misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/ */
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -461,8 +462,8 @@ int AMXAPI dbg_GetVariable(AMX_DBG *amxdbg, const char *symname, ucell scopeaddr
break; break;
/* check the range, keep a pointer to the symbol with the smallest range */ /* check the range, keep a pointer to the symbol with the smallest range */
if (strcmp(amxdbg->symboltbl[index]->name, symname) == 0 if (strcmp(amxdbg->symboltbl[index]->name, symname) == 0
&& ((codestart == 0 && codeend == 0) && (codestart == 0 && codeend == 0
|| (amxdbg->symboltbl[index]->codestart >= codestart && amxdbg->symboltbl[index]->codeend <= codeend))) || amxdbg->symboltbl[index]->codestart >= codestart && amxdbg->symboltbl[index]->codeend <= codeend))
{ {
*sym = amxdbg->symboltbl[index]; *sym = amxdbg->symboltbl[index];
codestart = amxdbg->symboltbl[index]->codestart; codestart = amxdbg->symboltbl[index]->codestart;

View File

@ -20,6 +20,8 @@
* 2. Altered source versions must be plainly marked as such, and must not be * 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. * misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/ */
#ifndef AMXDBG_H_INCLUDED #ifndef AMXDBG_H_INCLUDED
@ -47,7 +49,7 @@ extern "C" {
#endif #endif
#if !defined AMX_NO_ALIGN #if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__ #if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
#elif defined MACOS && defined __MWERKS__ #elif defined MACOS && defined __MWERKS__
#pragma options align=mac68k #pragma options align=mac68k
@ -63,8 +65,8 @@ extern "C" {
typedef struct tagAMX_DBG_HDR { typedef struct tagAMX_DBG_HDR {
int32_t size PACKED; /* size of the debug information chunk */ int32_t size PACKED; /* size of the debug information chunk */
uint16_t magic PACKED; /* signature, must be 0xf1ef */ uint16_t magic PACKED; /* signature, must be 0xf1ef */
char file_version; /* file format version */ char file_version PACKED; /* file format version */
char amx_version; /* required version of the AMX */ char amx_version PACKED; /* required version of the AMX */
int16_t flags PACKED; /* currently unused */ int16_t flags PACKED; /* currently unused */
int16_t files PACKED; /* number of entries in the "file" table */ int16_t files PACKED; /* number of entries in the "file" table */
int16_t lines PACKED; /* number of entries in the "line" table */ int16_t lines PACKED; /* number of entries in the "line" table */
@ -72,51 +74,51 @@ typedef struct tagAMX_DBG_HDR {
int16_t tags PACKED; /* number of entries in the "tag" table */ int16_t tags PACKED; /* number of entries in the "tag" table */
int16_t automatons PACKED; /* number of entries in the "automaton" table */ int16_t automatons PACKED; /* number of entries in the "automaton" table */
int16_t states PACKED; /* number of entries in the "state" table */ int16_t states PACKED; /* number of entries in the "state" table */
} PACKED AMX_DBG_HDR; } AMX_DBG_HDR PACKED;
#define AMX_DBG_MAGIC 0xf1ef #define AMX_DBG_MAGIC 0xf1ef
typedef struct tagAMX_DBG_FILE { typedef struct tagAMX_DBG_FILE {
ucell address PACKED; /* address in the code segment where generated code (for this file) starts */ ucell address PACKED; /* address in the code segment where generated code (for this file) starts */
const char name[1]; /* ASCII string, zero-terminated */ const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_FILE; } AMX_DBG_FILE PACKED;
typedef struct tagAMX_DBG_LINE { typedef struct tagAMX_DBG_LINE {
ucell address PACKED; /* address in the code segment where generated code (for this line) starts */ ucell address PACKED; /* address in the code segment where generated code (for this line) starts */
int32_t line PACKED; /* line number */ int32_t line PACKED; /* line number */
} PACKED AMX_DBG_LINE; } AMX_DBG_LINE PACKED;
typedef struct tagAMX_DBG_SYMBOL { typedef struct tagAMX_DBG_SYMBOL {
ucell address PACKED; /* address in the data segment or relative to the frame */ ucell address PACKED; /* address in the data segment or relative to the frame */
int16_t tag PACKED; /* tag for the symbol */ int16_t tag PACKED; /* tag for the symbol */
ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */ ucell codestart PACKED; /* address in the code segment from which this symbol is valid (in scope) */
ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */ ucell codeend PACKED; /* address in the code segment until which this symbol is valid (in scope) */
char ident; /* kind of symbol (function/variable) */ char ident PACKED; /* kind of symbol (function/variable) */
char vclass; /* class of symbol (global/local) */ char vclass PACKED; /* class of symbol (global/local) */
int16_t dim PACKED; /* number of dimensions */ int16_t dim PACKED; /* number of dimensions */
const char name[1]; /* ASCII string, zero-terminated */ const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_SYMBOL; } AMX_DBG_SYMBOL PACKED;
typedef struct tagAMX_DBG_SYMDIM { typedef struct tagAMX_DBG_SYMDIM {
int16_t tag PACKED; /* tag for the array dimension */ int16_t tag PACKED; /* tag for the array dimension */
ucell size PACKED; /* size of the array dimension */ ucell size PACKED; /* size of the array dimension */
} PACKED AMX_DBG_SYMDIM; } AMX_DBG_SYMDIM PACKED;
typedef struct tagAMX_DBG_TAG { typedef struct tagAMX_DBG_TAG {
int16_t tag PACKED; /* tag id */ int16_t tag PACKED; /* tag id */
const char name[1]; /* ASCII string, zero-terminated */ const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_TAG; } AMX_DBG_TAG PACKED;
typedef struct tagAMX_DBG_MACHINE { typedef struct tagAMX_DBG_MACHINE {
int16_t automaton PACKED; /* automaton id */ int16_t automaton PACKED; /* automaton id */
ucell address PACKED; /* address of state variable */ ucell address PACKED; /* address of state variable */
const char name[1]; /* ASCII string, zero-terminated */ const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_MACHINE; } AMX_DBG_MACHINE PACKED;
typedef struct tagAMX_DBG_STATE { typedef struct tagAMX_DBG_STATE {
int16_t state PACKED; /* state id */ int16_t state PACKED; /* state id */
int16_t automaton PACKED; /* automaton id */ int16_t automaton PACKED; /* automaton id */
const char name[1]; /* ASCII string, zero-terminated */ const char name[1] PACKED; /* ASCII string, zero-terminated */
} PACKED AMX_DBG_STATE; } AMX_DBG_STATE PACKED;
typedef struct tagAMX_DBG { typedef struct tagAMX_DBG {
AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */ AMX_DBG_HDR _FAR *hdr PACKED; /* points to the AMX_DBG header */
@ -126,7 +128,7 @@ typedef struct tagAMX_DBG {
AMX_DBG_TAG _FAR **tagtbl PACKED; AMX_DBG_TAG _FAR **tagtbl PACKED;
AMX_DBG_MACHINE _FAR **automatontbl PACKED; AMX_DBG_MACHINE _FAR **automatontbl PACKED;
AMX_DBG_STATE _FAR **statetbl PACKED; AMX_DBG_STATE _FAR **statetbl PACKED;
} PACKED AMX_DBG; } AMX_DBG PACKED;
#if !defined iVARIABLE #if !defined iVARIABLE
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */ #define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
@ -154,7 +156,7 @@ int AMXAPI dbg_GetArrayDim(AMX_DBG *amxdbg, const AMX_DBG_SYMBOL *sym, const AMX
#if !defined AMX_NO_ALIGN #if !defined AMX_NO_ALIGN
#if defined LINUX || defined __FreeBSD__ || defined __APPLE__ #if defined LINUX || defined __FreeBSD__
#pragma pack() /* reset default packing */ #pragma pack() /* reset default packing */
#elif defined MACOS && defined __MWERKS__ #elif defined MACOS && defined __MWERKS__
#pragma options align=reset #pragma options align=reset

View File

@ -56,9 +56,6 @@
; ;
;History (list of changes) ;History (list of changes)
;------------------------- ;-------------------------
; 24 february 2013 by Scott Ehlert
; Aligned stack to 16-byte boundary for native calls in case they make library
; calls on Mac OS X or use SSE instructions.
; 10 february 2006 by David Anderson ; 10 february 2006 by David Anderson
; Addition of float opcodes ; Addition of float opcodes
; 17 february 2005 by Thiadmer Riemersms ; 17 february 2005 by Thiadmer Riemersms
@ -192,21 +189,6 @@
%endif %endif
%endmacro %endmacro
%macro _STK_ALIGN 1 ; align stack to 16-byte boundary and
; allocate %1 bytes of stack space
%if %1 % 16 != 0
%error "expected 16-byte aligned value"
%endif
push edi
mov edi, esp
and esp, 0xFFFFFFF0
sub esp, %1
%endmacro
%macro _STK_RESTORE 0 ; restore stack pointer after 16-byte alignment
mov esp, edi
pop edi
%endmacro
Start_CODE Start_CODE
@ -1283,15 +1265,13 @@ OP_SYSREQ_PRI:
push ebp push ebp
push esi push esi
push edi push edi
_STK_ALIGN 16 ; align stack to 16-byte boundary and
; allocate 16 bytes of stack space
; push the parameters ; push the parameters
mov [esp+12], ecx push ecx
mov [esp+08], ebx push ebx
mov [esp+04], edx push edx
mov [esp], eax push eax
call [ebp+_callback] call [ebp+_callback]
_STK_RESTORE ; restore stack pointer _DROPARGS 10h ; remove arguments from stack
pop edi ; restore saved registers pop edi ; restore saved registers
pop esi pop esi
pop ebp pop ebp
@ -1328,13 +1308,11 @@ OP_SYSREQ_D: ; (TR)
push ebp push ebp
push esi push esi
push edi push edi
_STK_ALIGN 16 ; align stack to 16-byte boundary and
; allocate 16 bytes of stack space
; push the parameters ; push the parameters
mov [esp+04], edx push edx
mov [esp], eax push eax
call ebx ; direct call call ebx ; direct call
_STK_RESTORE ; restore stack pointer _DROPARGS 8 ; remove arguments from stack
pop edi ; restore saved registers pop edi ; restore saved registers
pop esi pop esi
pop ebp pop ebp
@ -1480,7 +1458,7 @@ OP_FLOAT_ROUND:
push 0 push 0
mov ebp,esp mov ebp,esp
fstcw [ebp] fstcw [ebp]
mov eax,[ebp] mov eax,[ebp]
push eax push eax
;clear the top bits ;clear the top bits
xor ah,ah xor ah,ah
@ -1492,24 +1470,14 @@ OP_FLOAT_ROUND:
;set the bits ;set the bits
or ah,dl ;set bits 15,14 of FCW to rounding method or ah,dl ;set bits 15,14 of FCW to rounding method
or ah,3 ;set precision to 64bit or ah,3 ;set precision to 64bit
;calculate
sub esp,4
fld dword [edi+ecx+4]
test edx,edx
jnz .skip_correct
;nearest mode
;correct so as to AVOID bankers rounding
or ah, 4 ;set rounding mode to floor
fadd dword [g_round_nearest]
.skip_correct:
mov [ebp], eax mov [ebp], eax
fldcw [ebp] fldcw [ebp]
;calculate
push 0
fld dword [edi+ecx+4]
frndint frndint
fistp dword [esp] fistp dword [esp]
pop eax pop eax
.done:
pop edx pop edx
;restore bits ;restore bits
pop ebp pop ebp
@ -1553,11 +1521,9 @@ OP_BREAK:
; call the debug hook ; call the debug hook
mov eax,ebp ; 1st parm: amx mov eax,ebp ; 1st parm: amx
_SAVEREGS _SAVEREGS
_STK_ALIGN 16 ; align stack to 16-byte boundary and push eax
; allocate 16 bytes of stack space
mov [esp], eax
call [ebp+_debug] ; call debug function call [ebp+_debug] ; call debug function
_STK_RESTORE ; restore stack pointer _DROPARGS 4 ; remove arguments from stack
cmp eax,AMX_ERR_NONE cmp eax,AMX_ERR_NONE
je short break_noabort; continue running je short break_noabort; continue running
mov [ebp+_error],eax ; save EAX (error code) before restoring all regs mov [ebp+_error],eax ; save EAX (error code) before restoring all regs
@ -1627,8 +1593,6 @@ Start_DATA
lodb_and DD 0ffh, 0ffffh, 0, 0ffffffffh lodb_and DD 0ffh, 0ffffh, 0, 0ffffffffh
g_round_nearest DD 0.5
GLOBAL g_flags GLOBAL g_flags
g_flags: g_flags:
DD -1 DD -1
@ -1776,10 +1740,10 @@ _amx_opcodelist DD OP_INVALID
DD OP_SYSREQ_D DD OP_SYSREQ_D
DD OP_SYMTAG DD OP_SYMTAG
DD OP_BREAK DD OP_BREAK
DD OP_FLOAT_MUL DD OP_FLOAT_MUL
DD OP_FLOAT_DIV DD OP_FLOAT_DIV
DD OP_FLOAT_ADD DD OP_FLOAT_ADD
DD OP_FLOAT_SUB DD OP_FLOAT_SUB
DD OP_FLOAT_TO DD OP_FLOAT_TO
DD OP_FLOAT_ROUND DD OP_FLOAT_ROUND
DD OP_FLOAT_CMP DD OP_FLOAT_CMP

View File

@ -6,14 +6,6 @@
; (27 disks, no output, DOS4/GW under Win95) with this implementation of the ; (27 disks, no output, DOS4/GW under Win95) with this implementation of the
; JIT compiler. ; JIT compiler.
; BUILD NOTE: Use nasm 0.97.x or 0.98.x with the options below.
; ----------------
; Windows : nasm -O2 -f win32 -o amxjitsn.obj amxjitsn.asm
; Linux : nasm -O2 -f elf -o amxjitsn.o amxjitsn.asm
; OS X : nasm -O2 -f macho -o amxjitsn-darwin.o amxjitsn.asm
; ----------------
; If nasm 2.x must be used, replace -O2 with -O0.
; NOTE 1: ; NOTE 1:
; There is only one pass implemented in this version. This means there is no ; There is only one pass implemented in this version. This means there is no
; way of knowing the size of the compiled code before it has actually been com- ; way of knowing the size of the compiled code before it has actually been com-
@ -98,9 +90,6 @@
; Revision History ; Revision History
; ---------------- ; ----------------
; 24 february 2013 by Scott Ehlert
; Aligned stack to 16-byte boundary for native calls in case they make library
; calls on Mac OS X or use SSE instructions.
; 16 august 2005 by David "BAILOPAN" Anderson (DA) ; 16 august 2005 by David "BAILOPAN" Anderson (DA)
; Changed JIT to not swap stack pointer during execution. This ; Changed JIT to not swap stack pointer during execution. This
; is playing with fire, especially with pthreads and signals on linux, ; is playing with fire, especially with pthreads and signals on linux,
@ -314,31 +303,13 @@
%endif %endif
%endmacro %endmacro
%macro _STK_ALIGN 1 ; align stack to 16-byte boundary and
; allocate %1 bytes of stack space
; top of stack allocation will hold original esp
%if %1 % 16 != 0
%error "expected 16-byte aligned value"
%endif
%push stkalign %ifdef WIN32
%assign stkspace %1 section .data exec
%else
section .text
%endif
mov ebp, esp
and esp, 0xFFFFFFF0
sub esp, %1
mov [esp+%1-4], ebp
%endmacro
%macro _STK_RESTORE 0 ; restore stack pointer after 16-byte alignment
%ifnctx stkalign
%fatal "expected _STK_ALIGN before _STK_RESTORE"
%endif
mov esp, [esp+stkspace-4]
%pop
%endmacro
global asm_runJIT, _asm_runJIT global asm_runJIT, _asm_runJIT
global amx_exec_jit, _amx_exec_jit global amx_exec_jit, _amx_exec_jit
@ -465,6 +436,15 @@ reloc_done:
pop ebp pop ebp
ret ret
; GWMV:
; The code below modifies itself to store the arguments to the Pawn opcodes
; in the compiled code. This is fine, but the .text section in an ELF executable
; is usually marked read-only, that's why this code is in the .data section.
%ifndef WIN32
section .data exec
%endif
OP_LOAD_PRI: OP_LOAD_PRI:
;nop; ;nop;
putval j_load_pri+2 putval j_load_pri+2
@ -1072,7 +1052,7 @@ OP_CALL:
j_call: j_call:
;call 12345678h ; tasm chokes on this out of a sudden ;call 12345678h ; tasm chokes on this out of a sudden
_PUSH 0 _PUSH 0
j_call_e8: j_call_e8
db 0e8h, 0, 0, 0, 0 db 0e8h, 0, 0, 0, 0
CHECKCODESIZE j_call CHECKCODESIZE j_call
@ -1979,24 +1959,14 @@ OP_FLOAT_ROUND:
;set the bits ;set the bits
or ah,dl ;set bits 15,14 of FCW to rounding method or ah,dl ;set bits 15,14 of FCW to rounding method
or ah,3 ;set precision to 64bit or ah,3 ;set precision to 64bit
;calculate
sub esp,4
fld dword [esi+4]
test edx,edx
jnz .skip_correct
;nearest mode
;correct so as to AVOID bankers rounding
or ah, 4 ;set rounding mode to floor
fadd dword [g_round_nearest]
.skip_correct:
mov [ebp], eax mov [ebp], eax
fldcw [ebp] fldcw [ebp]
;calculate
push 0
fld dword [esi+4]
frndint frndint
fistp dword [esp] fistp dword [esp]
pop eax pop eax
.done:
pop edx pop edx
;restore bits ;restore bits
pop ebp pop ebp
@ -2140,9 +2110,7 @@ err_heaplow:
_CHKMARGIN_HEAP: _CHKMARGIN_HEAP:
cmp esi,stp cmp esi,stp
jg err_stacklow jg err_stacklow
mov ebp,amx cmp dword hea,0
mov ebp,[ebp+_hlw]
cmp dword hea,ebp
jl err_heaplow jl err_heaplow
ret ret
@ -2273,10 +2241,8 @@ err_divide:
jmp _return_popstack jmp _return_popstack
JIT_OP_SYSREQ: JIT_OP_SYSREQ:
_STK_ALIGN 32 ; align stack to 16-byte boundary and push ecx
; allocate 32 bytes of stack space push esi
mov [esp+16], ecx
mov [esp+12], esi
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
sub esi,edi ; correct STK sub esi,edi ; correct STK
@ -2291,15 +2257,14 @@ JIT_OP_SYSREQ:
lea ebx,pri ; 3rd param: addr. of retval lea ebx,pri ; 3rd param: addr. of retval
;Our original esi is still pushed! ;Our original esi is still pushed!
mov [esp+08], ebx push ebx
mov [esp+04], eax ; 2nd param: function number push eax ; 2nd param: function number
mov [esp], ebp ; 1st param: amx push ebp ; 1st param: amx
call [ebp+_callback] call [ebp+_callback]
_DROPARGS 12 ; remove args from stack
mov esi, [esp+12] ; restore esi pop esi
mov ecx, [esp+16] ; restore ecx pop ecx
_STK_RESTORE ; restore stack pointer
cmp eax,AMX_ERR_NONE cmp eax,AMX_ERR_NONE
jne _return_popstack jne _return_popstack
.continue: .continue:
@ -2311,10 +2276,8 @@ JIT_OP_SYSREQ:
JIT_OP_SYSREQ_D: ; (TR) JIT_OP_SYSREQ_D: ; (TR)
_STK_ALIGN 16 ; align stack to 16-byte boundary and push ecx
; allocate 16 bytes of stack space push esi
mov [esp+08], ecx
mov [esp+04], esi
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
sub esi,edi ; correct STK sub esi,edi ; correct STK
@ -2327,12 +2290,11 @@ JIT_OP_SYSREQ_D: ; (TR)
mov [ebp+_frm],eax ; eax & ecx are invalid by now mov [ebp+_frm],eax ; eax & ecx are invalid by now
;esi is still pushed! ;esi is still pushed!
mov [esp], ebp ; 1st param: amx push ebp ; 1st param: amx
call ebx ; direct call call ebx ; direct call
_DROPARGS 8 ; remove args from stack
mov ecx, [esp+08] ; restore ecx
_STK_RESTORE ; restore stack pointer pop ecx
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
cmp dword [ebp+_error],AMX_ERR_NONE cmp dword [ebp+_error],AMX_ERR_NONE
jne _return_popstack; return error code, if any jne _return_popstack; return error code, if any
@ -2346,10 +2308,8 @@ JIT_OP_SYSREQ_D: ; (TR)
JIT_OP_BREAK: JIT_OP_BREAK:
%ifdef DEBUGSUPPORT %ifdef DEBUGSUPPORT
_STK_ALIGN 16 ; align stack to 16-byte boundary and push ecx
; allocate 16 bytes of stack space push esi
mov [esp+08], ecx
mov [esp+04], esi
mov ebp,amx ; get amx into EBP mov ebp,amx ; get amx into EBP
sub esi,edi ; correct STK sub esi,edi ; correct STK
@ -2363,13 +2323,12 @@ JIT_OP_BREAK:
mov [ebp+_frm],ebx ; EBX & ECX are invalid by now mov [ebp+_frm],ebx ; EBX & ECX are invalid by now
;??? storing CIP is not very useful, because the code changed (during JIT compile) ;??? storing CIP is not very useful, because the code changed (during JIT compile)
mov [esp], ebp ; 1st param: amx push ebp ; 1st param: amx
call [ebp+_debug] call [ebp+_debug]
_DROPARGS 4 ; remove args from stack
mov esi, [esp+04] ; restore esi pop esi
mov ecx, [esp+08] ; restore ecx pop ecx
_STK_RESTORE ; restore stack pointer
cmp eax,AMX_ERR_NONE cmp eax,AMX_ERR_NONE
jne _return_popstack; return error code, if any jne _return_popstack; return error code, if any
@ -2463,10 +2422,6 @@ g_flagsjit:
DD -1 DD -1
DD 0 DD 0
DD 1 DD 1
global g_round_nearest
g_round_nearest:
DD 0.5
global amx_opcodelist_jit, _amx_opcodelist_jit global amx_opcodelist_jit, _amx_opcodelist_jit
@ -2618,4 +2573,4 @@ _amx_opcodelist_jit:
DD OP_FLOAT_ROUND ; DA DD OP_FLOAT_ROUND ; DA
DD OP_FLOAT_CMP ; DA DD OP_FLOAT_CMP ; DA
END: END

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,38 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef AMXMODX_H #ifndef AMXMODX_H
#define AMXMODX_H #define AMXMODX_H
#if defined PLATFORM_POSIX #ifdef __linux__
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include "sclinux.h" #include "sclinux.h"
@ -20,23 +42,17 @@
#include <extdll.h> #include <extdll.h>
#include <meta_api.h> #include <meta_api.h>
#ifdef _MSC_VER #ifdef MEMORY_TEST
// MSVC8 - replace POSIX functions with ISO C++ conformant ones as they are deprecated #include "mmgr/mmgr.h"
#if _MSC_VER >= 1400
#define unlink _unlink
#define mkdir _mkdir
#define strdup _strdup
#endif
#endif #endif
#include "hashing.h" #include "md5.h"
#include "CVector.h"
#include "CList.h"
#include "CQueue.h"
#include "modules.h" #include "modules.h"
#include "CString.h"
#include "CPlugin.h" #include "CPlugin.h"
#include "CLibrarySys.h"
#include <auto-string.h>
#include <amtl/am-string.h>
#include <amtl/am-vector.h>
#include <amtl/am-inlinelist.h>
#include "CMisc.h" #include "CMisc.h"
#include "CVault.h" #include "CVault.h"
#include "CModule.h" #include "CModule.h"
@ -44,18 +60,14 @@
#include "CLogEvent.h" #include "CLogEvent.h"
#include "CForward.h" #include "CForward.h"
#include "CCmd.h" #include "CCmd.h"
#include "CMenu.h"
#include "CEvent.h" #include "CEvent.h"
#include "CLang.h" #include "CLang.h"
#include "fakemeta.h" #include "fakemeta.h"
#include "amxxlog.h" #include "amxxlog.h"
#include "CvarManager.h"
#include "CoreConfig.h"
#include "CFrameAction.h"
#include <amxmodx_version.h>
#include <HLTypeConversion.h>
#define AMXXLOG_Log g_log.Log #define AMXXLOG_Log g_log.Log
#define AMXXLOG_Error g_log.LogError #define AMX_VERSION "1.70"
extern AMX_NATIVE_INFO core_Natives[]; extern AMX_NATIVE_INFO core_Natives[];
extern AMX_NATIVE_INFO time_Natives[]; extern AMX_NATIVE_INFO time_Natives[];
@ -65,21 +77,13 @@ extern AMX_NATIVE_INFO file_Natives[];
extern AMX_NATIVE_INFO float_Natives[]; extern AMX_NATIVE_INFO float_Natives[];
extern AMX_NATIVE_INFO string_Natives[]; extern AMX_NATIVE_INFO string_Natives[];
extern AMX_NATIVE_INFO vault_Natives[]; extern AMX_NATIVE_INFO vault_Natives[];
extern AMX_NATIVE_INFO msg_Natives[];
extern AMX_NATIVE_INFO vector_Natives[];
extern AMX_NATIVE_INFO g_SortNatives[];
extern AMX_NATIVE_INFO g_DataStructNatives[];
extern AMX_NATIVE_INFO g_StackNatives[];
extern AMX_NATIVE_INFO g_TextParserNatives[];
extern AMX_NATIVE_INFO g_CvarNatives[];
extern AMX_NATIVE_INFO g_GameConfigNatives[];
#if defined PLATFORM_WINDOWS #ifndef __linux__
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path) #define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
#define DLPROC(m, func) GetProcAddress(m, func) #define DLPROC(m, func) GetProcAddress(m, func)
#define DLFREE(m) FreeLibrary(m) #define DLFREE(m) FreeLibrary(m)
#else #else
#define DLLOAD(path) (DLHANDLE)dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND) #define DLLOAD(path) (DLHANDLE)dlopen(path, RTLD_NOW)
#define DLPROC(m, func) dlsym(m, func) #define DLPROC(m, func) dlsym(m, func)
#define DLFREE(m) dlclose(m) #define DLFREE(m) dlclose(m)
#endif #endif
@ -95,7 +99,7 @@ extern AMX_NATIVE_INFO g_GameConfigNatives[];
#endif #endif
#endif #endif
#if defined PLATFORM_WINDOWS #ifndef __linux__
typedef HINSTANCE DLHANDLE; typedef HINSTANCE DLHANDLE;
#else #else
typedef void* DLHANDLE; typedef void* DLHANDLE;
@ -113,34 +117,19 @@ extern AMX_NATIVE_INFO g_GameConfigNatives[];
#define SETCLIENTLISTENING (*g_engfuncs.pfnVoice_SetClientListening) #define SETCLIENTLISTENING (*g_engfuncs.pfnVoice_SetClientListening)
#define SETCLIENTMAXSPEED (*g_engfuncs.pfnSetClientMaxspeed) #define SETCLIENTMAXSPEED (*g_engfuncs.pfnSetClientMaxspeed)
#define MAX_BUFFER_LENGTH 16384
char* UTIL_SplitHudMessage(register const char *src); char* UTIL_SplitHudMessage(register const char *src);
int UTIL_ReadFlags(const char* c); int UTIL_ReadFlags(const char* c);
void UTIL_ClientPrint(edict_t *pEntity, int msg_dest, char *msg); void UTIL_ClientPrint(edict_t *pEntity, int msg_dest, char *msg);
void UTIL_FakeClientCommand(edict_t *pEdict, const char *cmd, const char *arg1 = NULL, const char *arg2 = NULL, bool fwd = false); void UTIL_FakeClientCommand(edict_t *pEdict, const char *cmd, const char *arg1 = NULL, const char *arg2 = NULL);
void UTIL_GetFlags(char* flags, int flag); void UTIL_GetFlags(char* flags, int flag);
void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage); void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, char *pMessage);
void UTIL_DHudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage, unsigned int length);
void UTIL_IntToString(int value, char *output); void UTIL_IntToString(int value, char *output);
void UTIL_ShowMOTD(edict_t *client, char *motd, int mlen, const char *name); void UTIL_ShowMOTD(edict_t *client, char *motd, int mlen, const char *name);
void UTIL_ShowMenu(edict_t* pEntity, int slots, int time, char *menu, int mlen); void UTIL_ShowMenu(edict_t* pEntity, int slots, int time, char *menu, int mlen);
void UTIL_ClientSayText(edict_t *pEntity, int sender, char *msg);
void UTIL_TeamInfo(edict_t *pEntity, int playerIndex, const char *pszTeamName);
template <typename D> int UTIL_CheckValidChar(D *c); char *UTIL_VarArgs(const char *fmt, ...);
template <typename D, typename S> unsigned int strncopy(D *dest, const S *src, size_t count);
unsigned int UTIL_GetUTF8CharBytes(const char *stream);
size_t UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace, bool caseSensitive);
size_t UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive);
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive);
void UTIL_TrimLeft(char *buffer);
void UTIL_TrimRight(char *buffer);
char* utf8stristr(const char *string1, const char *string2);
int utf8strncasecmp(const char *string1, const char *string2, size_t n);
int utf8strcasecmp(const char *string1, const char *string2);
#define GET_PLAYER_POINTER(e) (&g_players[ENTINDEX(e)]) #define GET_PLAYER_POINTER(e) (&g_players[ENTINDEX(e)])
//#define GET_PLAYER_POINTER(e) (&g_players[(((int)e-g_edict_point)/sizeof(edict_t))]) //#define GET_PLAYER_POINTER(e) (&g_players[(((int)e-g_edict_point)/sizeof(edict_t))])
@ -148,7 +137,7 @@ int utf8strcasecmp(const char *string1, const char *string2);
struct WeaponsVault struct WeaponsVault
{ {
ke::AString fullName; String fullName;
short int iId; short int iId;
short int ammoSlot; short int ammoSlot;
}; };
@ -159,28 +148,28 @@ struct fakecmd_t
const char *argv[3]; const char *argv[3];
int argc; int argc;
bool fake; bool fake;
bool notify; // notify to plugins.
}; };
extern CLog g_log; extern CLog g_log;
extern CPluginMngr g_plugins; extern CPluginMngr g_plugins;
extern CTaskMngr g_tasksMngr; extern CTaskMngr g_tasksMngr;
extern CFrameActionMngr g_frameActionMngr;
extern CPlayer g_players[33]; extern CPlayer g_players[33];
extern CPlayer* mPlayer; extern CPlayer* mPlayer;
extern CmdMngr g_commands; extern CmdMngr g_commands;
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcemodels; extern CList<CCVar> g_cvars;
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcesounds; extern CList<ForceObject> g_forcemodels;
extern ke::Vector<ke::AutoPtr<ForceObject>> g_forcegeneric; extern CList<ForceObject> g_forcesounds;
extern ke::Vector<ke::AutoPtr<CPlayer *>> g_auth; extern CList<ForceObject> g_forcegeneric;
extern ke::InlineList<CModule> g_modules; extern CList<CModule, const char *> g_modules;
extern ke::InlineList<CScript> g_loadedscripts; extern CList<CScript, AMX*> g_loadedscripts;
extern CList<CPlayer*> g_auth;
extern EventsMngr g_events; extern EventsMngr g_events;
extern Grenades g_grenades; extern Grenades g_grenades;
extern LogEventsMngr g_logevents; extern LogEventsMngr g_logevents;
extern MenuMngr g_menucmds;
extern CLangMngr g_langMngr; extern CLangMngr g_langMngr;
extern ke::AString g_log_dir; extern String g_log_dir;
extern ke::AString g_mod_name; extern String g_mod_name;
extern TeamIds g_teamsIds; extern TeamIds g_teamsIds;
extern Vault g_vault; extern Vault g_vault;
extern CForwardMngr g_forwards; extern CForwardMngr g_forwards;
@ -188,17 +177,9 @@ extern WeaponsVault g_weaponsData[MAX_WEAPONS];
extern XVars g_xvars; extern XVars g_xvars;
extern bool g_bmod_cstrike; extern bool g_bmod_cstrike;
extern bool g_bmod_dod; extern bool g_bmod_dod;
extern bool g_bmod_dmc;
extern bool g_bmod_ricochet;
extern bool g_bmod_valve;
extern bool g_bmod_gearbox;
extern bool g_official_mod;
extern bool g_dontprecache; extern bool g_dontprecache;
extern int g_srvindex; extern int g_srvindex;
extern cvar_t* amxmodx_version; extern cvar_t* amxmodx_version;
extern cvar_t* amxmodx_debug;
extern cvar_t* amxmodx_language;
extern cvar_t* amxmodx_perflog;
extern cvar_t* hostname; extern cvar_t* hostname;
extern cvar_t* mp_timelimit; extern cvar_t* mp_timelimit;
extern fakecmd_t g_fakecmd; extern fakecmd_t g_fakecmd;
@ -239,8 +220,6 @@ extern int gmsgWeaponList;
extern int gmsgintermission; extern int gmsgintermission;
extern int gmsgResetHUD; extern int gmsgResetHUD;
extern int gmsgRoundTime; extern int gmsgRoundTime;
extern int gmsgSayText;
extern int gmsgInitHUD;
void Client_AmmoPickup(void*); void Client_AmmoPickup(void*);
void Client_AmmoX(void*); void Client_AmmoX(void*);
@ -253,7 +232,6 @@ void Client_VGUIMenu(void*);
void Client_WeaponList(void*); void Client_WeaponList(void*);
void Client_DamageEnd(void*); void Client_DamageEnd(void*);
void Client_DeathMsg(void*); void Client_DeathMsg(void*);
void Client_InitHUDEnd(void*);
void amx_command(); void amx_command();
void plugin_srvcmd(); void plugin_srvcmd();
@ -265,6 +243,10 @@ int loadModules(const char* filename, PLUG_LOADTIME now);
void detachModules(); void detachModules();
void detachReloadModules(); void detachReloadModules();
#ifdef FAKEMETA
void attachModules();
#endif
// Count modules // Count modules
enum CountModulesMode enum CountModulesMode
{ {
@ -275,37 +257,31 @@ enum CountModulesMode
int countModules(CountModulesMode mode); int countModules(CountModulesMode mode);
void modules_callPluginsLoaded(); void modules_callPluginsLoaded();
void modules_callPluginsUnloaded();
void modules_callPluginsUnloading();
cell* get_amxaddr(AMX *amx, cell amx_addr); cell* get_amxaddr(AMX *amx, cell amx_addr);
char* build_pathname(const char *fmt, ...); char* build_pathname(char *fmt, ...);
char* build_pathname_r(char *buffer, size_t maxlen, const char *fmt, ...); char* build_pathname_r(char *buffer, size_t maxlen, char *fmt, ...);
char* format_amxstring(AMX *amx, cell *params, int parm, int& len); char* format_amxstring(AMX *amx, cell *params, int parm, int& len);
AMX* get_amxscript(int, void**, const char**); AMX* get_amxscript(int, void**, const char**);
const char* get_amxscriptname(AMX* amx); const char* get_amxscriptname(AMX* amx);
char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len); char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len);
char* get_amxstring_null(AMX *amx, cell amx_addr, int id, int& len);
cell* get_amxvector_null(AMX *amx, cell amx_addr);
extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, int maxlen); extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, int maxlen);
int amxstring_len(cell* cstr); int amxstring_len(cell* cstr);
int load_amxscript(AMX* amx, void** program, const char* path, char error[64], int debug); int load_amxscript(AMX* amx, void** program, const char* path, char error[64], int debug);
int load_amxscript_ex(AMX* amx, void** program, const char* path, char *error, size_t maxLength, int debug);
int set_amxnatives(AMX* amx, char error[64]); int set_amxnatives(AMX* amx, char error[64]);
int set_amxstring(AMX *amx, cell amx_addr, const char *source, int max); int set_amxstring(AMX *amx, cell amx_addr, const char *source, int max);
int set_amxstring_simple(cell *dest, const char *source, int max);
template <typename T> int set_amxstring_utf8(AMX *amx, cell amx_addr, const T *source, size_t sourcelen, size_t maxlen);
int set_amxstring_utf8_char(AMX *amx, cell amx_addr, const char *source, size_t sourcelen, size_t maxlen);
int set_amxstring_utf8_cell(AMX *amx, cell amx_addr, const cell *source, size_t sourcelen, size_t maxlen);
int unload_amxscript(AMX* amx, void** program); int unload_amxscript(AMX* amx, void** program);
void copy_amxmemory(cell* dest, cell* src, int len); void copy_amxmemory(cell* dest, cell* src, int len);
void get_modname(char*); void get_modname(char*);
void print_srvconsole(const char *fmt, ...); void print_srvconsole(char *fmt, ...);
void report_error(int code, const char* fmt, ...); void report_error(int code, char* fmt, ...);
void* alloc_amxmemory(void**, int size);
void free_amxmemory(void **ptr);
// get_localinfo // get_localinfo
const char* get_localinfo(const char* name, const char* def); const char* get_localinfo(const char* name, const char* def);
cell AMX_NATIVE_CALL require_module(AMX *amx, cell *params);
extern "C" void LogError(AMX *amx, int err, const char *fmt, ...); extern "C" void LogError(AMX *amx, int err, const char *fmt, ...);
enum ModuleCallReason enum ModuleCallReason
@ -340,8 +316,6 @@ extern int FF_PluginEnd;
extern int FF_InconsistentFile; extern int FF_InconsistentFile;
extern int FF_ClientAuthorized; extern int FF_ClientAuthorized;
extern int FF_ChangeLevel; extern int FF_ChangeLevel;
extern int FF_ClientConnectEx;
extern bool g_coloredmenus; extern bool g_coloredmenus;
typedef void (*AUTHORIZEFUNC)(int player, const char *authstring); typedef void (*AUTHORIZEFUNC)(int player, const char *authstring);
@ -354,23 +328,4 @@ struct func_s
const char *desc; const char *desc;
}; };
enum AdminProperty
{
Admin_Auth = 0,
Admin_Password,
Admin_Access,
Admin_Flags
};
enum PrintColor
{
print_team_default = 0,
print_team_grey =-1,
print_team_red = -2,
print_team_blue = -3,
};
extern enginefuncs_t *g_pEngTable;
extern HLTypeConversion TypeConversion;
#endif // AMXMODX_H #endif // AMXMODX_H

View File

@ -2,6 +2,8 @@
* *
* Copyright (c) ITB CompuPhase, 2001-2002 * Copyright (c) ITB CompuPhase, 2001-2002
* This file may be freely used. No warranties of any kind. * This file may be freely used. No warranties of any kind.
*
* Version: $Id$
*/ */
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
@ -52,7 +54,7 @@ static cell AMX_NATIVE_CALL _time(AMX *amx, cell *params)
/* the time() function returns the number of seconds since January 1 1970 /* the time() function returns the number of seconds since January 1 1970
* in Universal Coordinated Time (the successor to Greenwich Mean Time) * in Universal Coordinated Time (the successor to Greenwich Mean Time)
*/ */
return (cell)sec1970; return sec1970;
} }
#if defined __BORLANDC__ || defined __WATCOMC__ #if defined __BORLANDC__ || defined __WATCOMC__

11
amxmodx/amxx_mm.def Executable file
View File

@ -0,0 +1,11 @@
; /usr/local/cross-tools/bin/i386-mingw32msvc-dlltool --base-file /tmp/cc4kB6s0.base --output-exp amx_mm.exp --dllname amx_mm.dll --output-def amx_mm.def --add-stdcall-alias --exclude-symbol=DllMainCRTStartup@12 --def /tmp/ccyI7I7K.def
EXPORTS
GetEngineFunctions @ 1 ;
GetEngineFunctions_Post @ 2 ;
GetEntityAPI2 @ 3 ;
GetEntityAPI2_Post @ 4 ;
GiveFnptrsToDll = GiveFnptrsToDll@8 @ 5 ;
GiveFnptrsToDll@8 @ 6 ;
Meta_Attach @ 7 ;
Meta_Detach @ 8 ;
Meta_Query @ 9 ;

View File

@ -1,11 +1,32 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. * This program is free software; you can redistribute it and/or modify it
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * under the terms of the GNU General Public License as published by the
// https://alliedmods.net/amxmodx-license * Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "amxxfile.h" #include "amxxfile.h"
@ -21,7 +42,7 @@
#define PACKED #define PACKED
#endif #endif
#if defined(__linux__) || defined(__APPLE__) #if defined __linux__
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
#else #else
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
@ -32,7 +53,7 @@
struct TableEntry struct TableEntry
{ {
mint8_t cellSize; mint8_t cellSize PACKED;
mint32_t origSize PACKED; // contains AMX_HEADER->stp mint32_t origSize PACKED; // contains AMX_HEADER->stp
mint32_t offset PACKED; mint32_t offset PACKED;
}; };
@ -88,7 +109,7 @@ CAmxxReader::CAmxxReader(const char *filename, int cellsize)
{ {
DATAREAD(&m_Bh.version, sizeof(int16_t), 1); DATAREAD(&m_Bh.version, sizeof(int16_t), 1);
if (m_Bh.version > MAGIC_VERSION) if (m_Bh.version != MAGIC_VERSION)
{ {
m_Status = Err_OldFile; m_Status = Err_OldFile;
fclose(m_pFile); fclose(m_pFile);
@ -106,7 +127,7 @@ CAmxxReader::CAmxxReader(const char *filename, int cellsize)
for (mint8_t i = 0; i < m_Bh.numPlugins; i++) for (mint8_t i = 0; i < m_Bh.numPlugins; i++)
{ {
pe = &(m_Bh.plugins[(unsigned)i]); pe = &(m_Bh.plugins[i]);
DATAREAD(&pe->cellsize, sizeof(mint8_t), 1); DATAREAD(&pe->cellsize, sizeof(mint8_t), 1);
DATAREAD(&pe->disksize, sizeof(int32_t), 1); DATAREAD(&pe->disksize, sizeof(int32_t), 1);
DATAREAD(&pe->imagesize, sizeof(int32_t), 1); DATAREAD(&pe->imagesize, sizeof(int32_t), 1);
@ -116,7 +137,7 @@ CAmxxReader::CAmxxReader(const char *filename, int cellsize)
for (mint8_t i = 0; i < m_Bh.numPlugins; i++) for (mint8_t i = 0; i < m_Bh.numPlugins; i++)
{ {
pe = &(m_Bh.plugins[(unsigned)i]); pe = &(m_Bh.plugins[i]);
if (pe->cellsize == m_CellSize) if (pe->cellsize == m_CellSize)
{ {
@ -279,7 +300,7 @@ size_t CAmxxReader::GetBufferSize()
#undef DATAREAD #undef DATAREAD
#define DATAREAD(addr, itemsize, itemcount) \ #define DATAREAD(addr, itemsize, itemcount) \
if (fread(addr, itemsize, itemcount, m_pFile) != static_cast<size_t>(itemcount)) \ if (fread(addr, itemsize, itemcount, m_pFile) != itemcount) \
{ \ { \
if (feof(m_pFile)) \ if (feof(m_pFile)) \
m_Status = Err_FileInvalid; \ m_Status = Err_FileInvalid; \
@ -289,18 +310,7 @@ size_t CAmxxReader::GetBufferSize()
m_pFile = NULL; \ m_pFile = NULL; \
return m_Status; \ return m_Status; \
} }
#define DATAREAD_RELEASE(addr, itemsize, itemcount) \
if (fread(addr, itemsize, itemcount, m_pFile) != static_cast<size_t>(itemcount)) \
{ \
if (feof(m_pFile)) \
m_Status = Err_FileInvalid; \
else \
m_Status = Err_FileRead; \
fclose(m_pFile); \
m_pFile = NULL; \
delete[] tempBuffer;\
return m_Status; \
}
CAmxxReader::Error CAmxxReader::GetSection(void *buffer) CAmxxReader::Error CAmxxReader::GetSection(void *buffer)
{ {
if (!m_pFile) if (!m_pFile)
@ -322,7 +332,7 @@ CAmxxReader::Error CAmxxReader::GetSection(void *buffer)
PluginEntry *pe = &(m_Bh.plugins[m_Entry]); PluginEntry *pe = &(m_Bh.plugins[m_Entry]);
char *tempBuffer = new char[m_SectionLength + 1]; char *tempBuffer = new char[m_SectionLength + 1];
fseek(m_pFile, pe->offs, SEEK_SET); fseek(m_pFile, pe->offs, SEEK_SET);
DATAREAD_RELEASE((void *)tempBuffer, 1, m_SectionLength); DATAREAD((void *)tempBuffer, 1, m_SectionLength);
uLongf destLen = GetBufferSize(); uLongf destLen = GetBufferSize();
int result = uncompress((Bytef *)buffer, &destLen, (Bytef *)tempBuffer, m_SectionLength); int result = uncompress((Bytef *)buffer, &destLen, (Bytef *)tempBuffer, m_SectionLength);
delete [] tempBuffer; delete [] tempBuffer;
@ -346,7 +356,7 @@ CAmxxReader::Error CAmxxReader::GetSection(void *buffer)
// read the data to a temporary buffer // read the data to a temporary buffer
char *tempBuffer = new char[m_SectionLength + 1]; char *tempBuffer = new char[m_SectionLength + 1];
//fread(tempBuffer, sizeof(char), m_SectionLength, m_pFile); //fread(tempBuffer, sizeof(char), m_SectionLength, m_pFile);
DATAREAD_RELEASE((void*)tempBuffer, 1, m_SectionLength); DATAREAD((void*)tempBuffer, 1, m_SectionLength);
// decompress // decompress
int result = uncompress((Bytef *)buffer, &destLen, (Bytef *)tempBuffer, m_SectionLength); int result = uncompress((Bytef *)buffer, &destLen, (Bytef *)tempBuffer, m_SectionLength);
delete [] tempBuffer; delete [] tempBuffer;

View File

@ -1,11 +1,33 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef __AMXXFILE_H__ #ifndef __AMXXFILE_H__
#define __AMXXFILE_H__ #define __AMXXFILE_H__
@ -70,7 +92,6 @@ public:
Error GetStatus(); // Get the current status Error GetStatus(); // Get the current status
size_t GetBufferSize(); // Get the size for the buffer size_t GetBufferSize(); // Get the size for the buffer
Error GetSection(void *buffer); // Copy the currently selected section to the buffer Error GetSection(void *buffer); // Copy the currently selected section to the buffer
inline bool IsOldFile() const { return m_OldFile; }
}; };
#endif // __AMXXFILE_H__ #endif // __AMXXFILE_H__

View File

@ -1,11 +1,32 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. *
// *
// This software is licensed under the GNU General Public License, version 3 or higher. * This program is free software; you can redistribute it and/or modify it
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * under the terms of the GNU General Public License as published by the
// https://alliedmods.net/amxmodx-license * Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
// amxx_logging localinfo: // amxx_logging localinfo:
// 0 = no logging // 0 = no logging
@ -14,23 +35,19 @@
// 3 = HL Logs // 3 = HL Logs
#include <time.h> #include <time.h>
#if defined(_WIN32) #ifndef __linux__
#include <io.h> #include <io.h>
#endif #endif
#include "amxmodx.h" #include "amxmodx.h"
#if defined(_WIN32WIN32) #ifndef __linux__
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#endif #endif
#include <amxmodx_version.h>
CLog::CLog() CLog::CLog()
{ {
m_LogType = 0; m_LogType = 0;
m_LogFile = nullptr; m_LogFile.clear();
m_FoundError = false;
m_LoggedErrMap = false;
} }
CLog::~CLog() CLog::~CLog()
@ -41,14 +58,14 @@ CLog::~CLog()
void CLog::CloseFile() void CLog::CloseFile()
{ {
// log "log file closed" to old file, if any // log "log file closed" to old file, if any
if (m_LogFile.length()) if (!m_LogFile.empty())
{ {
FILE *fp = fopen(m_LogFile.chars(), "r"); FILE *fp = fopen(m_LogFile.c_str(), "r");
if (fp) if (fp)
{ {
fclose(fp); fclose(fp);
fp = fopen(m_LogFile.chars(), "a+"); fp = fopen(m_LogFile.c_str(), "a+");
// get time // get time
time_t td; time_t td;
@ -61,99 +78,88 @@ void CLog::CloseFile()
fprintf(fp, "L %s: %s\n", date, "Log file closed."); fprintf(fp, "L %s: %s\n", date, "Log file closed.");
fclose(fp); fclose(fp);
} }
m_LogFile = nullptr; m_LogFile.clear();
} }
} }
void CLog::CreateNewFile() void CLog::CreateNewFile()
{ {
CloseFile(); CloseFile();
// build filename // build filename
time_t td; time_t td;
time(&td); time(&td);
tm *curTime = localtime(&td); tm *curTime = localtime(&td);
char file[PLATFORM_MAX_PATH];
char name[256];
int i = 0; int i = 0;
while (true) while (true)
{ {
ke::SafeSprintf(name, sizeof(name), "%s/L%02d%02d%03d.log", g_log_dir.chars(), curTime->tm_mon + 1, curTime->tm_mday, i); FILE *pTmpFile = fopen(m_LogFile.c_str(), "r"); // open for reading to check whether the file exists
build_pathname_r(file, sizeof(file), "%s", name);
FILE *pTmpFile = fopen(file, "r"); // open for reading to check whether the file exists
if (!pTmpFile) if (!pTmpFile)
break; break;
fclose(pTmpFile); fclose(pTmpFile);
++i; ++i;
} }
m_LogFile = file;
// Log logfile start // Log logfile start
FILE *fp = fopen(m_LogFile.chars(), "w"); FILE *fp = fopen(m_LogFile.c_str(), "w");
if (!fp) if (!fp)
{ {
ALERT(at_logged, "[AMXX] Unexpected fatal logging error. AMXX Logging disabled.\n"); ALERT(at_logged, "[AMXX] Unexpected fatal logging error. AMXX Logging disabled.\n");
SET_LOCALINFO("amxx_logging", "0"); SET_LOCALINFO("amxx_logging", "0");
} else { } else {
fprintf(fp, "AMX Mod X log file started (file \"%s\") (version \"%s\")\n", name, AMXX_VERSION); fprintf(fp, "AMX Mod X log file started (file \"%s/L%02d%02d%03d.log\") (version \"%s\")\n", g_log_dir.c_str(), curTime->tm_mon + 1, curTime->tm_mday, i, AMX_VERSION);
fclose(fp); fclose(fp);
} }
} }
void CLog::UseFile(const ke::AString &fileName) void CLog::UseFile(const String &fileName)
{ {
static char file[PLATFORM_MAX_PATH]; static char file[256];
m_LogFile = build_pathname_r(file, sizeof(file), "%s/%s", g_log_dir.chars(), fileName.chars()); m_LogFile.assign(build_pathname_r(file, sizeof(file)-1, "%s/%s", g_log_dir.c_str(), fileName.c_str()));
}
void CLog::SetLogType(const char* localInfo)
{
m_LogType = atoi(get_localinfo(localInfo, "1"));
if (m_LogType < 0 || m_LogType > 3)
{
SET_LOCALINFO(localInfo, "1");
m_LogType = 1;
print_srvconsole("[AMXX] Invalid amxx_logging value; setting back to 1...");
}
} }
void CLog::MapChange() void CLog::MapChange()
{ {
// create dir if not existing // create dir if not existing
char file[PLATFORM_MAX_PATH]; char file[256];
#if defined(__linux__) || defined(__APPLE__) #ifdef __linux
mkdir(build_pathname_r(file, sizeof(file), "%s", g_log_dir.chars()), 0700); mkdir(build_pathname_r(file, sizeof(file)-1, "%s", g_log_dir.c_str()), 0700);
#else #else
mkdir(build_pathname_r(file, sizeof(file), "%s", g_log_dir.chars())); mkdir(build_pathname_r(file, sizeof(file)-1, "%s", g_log_dir.c_str()));
#endif #endif
SetLogType("amxx_logging"); m_LogType = atoi(get_localinfo("amxx_logging", "1"));
m_LoggedErrMap = false; if (m_LogType < 0 || m_LogType > 3)
{
SET_LOCALINFO("amxx_logging", "1");
m_LogType = 1;
print_srvconsole("[AMXX] Invalid amxx_logging value; setting back to 1...");
}
if (m_LogType == 2) if (m_LogType == 2)
{ {
// create new logfile // create new logfile
CreateNewFile(); CreateNewFile();
} else if (m_LogType == 1) {
Log("-------- Mapchange to %s --------", STRING(gpGlobals->mapname));
} else {
return;
} }
else if (m_LogType == 1)
{
Log("-------- Mapchange to %s --------", STRING(gpGlobals->mapname));
}
else
return;
} }
void CLog::Log(const char *fmt, ...) void CLog::Log(const char *fmt, ...)
{ {
static char file[PLATFORM_MAX_PATH]; static char file[256];
if (m_LogType == 1 || m_LogType == 2) if (m_LogType == 1 || m_LogType == 2)
{ {
// get time // get time
@ -175,24 +181,24 @@ void CLog::Log(const char *fmt, ...)
FILE *pF = NULL; FILE *pF = NULL;
if (m_LogType == 2) if (m_LogType == 2)
{ {
pF = fopen(m_LogFile.chars(), "a+"); pF = fopen(m_LogFile.c_str(), "a+");
if (!pF) if (!pF)
{ {
CreateNewFile(); CreateNewFile();
pF = fopen(m_LogFile.chars(), "a+"); pF = fopen(m_LogFile.c_str(), "a+");
if (!pF) if (!pF)
{ {
ALERT(at_logged, "[AMXX] Unexpected fatal logging error (couldn't open %s for a+). AMXX Logging disabled for this map.\n", m_LogFile.chars()); ALERT(at_logged, "[AMXX] Unexpected fatal logging error (couldn't open %s for a+). AMXX Logging disabled for this map.\n", m_LogFile.c_str());
m_LogType = 0; m_LogType = 0;
return; return;
} }
} }
} else { } else {
build_pathname_r(file, sizeof(file), "%s/L%04d%02d%02d.log", g_log_dir.chars(), (curTime->tm_year + 1900), curTime->tm_mon + 1, curTime->tm_mday); build_pathname_r(file, sizeof(file)-1, "%s/L%02d%02d.log", g_log_dir.c_str(), curTime->tm_mon + 1, curTime->tm_mday);
pF = fopen(file, "a+"); pF = fopen(file, "a+");
} }
if (pF) if (pF)
{ {
fprintf(pF, "L %s: %s\n", date, msg); fprintf(pF, "L %s: %s\n", date, msg);
@ -205,7 +211,9 @@ void CLog::Log(const char *fmt, ...)
// print on server console // print on server console
print_srvconsole("L %s: %s\n", date, msg); print_srvconsole("L %s: %s\n", date, msg);
} else if (m_LogType == 3) { }
else if (m_LogType == 3)
{
// build message // build message
static char msg_[3072]; static char msg_[3072];
va_list arglst; va_list arglst;
@ -215,54 +223,3 @@ void CLog::Log(const char *fmt, ...)
ALERT(at_logged, "%s\n", msg_); ALERT(at_logged, "%s\n", msg_);
} }
} }
void CLog::LogError(const char *fmt, ...)
{
static char file[PLATFORM_MAX_PATH];
static char name[256];
if (m_FoundError)
{
return;
}
// get time
time_t td;
time(&td);
tm *curTime = localtime(&td);
char date[32];
strftime(date, 31, "%m/%d/%Y - %H:%M:%S", curTime);
// msg
static char msg[3072];
va_list arglst;
va_start(arglst, fmt);
vsnprintf(msg, sizeof(msg)-1, fmt, arglst);
va_end(arglst);
FILE *pF = NULL;
ke::SafeSprintf(name, sizeof(name), "%s/error_%04d%02d%02d.log", g_log_dir.chars(), curTime->tm_year + 1900, curTime->tm_mon + 1, curTime->tm_mday);
build_pathname_r(file, sizeof(file), "%s", name);
pF = fopen(file, "a+");
if (pF)
{
if (!m_LoggedErrMap)
{
fprintf(pF, "L %s: Start of error session.\n", date);
fprintf(pF, "L %s: Info (map \"%s\") (file \"%s\")\n", date, STRING(gpGlobals->mapname), name);
m_LoggedErrMap = true;
}
fprintf(pF, "L %s: %s\n", date, msg);
fclose(pF);
} else {
ALERT(at_logged, "[AMXX] Unexpected fatal logging error (couldn't open %s for a+). AMXX Error Logging disabled for this map.\n", file);
m_FoundError = true;
return;
}
// print on server console
print_srvconsole("L %s: %s\n", date, msg);
}

View File

@ -1,11 +1,32 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. *
// *
// This software is licensed under the GNU General Public License, version 3 or higher. * This program is free software; you can redistribute it and/or modify it
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * under the terms of the GNU General Public License as published by the
// https://alliedmods.net/amxmodx-license * Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef __AMXXLOG_H__ #ifndef __AMXXLOG_H__
#define __AMXXLOG_H__ #define __AMXXLOG_H__
@ -13,23 +34,19 @@
class CLog class CLog
{ {
private: private:
ke::AString m_LogFile; String m_LogFile;
int m_LogType; int m_LogType;
bool m_FoundError;
bool m_LoggedErrMap;
void GetLastFile(int &outMonth, int &outDay, ke::AString &outFilename); void GetLastFile(int &outMonth, int &outDay, String &outFilename);
void UseFile(const ke::AString &fileName); void UseFile(const String &fileName);
public: public:
CLog(); CLog();
~CLog(); ~CLog();
void CreateNewFile(); void CreateNewFile();
void CloseFile(); void CloseFile();
void SetLogType(const char* localInfo);
void MapChange(); void MapChange();
void Log(const char *fmt, ...); void Log(const char *fmt, ...);
void LogError(const char *fmt, ...);
}; };
#endif // __AMXXLOG_H__ #endif // __AMXXLOG_H__

View File

@ -1,371 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#if defined BINLOG_ENABLED
#include <time.h>
#include "amxmodx.h"
#include "binlog.h"
#include "debugger.h"
BinLog g_BinLog;
int g_binlog_level = 0;
int g_binlog_maxsize = 0;
// Helper function to get a filename index
#define USHR(x) ((unsigned int)(x)>>1)
int LookupFile(AMX_DBG *amxdbg, ucell address)
{
int high, low, mid;
high = amxdbg->hdr->files;
low = -1;
while (high - low > 1)
{
mid = USHR(low + high);
if (amxdbg->filetbl[mid]->address <= address)
{
low = mid;
} else {
high = mid;
}
}
if (low == -1)
{
return -1;
}
return low;
}
bool BinLog::Open()
{
const char *data = get_localinfo("amxmodx_datadir", "addons/amxmodx/data");
char path[PLATFORM_MAX_PATH];
build_pathname_r(path, sizeof(path), "%s/binlogs", data);
if (!DirExists(path))
{
mkdir(path
#if defined(__linux__) || defined(__APPLE__)
, 0755
#endif
);
if (!DirExists(path))
return false;
}
char file[PLATFORM_MAX_PATH];
build_pathname_r(file, sizeof(file), "%s/binlogs/lastlog", data);
unsigned int lastcntr = 0;
FILE *lastlog = fopen(file, "rb");
if (lastlog)
{
if (fread(&lastcntr, sizeof(int), 1, lastlog) != 1)
lastcntr = 0;
fclose(lastlog);
}
lastlog = fopen(file, "wb");
if (lastlog)
{
lastcntr++;
fwrite(&lastcntr, sizeof(int), 1, lastlog);
fclose(lastlog);
}
build_pathname_r(file, sizeof(file), "%s/binlogs/binlog%04d.blg", data, lastcntr);
m_logfile = file;
/**
* it's now safe to create the binary log
*/
FILE *fp = fopen(m_logfile.chars(), "wb");
if (!fp)
return false;
int magic = BINLOG_MAGIC;
short vers = BINLOG_VERSION;
char c = sizeof(time_t);
fwrite(&magic, sizeof(int), 1, fp);
fwrite(&vers, sizeof(short), 1, fp);
fwrite(&c, sizeof(char), 1, fp);
WritePluginDB(fp);
fclose(fp);
m_state = true;
WriteOp(BinLog_Start, -1);
return true;
}
void BinLog::Close()
{
WriteOp(BinLog_End, -1);
m_state = false;
}
void BinLog::WriteOp(BinLogOp op, int plug, ...)
{
if (!m_state)
return;
FILE *fp = fopen(m_logfile.chars(), "ab");
if (!fp)
return;
if (g_binlog_maxsize && op != BinLog_End)
{
fseek(fp, 0, SEEK_END);
if (ftell(fp) > (g_binlog_maxsize * (1024 * 1024)))
{
fclose(fp);
Close();
Open();
fp = fopen(m_logfile.chars(), "ab");
if (!fp)
return;
}
}
unsigned char c = static_cast<char>(op);
time_t t = time(NULL);
float gt = gpGlobals->time;
fwrite(&c, sizeof(char), 1, fp);
fwrite(&t, sizeof(time_t), 1, fp);
fwrite(&gt, sizeof(float), 1, fp);
fwrite(&plug, sizeof(int), 1, fp);
va_list ap;
va_start(ap, plug);
AMX *amx = NULL;
bool debug = false;
AMX_DBG *dbg = NULL;
CPluginMngr::CPlugin *pl = NULL;
if (plug != -1)
{
pl = g_plugins.findPlugin(plug);
if ((debug = pl->isDebug()))
{
amx = pl->getAMX();
dbg = static_cast<Debugger *>(amx->userdata[UD_DEBUGGER])->m_pAmxDbg;
}
}
switch (c)
{
case BinLog_Registered:
{
const char *title = va_arg(ap, const char *);
const char *vers = va_arg(ap, const char *);
c = (char)strlen(title);
fwrite(&c, sizeof(char), 1, fp);
fwrite(title, sizeof(char), c+1, fp);
c = (char)strlen(vers);
fwrite(&c, sizeof(char), 1 ,fp);
fwrite(vers, sizeof(char), c+1, fp);
break;
}
case BinLog_NativeCall:
{
int file;
int native = va_arg(ap, int);
int params = va_arg(ap, int);
fwrite(&native, sizeof(int), 1, fp);
fwrite(&params, sizeof(int), 1, fp);
if (debug)
{
file = LookupFile(dbg, amx->cip);
fwrite(&file, sizeof(int), 1, fp);
} else {
file = 0;
fwrite(&file, sizeof(int), 1, fp);
}
break;
}
case BinLog_NativeRet:
{
cell retval = va_arg(ap, cell);
fwrite(&retval, sizeof(cell), 1, fp);
break;
}
case BinLog_NativeError:
{
int err = va_arg(ap, int);
const char *msg = va_arg(ap, const char *);
short len = (short)strlen(msg);
fwrite(&err, sizeof(int), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(msg, sizeof(char), len+1, fp);
break;
}
case BinLog_CallPubFunc:
{
int file;
int num = va_arg(ap, int);
fwrite(&num, sizeof(int), 1, fp);
if (debug)
{
file = LookupFile(dbg, amx->cip);
fwrite(&file, sizeof(int), 1, fp);
} else {
file = 0;
fwrite(&file, sizeof(int), 1, fp);
}
break;
}
case BinLog_SetLine:
{
int file;
int line = va_arg(ap, int);
fwrite(&line, sizeof(int), 1, fp);
if (debug)
{
file = LookupFile(dbg, amx->cip);
fwrite(&file, sizeof(int), 1, fp);
} else {
file = 0;
fwrite(&file, sizeof(int), 1, fp);
}
break;
}
case BinLog_FormatString:
{
int param = va_arg(ap, int);
int maxlen = va_arg(ap, int);
const char *str = va_arg(ap, const char *);
short len = (short)strlen(str);
fwrite(&param, sizeof(int), 1, fp);
fwrite(&maxlen, sizeof(int), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(str, sizeof(char), len+1, fp);
break;
}
case BinLog_NativeParams:
{
cell *params = va_arg(ap, cell *);
cell num = params[0] / sizeof(cell);
fwrite(&num, sizeof(cell), 1, fp);
for (cell i=1; i<=num; i++)
fwrite(&(params[i]), sizeof(cell), 1, fp);
break;
}
case BinLog_GetString:
{
cell addr = va_arg(ap, cell);
const char *str = va_arg(ap, const char *);
short len = (short)strlen(str);
fwrite(&addr, sizeof(cell), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(str, sizeof(char), len+1, fp);
break;
}
case BinLog_SetString:
{
cell addr = va_arg(ap, cell);
int maxlen = va_arg(ap, int);
const char *str = va_arg(ap, const char *);
short len = (short)strlen(str);
fwrite(&addr, sizeof(cell), 1, fp);
fwrite(&maxlen, sizeof(int), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(str, sizeof(char), len+1, fp);
break;
}
};
va_end(ap);
fclose(fp);
}
void BinLog::WritePluginDB(FILE *fp)
{
int num = g_plugins.getPluginsNum();
fwrite(&num, sizeof(int), 1, fp);
CPluginMngr::CPlugin *pl;
char c;
unsigned char len;
for (CPluginMngr::iterator iter = g_plugins.begin(); iter; ++iter)
{
pl = &(*iter);
if (pl->isValid())
c = 1;
else
c = 0;
if (c && pl->isDebug())
c = 2;
fwrite(&c, sizeof(char), 1, fp);
if (c)
{
Debugger *pd = NULL;
len = (char)strlen(pl->getName());
fwrite(&len, sizeof(char), 1, fp);
len++;
fwrite(pl->getName(), sizeof(char), len, fp);
int natives, publics, files;
AMX *amx = pl->getAMX();
// Write the number of Filenames
if (c == 2)
{
pd = static_cast<Debugger *>(amx->userdata[UD_DEBUGGER]);
files = pd->m_pAmxDbg->hdr->files;
fwrite(&files, sizeof(int), 1, fp);
}
amx_NumNatives(amx, &natives);
amx_NumPublics(amx, &publics);
fwrite(&natives, sizeof(int), 1, fp);
fwrite(&publics, sizeof(int), 1, fp);
char name[34];
// Write the Filenames to the binfile
if (c == 2)
{
AMX_DBG_FILE **ftable = pd->m_pAmxDbg->filetbl;
for (int i=0; i<files; i++)
{
len = (char)strlen(ftable[i]->name);
fwrite(&len, sizeof(char), 1, fp);
len++;
fwrite(ftable[i]->name, sizeof(char), len, fp);
}
}
for (int i=0; i<natives; i++)
{
amx_GetNative(amx, i, name);
len = (char)strlen(name);
fwrite(&len, sizeof(char), 1, fp);
len++;
fwrite(name, sizeof(char), len, fp);
}
for (int i=0; i<publics; i++)
{
amx_GetPublic(amx, i, name);
len = (char)strlen(name);
fwrite(&len, sizeof(char), 1, fp);
len++;
fwrite(name, sizeof(char), len, fp);
}
} else {
char empty[] = " ";
len = 1;
fwrite(&len, sizeof(char), 1, fp);
fwrite(empty, sizeof(char), len, fp);
int no = 0;
fwrite(&no, sizeof(int), 1, fp);
fwrite(&no, sizeof(int), 1, fp);
}
}
}
#endif //BINLOG_ENABLED

View File

@ -1,93 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _INCLUDE_BINLOG_H
#define _INCLUDE_BINLOG_H
#if defined BINLOG_ENABLED
#include <amtl/am-string.h>
#define BINLOG_MAGIC 0x414D424C
#define BINLOG_VERSION 0x0300
/**
* Format of binlog:
* uint32 magic
* uint16 version
* uint8 sizeof(time_t)
* uint32 num plugins
* [
* uint8 status codes
* str[int8] filename
* if(status==2)
* uint32 num filenames
* uint32 num natives
* uint32 num publics
* if (status==2)
* [
* str[uint8] file name
* ]
* [
* str[uint8] native name
* ]
* [
* str[uint8] public name
* ]
* ]
* [
* uint8 operation code
* time_t realtime
* float gametime
* int32 plugin id
* <extra info>
* ]
* If filename id is 0 skip as plugin was not in debug mode, if -1 there was an error.
*/
enum BinLogOp
{
BinLog_Start=1,
BinLog_End,
BinLog_NativeCall, //<int32 native id> <int32_t num_params> <int32_t filename id>
BinLog_NativeError, //<int32 errornum> <str[int16] string>
BinLog_NativeRet, //<cell value>
BinLog_CallPubFunc, //<int32 public id> <int32_t filename id>
BinLog_SetLine, //<int32 line no#> <int32_t filename id>
BinLog_Registered, //<string title> <string version>
BinLog_FormatString, //<int32 param#> <int32 maxlen> <str[int16] string>
BinLog_NativeParams, //<int32 num> <cell ...>
BinLog_GetString, //<cell addr> <string[int16]>
BinLog_SetString, //<cell addr> <int maxlen> <string[int16]>
};
class BinLog
{
public:
BinLog() : m_state(false)
{
};
public:
bool Open();
void Close();
void WriteOp(BinLogOp op, int plug, ...);
private:
void WritePluginDB(FILE *fp);
private:
ke::AString m_logfile;
bool m_state;
};
extern BinLog g_BinLog;
extern int g_binlog_level;
extern int g_binlog_maxsize;
#endif //BINLOG_ENABLED
#endif //_INCLUDE_BINLOG_H

View File

@ -1,729 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "CvarManager.h"
#include "amxmodx.h"
#include "nongpl_matches.h"
char CVarTempBuffer[64];
const char *invis_cvar_list[5] ={ "amxmodx_version", "amxmodx_modules", "amx_debug", "amx_mldebug", "amx_client_languages" };
// create_cvar(const name[], const default_value[], flags = 0, const description[] = "", bool:has_min = false, Float:min_val = 0.0, bool:has_max = false, Float:max_val = 0.0)
static cell AMX_NATIVE_CALL create_cvar(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
const char* value = get_amxstring(amx, params[2], 1, length);
const char* helpText = get_amxstring(amx, params[4], 2, length);
int flags = params[3];
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
if (CheckBadConList(name, 0))
{
plugin->AddToFailCounter(1);
}
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags, helpText);
if (info)
{
bool hasMin = params[5] != 0;
bool hasMax = params[7] != 0;
float minVal = amx_ctof(params[6]);
float maxVal = amx_ctof(params[8]);
if (hasMin && hasMax)
{
if (minVal > maxVal)
{
LogError(amx, AMX_ERR_NATIVE, "The minimum value can not be above the maximum value");
return 0;
}
else if (maxVal < minVal)
{
LogError(amx, AMX_ERR_NATIVE, "The maximum value can not be below the minimum value");
return 0;
}
}
g_CvarManager.SetCvarMin(info, hasMin, minVal, plugin->getId());
g_CvarManager.SetCvarMax(info, hasMax, maxVal, plugin->getId());
return reinterpret_cast<cell>(info->var);
}
return 0;
}
// register_cvar(const name[], const string[], flags=0, Float:fvalue=0.0)
static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
const char* value = get_amxstring(amx, params[2], 1, length);
int flags = params[3];
float fvalue = amx_ctof(params[4]);
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
if (CheckBadConList(name, 0))
{
plugin->AddToFailCounter(1);
}
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags);
if (info)
{
return reinterpret_cast<cell>(info->var);
}
return 0;
}
// cvar_exists(const cvar[])
static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params)
{
int ilen;
return (g_CvarManager.FindCvar(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0);
}
// get_cvar_pointer(const cvar[])
static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params)
{
int len;
const char *name = get_amxstring(amx, params[1], 0, len);
CvarInfo* info = g_CvarManager.FindCvar(name);
return reinterpret_cast<cell>(info ? info->var : 0);
}
// hook_cvar_change(cvarHandle, const callback[])
static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params)
{
cvar_t* var = reinterpret_cast<cvar_t*>(params[1]);
if (!var)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar handle: %p", var);
return 0;
}
const char* callback;
AutoForward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback);
if (!forward)
{
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", callback);
return 0;
}
return reinterpret_cast<cell>(forward);
}
// enable_cvar_hook(cvarhook:handle);
static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params)
{
AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]);
if (!forward)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
return 0;
}
forward->state = AutoForward::FSTATE_OK;
return 1;
}
// disable_cvar_hook(cvarhook:handle);
static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params)
{
AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]);
if (!forward)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
return 0;
}
forward->state = AutoForward::FSTATE_STOP;
return 1;
}
// get_cvar_flags(const cvar[])
static cell AMX_NATIVE_CALL get_cvar_flags(AMX *amx, cell *params)
{
int ilen;
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
return info ? info->var->flags : 0;
}
// get_cvar_float(const cvarname[])
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
CvarInfo* info = g_CvarManager.FindCvar(name);
return info ? amx_ftoc(info->var->value) : 0;
}
// get_cvar_num(const cvarname[])
static cell AMX_NATIVE_CALL get_cvar_num(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
CvarInfo* info = g_CvarManager.FindCvar(name);
return info ? (int)info->var->value : 0;
}
// get_cvar_string(const cvarname[], output[], iLen)
static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
CvarInfo* info = g_CvarManager.FindCvar(name);
const char *value = info ? info->var->string : "";
length = info ? strlen(value) : 0;
return set_amxstring_utf8(amx, params[2], value, length, params[3]);
}
// set_cvar_flags(const cvar[], flags)
static cell AMX_NATIVE_CALL set_cvar_flags(AMX *amx, cell *params)
{
int ilen;
const char* sCvar = get_amxstring(amx, params[1], 0, ilen);
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
return 0;
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
if (info)
{
info->var->flags |= (int)(params[2]);
return 1;
}
return 0;
}
// set_cvar_float(const cvar[], Float:value)
static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
CvarInfo* info = g_CvarManager.FindCvar(name);
if (info)
{
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%f", amx_ctof(params[2]));
CVAR_DIRECTSET(info->var, &CVarTempBuffer[0]);
}
return 1;
}
// set_cvar_num(const cvarname[], value)
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
int value = params[2];
CvarInfo* info = g_CvarManager.FindCvar(name);
if (info)
{
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%d", value);
CVAR_DIRECTSET(info->var, &CVarTempBuffer[0]);
}
return 1;
}
// set_cvar_string(const cvar[], const value[])
static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params)
{
int length;
const char* name = get_amxstring(amx, params[1], 0, length);
CvarInfo* info = g_CvarManager.FindCvar(name);
if (info)
{
CVAR_DIRECTSET(info->var, get_amxstring(amx, params[2], 1, length));
}
return 1;
}
// get_pcvar_flags(pcvar)
static cell AMX_NATIVE_CALL get_pcvar_flags(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
return ptr->flags;
}
// Float:get_pcvar_float(pcvar)
static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
return amx_ftoc(ptr->value);
}
// get_pcvar_num(pcvar)
static cell AMX_NATIVE_CALL get_pcvar_num(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
return (int)ptr->value;
}
// bool:get_pcvar_bool(pcvar)
static cell AMX_NATIVE_CALL get_pcvar_bool(AMX *amx, cell *params)
{
return !!get_pcvar_num(amx, params);
}
// get_pcvar_string(pcvar, string[], maxlen)
static cell AMX_NATIVE_CALL get_pcvar_string(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
return set_amxstring_utf8(amx, params[2], ptr->string ? ptr->string : "", ptr->string ? strlen(ptr->string) : 0, params[3]);
}
// get_pcvar_bounds(pcvar, CvarBounds:type, &Float:value)
static cell AMX_NATIVE_CALL get_pcvar_bounds(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
CvarInfo* info = nullptr;
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
bool hasBound = false;
float bound;
switch (params[2])
{
case CvarBound_Lower:
hasBound = info->bound.hasMin;
bound = info->bound.minVal;
break;
case CvarBound_Upper:
hasBound = info->bound.hasMax;
bound = info->bound.maxVal;
break;
default:
LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]);
return 0;
}
*get_amxaddr(amx, params[3]) = amx_ftoc(bound);
return hasBound;
}
// bind_pcvar_float(pcvar, &Float:var)
static cell AMX_NATIVE_CALL bind_pcvar_float(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
CvarInfo* info = nullptr;
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Float, amx, params[2]);
}
// bind_pcvar_num(pcvar, &any:var)
static cell AMX_NATIVE_CALL bind_pcvar_num(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
CvarInfo* info = nullptr;
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Int, amx, params[2]);
}
// bind_pcvar_string(pcvar, any:var[], varlen)
static cell AMX_NATIVE_CALL bind_pcvar_string(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
CvarInfo* info = nullptr;
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
return g_CvarManager.BindCvar(info, CvarBind::CvarType_String, amx, params[2], params[3]);
}
// set_pcvar_flags(pcvar, flags)
static cell AMX_NATIVE_CALL set_pcvar_flags(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
ptr->flags = static_cast<int>(params[2]);
return 1;
}
// set_pcvar_float(pcvar, Float:num)
static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%f", amx_ctof(params[2]));
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
return 1;
}
// set_pcvar_num(pcvar, num)
static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
ke::SafeSprintf(CVarTempBuffer, sizeof(CVarTempBuffer), "%d", params[2]);
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
return 1;
}
// set_pcvar_string(pcvar, const string[])
static cell AMX_NATIVE_CALL set_pcvar_string(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
int len;
CVAR_DIRECTSET(ptr, get_amxstring(amx, params[2], 0, len));
return 1;
}
// set_pcvar_bounds(pcvar, CvarBounds:type, bool:set, Float:value = 0.0)
static cell AMX_NATIVE_CALL set_pcvar_bounds(AMX *amx, cell *params)
{
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
CvarInfo* info = nullptr;
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
return 0;
}
bool set = params[3] != 0;
int pluginId = g_plugins.findPluginFast(amx)->getId();
float value = amx_ctof(params[4]);
switch (params[2])
{
case CvarBound_Lower:
{
if (set && info->bound.hasMax && value > info->bound.maxVal)
{
LogError(amx, AMX_ERR_NATIVE, "The minimum value can not be above the maximum value");
return 0;
}
g_CvarManager.SetCvarMin(info, set, value, pluginId);
break;
}
case CvarBound_Upper:
{
if (set && info->bound.hasMin && value < info->bound.minVal)
{
LogError(amx, AMX_ERR_NATIVE, "The maximum value can not be below the minimum value");
return 0;
}
g_CvarManager.SetCvarMax(info, set, value, pluginId);
break;
}
default:
{
LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]);
return 0;
}
}
return 1;
}
// remove_cvar_flags(const cvar[], flags=-1)
static cell AMX_NATIVE_CALL remove_cvar_flags(AMX *amx, cell *params)
{
int ilen;
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
return 0;
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
if (info)
{
info->var->flags &= ~((int)(params[2]));
return 1;
}
return 0;
}
// get_plugins_cvar(id, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0, description[]="", desc_len=0)
static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params)
{
CvarInfo* info = g_CvarManager.FindCvar(params[1]);
if (info)
{
set_amxstring(amx, params[2], info->name.chars(), params[3]);
*get_amxaddr(amx, params[4]) = info->var->flags;
*get_amxaddr(amx, params[5]) = info->pluginId;
*get_amxaddr(amx, params[6]) = reinterpret_cast<cell>(info->var);
if (*params / sizeof(cell) >= 7)
{
set_amxstring(amx, params[7], info->description.chars(), params[8]);
}
return 1;
}
return 0;
}
// get_plugins_cvarsnum()
static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params)
{
return g_CvarManager.GetRegCvarsCount();
}
#if defined AMD64
static bool g_warned_ccqv = false;
#endif
// query_client_cvar(id, const cvar[], const resultfunc[])
static cell AMX_NATIVE_CALL query_client_cvar(AMX *amx, cell *params)
{
int numParams = params[0] / sizeof(cell);
if (numParams != 3 && numParams != 5)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed!");
return 0;
}
#if defined AMD64
if (!g_warned_ccqv)
{
LogError(amx, AMX_ERR_NATIVE, "[AMXX] Client CVAR Querying is not available on AMD64 (one time warn)");
g_warned_ccqv = true;
}
return 0;
#endif
if (!g_NewDLL_Available)
{
LogError(amx, AMX_ERR_NATIVE, "Client CVAR querying is not enabled - check MM version!");
return 0;
}
int id = params[1];
if (id < 1 || id > gpGlobals->maxClients)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid player id %d", id);
return 0;
}
CPlayer *pPlayer = GET_PLAYER_POINTER_I(id);
if (!pPlayer->initialized || pPlayer->IsBot())
{
LogError(amx, AMX_ERR_NATIVE, "Player %d is either not connected or a bot", id);
return 0;
}
int dummy;
const char *cvarname = get_amxstring(amx, params[2], 0, dummy);
const char *resultfuncname = get_amxstring(amx, params[3], 1, dummy);
// public clientcvarquery_result(id, const cvar[], const result[], [const param[]])
int iFunc;
if (numParams == 5 && params[4] != 0)
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_ARRAY, FP_DONE);
else
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
if (iFunc == -1)
{
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", resultfuncname);
return 0;
}
ClientCvarQuery_Info *queryObject = new ClientCvarQuery_Info;
queryObject->resultFwd = iFunc;
queryObject->requestId = MAKE_REQUESTID(PLID);
if (numParams == 5 && params[4] != 0)
{
queryObject->paramLen = params[4] + 1;
queryObject->params = new cell[queryObject->paramLen];
if (!queryObject->params)
{
delete queryObject;
unregisterSPForward(iFunc);
LogError(amx, AMX_ERR_MEMORY, "Hmm. Out of memory?");
return 0;
}
memcpy(reinterpret_cast<void*>(queryObject->params), reinterpret_cast<const void *>(get_amxaddr(amx, params[5])), queryObject->paramLen * sizeof(cell));
queryObject->params[queryObject->paramLen - 1] = 0;
}
else {
queryObject->params = NULL;
queryObject->paramLen = 0;
}
pPlayer->queries.push_back(queryObject);
QUERY_CLIENT_CVAR_VALUE2(pPlayer->pEdict, cvarname, queryObject->requestId);
return 1;
}
AMX_NATIVE_INFO g_CvarNatives[] =
{
{"create_cvar", create_cvar},
{"register_cvar", register_cvar},
{"cvar_exists", cvar_exists},
{"get_cvar_pointer", get_cvar_pointer},
{"hook_cvar_change", hook_cvar_change},
{"enable_cvar_hook", enable_cvar_hook},
{"disable_cvar_hook", disable_cvar_hook},
{"get_cvar_flags", get_cvar_flags},
{"get_cvar_float", get_cvar_float},
{"get_cvar_num", get_cvar_num},
{"get_cvar_string", get_cvar_string},
{"set_cvar_flags", set_cvar_flags},
{"set_cvar_float", set_cvar_float},
{"set_cvar_num", set_cvar_num},
{"set_cvar_string", set_cvar_string},
{"get_pcvar_flags", get_pcvar_flags},
{"get_pcvar_float", get_pcvar_float},
{"get_pcvar_num", get_pcvar_num},
{"get_pcvar_bool", get_pcvar_bool},
{"get_pcvar_string", get_pcvar_string},
{"get_pcvar_bounds", get_pcvar_bounds},
{"set_pcvar_flags", set_pcvar_flags},
{"set_pcvar_float", set_pcvar_float},
{"set_pcvar_num", set_pcvar_num},
{"set_pcvar_bool", set_pcvar_num},
{"set_pcvar_string", set_pcvar_string},
{"set_pcvar_bounds", set_pcvar_bounds},
{"remove_cvar_flags", remove_cvar_flags},
{"bind_pcvar_float", bind_pcvar_float},
{"bind_pcvar_num", bind_pcvar_num},
{"bind_pcvar_string", bind_pcvar_string},
{"get_plugins_cvar", get_plugins_cvar},
{"get_plugins_cvarsnum", get_plugins_cvarsnum},
{"query_client_cvar", query_client_cvar},
{NULL, NULL}
};

View File

@ -1,250 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*/
#include "CDataPack.h"
NativeHandle<CDataPack> DataPackHandles;
static cell AMX_NATIVE_CALL CreateDataPack(AMX* amx, cell* params)
{
return static_cast<cell>(DataPackHandles.create());
}
static cell AMX_NATIVE_CALL WritePackCell(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
d->PackCell(params[2]);
return 1;
}
static cell AMX_NATIVE_CALL WritePackFloat(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
d->PackFloat(amx_ctof(params[2]));
return 1;
}
static cell AMX_NATIVE_CALL WritePackString(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
int len;
const char *str = get_amxstring(amx, params[2], 0, len);
d->PackString(str);
return len;
}
static cell AMX_NATIVE_CALL ReadPackCell(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
if (!d->CanReadCell())
{
LogError(amx, AMX_ERR_NATIVE, "Datapack operation is invalid.");
return 0;
}
return d->ReadCell();
}
static cell AMX_NATIVE_CALL ReadPackFloat(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
if (!d->CanReadFloat())
{
LogError(amx, AMX_ERR_NATIVE, "Datapack operation is invalid.");
return 0;
}
float value = d->ReadFloat();
return amx_ftoc(value);
}
static cell AMX_NATIVE_CALL ReadPackString(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
if (!d->CanReadString(NULL))
{
LogError(amx, AMX_ERR_NATIVE, "Datapack operation is invalid.");
return 0;
}
size_t len;
const char *str = d->ReadString(&len);
return set_amxstring_utf8(amx, params[2], str, len, params[3]);
}
static cell AMX_NATIVE_CALL ResetPack(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
d->Reset();
if (params[2])
{
d->ResetSize();
}
return 1;
}
static cell AMX_NATIVE_CALL GetPackPosition(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
return static_cast<cell>(d->GetPosition());
}
static cell AMX_NATIVE_CALL SetPackPosition(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
if (!d->SetPosition(params[2]))
{
LogError(amx, AMX_ERR_NATIVE, "Invalid DataPack position, %d is out of bounds", params[2]);
return 0;
}
return 1;
}
static cell AMX_NATIVE_CALL IsPackEnded(AMX* amx, cell* params)
{
CDataPack *d = DataPackHandles.lookup(params[1]);
if (!d)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid datapack handle provided (%d)", params[1]);
return 0;
}
return d->IsReadable(1) ? false : true;
}
static cell AMX_NATIVE_CALL DestroyDataPack(AMX* amx, cell* params)
{
cell *ptr = get_amxaddr(amx, params[1]);
CDataPack *d = DataPackHandles.lookup(*ptr);
if (!d)
{
return 0;
}
if (DataPackHandles.destroy(*ptr))
{
*ptr = 0;
return 1;
}
return 0;
}
AMX_NATIVE_INFO g_DatapackNatives[] =
{
{ "CreateDataPack" , CreateDataPack },
{ "WritePackCell" , WritePackCell },
{ "WritePackFloat" , WritePackFloat },
{ "WritePackString", WritePackString },
{ "ReadPackCell" , ReadPackCell },
{ "ReadPackFloat" , ReadPackFloat },
{ "ReadPackString" , ReadPackString },
{ "ResetPack" , ResetPack },
{ "GetPackPosition", GetPackPosition },
{ "SetPackPosition", SetPackPosition },
{ "IsPackEnded" , IsPackEnded },
{ "DestroyDataPack", DestroyDataPack },
{ nullptr , nullptr}
};

View File

@ -1,935 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "amxmodx.h"
#include "datastructs.h"
#include <amtl/am-utility.h>
NativeHandle<CellArray> ArrayHandles;
// Array:ArrayCreate(cellsize=1, reserved=32);
static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params)
{
// params[1] (cellsize) is how big in cells each element is.
// this MUST be greater than 0!
int cellsize = params[1];
// params[2] (reserved) is how many elements to allocate
// immediately when the list is created.
int reserved = params[2];
if (cellsize <= 0)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", cellsize);
return -1;
}
if (reserved < 0)
{
reserved = 0;
}
return ArrayHandles.create(cellsize, reserved);
}
// native ArrayClear(Array:which);
static cell AMX_NATIVE_CALL ArrayClear(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
vec->clear();
return 1;
}
// native ArraySize(Array:which);
static cell AMX_NATIVE_CALL ArraySize(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
return vec->size();
}
// native bool:ArrayResize(Array:which, newsize);
static cell AMX_NATIVE_CALL ArrayResize(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
if (!vec->resize(params[2]))
{
LogError(amx, AMX_ERR_NATIVE, "Unable to resize array to \"%u\"", params[2]);
return 0;
}
return 1;
}
// native Array:ArrayClone(Array:which);
static cell AMX_NATIVE_CALL ArrayClone(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
auto data = vec->clone();
if (!data)
{
LogError(amx, AMX_ERR_NATIVE, "Failed to clone array. Out of memory.");
return 0;
}
return ArrayHandles.clone(data);
}
// native ArrayGetArray(Array:which, item, any:output[], size = -1);
static cell AMX_NATIVE_CALL ArrayGetArray(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
cell *blk = vec->at(idx);
size_t indexes = vec->blocksize();
if (*params / sizeof(cell) == 4)
{
if (params[4] != -1 && (size_t)params[4] <= vec->blocksize())
{
indexes = params[4];
}
}
cell *addr = get_amxaddr(amx, params[3]);
memcpy(addr, blk, sizeof(cell) * indexes);
return indexes;
}
// native any:ArrayGetCell(Array:which, item, block = 0, bool:asChar = false);
static cell AMX_NATIVE_CALL ArrayGetCell(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
cell *blk = vec->at(idx);
if (*params / sizeof(cell) <= 2)
{
return *blk;
}
idx = (size_t)params[3];
if (!params[4])
{
if (idx >= vec->blocksize())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize());
return 0;
}
return blk[idx];
}
else
{
if (idx >= vec->blocksize() * 4)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4);
return 0;
}
return (cell)*((char *)blk + idx);
}
return 0;
}
// native ArrayGetString(Array:which, item, output[], size);
static cell AMX_NATIVE_CALL ArrayGetString(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
cell *blk = vec->at(idx);
return set_amxstring_utf8(amx, params[3], blk, amxstring_len(blk), params[4]);
}
// native ArraySetArray(Array:which, item, const any:input[], size =-1);
static cell AMX_NATIVE_CALL ArraySetArray(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
cell *blk = vec->at(idx);
size_t indexes = vec->blocksize();
if (*params / sizeof(cell) == 4)
{
if (params[4] != -1 && (size_t)params[4] <= vec->blocksize())
{
indexes = params[4];
}
}
cell *addr = get_amxaddr(amx, params[3]);
memcpy(blk, addr, sizeof(cell) * indexes);
return indexes;
}
// native ArraySetCell(Array:which, item, any:input, block = 0, bool:asChar = false);
static cell AMX_NATIVE_CALL ArraySetCell(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
cell *blk = vec->at(idx);
idx = (size_t)params[4];
if (*params / sizeof(cell) <= 3)
{
*blk = params[3];
return 1;
}
if (params[5] == 0)
{
if (idx >= vec->blocksize())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid block %d (blocksize: %d)", idx, vec->blocksize());
return 0;
}
blk[idx] = params[3];
}
else
{
if (idx >= vec->blocksize() * 4)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid byte %d (blocksize: %d bytes)", idx, vec->blocksize() * 4);
return 0;
}
*((char *)blk + idx) = (char)params[3];
}
return 1;
}
// native ArraySetString(Array:which, item, const input[]);
static cell AMX_NATIVE_CALL ArraySetString(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
cell *blk = vec->at(idx);
int len;
char *str = get_amxstring(amx, params[3], 0, len);
return strncopy(blk, str, ke::Min((size_t)len + 1, vec->blocksize()));
}
// native ArrayPushArray(Array:which, const any:input[], size = -1);
static cell AMX_NATIVE_CALL ArrayPushArray(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
cell *blk = vec->push();
if (!blk)
{
LogError(amx, AMX_ERR_NATIVE, "Failed to grow array");
return 0;
}
cell *addr = get_amxaddr(amx, params[2]);
size_t indexes = vec->blocksize();
if (*params / sizeof(cell) == 3)
{
if (params[3] != -1 && (size_t)params[3] <= vec->blocksize())
{
indexes = params[3];
}
}
memcpy(blk, addr, sizeof(cell) * indexes);
return static_cast<cell>((vec->size() - 1));
}
// native ArrayPushCell(Array:which, any:input);
static cell AMX_NATIVE_CALL ArrayPushCell(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
cell *blk = vec->push();
if (!blk)
{
LogError(amx, AMX_ERR_NATIVE, "Failed to grow array");
return 0;
}
*blk = params[2];
return static_cast<cell>((vec->size() - 1));
}
// native ArrayPushString(Array:which, const input[]);
static cell AMX_NATIVE_CALL ArrayPushString(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
cell *blk = vec->push();
if (!blk)
{
LogError(amx, AMX_ERR_NATIVE, "Failed to grow array");
return 0;
}
strncopy(blk, get_amxaddr(amx, params[2]), vec->blocksize());
return static_cast<cell>((vec->size() - 1));
}
// native DoNotUse : ArrayGetStringHandle(Array : which, item);
static cell AMX_NATIVE_CALL ArrayGetStringHandle(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
cell* ptr = vec->at(idx);
if (ptr == NULL)
{
return 0;
}
return reinterpret_cast<cell>(ptr);
}
// native ArrayInsertArrayAfter(Array:which, item, const any:input[]);
static cell AMX_NATIVE_CALL ArrayInsertArrayAfter(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = params[2] + 1;
if (idx > vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayAfter (%d:%d)", idx, vec->size());
return 0;
}
cell *addr = get_amxaddr(amx, params[3]);
memcpy(vec->insert_at(idx), addr, sizeof(cell) * vec->blocksize());
return 1;
}
// native ArrayInsertCellAfter(Array:which, item, any:input);
static cell AMX_NATIVE_CALL ArrayInsertCellAfter(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = params[2] + 1;
if (idx > vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellAfter (%d:%d)", idx, vec->size());
return 0;
}
*vec->insert_at(idx) = params[3];
return 1;
}
// native ArrayInsertStringAfter(Array:which, item, const input[]);
static cell AMX_NATIVE_CALL ArrayInsertStringAfter(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = params[2] + 1;
if (idx > vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringAfter (%d:%d)", idx, vec->size());
return 0;
}
int len;
const char *str = get_amxstring(amx, params[3], 0, len);
return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize()));
}
// native ArrayInsertArrayBefore(Array:which, item, const any:input[]);
static cell AMX_NATIVE_CALL ArrayInsertArrayBefore(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertArrayBefore (%d:%d)", idx, vec->size());
return 0;
}
cell *addr = get_amxaddr(amx, params[3]);
memcpy(vec->insert_at(idx), addr, vec->blocksize() * sizeof(cell));
return 1;
}
// native ArrayInsertCellBefore(Array:which, item, const any:input);
static cell AMX_NATIVE_CALL ArrayInsertCellBefore(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertCellBefore (%d:%d)", idx, vec->size());
return 0;
}
*vec->insert_at(idx) = params[3];
return 1;
}
// native ArrayInsertStringBefore(Array:which, item, const input[]);
static cell AMX_NATIVE_CALL ArrayInsertStringBefore(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid item specified in ArrayInsertStringBefore (%d:%d)", idx, vec->size());
return 0;
}
int len;
const char *str = get_amxstring(amx, params[3], 0, len);
return strncopy(vec->insert_at(idx), str, ke::Min((size_t)len + 1, vec->blocksize()));
}
// native ArraySwap(Array:which, item1, item2);
static cell AMX_NATIVE_CALL ArraySwap(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx1 = (size_t)params[2];
size_t idx2 = (size_t)params[3];
if (idx1 >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx1, vec->size());
return 0;
}
if (idx2 >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx2, vec->size());
return 0;
}
vec->swap(idx1, idx2);
return 1;
}
// native ArrayDeleteItem(Array:which, item);
static cell AMX_NATIVE_CALL ArrayDeleteItem(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
size_t idx = (size_t)params[2];
if (idx >= vec->size())
{
LogError(amx, AMX_ERR_NATIVE, "Invalid index %d (count: %d)", idx, vec->size());
return 0;
}
vec->remove(idx);
return 1;
}
// native ArrayDestroy(&Array:which);
static cell AMX_NATIVE_CALL ArrayDestroy(AMX* amx, cell* params)
{
cell *handle = get_amxaddr(amx, params[1]);
CellArray* vec = ArrayHandles.lookup(*handle);
if (!vec)
{
return 0;
}
if (ArrayHandles.destroy(*handle))
{
*handle = 0;
return 1;
}
return 1;
}
struct ArraySort_s
{
int func;
cell array_hndl;
cell* array_base;
cell array_bsize;
cell data;
cell size;
cell addr1;
cell addr2;
AMX *amx;
};
ArraySort_s SortInfo;
int SortArrayList(const void *elem1, const void *elem2)
{
return executeForwards(
SortInfo.func,
SortInfo.array_hndl,
((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize,
((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize,
SortInfo.data,
SortInfo.size
);
}
// native ArraySort(Array:array, const comparefunc[], data[]="", data_size=0);
static cell AMX_NATIVE_CALL ArraySort(AMX* amx, cell* params)
{
cell handle = params[1];
CellArray* vec = ArrayHandles.lookup(handle);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", handle);
return 0;
}
int len;
char* funcName = get_amxstring(amx, params[2], 0, len);
// MySortFunc(Array:array, item1, item2, const data[], data_size)
int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
if (func < 0)
{
LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName);
return 0;
}
size_t arraysize = vec->size();
size_t blocksize = vec->blocksize();
cell *array = vec->base();
ArraySort_s oldinfo = SortInfo;
SortInfo.func = func;
SortInfo.array_base = array;
SortInfo.array_bsize = static_cast<cell>(blocksize);
SortInfo.array_hndl = handle;
SortInfo.data = params[3];
SortInfo.size = params[4];
qsort(array, arraysize, blocksize * sizeof(cell), SortArrayList);
SortInfo = oldinfo;
unregisterSPForward(func);
return 1;
}
int SortArrayListExCell(const void *elem1, const void *elem2)
{
size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize;
size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize;
return executeForwards(
SortInfo.func,
SortInfo.array_hndl,
*&SortInfo.array_base[index1 * SortInfo.array_bsize],
*&SortInfo.array_base[index2 * SortInfo.array_bsize],
SortInfo.data,
SortInfo.size
);
}
int SortArrayListExArray(const void *elem1, const void *elem2)
{
size_t index1 = ((cell)((cell *)elem1 - SortInfo.array_base)) / SortInfo.array_bsize;
size_t index2 = ((cell)((cell *)elem2 - SortInfo.array_base)) / SortInfo.array_bsize;
cell *addr1 = get_amxaddr(SortInfo.amx, SortInfo.addr1);
cell *addr2 = get_amxaddr(SortInfo.amx, SortInfo.addr2);
memcpy(addr1, &SortInfo.array_base[index1 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell));
memcpy(addr2, &SortInfo.array_base[index2 * SortInfo.array_bsize], SortInfo.array_bsize * sizeof(cell));
return executeForwards(
SortInfo.func,
SortInfo.array_hndl,
SortInfo.addr1,
SortInfo.addr2,
SortInfo.data,
SortInfo.size
);
}
// native ArraySortEx(Array:array, const comparefunc[], data[]="", data_size=0);
static cell AMX_NATIVE_CALL ArraySortEx(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return 0;
}
int len;
char* funcName = get_amxstring(amx, params[2], 0, len);
int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
if (!func)
{
LogError(amx, AMX_ERR_NATIVE, "The public function \"%s\" was not found.", funcName);
return 0;
}
size_t arraysize = vec->size();
size_t blocksize = vec->blocksize();
cell *array = vec->base();
cell amx_addr1 = 0, amx_addr2 = 0, *phys_addr = NULL;
if (blocksize > 1)
{
int err;
if ((err = amx_Allot(amx, blocksize, &amx_addr1, &phys_addr)) != AMX_ERR_NONE
|| ( err = amx_Allot(amx, blocksize, &amx_addr2, &phys_addr)) != AMX_ERR_NONE)
{
LogError(amx, err, "Ran out of memory");
return 0;
}
}
ArraySort_s oldinfo = SortInfo;
SortInfo.func = func;
SortInfo.array_base = array;
SortInfo.array_bsize = static_cast<cell>(blocksize);
SortInfo.array_hndl = params[1];
SortInfo.data = params[3];
SortInfo.size = params[4];
SortInfo.amx = amx;
SortInfo.addr1 = amx_addr1;
SortInfo.addr2 = amx_addr2;
qsort(array, arraysize, blocksize * sizeof(cell), blocksize > 1 ? SortArrayListExArray : SortArrayListExCell);
SortInfo = oldinfo;
if (blocksize > 1)
{
amx_Release(amx, amx_addr1);
amx_Release(amx, amx_addr2);
}
unregisterSPForward(func);
return 1;
}
extern bool fastcellcmp(cell *a, cell *b, cell len);
extern int amxstring_len(cell* a);
// native ArrayFindString(Array:which, const item[]);
static cell AMX_NATIVE_CALL ArrayFindString(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return -1;
}
cell *b, *a = get_amxaddr(amx, params[2]);
size_t cellcount = vec->blocksize();
size_t a_len = ke::Max(1, amxstring_len(a));
size_t len = a_len > cellcount ? cellcount : a_len;
for (size_t i = 0; i < vec->size(); i++)
{
b = vec->at(i);
if (fastcellcmp(a, b, len))
{
return static_cast<cell>(i);
}
}
return -1;
}
// native ArrayFindValue(Array:which, any:item);
static cell AMX_NATIVE_CALL ArrayFindValue(AMX* amx, cell* params)
{
CellArray* vec = ArrayHandles.lookup(params[1]);
if (!vec)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid array handle provided (%d)", params[1]);
return -1;
}
for (size_t i = 0; i < vec->size(); i++)
{
if (params[2] == *vec->at(i))
{
return static_cast<cell>(i);
}
}
return -1;
}
AMX_NATIVE_INFO g_DataStructNatives[] =
{
{ "ArrayCreate" , ArrayCreate },
{ "ArrayClear" , ArrayClear },
{ "ArrayClone" , ArrayClone },
{ "ArraySize" , ArraySize },
{ "ArrayResize" , ArrayResize },
{ "ArrayGetArray" , ArrayGetArray },
{ "ArrayGetCell" , ArrayGetCell },
{ "ArrayGetString" , ArrayGetString },
{ "ArraySetArray" , ArraySetArray },
{ "ArraySetCell" , ArraySetCell },
{ "ArraySetString" , ArraySetString },
{ "ArrayPushArray" , ArrayPushArray },
{ "ArrayPushCell" , ArrayPushCell },
{ "ArrayPushString" , ArrayPushString },
{ "ArrayInsertArrayAfter" , ArrayInsertArrayAfter },
{ "ArrayInsertCellAfter" , ArrayInsertCellAfter },
{ "ArrayInsertStringAfter" , ArrayInsertStringAfter },
{ "ArrayInsertArrayBefore" , ArrayInsertArrayBefore },
{ "ArrayInsertCellBefore" , ArrayInsertCellBefore },
{ "ArrayInsertStringBefore", ArrayInsertStringBefore },
{ "ArraySwap" , ArraySwap },
{ "ArrayDeleteItem" , ArrayDeleteItem },
{ "ArrayGetStringHandle" , ArrayGetStringHandle },
{ "ArrayDestroy" , ArrayDestroy },
{ "ArraySort" , ArraySort },
{ "ArraySortEx" , ArraySortEx },
{ "ArrayFindString" , ArrayFindString },
{ "ArrayFindValue" , ArrayFindValue },
{ nullptr , nullptr }
};

View File

@ -1,197 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef DATASTRUCTS_H
#define DATASTRUCTS_H
#include "natives_handles.h"
class CellArray
{
public:
CellArray(size_t blocksize, size_t basesize = 0) : m_Data(nullptr), m_BlockSize(blocksize), m_AllocSize(0), m_BaseSize(basesize > 0 ? basesize : 8), m_Size(0)
{
}
~CellArray()
{
free(m_Data);
}
size_t size() const
{
return m_Size;
}
cell *push()
{
if (!GrowIfNeeded(1))
{
return NULL;
}
cell *arr = &m_Data[m_Size * m_BlockSize];
m_Size++;
return arr;
}
cell *at(size_t b) const
{
return &m_Data[b * m_BlockSize];
}
size_t blocksize() const
{
return m_BlockSize;
}
void clear()
{
m_Size = 0;
}
bool swap(size_t item1, size_t item2)
{
/* Make sure there is extra space available */
if (!GrowIfNeeded(1))
{
return false;
}
cell *pri = at(item1);
cell *alt = at(item2);
/* Get our temporary array 1 after the limit */
cell *temp = &m_Data[m_Size * m_BlockSize];
memcpy(temp, pri, sizeof(cell)* m_BlockSize);
memcpy(pri, alt, sizeof(cell)* m_BlockSize);
memcpy(alt, temp, sizeof(cell)* m_BlockSize);
return true;
}
void remove(size_t index)
{
/* If we're at the end, take the easy way out */
if (index == m_Size - 1)
{
m_Size--;
return;
}
/* Otherwise, it's time to move stuff! */
size_t remaining_indexes = (m_Size - 1) - index;
cell *src = at(index + 1);
cell *dest = at(index);
memmove(dest, src, sizeof(cell)* m_BlockSize * remaining_indexes);
m_Size--;
}
cell *insert_at(size_t index)
{
/* Make sure it'll fit */
if (!GrowIfNeeded(1))
{
return nullptr;
}
/* move everything up */
cell *src = at(index);
cell *dst = at(index + 1);
memmove(dst, src, sizeof(cell)* m_BlockSize * (m_Size - index));
m_Size++;
return src;
}
bool resize(size_t count)
{
if (count <= m_Size)
{
m_Size = count;
return true;
}
if (!GrowIfNeeded(count - m_Size))
{
return false;
}
m_Size = count;
return true;
}
CellArray *clone()
{
CellArray *array = new CellArray(m_BlockSize);
array->m_AllocSize = m_AllocSize;
array->m_Size = m_Size;
array->m_Data = (cell *)malloc(sizeof(cell)* m_BlockSize * m_AllocSize);
if (!array->m_Data)
{
delete array;
return nullptr;
}
memcpy(array->m_Data, m_Data, sizeof(cell)* m_BlockSize * m_Size);
return array;
}
cell *base()
{
return m_Data;
}
size_t mem_usage()
{
return m_AllocSize * m_BlockSize * sizeof(cell);
}
private:
bool GrowIfNeeded(size_t count)
{
/* Shortcut out if we can store this */
if (m_Size + count <= m_AllocSize)
{
return true;
}
/* Set a base allocation size of 8 items */
if (!m_AllocSize)
{
m_AllocSize = m_BaseSize;
}
/* If it's not enough, keep doubling */
while (m_Size + count > m_AllocSize)
{
m_AllocSize *= 2;
}
/* finally, allocate the new block */
if (m_Data)
{
m_Data = (cell *)realloc(m_Data, sizeof(cell)* m_BlockSize * m_AllocSize);
}
else {
m_Data = (cell *)malloc(sizeof(cell)* m_BlockSize * m_AllocSize);
}
return (m_Data != NULL);
}
private:
cell *m_Data;
size_t m_BlockSize;
size_t m_AllocSize;
size_t m_BaseSize;
size_t m_Size;
};
extern NativeHandle<CellArray> ArrayHandles;
#endif

View File

@ -1,15 +1,40 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "debugger.h" #include "debugger.h"
#include "binlog.h"
#if !defined WIN32 && !defined _WIN32
#define _snprintf snprintf
#endif
/** /**
* AMX Mod X Debugging Engine * AMX Mod X Debugging Engine
@ -259,11 +284,11 @@ void Debugger::BeginExec()
m_Top++; m_Top++;
assert(m_Top >= 0); assert(m_Top >= 0);
if (m_Top >= (int)m_pCalls.length()) if (m_Top >= (int)m_pCalls.size())
{ {
Tracer *pTracer = new Tracer(); Tracer *pTracer = new Tracer();
m_pCalls.append(pTracer); m_pCalls.push_back(pTracer);
assert(m_Top == static_cast<int>(m_pCalls.length() - 1)); assert(m_Top == (m_pCalls.size() - 1));
} }
m_pCalls[m_Top]->Reset(); m_pCalls[m_Top]->Reset();
@ -271,7 +296,7 @@ void Debugger::BeginExec()
void Debugger::EndExec() void Debugger::EndExec()
{ {
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
m_pCalls[m_Top]->Reset(); m_pCalls[m_Top]->Reset();
@ -280,20 +305,7 @@ void Debugger::EndExec()
void Debugger::StepI() void Debugger::StepI()
{ {
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
#if defined BINLOG_ENABLED
if (g_binlog_level & 32)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
if (pl)
{
long line;
dbg_LookupLine(m_pAmxDbg, m_pAmx->cip, &line);
g_BinLog.WriteOp(BinLog_SetLine, pl->getId(), (int)(line + 1));
}
}
#endif
m_pCalls[m_Top]->StepI(m_pAmx->frm, m_pAmx->cip); m_pCalls[m_Top]->StepI(m_pAmx->frm, m_pAmx->cip);
} }
@ -306,21 +318,21 @@ void Debugger::Reset()
int Debugger::GetTracedError() int Debugger::GetTracedError()
{ {
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
return m_pCalls[m_Top]->m_Error; return m_pCalls[m_Top]->m_Error;
} }
void Debugger::SetTracedError(int error) void Debugger::SetTracedError(int error)
{ {
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
m_pCalls[m_Top]->m_Error = error; m_pCalls[m_Top]->m_Error = error;
} }
trace_info_t *Debugger::GetTraceStart() const trace_info_t *Debugger::GetTraceStart() const
{ {
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
return m_pCalls[m_Top]->GetEnd(); return m_pCalls[m_Top]->GetEnd();
} }
@ -346,7 +358,7 @@ trace_info_t *Debugger::GetNextTrace(trace_info_t *pTraceInfo)
bool Debugger::ErrorExists() bool Debugger::ErrorExists()
{ {
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
return (m_pCalls[m_Top]->m_Error != AMX_ERR_NONE); return (m_pCalls[m_Top]->m_Error != AMX_ERR_NONE);
} }
@ -356,18 +368,18 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
if (!ErrorExists()) if (!ErrorExists())
return -1; return -1;
assert(m_Top >= 0 && m_Top < (int)m_pCalls.length()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
Tracer *pTracer = m_pCalls[m_Top]; Tracer *pTracer = m_pCalls[m_Top];
int error = pTracer->m_Error; int error = pTracer->m_Error;
const char *gen_err = GenericError(error); const char *gen_err = GenericError(error);
int size = 0; int size = 0;
//trace_info_t *pTrace = pTracer->GetEnd(); trace_info_t *pTrace = pTracer->GetEnd();
//cell cip = _CipAsVa(m_pAmx->cip); cell cip = _CipAsVa(m_pAmx->cip);
//cell *p_cip = NULL; cell *p_cip = NULL;
//int amx_err = AMX_ERR_NONE; int amx_err = AMX_ERR_NONE;
size += ke::SafeSprintf(buffer, maxLength, "Run time error %d: %s ", error, gen_err); size += _snprintf(buffer, maxLength, "Run time error %d: %s ", error, gen_err);
buffer += size; buffer += size;
maxLength -= size; maxLength -= size;
@ -384,13 +396,13 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
}*/ }*/
//New code only requires this... //New code only requires this...
num = (int)(_INT_PTR)m_pAmx->usertags[UT_NATIVE]; num = (int)(_INT_PTR)m_pAmx->usertags[UT_NATIVE];
/*amx_err = */amx_GetNative(m_pAmx, num, native_name); amx_err = amx_GetNative(m_pAmx, num, native_name);
/*if (num) /*if (num)
amx_err = amx_GetNative(m_pAmx, (int)*p_cip, native_name); amx_err = amx_GetNative(m_pAmx, (int)*p_cip, native_name);
else else
amx_err = AMX_ERR_NOTFOUND;*/ amx_err = AMX_ERR_NOTFOUND;*/
//if (!amx_err) //if (!amx_err)
size += ke::SafeSprintf(buffer, maxLength, "(native \"%s\")", native_name); size += _snprintf(buffer, maxLength, "(native \"%s\")", native_name);
} }
return size; return size;
@ -521,10 +533,8 @@ int AMXAPI Debugger::DebugHook(AMX *amx)
void Debugger::Clear() void Debugger::Clear()
{ {
for (size_t i = 0; i < m_pCalls.length(); i++) for (size_t i=0; i<m_pCalls.size(); i++)
{ delete m_pCalls[i];
delete m_pCalls[i];
}
m_pCalls.clear(); m_pCalls.clear();
} }
@ -532,21 +542,16 @@ void Debugger::Clear()
void Debugger::DisplayTrace(const char *message) void Debugger::DisplayTrace(const char *message)
{ {
if (message != NULL) if (message != NULL)
AMXXLOG_Error("%s", message); AMXXLOG_Log("%s", message);
char buffer[512]; char buffer[512];
int length = FormatError(buffer, sizeof(buffer)-1); FormatError(buffer, sizeof(buffer)-1);
const char *filename = _GetFilename(); const char *filename = _GetFilename();
const char *version = _GetVersion();
AMXXLOG_Error("[AMXX] Displaying debug trace (plugin \"%s\", version \"%s\")", filename, version); AMXXLOG_Log("[AMXX] Displaying debug trace (plugin \"%s\")", filename);
AMXXLOG_Log("[AMXX] %s", buffer);
if (length != -1) // Don't show blank line if AMX_ERR_NONE is set since there is no error message.
{
AMXXLOG_Error("[AMXX] %s", buffer);
}
int count = 0; int count = 0;
long lLine; long lLine;
const char *file, *function; const char *file, *function;
@ -554,7 +559,7 @@ void Debugger::DisplayTrace(const char *message)
while (pTrace) while (pTrace)
{ {
GetTraceInfo(pTrace, lLine, function, file); GetTraceInfo(pTrace, lLine, function, file);
AMXXLOG_Error( AMXXLOG_Log(
"[AMXX] [%d] %s::%s (line %d)", "[AMXX] [%d] %s::%s (line %d)",
count, count,
file, file,
@ -568,76 +573,42 @@ void Debugger::DisplayTrace(const char *message)
const char *Debugger::_GetFilename() const char *Debugger::_GetFilename()
{ {
if (m_FileName.length() < 1) if (m_FileName.size() < 1)
{ {
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx); const char *filename = "";
if (pl) CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
{ if (pl)
m_FileName = pl->getName(); {
} filename = pl->getName();
else } else {
{ CList<CScript,AMX*>::iterator a = g_loadedscripts.find(m_pAmx);
for (auto script : g_loadedscripts) if (a)
{ filename = (*a).getName();
if (script->getAMX() == m_pAmx) }
{ m_FileName.assign(filename);
m_FileName = script->getName(); }
break;
}
}
}
}
return m_FileName.chars();
}
const char *Debugger::_GetVersion() return m_FileName.c_str();
{
if (m_Version.length() < 1)
{
const char *version = "";
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
if (pl)
{
version = pl->getVersion();
}
m_Version = version;
}
return m_Version.chars();
} }
void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLength) void Debugger::FmtGenericMsg(AMX *amx, int error, char buffer[], size_t maxLength)
{ {
const char *filename = ""; const char *filename = "";
char native[sNAMEMAX+1];
for (auto script : g_loadedscripts)
{
if (script->getAMX() == amx)
{
filename = script->getName();
break;
}
}
size_t len = strlen(filename);
for (size_t i=len-1; i<len; i--)
{
if ((filename[i] == '/' || filename[i] == '\\') && i != len - 1)
{
filename = &(filename[i+1]);
break;
}
}
if (error == AMX_ERR_EXIT) CList<CScript,AMX*>::iterator a = g_loadedscripts.find(amx);
{ if (a)
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - %s", error, filename, GenericError(AMX_ERR_EXIT)); filename = (*a).getName();
} else if (error == AMX_ERR_NATIVE) { size_t len = strlen(filename);
amx_GetNative(amx, reinterpret_cast<long>(amx->usertags[UT_NATIVE]), native); for (size_t i=len-1; i>=0; i--)
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") (native \"%s\") - debug not enabled!", error, filename, native); {
} else { if (filename[i] == '/' || filename[i] == '\\' && i != len - 1)
ke::SafeSprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename); {
} filename = &(filename[i+1]);
break;
}
}
_snprintf(buffer, maxLength, "Run time error %d (plugin \"%s\") - debug not enabled!", error, filename);
} }
void Debugger::GenericMessage(AMX *amx, int err) void Debugger::GenericMessage(AMX *amx, int err)
@ -648,14 +619,12 @@ void Debugger::GenericMessage(AMX *amx, int err)
Debugger::FmtGenericMsg(amx, err, buffer, sizeof(buffer)-1); Debugger::FmtGenericMsg(amx, err, buffer, sizeof(buffer)-1);
if (buffer[0] != '\0') if (buffer[0] != '\0')
AMXXLOG_Error("[AMXX] %s", buffer); AMXXLOG_Log("[AMXX] %s", buffer);
} }
Debugger::~Debugger() Debugger::~Debugger()
{ {
Clear(); Clear();
dbg_FreeInfo(m_pAmxDbg);
delete m_pAmxDbg;
} }
int Handler::SetErrorHandler(const char *function) int Handler::SetErrorHandler(const char *function)
@ -664,7 +633,7 @@ int Handler::SetErrorHandler(const char *function)
error = amx_FindPublic(m_pAmx, function, &m_iErrFunc); error = amx_FindPublic(m_pAmx, function, &m_iErrFunc);
if (error != AMX_ERR_NONE && m_iErrFunc < 0) if (error != AMX_ERR_NONE && m_iErrFunc < 1)
m_iErrFunc = -1; m_iErrFunc = -1;
return error; return error;
@ -676,7 +645,7 @@ int Handler::SetModuleFilter(const char *function)
error = amx_FindPublic(m_pAmx, function, &m_iModFunc); error = amx_FindPublic(m_pAmx, function, &m_iModFunc);
if (error != AMX_ERR_NONE && m_iModFunc < 0) if (error != AMX_ERR_NONE && m_iModFunc < 1)
m_iModFunc = -1; m_iModFunc = -1;
return error; return error;
@ -697,22 +666,22 @@ int Handler::SetNativeFilter(const char *function)
void Handler::SetErrorMsg(const char *msg) void Handler::SetErrorMsg(const char *msg)
{ {
if (!msg) if (!msg)
m_MsgCache = nullptr; m_MsgCache.clear();
else else
m_MsgCache = msg; m_MsgCache.assign(msg);
} }
const char *Handler::GetLastMsg() const char *Handler::GetLastMsg()
{ {
if (m_MsgCache.length() < 1) if (m_MsgCache.size() < 1)
return NULL; return NULL;
return m_MsgCache.chars(); return m_MsgCache.c_str();
} }
int Handler::HandleModule(const char *module, bool isClass) int Handler::HandleModule(const char *module)
{ {
if (m_iModFunc < 0) if (m_iModFunc < 1)
return 0; return 0;
/** /**
@ -726,9 +695,8 @@ int Handler::HandleModule(const char *module, bool isClass)
//temporarily set prenit //temporarily set prenit
m_pAmx->flags |= AMX_FLAG_PRENIT; m_pAmx->flags |= AMX_FLAG_PRENIT;
amx_Push(m_pAmx, isClass ? 1 : 0);
amx_PushString(m_pAmx, &hea_addr, &phys_addr, module, 0, 0); amx_PushString(m_pAmx, &hea_addr, &phys_addr, module, 0, 0);
int err = amx_ExecPerf(m_pAmx, &retval, m_iModFunc); int err = amx_Exec(m_pAmx, &retval, m_iModFunc);
amx_Release(m_pAmx, hea_addr); amx_Release(m_pAmx, hea_addr);
m_pAmx->flags &= ~AMX_FLAG_PRENIT; m_pAmx->flags &= ~AMX_FLAG_PRENIT;
@ -768,7 +736,7 @@ int Handler::HandleNative(const char *native, int index, int trap)
amx_Push(m_pAmx, trap); amx_Push(m_pAmx, trap);
amx_Push(m_pAmx, index); amx_Push(m_pAmx, index);
amx_PushString(m_pAmx, &hea_addr, &phys_addr, native, 0, 0); amx_PushString(m_pAmx, &hea_addr, &phys_addr, native, 0, 0);
int err = amx_ExecPerf(m_pAmx, &retval, m_iNatFunc); int err = amx_Exec(m_pAmx, &retval, m_iNatFunc);
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
{ {
//LogError() took care of something for us. //LogError() took care of something for us.
@ -780,7 +748,7 @@ int Handler::HandleNative(const char *native, int index, int trap)
} }
if (!trap) if (!trap)
{ {
AMXXLOG_Error("[AMXX] Runtime failure %d occurred in native filter. Aborting plugin load.", err); AMXXLOG_Log("[AMXX] Runtime failure %d occurred in native filter. Aborting plugin load.", err);
return 0; return 0;
} }
//handle this manually. //handle this manually.
@ -791,7 +759,7 @@ int Handler::HandleNative(const char *native, int index, int trap)
} else if (err != -1) { } else if (err != -1) {
LogError(m_pAmx, err, NULL); LogError(m_pAmx, err, NULL);
} }
AMXXLOG_Error("[AMXX] NOTE: Runtime failures in native filters are not good!"); AMXXLOG_Log("[AMXX] NOTE: Runtime failures in native filters are not good!");
retval = 0; retval = 0;
} }
if (!trap) if (!trap)
@ -814,8 +782,8 @@ int Handler::HandleError(const char *msg)
return 0; return 0;
m_Handling = true; m_Handling = true;
m_pTrace = nullptr; m_pTrace = NULL;
m_FmtCache = nullptr; m_FmtCache.clear();
Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER]; Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER];
@ -827,11 +795,11 @@ int Handler::HandleError(const char *msg)
pDebugger->SetTracedError(error); pDebugger->SetTracedError(error);
m_pTrace = pDebugger->GetTraceStart(); m_pTrace = pDebugger->GetTraceStart();
pDebugger->FormatError(_buffer, sizeof(_buffer)-1); pDebugger->FormatError(_buffer, sizeof(_buffer)-1);
m_FmtCache = _buffer; m_FmtCache.assign(_buffer);
pDebugger->BeginExec(); pDebugger->BeginExec();
} else { } else {
Debugger::FmtGenericMsg(m_pAmx, error, _buffer, sizeof(_buffer)-1); Debugger::FmtGenericMsg(m_pAmx, error, _buffer, sizeof(_buffer)-1);
m_FmtCache = _buffer; m_FmtCache.assign(_buffer);
} }
SetErrorMsg(msg); SetErrorMsg(msg);
@ -841,7 +809,7 @@ int Handler::HandleError(const char *msg)
amx_PushString(m_pAmx, &hea_addr, &phys_addr, msg, 0, 0); amx_PushString(m_pAmx, &hea_addr, &phys_addr, msg, 0, 0);
amx_Push(m_pAmx, pDebugger ? 1 : 0); amx_Push(m_pAmx, pDebugger ? 1 : 0);
amx_Push(m_pAmx, error); amx_Push(m_pAmx, error);
int err = amx_ExecPerf(m_pAmx, &result, m_iErrFunc); int err = amx_Exec(m_pAmx, &result, m_iErrFunc);
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
{ {
//handle this manually. //handle this manually.
@ -851,10 +819,10 @@ int Handler::HandleError(const char *msg)
pDebugger->DisplayTrace(msg); pDebugger->DisplayTrace(msg);
} else { } else {
if (GetLastMsg()) if (GetLastMsg())
AMXXLOG_Error("%s", GetLastMsg()); AMXXLOG_Log("%s", GetLastMsg());
Debugger::GenericMessage(m_pAmx, err); Debugger::GenericMessage(m_pAmx, err);
} }
AMXXLOG_Error("[AMXX] NOTE: Runtime failures in an error filter are not good!"); AMXXLOG_Log("[AMXX] NOTE: Runtime failures in an error filter are not good!");
} }
if (pDebugger) if (pDebugger)
@ -863,8 +831,8 @@ int Handler::HandleError(const char *msg)
amx_Release(m_pAmx, hea_addr); amx_Release(m_pAmx, hea_addr);
m_Handling = false; m_Handling = false;
m_pTrace = nullptr; m_pTrace = NULL;
m_FmtCache = nullptr; m_FmtCache.clear();
if (err != AMX_ERR_NONE || !result) if (err != AMX_ERR_NONE || !result)
return 0; return 0;
@ -882,7 +850,7 @@ static cell AMX_NATIVE_CALL set_error_filter(AMX *amx, cell *params)
if (!pHandler) if (!pHandler)
{ {
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Error("[AMXX] Plugin not initialized correctly."); AMXXLOG_Log("[AMXX] Plugin not initialized correctly.");
return 0; return 0;
} }
@ -890,7 +858,7 @@ static cell AMX_NATIVE_CALL set_error_filter(AMX *amx, cell *params)
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
{ {
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Error("[AMXX] Function not found: %s", function); AMXXLOG_Log("[AMXX] Function not found: %s", function);
return 0; return 0;
} }
@ -970,7 +938,7 @@ static cell AMX_NATIVE_CALL set_native_filter(AMX *amx, cell *params)
if (!pHandler) if (!pHandler)
{ {
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Error("[AMXX] Plugin not initialized correctly."); AMXXLOG_Log("[AMXX] Plugin not initialized correctly.");
return 0; return 0;
} }
@ -989,7 +957,7 @@ static cell AMX_NATIVE_CALL set_native_filter(AMX *amx, cell *params)
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
{ {
Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND); Debugger::GenericMessage(amx, AMX_ERR_NOTFOUND);
AMXXLOG_Error("[AMXX] Function not found: %s", function); AMXXLOG_Log("[AMXX] Function not found: %s", function);
return 0; return 0;
} }

View File

@ -1,15 +1,38 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef _INCLUDE_DEBUGGER_H_ #ifndef _INCLUDE_DEBUGGER_H_
#define _INCLUDE_DEBUGGER_H_ #define _INCLUDE_DEBUGGER_H_
#include "CVector.h"
#include "amxdbg.h" #include "amxdbg.h"
/** /**
@ -27,7 +50,7 @@ public:
struct trace_info struct trace_info
{ {
trace_info() : cip(0), frm(0), next(NULL), prev(NULL), used(false) {}; trace_info() : cip(0), frm(0), used(false), next(NULL), prev(NULL) {};
cell cip; cell cip;
cell frm; cell frm;
@ -115,17 +138,15 @@ private:
cell _CipAsVa(cell cip); cell _CipAsVa(cell cip);
const char *_GetFilename(); const char *_GetFilename();
const char *_GetVersion();
public: public:
AMX *m_pAmx; AMX *m_pAmx;
AMX_DBG *m_pAmxDbg; AMX_DBG *m_pAmxDbg;
int m_Top; int m_Top;
cell *m_pOpcodeList; cell *m_pOpcodeList;
ke::AString m_FileName; String m_FileName;
ke::AString m_Version;
CVector<Tracer *> m_pCalls;
ke::Vector<Tracer *> m_pCalls;
}; };
typedef Debugger::Tracer::trace_info trace_info_t; typedef Debugger::Tracer::trace_info trace_info_t;
@ -146,16 +167,16 @@ public:
public: public:
int HandleError(const char *msg); int HandleError(const char *msg);
int HandleNative(const char *native, int index, int trap); int HandleNative(const char *native, int index, int trap);
int HandleModule(const char *module, bool isClass=false); int HandleModule(const char *module);
public: public:
bool IsHandling() const { return m_Handling; } bool IsHandling() const { return m_Handling; }
void SetErrorMsg(const char *msg); void SetErrorMsg(const char *msg);
const char *GetLastMsg(); const char *GetLastMsg();
trace_info_t *GetTrace() const { return m_pTrace; } trace_info_t *GetTrace() const { return m_pTrace; }
const char *GetFmtCache() { return m_FmtCache.chars(); } const char *GetFmtCache() { return m_FmtCache.c_str(); }
bool IsNativeFiltering() { return (m_iNatFunc > -1); } bool IsNativeFiltering() { return (m_iNatFunc > 0); }
bool InNativeFilter() { return m_InNativeFilter; } bool InNativeFilter() { return m_InNativeFilter; }
private: private:
AMX *m_pAmx; AMX *m_pAmx;
@ -169,8 +190,8 @@ private:
//in the future, make this a stack! //in the future, make this a stack!
bool m_InNativeFilter; bool m_InNativeFilter;
ke::AString m_MsgCache; String m_MsgCache;
ke::AString m_FmtCache; String m_FmtCache;
trace_info_t *m_pTrace; trace_info_t *m_pTrace;
}; };

View File

@ -1,14 +1,35 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. * originally developed by OLO
// *
// This software is licensed under the GNU General Public License, version 3 or higher. *
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * This program is free software; you can redistribute it and/or modify it
// https://alliedmods.net/amxmodx-license * under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "CMenu.h"
int gmsgAmmoPickup; int gmsgAmmoPickup;
int gmsgAmmoX; int gmsgAmmoX;
@ -30,8 +51,6 @@ int gmsgWeaponList;
int gmsgintermission; int gmsgintermission;
int gmsgResetHUD; int gmsgResetHUD;
int gmsgRoundTime; int gmsgRoundTime;
int gmsgSayText;
int gmsgInitHUD;
TeamIds g_teamsIds; TeamIds g_teamsIds;
WeaponsVault g_weaponsData[MAX_WEAPONS]; WeaponsVault g_weaponsData[MAX_WEAPONS];
@ -73,10 +92,9 @@ void Client_ShowMenu(void* mValue)
} }
} }
extern bool g_bmod_tfc;
void Client_TeamInfo(void* mValue) void Client_TeamInfo(void* mValue)
{ {
if (mPlayer && !g_bmod_tfc) return; if (mPlayer) return;
static int index; static int index;
switch (mState++) switch (mState++)
@ -87,48 +105,8 @@ void Client_TeamInfo(void* mValue)
case 1: case 1:
if (index < 1 || index > gpGlobals->maxClients) break; if (index < 1 || index > gpGlobals->maxClients) break;
char* msg = (char*)mValue; char* msg = (char*)mValue;
if (!msg) break; g_players[index].team.assign(msg);
auto pPlayer = GET_PLAYER_POINTER_I(index);
pPlayer->team = msg;
g_teamsIds.registerTeam(msg, -1); g_teamsIds.registerTeam(msg, -1);
pPlayer->teamId = g_teamsIds.findTeamId(msg);
if (pPlayer->teamId == -1)
{
/**
* CS fix for SPECTATOR team.
* -
* When a player chooses spectator, ScoreInfo is sent before TeamInfo and with 0 as index.
* This means for the first round of first spectator, SPECTATOR name is not associated with its index.
* The following fix manually sets the team index when we hit SPECTATOR team.
*/
if (g_bmod_cstrike && !strcmp(msg, "SPECTATOR"))
{
pPlayer->teamId = 3;
g_teamsIds.registerTeam(msg, 3);
}
/**
* Fixes in-between situation where the team name is not yet associated with a valid index
* and ScoreInfo is executed later (used to retrieve the index). E.g. a player is dead,
* then changes team. Index will return -1 until ScoreInfo is sent, usually at the next spawn.
*/
else if ((g_bmod_cstrike || g_bmod_dod || g_bmod_tfc || g_bmod_gearbox || g_bmod_valve)
&& pPlayer->pEdict->pvPrivateData
&& !pPlayer->IsAlive())
{
GET_OFFSET_NO_ERROR("CBasePlayer", m_iTeam);
const auto teamId = get_pdata<int>(pPlayer->pEdict, m_iTeam);
pPlayer->teamId = teamId;
g_teamsIds.registerTeam(msg, teamId);
}
}
break;
} }
} }
@ -210,7 +188,7 @@ void Client_WeaponList(void* mValue)
wpnList |= (1<<iId); wpnList |= (1<<iId);
g_weaponsData[iId].iId = iId; g_weaponsData[iId].iId = iId;
g_weaponsData[iId].ammoSlot = iSlot; g_weaponsData[iId].ammoSlot = iSlot;
g_weaponsData[iId].fullName = wpnName; g_weaponsData[iId].fullName.assign(wpnName);
} }
} }
@ -231,15 +209,9 @@ void Client_CurWeapon(void* mValue)
case 2: case 2:
if (!mPlayer) return; if (!mPlayer) return;
if (!iState || (iId < 1 || iId >= MAX_WEAPONS)) break; if (!iState || (iId < 1 || iId >= MAX_WEAPONS)) break;
mPlayer->current = iId;
if (*(int*)mValue < mPlayer->weapons[iId].clip && // Only update the lastHit vector if the clip size is decreasing
*(int*)mValue != -1) // But not if it's a melee weapon
{
mPlayer->lastHit = mPlayer->lastTrace;
}
mPlayer->weapons[iId].clip = *(int*)mValue; mPlayer->weapons[iId].clip = *(int*)mValue;
mPlayer->current = iId;
mPlayer->lastHit = mPlayer->lastTrace;
} }
} }
@ -296,7 +268,7 @@ void Client_ScoreInfo(void* mValue)
pPlayer->deaths = deaths; pPlayer->deaths = deaths;
pPlayer->teamId = *(int*)mValue; pPlayer->teamId = *(int*)mValue;
if (g_teamsIds.isNewTeam()) if (g_teamsIds.isNewTeam())
g_teamsIds.registerTeam(pPlayer->team.chars(), pPlayer->teamId); g_teamsIds.registerTeam(pPlayer->team.c_str(), pPlayer->teamId);
} }
} }
@ -310,7 +282,7 @@ void Client_DamageEnd(void* mValue)
g_events.parseValue(dead->death_killer); g_events.parseValue(dead->death_killer);
g_events.parseValue(dead->index); g_events.parseValue(dead->index);
g_events.parseValue(dead->death_headshot); g_events.parseValue(dead->death_headshot);
g_events.parseValue(dead->death_weapon.chars()); g_events.parseValue(dead->death_weapon.c_str());
g_events.parseValue(dead->death_tk ? 1 : 0); g_events.parseValue(dead->death_tk ? 1 : 0);
g_events.executeEvents(); g_events.executeEvents();
dead->death_killer = 0; dead->death_killer = 0;
@ -341,31 +313,11 @@ void Client_DeathMsg(void* mValue)
case 3: case 3:
if (!killer || !victim) break; if (!killer || !victim) break;
victim->death_killer = killer_id; victim->death_killer = killer_id;
victim->death_weapon = (char*)mValue; victim->death_weapon.assign((char*)mValue);
victim->death_headshot = hs; victim->death_headshot = hs;
victim->death_tk = (killer->teamId == victim->teamId); victim->death_tk = (killer->teamId == victim->teamId);
} }
} }
void Client_InitHUDEnd(void* mValue)
{
if (!g_bmod_cstrike)
return;
CPlayer *pPlayer = mPlayer;
if (!pPlayer->teamIdsInitialized && !pPlayer->IsBot())
{
// This creates specific indexes (> maxplayers) for print_chat_color().
// 33 : print_team_grey / spectator
// 34 : print_team_red / terrorist
// 35 : print_team_blue / ct
UTIL_TeamInfo(pPlayer->pEdict, 33 + 1, "TERRORIST"); // print_team_red
UTIL_TeamInfo(pPlayer->pEdict, 33 + 2, "CT"); // print_team_blue
pPlayer->teamIdsInitialized = true;
}
}
/* /*
void Client_SendAudio(void* mValue) void Client_SendAudio(void* mValue)
{ {

View File

@ -1,11 +1,32 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. *
// *
// This software is licensed under the GNU General Public License, version 3 or higher. * This program is free software; you can redistribute it and/or modify it
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * under the terms of the GNU General Public License as published by the
// https://alliedmods.net/amxmodx-license * Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#include "amxmodx.h" #include "amxmodx.h"
#include "fakemeta.h" #include "fakemeta.h"

View File

@ -1,11 +1,32 @@
// vim: set ts=4 sw=4 tw=99 noet: /* AMX Mod X
// *
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). * by the AMX Mod X Development Team
// Copyright (C) The AMX Mod X Development Team. *
// *
// This software is licensed under the GNU General Public License, version 3 or higher. * This program is free software; you can redistribute it and/or modify it
// Additional exceptions apply. For full license details, see LICENSE.txt or visit: * under the terms of the GNU General Public License as published by the
// https://alliedmods.net/amxmodx-license * Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*/
#ifndef __FAKEMETA_H__ #ifndef __FAKEMETA_H__
#define __FAKEMETA_H__ #define __FAKEMETA_H__

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@
#include <stdlib.h> /* for atof() */ #include <stdlib.h> /* for atof() */
#include <stdio.h> /* for NULL */ #include <stdio.h> /* for NULL */
#include <assert.h> #include <assert.h>
#include <cmath> #include <math.h>
// this file does not include amxmodx.h, so we have to include the memory manager here // this file does not include amxmodx.h, so we have to include the memory manager here
#ifdef MEMORY_TEST #ifdef MEMORY_TEST
@ -368,6 +368,7 @@ static cell AMX_NATIVE_CALL n_floatatan(AMX *amx, cell *params)
* params[2] = radix * params[2] = radix
*/ */
REAL fA = amx_ctof(params[1]); REAL fA = amx_ctof(params[1]);
fA = ToRadians(fA, params[2]);
fA = atan(fA); fA = atan(fA);
fA = FromRadians(fA, params[2]); fA = FromRadians(fA, params[2]);
return amx_ftoc(fA); return amx_ftoc(fA);
@ -424,54 +425,6 @@ static cell AMX_NATIVE_CALL n_floatatan2(AMX *amx, cell *params)
return amx_ftoc(fC); return amx_ftoc(fC);
} }
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
/* Added by DS */
static cell AMX_NATIVE_CALL n_floatsinh(AMX *amx, cell *params)
{
/*
* params[1] = angle
* params[2] = radix
*/
REAL fA = amx_ctof(params[1]);
fA = ToRadians(fA, params[2]);
fA = sinh(fA);
return amx_ftoc(fA);
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
/* Added by DS */
static cell AMX_NATIVE_CALL n_floatcosh(AMX *amx, cell *params)
{
/*
* params[1] = angle
* params[2] = radix
*/
REAL fA = amx_ctof(params[1]);
fA = ToRadians(fA, params[2]);
fA = cosh(fA);
return amx_ftoc(fA);
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
/* Added by DS */
static cell AMX_NATIVE_CALL n_floattanh(AMX *amx, cell *params)
{
/*
* params[1] = angle
* params[2] = radix
*/
REAL fA = amx_ctof(params[1]);
fA = ToRadians(fA, params[2]);
fA = tanh(fA);
return amx_ftoc(fA);
}
#if defined __BORLANDC__ || defined __WATCOMC__ #if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused #pragma argsused
#endif #endif
@ -504,9 +457,6 @@ AMX_NATIVE_INFO float_Natives[] = {
{ "floatacos", n_floatacos }, { "floatacos", n_floatacos },
{ "floatatan", n_floatatan }, { "floatatan", n_floatatan },
{ "floatatan2", n_floatatan2 }, { "floatatan2", n_floatatan2 },
{ "floatsinh", n_floatsinh },
{ "floatcosh", n_floatcosh },
{ "floattanh", n_floattanh },
{ NULL, NULL } /* terminator */ { NULL, NULL } /* terminator */
}; };

View File

@ -1,15 +1,5 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "amxmodx.h" #include "amxmodx.h"
#include "format.h" #include "format.h"
#include "datastructs.h"
//Adapted from Quake3's vsprintf //Adapted from Quake3's vsprintf
// thanks to cybermind for linking me to this :) // thanks to cybermind for linking me to this :)
@ -27,7 +17,6 @@
#define SHORTINT 0x00000040 /* short integer */ #define SHORTINT 0x00000040 /* short integer */
#define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */ #define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */
#define FPT 0x00000100 /* floating point number */ #define FPT 0x00000100 /* floating point number */
#define UPPERDIGITS 0x00000200 /* make alpha digits uppercase */
#define to_digit(c) ((c) - '0') #define to_digit(c) ((c) - '0')
#define is_digit(c) ((unsigned)to_digit(c) <= 9) #define is_digit(c) ((unsigned)to_digit(c) <= 9)
#define to_char(n) ((n) + '0') #define to_char(n) ((n) + '0')
@ -37,134 +26,97 @@
return 0; \ return 0; \
} }
template size_t atcprintf<cell, cell>(cell *, size_t, const cell *, AMX *, cell *, int *); THash<String, lang_err> BadLang_Table;
template size_t atcprintf<char, cell>(char *, size_t, const cell *, AMX *, cell *, int *);
template size_t atcprintf<cell, char>(cell *, size_t, const char *, AMX *, cell *, int *);
template size_t atcprintf<char, char>(char *, size_t, const char *, AMX *, cell *, int *);
THash<ke::AString, lang_err> BadLang_Table; static cvar_t *amx_mldebug = NULL;
static cvar_t *amx_cl_langs = NULL;
static cvar_t *amx_mldebug = nullptr; const char *translate(AMX *amx, cell amxaddr, const char *key)
static cvar_t *amx_cl_langs = nullptr;
const char *playerlang(const cell index)
{ {
const char *pLangName = nullptr; const char *pLangName = NULL;
const char *def = NULL;
if (index == LANG_PLAYER) int status;
cell *addr = get_amxaddr(amx, amxaddr);
char name[4];
if (addr[0] == LANG_PLAYER)
{ {
if (!amx_cl_langs) if (!amx_cl_langs)
{
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages"); amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
} if ( (int)amx_cl_langs->value == 0 )
if (static_cast<int>(amx_cl_langs->value) == 0)
{
pLangName = amxmodx_language->string;
}
else
{ {
pLangName = g_vault.get("server_language");
} else {
pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(g_langMngr.GetDefLang())->pEdict, "lang"); pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(g_langMngr.GetDefLang())->pEdict, "lang");
} }
} } else if (addr[0] == LANG_SERVER) {
else if (index == LANG_SERVER) pLangName = g_vault.get("server_language");
{ } else if (addr[0] >= 1 && addr[0] <= gpGlobals->maxClients) {
pLangName = amxmodx_language->string;
}
else if (index >= 1 && index <= gpGlobals->maxClients)
{
if (!amx_cl_langs) if (!amx_cl_langs)
{
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages"); amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
} if ( (int)amx_cl_langs->value == 0 )
if (static_cast<int>(amx_cl_langs->value) == 0)
{ {
pLangName = amxmodx_language->string; pLangName = g_vault.get("server_language");
} } else {
else pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(addr[0])->pEdict, "lang");
{
pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(index)->pEdict, "lang");
} }
} else {
get_amxstring_r(amx, amxaddr, name, 3);
pLangName = name;
} }
return pLangName;
}
const char *translate(AMX *amx, const char *lang, const char *key)
{
auto pLangName = lang;
int status;
if (!pLangName || !isalpha(pLangName[0])) if (!pLangName || !isalpha(pLangName[0]))
{ pLangName = "en";
pLangName = amxmodx_language->string; //next parameter!
} def = g_langMngr.GetDef(pLangName, key, status);
auto def = g_langMngr.GetDef(pLangName, key, status);
if (!amx_mldebug) if (!amx_mldebug)
{
amx_mldebug = CVAR_GET_POINTER("amx_mldebug"); amx_mldebug = CVAR_GET_POINTER("amx_mldebug");
}
auto debug = (amx_mldebug && amx_mldebug->string && (amx_mldebug->string[0] != '\0'));
bool debug = (amx_mldebug && amx_mldebug->string && (amx_mldebug->string[0] != '\0'));
if (debug) if (debug)
{ {
int debug_status; int debug_status;
auto validlang = true; bool validlang = true;
auto testlang = amx_mldebug->string; const char *testlang = amx_mldebug->string;
if (!g_langMngr.LangExists(testlang)) if (!g_langMngr.LangExists(testlang))
{ {
AMXXLOG_Error("[AMXX] \"%s\" is an invalid debug language", testlang); AMXXLOG_Log("[AMXX] \"%s\" is an invalid debug language", testlang);
validlang = false; validlang = false;
} }
g_langMngr.GetDef(testlang, key, debug_status); g_langMngr.GetDef(testlang, key, debug_status);
if (validlang && debug_status == ERR_BADKEY) if (validlang && debug_status == ERR_BADKEY)
{ AMXXLOG_Log("[AMXX] Language key \"%s\" not found for language \"%s\", check \"%s\"", key, testlang, GetFileName(amx));
AMXXLOG_Error("[AMXX] Language key \"%s\" not found for language \"%s\", check \"%s\"", key, testlang, GetFileName(amx));
}
} }
if (!def) if (def == NULL)
{ {
if (debug && status == ERR_BADLANG) if (debug)
{ {
ke::AString langName(pLangName); if (status == ERR_BADLANG && (BadLang_Table.AltFindOrInsert(pLangName).last + 120.0f < gpGlobals->time))
auto &err = BadLang_Table.AltFindOrInsert(ke::Move(langName));
if (err.last + 120.0f < gpGlobals->time)
{ {
AMXXLOG_Error("[AMXX] Language \"%s\" not found", pLangName); AMXXLOG_Log("[AMXX] Language \"%s\" not found", pLangName);
err.last = gpGlobals->time; BadLang_Table.AltFindOrInsert(pLangName).last = gpGlobals->time;
} }
} }
if (strcmp(pLangName, amxmodx_language->string) != 0) if (addr[0] != LANG_SERVER)
{ def = g_langMngr.GetDef(g_vault.get("server_language"), key, status);
def = g_langMngr.GetDef(amxmodx_language->string, key, status);
} if (!def && (strcmp(pLangName, "en") != 0 && strcmp(g_vault.get("server_language"), "en") != 0))
if (!def && (strcmp(pLangName, "en") != 0 && strcmp(amxmodx_language->string, "en") != 0))
{
def = g_langMngr.GetDef("en", key, status); def = g_langMngr.GetDef("en", key, status);
}
} }
return def; return def;
} }
template <typename U, typename S> template <typename U>
void AddString(U **buf_p, size_t &maxlen, const S *string, int width, int prec) void AddString(U **buf_p, size_t &maxlen, const cell *string, int width, int prec)
{ {
int size = 0; int size = 0;
U *buf; U *buf;
static S nlstr[] = {'(','n','u','l','l',')','\0'}; static cell nlstr[] = {'(','n','u','l','l',')','\0'};
buf = *buf_p; buf = *buf_p;
@ -189,12 +141,6 @@ void AddString(U **buf_p, size_t &maxlen, const S *string, int width, int prec)
if (size > (int)maxlen) if (size > (int)maxlen)
size = maxlen; size = maxlen;
/* If precision is provided, make sure we don't truncate a multi-byte character */
if (prec >= size && (string[size - 1] & 1 << 7))
{
size -= UTIL_CheckValidChar((cell *)string + size - 1);
}
maxlen -= size; maxlen -= size;
width -= size; width -= size;
@ -211,221 +157,71 @@ void AddString(U **buf_p, size_t &maxlen, const S *string, int width, int prec)
} }
template <typename U> template <typename U>
void AddFloat(U **buf_p, size_t &maxlen, double fval, int width, int prec, int flags) void AddFloat(U **buf_p, size_t &maxlen, double fval, int width, int prec)
{
int digits; // non-fraction part digits
double tmp; // temporary
U *buf = *buf_p; // output buffer pointer
int val; // temporary
int sign = 0; // 0: positive, 1: negative
int fieldlength; // for padding
int significant_digits = 0; // number of significant digits written
const int MAX_SIGNIFICANT_DIGITS = 16;
// default precision
if (prec < 0)
{
prec = 6;
}
// get the sign
if (fval < 0)
{
fval = -fval;
sign = 1;
}
// compute whole-part digits count
digits = (int)log10(fval) + 1;
// Only print 0.something if 0 < fval < 1
if (digits < 1)
{
digits = 1;
}
// compute the field length
fieldlength = digits + prec + ((prec > 0) ? 1 : 0) + sign;
// minus sign BEFORE left padding if padding with zeros
if (sign && maxlen && (flags & ZEROPAD))
{
*buf++ = '-';
maxlen--;
}
// right justify if required
if ((flags & LADJUST) == 0)
{
while ((fieldlength < width) && maxlen)
{
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
width--;
maxlen--;
}
}
// minus sign AFTER left padding if padding with spaces
if (sign && maxlen && !(flags & ZEROPAD))
{
*buf++ = '-';
maxlen--;
}
// write the whole part
tmp = pow(10.0, digits-1);
while ((digits--) && maxlen)
{
if (++significant_digits > MAX_SIGNIFICANT_DIGITS)
{
*buf++ = '0';
}
else
{
val = (int)(fval / tmp);
*buf++ = '0' + val;
fval -= val * tmp;
tmp *= 0.1;
}
maxlen--;
}
// write the fraction part
if (maxlen && prec)
{
*buf++ = '.';
maxlen--;
}
tmp = pow(10.0, prec);
fval *= tmp;
while (prec-- && maxlen)
{
if (++significant_digits > MAX_SIGNIFICANT_DIGITS)
{
*buf++ = '0';
}
else
{
tmp *= 0.1;
val = (int)(fval / tmp);
*buf++ = '0' + val;
fval -= val * tmp;
}
maxlen--;
}
// left justify if required
if (flags & LADJUST)
{
while ((fieldlength < width) && maxlen)
{
// right-padding only with spaces, ZEROPAD is ignored
*buf++ = ' ';
width--;
maxlen--;
}
}
// update parent's buffer pointer
*buf_p = buf;
}
template <typename U>
void AddBinary(U **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
{
char text[32];
int digits;
U *buf;
digits = 0;
do
{
if (val & 1)
{
text[digits++] = '1';
}
else
{
text[digits++] = '0';
}
val >>= 1;
} while (val);
buf = *buf_p;
if (!(flags & LADJUST))
{
while (digits < width && maxlen)
{
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
width--;
maxlen--;
}
}
while (digits-- && maxlen)
{
*buf++ = text[digits];
width--;
maxlen--;
}
if (flags & LADJUST)
{
while (width-- && maxlen)
{
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
maxlen--;
}
}
*buf_p = buf;
}
template <typename U>
void AddUInt(U **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
{ {
U text[32]; U text[32];
int digits; int digits;
double signedVal;
U *buf; U *buf;
int val;
// get the sign
signedVal = fval;
if (fval < 0)
fval = -fval;
// write the float number
digits = 0; digits = 0;
val = (int)fval;
do { do {
text[digits++] = '0' + val % 10; text[digits++] = '0' + val % 10;
val /= 10; val /= 10;
} while (val); } while (val);
if (signedVal < 0)
text[digits++] = '-';
buf = *buf_p; buf = *buf_p;
if( !(flags & LADJUST) ) while (digits < width && maxlen)
{ {
while (digits < width && maxlen) *buf++ = ' ';
{ width--;
*buf++ = (flags & ZEROPAD) ? '0' : ' '; maxlen--;
width--;
maxlen--;
}
} }
while (digits-- && maxlen) while (digits-- && maxlen)
{ {
*buf++ = text[digits]; *buf++ = text[digits];
width--;
maxlen--; maxlen--;
} }
if (flags & LADJUST) *buf_p = buf;
if (prec < 0)
prec = 6;
// write the fraction
digits = 0;
while (digits < prec)
{ {
while (width-- && maxlen) fval -= (int) fval;
{ fval *= 10.0;
*buf++ = (flags & ZEROPAD) ? '0' : ' '; val = (int) fval;
maxlen--; text[digits++] = '0' + val % 10;
}
} }
*buf_p = buf; if (digits > 0 && maxlen)
{
buf = *buf_p;
*buf++ = '.';
maxlen--;
for (prec = 0; maxlen && prec < digits; prec++)
{
*buf++ = text[prec];
maxlen--;
}
*buf_p = buf;
}
} }
template <typename U> template <typename U>
@ -435,21 +231,15 @@ void AddInt(U **buf_p, size_t &maxlen, int val, int width, int flags)
int digits; int digits;
int signedVal; int signedVal;
U *buf; U *buf;
unsigned int unsignedVal;
digits = 0; digits = 0;
signedVal = val; signedVal = val;
if (val < 0) if (val < 0)
{ val = -val;
/* we want the unsigned version */
unsignedVal = abs(val);
} else {
unsignedVal = val;
}
do { do {
text[digits++] = '0' + unsignedVal % 10; text[digits++] = '0' + val % 10;
unsignedVal /= 10; val /= 10;
} while (unsignedVal); } while (val);
if (signedVal < 0) if (signedVal < 0)
text[digits++] = '-'; text[digits++] = '-';
@ -485,66 +275,6 @@ void AddInt(U **buf_p, size_t &maxlen, int val, int width, int flags)
*buf_p = buf; *buf_p = buf;
} }
template <typename U>
void AddHex(U **buf_p, size_t &maxlen, unsigned int val, int width, int flags)
{
U text[32];
int digits;
U *buf;
U digit;
int hexadjust;
if (flags & UPPERDIGITS)
{
hexadjust = 'A' - '9' - 1;
} else {
hexadjust = 'a' - '9' - 1;
}
digits = 0;
do
{
digit = ('0' + val % 16);
if (digit > '9')
{
digit += hexadjust;
}
text[digits++] = digit;
val /= 16;
} while (val);
buf = *buf_p;
if( !(flags & LADJUST) )
{
while (digits < width && maxlen)
{
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
width--;
maxlen--;
}
}
while (digits-- && maxlen)
{
*buf++ = text[digits];
width--;
maxlen--;
}
if (flags & LADJUST)
{
while (width-- && maxlen)
{
*buf++ = (flags & ZEROPAD) ? '0' : ' ';
maxlen--;
}
}
*buf_p = buf;
}
template <typename D, typename S> template <typename D, typename S>
size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param) size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param)
{ {
@ -556,7 +286,7 @@ size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *para
int width; int width;
int prec; int prec;
int n; int n;
//char sign; char sign;
const S *fmt; const S *fmt;
size_t llen = maxlen; size_t llen = maxlen;
@ -584,7 +314,7 @@ size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *para
flags = 0; flags = 0;
width = 0; width = 0;
prec = -1; prec = -1;
//sign = '\0'; sign = '\0';
rflag: rflag:
ch = static_cast<D>(*fmt++); ch = static_cast<D>(*fmt++);
@ -622,12 +352,6 @@ reswitch:
case 'c': case 'c':
CHECK_ARGS(0); CHECK_ARGS(0);
*buf_p++ = static_cast<D>(*get_amxaddr(amx, params[arg])); *buf_p++ = static_cast<D>(*get_amxaddr(amx, params[arg]));
llen--;
arg++;
break;
case 'b':
CHECK_ARGS(0);
AddBinary(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
arg++; arg++;
break; break;
case 'd': case 'd':
@ -636,71 +360,27 @@ reswitch:
AddInt(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags); AddInt(&buf_p, llen, *get_amxaddr(amx, params[arg]), width, flags);
arg++; arg++;
break; break;
case 'u':
CHECK_ARGS(0);
AddUInt(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
arg++;
break;
case 'f': case 'f':
CHECK_ARGS(0); CHECK_ARGS(0);
AddFloat(&buf_p, llen, amx_ctof(*get_amxaddr(amx, params[arg])), width, prec, flags); AddFloat(&buf_p, llen, amx_ctof(*get_amxaddr(amx, params[arg])), width, prec);
arg++; arg++;
break; break;
case 'X':
CHECK_ARGS(0);
flags |= UPPERDIGITS;
AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
arg++;
break;
case 'x':
CHECK_ARGS(0);
AddHex(&buf_p, llen, static_cast<unsigned int>(*get_amxaddr(amx, params[arg])), width, flags);
arg++;
break;
case 'a':
{
CHECK_ARGS(0);
// %a is passed a pointer directly to a cell string.
cell* ptr=reinterpret_cast<cell*>(*get_amxaddr(amx, params[arg]));
if (!ptr)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid vector string handle provided (%d)", *get_amxaddr(amx, params[arg]));
return 0;
}
AddString(&buf_p, llen, ptr, width, prec);
arg++;
break;
}
case 's': case 's':
CHECK_ARGS(0); CHECK_ARGS(0);
AddString(&buf_p, llen, get_amxaddr(amx, params[arg]), width, prec); AddString(&buf_p, llen, get_amxaddr(amx, params[arg]), width, prec);
arg++; arg++;
break; break;
case 'L': case 'L':
case 'l':
{ {
const char *lang; CHECK_ARGS(1);
cell addr = params[arg++];
int len; int len;
if (ch == 'L')
{
CHECK_ARGS(1);
auto currParam = params[arg++];
lang = playerlang(*get_amxaddr(amx, currParam));
if (!lang)
lang = get_amxstring(amx, currParam, 2, len);
}
else
{
CHECK_ARGS(0);
lang = playerlang(g_langMngr.GetDefLang());
}
const char *key = get_amxstring(amx, params[arg++], 3, len); const char *key = get_amxstring(amx, params[arg++], 3, len);
const char *def = translate(amx, lang, key); const char *def = translate(amx, addr, key);
if (!def) if (!def)
{ {
static char buf[255]; static char buf[255];
ke::SafeSprintf(buf, sizeof(buf), "ML_NOTFOUND: %s", key); snprintf(buf, sizeof(buf)-1, "ML_NOTFOUND: %s", key);
def = buf; def = buf;
} }
size_t written = atcprintf(buf_p, llen, def, amx, params, &arg); size_t written = atcprintf(buf_p, llen, def, amx, params, &arg);
@ -708,72 +388,6 @@ reswitch:
llen -= written; llen -= written;
break; break;
} }
case 'N':
{
CHECK_ARGS(0);
cell *addr = get_amxaddr(amx, params[arg]);
char buffer[255];
if (*addr)
{
CPlayer *player = NULL;
if (*addr >= 1 && *addr <= gpGlobals->maxClients)
{
player = GET_PLAYER_POINTER_I(*addr);
}
if (!player || !player->initialized)
{
LogError(amx, AMX_ERR_NATIVE, "Client index %d is invalid", *addr);
return 0;
}
const char *auth = GETPLAYERAUTHID(player->pEdict);
if (!auth || auth[0] == '\0')
{
auth = "STEAM_ID_PENDING";
}
int userid = GETPLAYERUSERID(player->pEdict);
ke::SafeSprintf(buffer, sizeof(buffer), "%s<%d><%s><%s>", player->name.chars(), userid, auth, player->team.chars());
}
else
{
ke::SafeSprintf(buffer, sizeof(buffer), "Console<0><Console><Console>");
}
AddString(&buf_p, llen, buffer, width, prec);
arg++;
break;
}
case 'n':
{
CHECK_ARGS(0);
cell *addr = get_amxaddr(amx, params[arg]);
const char *name = "Console";
if (*addr)
{
CPlayer *player = NULL;
if (*addr >= 1 && *addr <= gpGlobals->maxClients)
{
player = GET_PLAYER_POINTER_I(*addr);
}
if (!player || !player->initialized)
{
LogError(amx, AMX_ERR_NATIVE, "Client index %d is invalid", *addr);
return 0;
}
name = player->name.chars();
}
AddString(&buf_p, llen, name, width, prec);
arg++;
break;
}
case '%': case '%':
*buf_p++ = static_cast<D>(ch); *buf_p++ = static_cast<D>(ch);
if (!llen) if (!llen)
@ -799,14 +413,6 @@ reswitch:
done: done:
*buf_p = static_cast<D>(0); *buf_p = static_cast<D>(0);
*param = arg; *param = arg;
/* if max buffer length consumed, make sure we don't truncate a multi-byte character */
if (llen <= 0 && *(buf_p - 1) & 1 << 7)
{
llen += UTIL_CheckValidChar(buf_p - 1);
*(buf_p - llen) = static_cast<D>(0);
}
return maxlen-llen; return maxlen-llen;
} }

View File

@ -1,12 +1,3 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _INCLUDE_FORMATTING_H #ifndef _INCLUDE_FORMATTING_H
#define _INCLUDE_FORMATTING_H #define _INCLUDE_FORMATTING_H
@ -14,7 +5,4 @@
template <typename D, typename S> template <typename D, typename S>
size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param); size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param);
const char *playerlang(const cell index);
const char *translate(AMX *amx, const char *lang, const char *key);
#endif //_INCLUDE_FORMATTING_H #endif //_INCLUDE_FORMATTING_H

View File

@ -1,175 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "gameconfigs.h"
#include "amxmodx.h"
#include "CGameConfigs.h"
NativeHandle<GameConfigNative> GameConfigHandle;
// native GameConfig:LoadGameConfigFile(const file[]);
static cell AMX_NATIVE_CALL LoadGameConfigFile(AMX *amx, cell *params)
{
int length;
const char *filename = get_amxstring(amx, params[1], 0, length);
IGameConfig *config = nullptr;
char error[128];
if (!ConfigManager.LoadGameConfigFile(filename, &config, error, sizeof(error)))
{
ConfigManager.CloseGameConfigFile(config);
LogError(amx, AMX_ERR_NATIVE, "Unable to open %s: %s", filename, error);
return 0;
}
int handle = GameConfigHandle.create();
auto configHandle = GameConfigHandle.lookup(handle);
if (!configHandle)
{
return 0;
}
configHandle->m_config = config;
return handle;
}
// native GameConfGetOffset(GameConfig:handle, const key[]);
static cell AMX_NATIVE_CALL GameConfGetOffset(AMX *amx, cell *params)
{
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
if (!handle)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
return 0;
}
int length;
TypeDescription value;
const char *key = get_amxstring(amx, params[2], 0, length);
if (!handle->m_config->GetOffset(key, &value))
{
return -1;
}
return value.fieldOffset;
}
// native GameConfGetClassOffset(GameConfig:handle, const classname[], const key[]);
static cell AMX_NATIVE_CALL GameConfGetClassOffset(AMX *amx, cell *params)
{
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
if (!handle)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
return 0;
}
int length;
TypeDescription value;
const char *classname = get_amxstring(amx, params[2], 0, length);
const char *key = get_amxstring(amx, params[3], 1, length);
if (!handle->m_config->GetOffsetByClass(classname, key, &value))
{
return -1;
}
return value.fieldOffset;
}
// native bool:GameConfGetKeyValue(GameConfig:handle, const key[], buffer[], maxlen);
static cell AMX_NATIVE_CALL GameConfGetKeyValue(AMX *amx, cell *params)
{
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
if (!handle)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
return 0;
}
int length;
const char *value;
const char *key = get_amxstring(amx, params[2], 0, length);
if (!(value = handle->m_config->GetKeyValue(key)))
{
return 0;
}
set_amxstring_utf8(amx, params[3], value, strlen(value), params[4]);
return 1;
}
// native GameConfGetAddress(GameConfig:handle, const name[]);
static cell AMX_NATIVE_CALL GameConfGetAddress(AMX *amx, cell *params)
{
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
if (!handle)
{
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
return 0;
}
int length;
void *value;
const char *key = get_amxstring(amx, params[2], 0, length);
if (!handle->m_config->GetAddress(key, &value))
{
return 0;
}
return reinterpret_cast<cell>(value);
}
// native CloseGameConfigFile(&GameConfig:handle);
static cell AMX_NATIVE_CALL CloseGameConfigFile(AMX *amx, cell *params)
{
cell *address = get_amxaddr(amx, params[1]);
GameConfigNative *handle = GameConfigHandle.lookup(*address);
if (!handle)
{
return 0;
}
if (GameConfigHandle.destroy(*address))
{
*address = 0;
return 1;
}
return 0;
}
AMX_NATIVE_INFO g_GameConfigNatives[] =
{
{ "LoadGameConfigFile" , LoadGameConfigFile },
{ "GameConfGetOffset" , GameConfGetOffset },
{ "GameConfGetClassOffset", GameConfGetClassOffset },
{ "GameConfGetKeyValue" , GameConfGetKeyValue },
{ "GameConfGetAddress" , GameConfGetAddress },
{ "CloseGameConfigFile" , CloseGameConfigFile },
{ nullptr , nullptr }
};

View File

@ -1,18 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "IGameConfigs.h"
#include "natives_handles.h"
struct GameConfigNative
{
IGameConfig *m_config;
};
extern NativeHandle<GameConfigNative> GameConfigHandle;

View File

@ -1,52 +0,0 @@
; vim: set ts=4 sw=4 tw=99 noet ft=nasm:
;
; AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
; Copyright (C) The AMX Mod X Development Team.
;
; This software is licensed under the GNU General Public License, version 3 or higher.
; Additional exceptions apply. For full license details, see LICENSE.txt or visit:
; https://alliedmods.net/amxmodx-license
section .text
global amxx_CpuSupport, _amxx_CpuSupport
amxx_CpuSupport:
_amxx_CpuSupport:
push ebp
mov ebp, esp
push ebx
mov eax, 0
cpuid
cmp eax, 1
jl .fail
mov eax, 1
cpuid
;check if family == 5 or 4
and eax, 0780h ;family mask
shr eax, 7 ;family shift
cmp eax, 5
je .fail
cmp eax, 4
je .fail
;check if CMOV exists
shr edx, 15
and edx, 1
cmp edx, 0
je .fail
mov eax, 1
jmp .end
.fail:
xor eax, eax
.end:
pop ebx
pop ebp
ret

View File

@ -1,252 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#include "libraries.h"
#include "sh_list.h"
List<Library *> g_libraries;
bool AddLibrary(const char *name, LibType type, LibSource src, void *parent)
{
if (FindLibrary(name, type))
return false;
Library *lib = new Library;
lib->name = name;
lib->type = type;
lib->src = src;
lib->parent = parent;
g_libraries.push_back(lib);
return true;
}
bool DecodeLibCmdString(const char *str, LibDecoder *dec)
{
if (dec->buffer)
{
free(dec->buffer);
dec->buffer = NULL;
}
if (str[0] != '?')
{
return false;
} else {
str++;
if (*str == 'r')
{
str++;
if (*str == 'c')
dec->cmd = LibCmd_ReqClass;
else if (*str == 'l')
dec->cmd = LibCmd_ReqLib;
else
return false;
str++;
} else if (*str == 'f') {
str++;
dec->cmd = LibCmd_ForceLib;
} else if (*str == 'e') {
str++;
if (*str == 'c')
dec->cmd = LibCmd_ExpectClass;
else if (*str == 'l')
dec->cmd = LibCmd_ExpectLib;
else
return false;
str++;
} else if (*str == 'd') {
str++;
dec->cmd = LibCmd_DefaultLib;
}
if (*str != '_')
return false;
str++;
if (dec->cmd < LibCmd_ExpectLib)
{
dec->buffer = strdup(str);
dec->param1 = dec->buffer;
dec->param2 = NULL;
} else {
dec->buffer = strdup(str);
char *p = strchr(dec->buffer, '_');
while (p && (*(p+1) == '_'))
p = strchr(p+2, '_');
if (!p || !*(p+1))
return false;
*p = '\0';
dec->param1 = dec->buffer;
dec->param2 = p+1;
}
}
return true;
}
size_t AddLibrariesFromString(const char *name, LibType type, LibSource src, void *parent)
{
char buffer[255];
char *ptr, *p, s;
size_t count = 0;
ke::SafeSprintf(buffer, sizeof(buffer), "%s", name);
ptr = buffer;
p = buffer;
while (*p)
{
while (*p && (*p != ','))
p++;
s = *p;
*p = '\0';
if (AddLibrary(ptr, type, src, parent))
count++;
if (!s)
break;
p++;
while (*p && (*p == ','))
p++;
ptr = p;
}
return count;
}
size_t ClearLibraries(LibSource src)
{
List<Library *>::iterator iter;
size_t count = 0;
iter = g_libraries.begin();
while (iter != g_libraries.end())
{
if ( (*iter)->src == src )
{
delete (*iter);
iter = g_libraries.erase(iter);
count++;
} else {
iter++;
}
}
return count;
}
size_t RemoveLibraries(void *parent)
{
List<Library *>::iterator iter;
Library *lib;
size_t count = 0;
iter = g_libraries.begin();
while (iter != g_libraries.end())
{
lib = (*iter);
if (lib->parent == parent)
{
delete (*iter);
iter = g_libraries.erase(iter);
count++;
} else {
iter++;
}
}
return count;
}
bool FindLibrary(const char *name, LibType type)
{
List<Library *>::iterator iter;
Library *lib;
for (iter = g_libraries.begin(); iter != g_libraries.end(); iter++)
{
lib = (*iter);
if (lib->type != type)
continue;
if (strcasecmp(lib->name.chars(), name) == 0)
{
return true;
}
}
return false;
}
LibError RunLibCommand(const LibDecoder *enc)
{
List<Library *>::iterator iter,end;
Library *lib;
iter = g_libraries.begin();
end = g_libraries.end();
if ( (enc->cmd == LibCmd_ReqLib) || (enc->cmd == LibCmd_ReqClass) )
{
LibType expect = LibType_Library;
if (enc->cmd == LibCmd_ReqLib)
expect = LibType_Library;
else if (enc->cmd == LibCmd_ReqClass)
expect = LibType_Class;
/** see if it exists */
for (; iter != end; iter++)
{
lib = (*iter);
if (lib->type != expect)
continue;
if (strcasecmp(lib->name.chars(), enc->param1) == 0)
return LibErr_None;
}
if (expect == LibType_Library)
return LibErr_NoLibrary;
else if (expect == LibType_Class)
return LibErr_NoClass;
return LibErr_NoLibrary;
} else if (enc->cmd == LibCmd_ForceLib) {
if (!LoadModule(enc->param1, PT_ANYTIME, true, true))
{
return LibErr_NoLibrary;
}
} else if ( (enc->cmd == LibCmd_DefaultLib) ||
((enc->cmd == LibCmd_ExpectLib) || (enc->cmd == LibCmd_ExpectClass)) )
{
LibType expect;
if (enc->cmd == LibCmd_ExpectLib)
expect = LibType_Library;
else
expect = LibType_Class;
/** see if it exists */
for (; iter != end; iter++)
{
lib = (*iter);
if (lib->type != expect)
continue;
if (strcasecmp(lib->name.chars(), enc->param1) == 0)
return LibErr_None;
}
if (!LoadModule(enc->param2, PT_ANYTIME, true, true))
{
return LibErr_NoLibrary;
}
return LibErr_None;
}
return LibErr_None;
}

View File

@ -1,81 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _INCLUDE_LIBRARIES_H
#define _INCLUDE_LIBRARIES_H
#include <string.h>
#include "amxmodx.h"
enum LibSource
{
LibSource_Plugin,
LibSource_Module
};
enum LibType
{
LibType_Library,
LibType_Class
};
struct Library
{
ke::AString name;
LibSource src;
LibType type;
void *parent;
};
enum LibCmd
{
LibCmd_ReqLib,
LibCmd_ReqClass,
LibCmd_ForceLib,
LibCmd_ExpectLib,
LibCmd_ExpectClass,
LibCmd_DefaultLib,
};
enum LibError
{
LibErr_None = 0,
LibErr_NoLibrary,
LibErr_NoClass,
};
class LibDecoder
{
public:
LibDecoder() : buffer(NULL)
{
}
~LibDecoder()
{
free(buffer);
buffer = NULL;
param1 = NULL;
param2 = NULL;
}
char *buffer;
char *param1;
char *param2;
LibCmd cmd;
};
bool AddLibrary(const char *name, LibType type, LibSource src, void *parent=NULL);
bool DecodeLibCmdString(const char *str, LibDecoder *cmd);
size_t AddLibrariesFromString(const char *name, LibType type, LibSource src, void *parent=NULL);
size_t ClearLibraries(LibSource src);
LibError RunLibCommand(const LibDecoder *enc);
size_t RemoveLibraries(void *parent);
bool FindLibrary(const char *name, LibType type);
#endif //_INCLUDE_LIBRARIES_H

474
amxmodx/md5.cpp Executable file
View File

@ -0,0 +1,474 @@
// MD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
// Translation and modification (c) 1995 by Mordechai T. Abzug
// This translation/ modification is provided "as is," without express or
// implied warranty of any kind.
// The translator/ modifier does not claim (1) that MD5 will do what you think
// it does; (2) that this translation/ modification is accurate; or (3) that
// this software is "merchantible." (Language for this disclaimer partially
// copied from the disclaimer below).
/* based on:
MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
MDDRIVER.C - test driver for MD2, MD4 and MD5
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include "md5.h"
#include <assert.h>
#include <string.h>
// MD5 simple initialization method
MD5::MD5(){
init();
}
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block, and updating the
// context.
void MD5::update (uint1 *input, uint4 input_length) {
uint4 input_index, buffer_index;
uint4 buffer_space; // how much space is left in buffer
if (finalized){ // so we can't update!
/*cerr << "MD5::update: Can't update a finalized digest!" << endl;*/
return;
}
// Compute number of bytes mod 64
buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
// Update number of bits
if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
count[1]++;
count[1] += ((uint4)input_length >> 29);
buffer_space = 64 - buffer_index; // how much space is left in buffer
// Transform as many times as possible.
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
// fill the rest of the buffer and transform
memcpy (buffer + buffer_index, input, buffer_space);
transform (buffer);
// now, transform each 64-byte piece of the input, bypassing the buffer
for (input_index = buffer_space; input_index + 63 < input_length;
input_index += 64)
transform (input+input_index);
buffer_index = 0; // so we can buffer remaining
}
else
input_index=0; // so we can buffer the whole input
// and here we do the buffering:
memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
}
// MD5 update for files.
// Like above, except that it works on files (and uses above as a primitive.)
void MD5::update(FILE *file){
unsigned char buffer[1024];
int len;
while (len=fread(buffer, 1, 1024, file))
update(buffer, len);
fclose (file);
}
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
void MD5::finalize (){
unsigned char bits[8];
unsigned int index, padLen;
static uint1 PADDING[64]={
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (finalized){
/* cerr << "MD5::finalize: Already finalized this digest!" << endl;*/
return;
}
// Save number of bits
encode (bits, count, 8);
// Pad out to 56 mod 64.
index = (uint4) ((count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
update (PADDING, padLen);
// Append length (before padding)
update (bits, 8);
// Store state in digest
encode (digest, state, 16);
// Zeroize sensitive information
memset (buffer, 0, sizeof(*buffer));
finalized=1;
}
MD5::MD5(FILE *file){
init(); // must be called be all constructors
update(file);
finalize ();
}
unsigned char *MD5::raw_digest(){
uint1 *s = new uint1[16];
if (!finalized){
/* cerr << "MD5::raw_digest: Can't get digest if you haven't "<<
"finalized the digest!" <<endl;*/
return ( (unsigned char*) "");
}
memcpy(s, digest, 16);
return s;
}
char *MD5::hex_digest(){
int i;
char *s= new char[33];
if (!finalized){
/* cerr << "MD5::hex_digest: Can't get digest if you haven't "<<
"finalized the digest!" <<endl;*/
return "";
}
for (i=0; i<16; i++)
sprintf(s+i*2, "%02x", digest[i]);
s[32]='\0';
return s;
}
char *MD5::hex_digest(char buffer[33]){
int i;
if (!finalized)
{
/* cerr << "MD5::hex_digest: Can't get digest if you haven't "<<
"finalized the digest!" <<endl;*/
return "";
}
for (i=0; i<16; i++)
sprintf(buffer+i*2, "%02x", digest[i]);
buffer[32]='\0';
return buffer;
}
// PRIVATE METHODS:
void MD5::init(){
finalized=0; // we just started!
// Nothing counted, so count=0
count[0] = 0;
count[1] = 0;
// Load magic initialization constants.
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
// Constants for MD5Transform routine.
// Although we could use C++ style constants, defines are actually better,
// since they let us easily evade scope clashes.
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
// MD5 basic transformation. Transforms state based on block.
void MD5::transform (uint1 block[64]){
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode (x, block, 64);
assert(!finalized); // not just a user error, since the method is private
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset ( (uint1 *) x, 0, sizeof(x));
}
// Encodes input (UINT4) into output (unsigned char). Assumes len is
// a multiple of 4.
void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (uint1) (input[i] & 0xff);
output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
}
}
// Decodes input (unsigned char) into output (UINT4). Assumes len is
// a multiple of 4.
void MD5::decode (uint4 *output, uint1 *input, uint4 len){
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
(((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
}
// Note: Replace "for loop" with standard memcpy if possible.
void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
// Note: Replace "for loop" with standard memset if possible.
void MD5::memset (uint1 *output, uint1 value, uint4 len){
unsigned int i;
for (i = 0; i < len; i++)
output[i] = value;
}
// ROTATE_LEFT rotates x left n bits.
inline unsigned int MD5::rotate_left (uint4 x, uint4 n){
return (x << n) | (x >> (32-n)) ;
}
// F, G, H and I are basic MD5 functions.
inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){
return (x & y) | (~x & z);
}
inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){
return (x & z) | (y & ~z);
}
inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){
return x ^ y ^ z;
}
inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){
return y ^ (x | ~z);
}
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += F(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += G(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += H(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += I(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}

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