Compare commits

...

28 Commits

Author SHA1 Message Date
stickz
0b9de10651
Merge f6b8278fd8 into 1819f491b5 2025-11-28 05:58:01 +02:00
dependabot[bot]
1819f491b5
Bump actions/checkout from 5 to 6 (#2378)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 15:55:07 +00:00
caxanga334
c4d5235217
Update DoD:S Gamedata (#2377)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
Adds missing GetAttachment vtable offset.
2025-11-20 23:43:49 +00:00
Benoist
6439769d50
Introduce Virtual Address (#2226)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
SourcePawn scripting / build (ubuntu-latest, linux) (push) Has been cancelled
SourcePawn scripting / build (windows-latest, win) (push) Has been cancelled
In the current ongoing effort for sourcemod to fully support 64 bits, we are introducing "virtual address".

# Explanation

Because SourcePawn does not yet support a 64 bits-wide type it's been impossible for any plugins to hold addresses in regular 32-bits wide variable.

A first attempt at solving this issue was made in commit ce1a4dcac0 therein dubbed "PseudoAddress", however this turned out to be an unsatisfactory solution, as any 'high' address if offsetted could turn invalid (or outright be impossible to map).

This leaves us with three alternatives :
- New type
- Convert Address into a handle
- Virtual Address

A new type is the most destructive solution, as it entails breaking every single Address related method. While that solution is still not off the table, we're reserving it as the last attempt should this commit fail.

Converting into a handle type is a good compromise between a brand new type whilst also preserving the Address methods. However, this comes with two issues: the first being that you can no longer offset Address, the second is that we would require authors to free the handle type which will be very confusing. This will likely not be implemented.

# Virtual address

Under a reasonable assumption, we've noted that the average plugin is unlikely to play with more than 4 GB of memory; this shouldn't be too surprising as all valve games were once 32bits and therefore limited to 4GB. Assuming this stays mostly true and a plugin isn't interested with the mapped memory of lesser known modules (like soundlib or matlib), it is fair to assume plugins are unlikely to access more than 4GB of mapped memory. Working with this in mind, we map the memory the plugins are likely to access to our custom virtual address ranges (from 0 to 4Gb, the values of which can fit on 32bits variable). If any memory was missed and plugins were to try an access it later those ranges will be late-mapped to our virtual address ranges until we run out of them.

In order to use virtual addressing, whether on 32 bits or 64 bits. Plugins must now "#include <virtual_address>", as well as use the new SDKCall_VirtualAddress, SDKType_VirtualAddress, LoadAddressFromAddress & StoreAddressToAddress where it's appropriate to.
2025-11-13 13:23:13 +01:00
solidDoWant
0c900be7fc
Make PostgreSQL setup scripts idempotent (#2376)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
Signed-off-by: solidDoWant <fred.heinecke@yahoo.com>
2025-11-10 15:39:08 +00:00
F1F88
bc8d02c998
Add format specifier "%E" (#2099) (#2330)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
SourcePawn scripting / build (ubuntu-latest, linux) (push) Has been cancelled
SourcePawn scripting / build (windows-latest, win) (push) Has been cancelled
* Add format specifier "%E" (#2099)

* style: Remove extra blank lines
2025-11-08 17:09:57 +00:00
caxanga334
1fc841713e
Allow the time format used by SM log files to be configured by server ops. (#2372)
* Log Time Format Config

* Remove extra space

* Fix formatting inconsistency

---------

Co-authored-by: Nicholas Hastings <nshastings@gmail.com>
2025-11-08 17:08:32 +00:00
Alienmario
84f67fcd2d
Add new options to ArrayList FindString, FindValue (#2216) 2025-11-08 17:03:42 +00:00
Benoist
eb3b4d9822
Build tier1 & mathlib (#2368)
* Build tier1 & mathlib instead of statically linking

* update hl2sdk-manifests

* update hl2sdk-manifests

* update hl2sdk-manifests

* update hl2sdk-manifests

* Update hl2sdk-manifests

* Fix sdkhooks compilation

---------

Co-authored-by: Nicholas Hastings <nshastings@gmail.com>
2025-11-08 16:47:35 +00:00
Nicholas Hastings
a401d97b09 Update hl2sdk-manifests 2025-11-08 11:42:34 -05:00
F1F88
74e9cdd709
Fixed "%s" always being left justify (#2331) (#2332) 2025-11-08 16:36:01 +00:00
F1F88
2ae0d05a23
Fixed when the int value of "%0[width]d" is negative, the minus sign should be formatted before the padding '0' (#2329) 2025-11-08 16:33:30 +00:00
F1F88
22cc68808c
Supports "%f" formatting value as inf float (#2324)
* Fixed when the float value of "%f" is inf, it should be formatted as "Inf" instead of "0.0"

* Replace std::isinf with ke::IsInfinite
2025-11-08 16:32:09 +00:00
Nicholas Hastings
9952f62a33 Fix up GetGameBinArchSubdirectory 2025-11-08 11:26:03 -05:00
Nicholas Hastings
f382c3fb5b
Fix gamedata gamebin paths for x64, CS:GO-based games (#2370) (#2374)
Some checks are pending
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Waiting to run
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Waiting to run
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Waiting to run
hl2sdk-mock tests / mock (push) Waiting to run
2025-11-07 15:30:46 +00:00
Benoist
4374cb2168
Update Python version from 3.8 to 3.12 (#2375) 2025-11-07 15:30:17 +00:00
A1m`
98831a8667
Add the ability to work with the |this| parameter under dhooks callback (#2219)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Waiting to run
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Waiting to run
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Waiting to run
hl2sdk-mock tests / mock (push) Waiting to run
SourcePawn scripting / build (ubuntu-latest, linux) (push) Has been cancelled
SourcePawn scripting / build (windows-latest, win) (push) Has been cancelled
2025-11-06 16:33:41 +01:00
dependabot[bot]
66d3f5e60e
Bump actions/upload-artifact from 4 to 5 (#2369)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-01 16:32:21 +00:00
caxanga334
0ccf21ecb6
Update ZPS Gamedata (#2371)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
Updates virtual offsets of SDKHooks and SDKTools for ZPS version 3.3
2025-10-30 23:23:46 +01:00
Benoist
c9ee066a1d
Update python version for gh ci (#2367)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
2025-10-27 17:10:04 +00:00
Benoist
42c5444a10
Fix issues with -fPIC thunks (#2366)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
2025-10-26 17:33:38 +01:00
caxanga334
e4fda1bd78
Fix HL1MP Gamedata (#2364)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
2025-10-15 11:11:52 -07:00
caxanga334
e55747a9e4
Update Synergy Gamedata (#2361)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
Adds some missing virtual offsets for SDKHooks and SDKTools.
Updates some Windows signatures.
2025-10-03 19:58:28 +00:00
Mikusch
351917be35
Add new TF_CUSTOM_* values (#2360)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
SourcePawn scripting / build (ubuntu-latest, linux) (push) Has been cancelled
SourcePawn scripting / build (windows-latest, win) (push) Has been cancelled
2025-10-02 10:43:37 +02:00
Monster
063734607f
Incrase SetVariantString string limit (#2359)
Some checks are pending
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Waiting to run
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Waiting to run
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Waiting to run
hl2sdk-mock tests / mock (push) Waiting to run
2025-10-01 08:36:33 -04:00
Bakugo
19dce02a9c
Fix incorrect handling of _condition_bits in TF2 extension (#2357)
Some checks failed
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang, clang++, ubuntu-latest, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (clang-14, clang++-14, ubuntu-22.04, linux) (push) Has been cancelled
Continuous Integration / ${{ matrix.os_short }}-${{ matrix.compiler_cc }} (msvc, windows-latest, win) (push) Has been cancelled
hl2sdk-mock tests / mock (push) Has been cancelled
SourcePawn scripting / build (ubuntu-latest, linux) (push) Has been cancelled
SourcePawn scripting / build (windows-latest, win) (push) Has been cancelled
2025-09-26 15:06:59 +02:00
stickz
f6b8278fd8
Remove whitespace 2020-08-09 15:18:39 -04:00
stickz
d44669ef34
mapchooser: Set minimum number maps to include in vote
This commit allows the user to have a consistent minimum number of maps in the vote, regardless how many previous maps are excluded. It also improves the handling of the situation, when the number of previous maps to exclude is set higher than the number of available maps. Instead of excluding no previous maps, it will exclude until the minimum include count is reached.
2020-08-09 15:16:15 -04:00
52 changed files with 1023 additions and 527 deletions

View File

@ -36,7 +36,7 @@ jobs:
MYSQL_VERSION: '5.7'
MMSOURCE_VERSION: '1.12'
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
submodules: recursive
path: sourcemod
@ -54,9 +54,9 @@ jobs:
# Setup Python for AMBuild
- uses: actions/setup-python@v6
name: Setup Python 3.8
name: Setup Python 3.12
with:
python-version: 3.8
python-version: 3.12
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel

View File

@ -12,20 +12,20 @@ jobs:
mock:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
name: Clone sourcemod
with:
submodules: recursive
path: sourcemod
- uses: actions/checkout@v5
- uses: actions/checkout@v6
name: Clone metamod-source
with:
repository: alliedmodders/metamod-source
submodules: recursive
path: metamod-source
- uses: actions/checkout@v5
- uses: actions/checkout@v6
name: Clone hl2sdk-mock
with:
repository: alliedmodders/hl2sdk-mock

View File

@ -25,15 +25,15 @@ jobs:
env:
ARCH: x86,x86_64
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
submodules: recursive
# Setup Python for AMBuild
- uses: actions/setup-python@v6
name: Setup Python 3.8
name: Setup Python 3.12
with:
python-version: 3.8
python-version: 3.12
- name: Install AMBuild
run: |
python -m pip install --upgrade pip setuptools wheel
@ -67,7 +67,7 @@ jobs:
echo "SM_VERSION=$(cat ../product.version)" >> $GITHUB_ENV
- name: Archive tooling
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: sourcemod-tooling-${{ env.SM_VERSION }}-${{ matrix.os_short }}
path: build/package

View File

@ -10,7 +10,7 @@ jobs:
update_translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
submodules: recursive

View File

@ -15,7 +15,7 @@ jobs:
check_translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
name: Setup Python 3.10

3
.gitmodules vendored
View File

@ -12,3 +12,6 @@
[submodule "public/safetyhook"]
path = public/safetyhook
url = https://github.com/alliedmodders/safetyhook
[submodule "core/logic/libaddrz"]
path = core/logic/libaddrz
url = https://github.com/dvander/libaddrz.git

View File

@ -58,6 +58,7 @@ public:
virtual bool IsDirectory(const char *pFileName, const char *pathID = 0) = 0;
virtual void CreateDirHierarchy(const char *path, const char *pathID = 0) = 0;
virtual int GetSearchPath(const char* pathID, bool bGetPackFiles, char* pPath, int nMaxLen) = 0;
virtual const char * GetGameBinArchSubdirectory() = 0;
};
} // namespace SourceMod

View File

@ -21,6 +21,15 @@
*/
"LogMode" "daily"
/**
* This option determines the time format SourceMod logging should use.
*
* "default" - Uses SourceMod's default time format. (%m/%d/%Y - %H:%M:%S)
* You can specify any time format you want. See https://cplusplus.com/reference/ctime/strftime/ for a list of format parameters.
* Example: "%d/%m/%Y - %H:%M:%S"
*/
"LogTimeFormat" "default"
/**
* Language that multilingual enabled plugins and extensions will use to print messages.
* Only languages listed in languages.cfg are valid.

View File

@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS sm_cookie_cache
PRIMARY KEY (player, cookie_id)
);
CREATE LANGUAGE plpgsql;
CREATE OR REPLACE LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION add_or_update_cookie(in_player VARCHAR(65), in_cookie INT, in_value VARCHAR(100), in_time INT) RETURNS VOID AS
$$

View File

@ -1,4 +1,4 @@
CREATE TABLE sm_admins (
CREATE TABLE IF NOT EXISTS sm_admins (
id serial,
authtype varchar(6) NOT NULL,
CHECK (authtype in ('steam', 'name', 'ip')),
@ -10,7 +10,7 @@ CREATE TABLE sm_admins (
PRIMARY KEY (id)
);
CREATE TABLE sm_groups (
CREATE TABLE IF NOT EXISTS sm_groups (
id serial,
flags varchar(30) NOT NULL,
name varchar(120) NOT NULL,
@ -18,7 +18,7 @@ CREATE TABLE sm_groups (
PRIMARY KEY (id)
);
CREATE TABLE sm_group_immunity (
CREATE TABLE IF NOT EXISTS sm_group_immunity (
group_id int NOT NULL,
other_id int NOT NULL,
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
@ -26,7 +26,7 @@ CREATE TABLE sm_group_immunity (
PRIMARY KEY (group_id, other_id)
);
CREATE TABLE sm_group_overrides (
CREATE TABLE IF NOT EXISTS sm_group_overrides (
group_id int NOT NULL,
FOREIGN KEY (group_id) REFERENCES sm_groups(id) ON DELETE CASCADE,
type varchar(10) NOT NULL,
@ -37,7 +37,7 @@ CREATE TABLE sm_group_overrides (
PRIMARY KEY (group_id, type, name)
);
CREATE TABLE sm_overrides (
CREATE TABLE IF NOT EXISTS sm_overrides (
type varchar(10) NOT NULL,
CHECK (type in ('command', 'group')),
name varchar(32) NOT NULL,
@ -45,7 +45,7 @@ CREATE TABLE sm_overrides (
PRIMARY KEY (type,name)
);
CREATE TABLE sm_admins_groups (
CREATE TABLE IF NOT EXISTS sm_admins_groups (
admin_id int NOT NULL,
group_id int NOT NULL,
FOREIGN KEY (admin_id) REFERENCES sm_admins(id) ON DELETE CASCADE,
@ -56,10 +56,10 @@ CREATE TABLE sm_admins_groups (
-- side note, this is pgsql module, sm_config will not exist if the above stuff exists... and it's being left to the admin
-- to figure out if it exists.
CREATE TABLE sm_config (
CREATE TABLE IF NOT EXISTS sm_config (
cfg_key varchar(32) NOT NULL,
cfg_value varchar(255) NOT NULL,
PRIMARY KEY (cfg_key)
);
INSERT INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409');
INSERT INTO sm_config (cfg_key, cfg_value) VALUES ('admin_version', '1.0.0.1409') ON CONFLICT (cfg_key) DO UPDATE SET cfg_value = EXCLUDED.cfg_value;

View File

@ -86,9 +86,15 @@ for cxx in builder.targets:
'DatabaseConfBuilder.cpp',
'LumpManager.cpp',
'smn_entitylump.cpp',
'libaddrz/addrz.cpp',
'libaddrz/mapping.cpp',
'libaddrz/platform.cpp',
'libaddrz/proc_maps.cpp',
'PseudoAddrManager.cpp',
]
if binary.compiler.target.arch == 'x86_64':
binary.sources += ['PseudoAddrManager.cpp']
if binary.compiler.target.platform == 'linux':
binary.sources += ['libaddrz/platform_linux.cpp']
elif binary.compiler.target.platform == 'windows':
binary.sources += ['libaddrz/platform_windows.cpp']
SM.binaries += [builder.Add(binary)]

View File

@ -1094,13 +1094,18 @@ void GameBinPathManager::Init()
std::istringstream iss(search_path);
for (std::string path; std::getline(iss, path, ';');)
{
if (path.length() > 0
&& path.find(addons_folder) == std::string::npos
&& m_lookup.find(path) == m_lookup.cend()
)
if (path.length() > 0)
{
m_lookup.insert(path);
m_ordered.push_back(path);
const char* arch_subdir = bridge->filesystem->GetGameBinArchSubdirectory();
std::string full_path = path + arch_subdir;
if (full_path.find(addons_folder) == std::string::npos
&& m_lookup.find(full_path) == m_lookup.cend()
)
{
m_lookup.insert(full_path);
m_ordered.push_back(full_path);
}
}
}

View File

@ -29,6 +29,7 @@
* Version: $Id$
*/
#include <string_view>
#include <time.h>
#include <cstdarg>
#include "Logger.h"
@ -81,6 +82,19 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
return ConfigResult_Reject;
}
return ConfigResult_Accept;
} else if (strcasecmp(key, "LogTimeFormat") == 0) {
if (strcasecmp(value, "default") == 0)
{
m_isUsingDefaultTimeFormat = true;
m_UserTimeFormat.clear();
}
else {
// value is the time format string
m_isUsingDefaultTimeFormat = false;
m_UserTimeFormat.assign(value);
}
return ConfigResult_Accept;
}
@ -152,11 +166,7 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
char buffer[3072];
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
const char* date = GetFormattedDate();
fprintf(fp, "L %s: %s\n", date, buffer);
if (!sv_logecho || bridge->GetCvarBool(sv_logecho))
@ -174,10 +184,7 @@ void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
char buffer[3072];
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
const char* date = GetFormattedDate();
fprintf(fp, "L %s: %s\n", date, buffer);
fflush(fp);
@ -378,11 +385,7 @@ FILE *Logger::_OpenNormal()
if (!m_DamagedNormalFile)
{
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
const char* date = GetFormattedDate();
fprintf(pFile, "L %s: SourceMod log file session started (file \"%s\") (Version \"%s\")\n", date, m_NormalFileName.c_str(), SOURCEMOD_VERSION);
m_DamagedNormalFile = true;
}
@ -403,11 +406,7 @@ FILE *Logger::_OpenError()
if (!m_DamagedErrorFile)
{
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
const char* date = GetFormattedDate();
fprintf(pFile, "L %s: SourceMod error session started\n", date);
fprintf(pFile, "L %s: Info (map \"%s\") (file \"%s\")\n", date, m_CurrentMapName.c_str(), m_ErrorFileName.c_str());
m_DamagedErrorFile = true;
@ -452,3 +451,25 @@ void Logger::_CloseError()
void Logger::_CloseFatal()
{
}
const char* Logger::GetFormattedDate() const
{
static char date[256];
constexpr std::string_view DEFAULT_TIME_FORMAT{ "%m/%d/%Y - %H:%M:%S" };
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
if (m_isUsingDefaultTimeFormat)
{
strftime(date, sizeof(date), DEFAULT_TIME_FORMAT.data(), curtime);
}
else
{
strftime(date, sizeof(date), m_UserTimeFormat.c_str(), curtime);
}
return date;
}

View File

@ -53,7 +53,7 @@ enum LoggingMode
class Logger : public SMGlobalClass, public ILogger
{
public:
Logger() : m_Day(-1), m_Mode(LoggingMode_Daily), m_Active(true), m_DamagedNormalFile(false), m_DamagedErrorFile(false)
Logger() : m_Day(-1), m_Mode(LoggingMode_Daily), m_Active(true), m_DamagedNormalFile(false), m_DamagedErrorFile(false), m_isUsingDefaultTimeFormat(true)
{
}
public: //SMGlobalClass
@ -95,10 +95,12 @@ private:
void _LogFatalOpen(std::string &str);
void _PrintToGameLog(const char *fmt, va_list ap);
void _UpdateFiles(bool bLevelChange = false);
const char* GetFormattedDate() const;
private:
std::string m_NormalFileName;
std::string m_ErrorFileName;
std::string m_CurrentMapName;
std::string m_UserTimeFormat;
int m_Day;
@ -106,6 +108,7 @@ private:
bool m_Active;
bool m_DamagedNormalFile;
bool m_DamagedErrorFile;
bool m_isUsingDefaultTimeFormat;
};
extern Logger g_Logger;

View File

@ -330,6 +330,13 @@ bool CPlugin::ReadInfo()
else
m_MaxClientsVar = nullptr;
if (base->FindPubvarByName("PointerSize", &idx) == SP_ERROR_NONE) {
sp_pubvar_t* var = nullptr;
if (base->GetPubvarByIndex(idx, &var) == SP_ERROR_NONE && var) {
*var->offs = sizeof(void*);
}
}
return true;
}

View File

@ -28,6 +28,7 @@
*/
#include "PseudoAddrManager.h"
#include <bridge/include/CoreProvider.h>
#ifdef PLATFORM_APPLE
#include <mach/mach.h>
#include <mach/vm_region.h>
@ -35,135 +36,88 @@
#ifdef PLATFORM_LINUX
#include <inttypes.h>
#endif
#ifdef PLATFORM_WINDOWS
#include <Psapi.h>
#endif
PseudoAddressManager::PseudoAddressManager() : m_NumEntries(0)
PseudoAddressManager::PseudoAddressManager() : m_dictionary(am::IPlatform::GetDefault())
{
}
// A pseudo address consists of a table index in the upper 6 bits and an offset in the
// lower 26 bits. The table consists of memory allocation base addresses.
void PseudoAddressManager::Initialize() {
#ifdef PLATFORM_WINDOWS
auto process = GetCurrentProcess();
auto get_module_details = [process](const char* name, void*& baseAddress, size_t& moduleSize) {
if (process == NULL) {
return false;
}
auto hndl = GetModuleHandle(name);
if (hndl == NULL) {
return false;
}
MODULEINFO info;
if (!GetModuleInformation(process, hndl, &info, sizeof(info))) {
return false;
}
moduleSize = info.SizeOfImage;
baseAddress = info.lpBaseOfDll;
return true;
};
#endif
#ifdef PLATFORM_LINUX
auto get_module_details = [](const char* name, void* baseAddress, size_t& moduleSize) {
auto hndl = dlopen(name, RTLD_NOLOAD);
if (hndl == NULL) {
return false;
}
void* addr = dlsym(hndl, "CreateInterface");
dlclose(hndl);
if (!addr) {
return false;
}
Dl_info info;
if (dladdr(addr, &info) == 0) {
return false;
}
baseAddress = info.dli_fbase;
// It doesn't matter much if we figure out the module size
// libaddrz coalesce maps on linux
moduleSize = 0;
return true;
};
#endif
// Early map commonly used modules, it's okay if not all of them are here
// Everything else will be caught by "ToPseudoAddress" but you risk running out of ranges by then
const char* libs[] = { "engine", "server", "tier0", "vstdlib" };
char formattedName[64];
for (int i = 0; i < sizeof(libs) / sizeof(const char*); i++) {
bridge->FormatSourceBinaryName(libs[i], formattedName, sizeof(formattedName));
void* base_addr = nullptr;
size_t module_size = 0;
if (get_module_details(formattedName, base_addr, module_size)) {
// Create the mapping (hopefully)
m_dictionary.Make32bitAddress(base_addr, module_size);
}
}
}
void *PseudoAddressManager::FromPseudoAddress(uint32_t paddr)
{
#ifdef KE_ARCH_X64
uint8_t index = paddr >> PSEUDO_OFFSET_BITS;
uint32_t offset = paddr & ((1 << PSEUDO_OFFSET_BITS) - 1);
if (index >= m_NumEntries)
if (paddr == 0) {
return nullptr;
return reinterpret_cast<void *>(uintptr_t(m_AllocBases[index]) + offset);
#else
return nullptr;
#endif
}
return m_dictionary.RecoverAddress(paddr).value_or(nullptr);
}
uint32_t PseudoAddressManager::ToPseudoAddress(void *addr)
{
#ifdef KE_ARCH_X64
uint8_t index = 0;
uint32_t offset = 0;
bool hasEntry = false;
void *base = GetAllocationBase(addr);
if (base) {
for (int i = 0; i < m_NumEntries; i++) {
if (m_AllocBases[i] == base) {
index = i;
hasEntry = true;
break;
}
}
} else {
if (addr == nullptr) {
return 0;
}
if (!hasEntry) {
index = m_NumEntries;
if (m_NumEntries < SM_ARRAYSIZE(m_AllocBases))
m_AllocBases[m_NumEntries++] = base;
else
return 0; // Table is full
}
ptrdiff_t diff = uintptr_t(addr) - uintptr_t(base);
// Ensure difference fits in 26 bits
if (diff > (UINT32_MAX >> PSEUDO_INDEX_BITS))
return 0;
return (index << PSEUDO_OFFSET_BITS) | diff;
#else
return 0;
#endif
}
void *PseudoAddressManager::GetAllocationBase(void *ptr)
{
#if defined PLATFORM_WINDOWS
MEMORY_BASIC_INFORMATION info;
if (!VirtualQuery(ptr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
return nullptr;
return info.AllocationBase;
#elif defined PLATFORM_APPLE
#ifdef KE_ARCH_X86
typedef vm_region_info_t mach_vm_region_info_t;
typedef vm_region_basic_info_data_t mach_vm_region_basic_info_data_t;
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO;
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT;
#define mach_vm_region vm_region
#elif defined KE_ARCH_X64
typedef vm_region_info_64_t mach_vm_region_info_t ;
typedef vm_region_basic_info_data_64_t mach_vm_region_basic_info_data_t;
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO_64;
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT_64;
#define mach_vm_region vm_region_64
#endif
vm_size_t size;
vm_address_t vmaddr = reinterpret_cast<vm_address_t>(ptr);
mach_vm_region_basic_info_data_t info;
memory_object_name_t obj;
vm_region_flavor_t flavor = MACH_VM_REGION_BASIC_INFO;
mach_msg_type_number_t count = MACH_VM_REGION_BASIC_INFO_COUNT;
kern_return_t kr = mach_vm_region(mach_task_self(), &vmaddr, &size, flavor,
reinterpret_cast<mach_vm_region_info_t>(&info),
&count, &obj);
if (kr != KERN_SUCCESS)
return nullptr;
return reinterpret_cast<void *>(vmaddr);
#elif defined PLATFORM_LINUX
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
// Format:
// lower upper prot stuff path
// 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat
FILE *fp = fopen("/proc/self/maps", "r");
if (fp) {
uintptr_t lower, upper;
while (fscanf(fp, "%" PRIxPTR "-%" PRIxPTR, &lower, &upper) != EOF) {
if (addr >= lower && addr <= upper) {
fclose(fp);
return reinterpret_cast<void *>(lower);
}
// Read to end of line
int c;
while ((c = fgetc(fp)) != '\n') {
if (c == EOF)
break;
}
if (c == EOF)
break;
}
fclose(fp);
}
return nullptr;
#endif
return m_dictionary.Make32bitAddress(addr).value_or(0);
}

View File

@ -31,6 +31,7 @@
#define _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
#include "common_logic.h"
#include "libaddrz/addrz.h"
class PseudoAddressManager
{
@ -39,13 +40,9 @@ public:
public:
void *FromPseudoAddress(uint32_t paddr);
uint32_t ToPseudoAddress(void *addr);
void Initialize();
private:
void *GetAllocationBase(void *ptr);
private:
static constexpr uint8_t PSEUDO_OFFSET_BITS = 26;
static constexpr uint8_t PSEUDO_INDEX_BITS = sizeof(uint32_t) * 8 - PSEUDO_OFFSET_BITS;
void *m_AllocBases[1 << PSEUDO_INDEX_BITS];
uint8_t m_NumEntries;
am::AddressDict m_dictionary;
};
#endif // _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_

View File

@ -57,6 +57,7 @@
#include "RootConsoleMenu.h"
#include "CellArray.h"
#include "smn_entitylump.h"
#include "PseudoAddrManager.h"
#include <bridge/include/BridgeAPI.h>
#include <bridge/include/IProviderCallbacks.h>
@ -86,9 +87,7 @@ IScriptManager *scripts = &g_PluginSys;
IExtensionSys *extsys = &g_Extensions;
ILogger *logger = &g_Logger;
CNativeOwner g_CoreNatives;
#ifdef KE_ARCH_X64
PseudoAddressManager pseudoAddr;
#endif
EntityLumpParseResult lastParseResult;
@ -122,20 +121,12 @@ static void RegisterProfiler(IProfilingTool *tool)
static void *FromPseudoAddress(uint32_t paddr)
{
#ifdef KE_ARCH_X64
return pseudoAddr.FromPseudoAddress(paddr);
#else
return nullptr;
#endif
}
static uint32_t ToPseudoAddress(void *addr)
{
#ifdef KE_ARCH_X64
return pseudoAddr.ToPseudoAddress(addr);
#else
return 0;
#endif
}
static void SetEntityLumpWritable(bool writable)
@ -236,6 +227,7 @@ static void logic_init(CoreProvider* core, sm_logic_t* _logic)
g_pSourcePawn2 = *core->spe2;
SMGlobalClass::head = core->listeners;
pseudoAddr.Initialize();
g_ShareSys.Initialize();
g_pCoreIdent = g_ShareSys.CreateCoreIdentity();

1
core/logic/libaddrz Submodule

@ -0,0 +1 @@
Subproject commit 661cd316e6ff8e8560efa20db1794f3fa479647c

View File

@ -587,27 +587,68 @@ static cell_t FindStringInArray(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
}
// the blocknumber is not guaranteed to always be passed
// The parameters above 2 are optional
size_t blocknumber = 0;
if (params[0] >= 3)
{
blocknumber = (size_t)params[3];
if (blocknumber >= array->blocksize())
{
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", blocknumber, array->blocksize());
}
}
if (blocknumber >= array->blocksize())
int startidx = -1;
if (params[0] >= 4)
{
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", blocknumber, array->blocksize());
startidx = params[4];
if (startidx > 0 && startidx > array->size())
{
return pContext->ThrowNativeError("Invalid start index %d (max: %d)", startidx, array->size());
}
}
bool reverse = false;
if (params[0] >= 5)
{
reverse = params[5];
}
typedef int (*STRCOMPARE)(const char *, const char *);
STRCOMPARE comparefn = (params[0] < 6 || params[6]) ? strcmp : strcasecmp;
char *str;
pContext->LocalToString(params[2], &str);
for (unsigned int i = 0; i < array->size(); i++)
if (reverse)
{
const char *array_str = (const char *)&array->base()[i * array->blocksize() + blocknumber];
if (strcmp(str, array_str) == 0)
if (startidx < 0)
{
return (cell_t) i;
startidx = array->size();
}
for (int i = (startidx - 1); i >= 0; i--)
{
const char *array_str = (const char *)&array->base()[i * array->blocksize() + blocknumber];
if (comparefn(str, array_str) == 0)
{
return (cell_t) i;
}
}
}
else
{
if (startidx < -1)
{
startidx = -1;
}
for (unsigned int i = (startidx + 1); i < array->size(); i++)
{
const char *array_str = (const char *)&array->base()[i * array->blocksize() + blocknumber];
if (comparefn(str, array_str) == 0)
{
return (cell_t) i;
}
}
}
@ -626,24 +667,62 @@ static cell_t FindValueInArray(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
}
// the blocknumber is not guaranteed to always be passed
// The parameters above 2 are optional
size_t blocknumber = 0;
if (params[0] >= 3)
{
blocknumber = (size_t) params[3];
}
if (blocknumber >= array->blocksize())
{
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", blocknumber, array->blocksize());
}
for (unsigned int i = 0; i < array->size(); i++)
{
cell_t *blk = array->at(i);
if (params[2] == blk[blocknumber])
blocknumber = (size_t)params[3];
if (blocknumber >= array->blocksize())
{
return (cell_t) i;
return pContext->ThrowNativeError("Invalid block %d (blocksize: %d)", blocknumber, array->blocksize());
}
}
int startidx = -1;
if (params[0] >= 4)
{
startidx = params[4];
if (startidx > 0 && startidx > array->size())
{
return pContext->ThrowNativeError("Invalid start index %d (max: %d)", startidx, array->size());
}
}
bool reverse = false;
if (params[0] >= 5)
{
reverse = params[5];
}
if (reverse)
{
if (startidx < 0)
{
startidx = array->size();
}
for (int i = (startidx - 1); i >= 0; i--)
{
cell_t *blk = array->at(i);
if (params[2] == blk[blocknumber])
{
return (cell_t) i;
}
}
}
else
{
if (startidx < -1)
{
startidx = -1;
}
for (unsigned int i = (startidx + 1); i < array->size(); i++)
{
cell_t *blk = array->at(i);
if (params[2] == blk[blocknumber])
{
return (cell_t) i;
}
}
}

View File

@ -59,6 +59,7 @@
#include <bridge/include/CoreProvider.h>
#include <bridge/include/IScriptManager.h>
#include <bridge/include/IExtensionBridge.h>
#include "PseudoAddrManager.h"
#include <sh_vector.h>
using namespace SourceMod;
@ -863,11 +864,10 @@ enum NumberType
static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
{
#ifdef KE_ARCH_X86
void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
#endif
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
addr = pseudoAddr.FromPseudoAddress(params[1]);
}
if (addr == NULL)
{
@ -892,14 +892,12 @@ static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
}
}
static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
{
#ifdef KE_ARCH_X86
void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
#endif
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
addr = pseudoAddr.FromPseudoAddress(params[1]);
}
if (addr == NULL)
{
@ -950,6 +948,60 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
return 0;
}
static cell_t LoadAddressFromAddress(IPluginContext *pContext, const cell_t *params)
{
void *addr = reinterpret_cast<void*>(params[1]);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
addr = pseudoAddr.FromPseudoAddress(params[1]);
}
if (addr == NULL)
{
return pContext->ThrowNativeError("Address cannot be null");
}
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
}
void* data = *reinterpret_cast<void**>(addr);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
return pseudoAddr.ToPseudoAddress(data);
}
return reinterpret_cast<uintptr_t>(data);
}
static cell_t StoreAddressToAddress(IPluginContext *pContext, const cell_t *params)
{
void *addr = reinterpret_cast<void*>(params[1]);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
addr = pseudoAddr.FromPseudoAddress(params[1]);
}
if (addr == NULL)
{
return pContext->ThrowNativeError("Address cannot be null");
}
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
}
void *data = reinterpret_cast<void*>(params[2]);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
data = pseudoAddr.FromPseudoAddress(params[2]);
}
bool updateMemAccess = params[3];
if (updateMemAccess) {
SourceHook::SetMemAccess(addr, sizeof(void*), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC);
}
*reinterpret_cast<void**>(addr) = data;
return 0;
}
static cell_t IsNullVector(IPluginContext *pContext, const cell_t *params)
{
cell_t *pNullVec = pContext->GetNullRef(SP_NULL_VECTOR);
@ -1157,6 +1209,8 @@ REGISTER_NATIVES(coreNatives)
{"RequireFeature", RequireFeature},
{"LoadFromAddress", LoadFromAddress},
{"StoreToAddress", StoreToAddress},
{"LoadAddressFromAddress", LoadAddressFromAddress},
{"StoreAddressToAddress", StoreAddressToAddress},
{"IsNullVector", IsNullVector},
{"IsNullString", IsNullString},
{"LogStackTrace", LogStackTrace},

View File

@ -32,6 +32,7 @@
#include "common_logic.h"
#include <IHandleSys.h>
#include "GameConfigs.h"
#include "PseudoAddrManager.h"
HandleType_t g_GameConfigsType;
@ -155,11 +156,10 @@ static cell_t smn_GameConfGetAddress(IPluginContext *pCtx, const cell_t *params)
if (!gc->GetAddress(key, &val))
return 0;
#ifdef KE_ARCH_X86
return (cell_t)val;
#else
return pseudoAddr.ToPseudoAddress(val);
#endif
if (pCtx->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
return pseudoAddr.ToPseudoAddress(val);
}
return reinterpret_cast<uintptr_t>(val);
}
static cell_t smn_GameConfGetMemSig(IPluginContext *pCtx, const cell_t *params)
@ -187,11 +187,10 @@ static cell_t smn_GameConfGetMemSig(IPluginContext *pCtx, const cell_t *params)
return 0;
}
#ifdef KE_ARCH_X86
return (cell_t)val;
#else
return pseudoAddr.ToPseudoAddress(val);
#endif
if (pCtx->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
return pseudoAddr.ToPseudoAddress(val);
}
return reinterpret_cast<uintptr_t>(val);
}
static GameConfigsNatives s_GameConfigsNatives;

View File

@ -31,6 +31,7 @@
#include <am-float.h>
#include <am-string.h>
#include <IDBDriver.h>
#include <IGameHelpers.h>
#include <ITranslator.h>
#include <bridge/include/IScriptManager.h>
#include <bridge/include/CoreProvider.h>
@ -188,6 +189,15 @@ bool AddString(char **buf_p, size_t &maxlen, const char *string, int width, int
width -= size;
if (!(flags & LADJUST))
{
while ((width-- > 0) && maxlen)
{
*buf++ = ' ';
maxlen--;
}
}
if (g_FormatEscapeDatabase && (flags & NOESCAPE) == 0)
{
char *tempBuffer = NULL;
@ -226,10 +236,13 @@ bool AddString(char **buf_p, size_t &maxlen, const char *string, int width, int
}
}
while ((width-- > 0) && maxlen)
if (flags & LADJUST)
{
*buf++ = ' ';
maxlen--;
while ((width-- > 0) && maxlen)
{
*buf++ = ' ';
maxlen--;
}
}
*buf_p = buf;
@ -254,6 +267,12 @@ void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec, in
return;
}
if (ke::IsInfinite(static_cast<float>(fval)))
{
AddString(buf_p, maxlen, "Inf", width, prec, flags | NOESCAPE);
return;
}
// default precision
if (prec < 0)
{
@ -485,13 +504,15 @@ void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags)
unsignedVal /= 10;
} while (unsignedVal);
if (signedVal < 0)
{
text[digits++] = '-';
}
buf = *buf_p;
// minus sign BEFORE left padding if padding with zeros
if (signedVal < 0 && maxlen && (flags & ZEROPAD))
{
*buf++ = '-';
maxlen--;
}
if (!(flags & LADJUST))
{
while ((digits < width) && maxlen)
@ -502,6 +523,13 @@ void AddInt(char **buf_p, size_t &maxlen, int val, int width, int flags)
}
}
// minus sign AFTER left padding if padding with spaces
if (signedVal < 0 && maxlen && !(flags & ZEROPAD))
{
*buf++ = '-';
maxlen--;
}
while (digits-- && maxlen)
{
*buf++ = text[digits];
@ -1199,6 +1227,22 @@ reswitch:
arg++;
break;
}
case 'E':
{
CHECK_ARGS(0);
cell_t *value;
pCtx->LocalToPhysAddr(params[arg], &value);
CBaseEntity *entity = gamehelpers->ReferenceToEntity(*value);
if (!entity)
return pCtx->ThrowNativeError("Entity index %d is invalid (arg %d)", *value, arg);
const char *classname = gamehelpers->GetEntityClassname(entity);
if (!AddString(&buf_p, llen, classname, width, prec, flags))
return pCtx->ThrowNativeError("Escaped string would be truncated (arg %d)", arg);
arg++;
break;
}
case 's':
{
CHECK_ARGS(0);

View File

@ -194,6 +194,25 @@ public:
{
return filesystem->GetSearchPath(pathID, bGetPackFiles, pPath, nMaxLen);
}
const char* GetGameBinArchSubdirectory() override
{
#if defined( KE_ARCH_X64 ) && SOURCE_ENGINE >= SE_BLADE
#if defined( PLATFORM_WINDOWS )
#if SOURCE_ENGINE == SE_MCV
return "win64" PLATFORM_SEP;
#else
return "x64" PLATFORM_SEP;
#endif // SOURCE_ENGINE == SE_MCV
#elif defined( PLATFORM_LINUX )
return "linux64" PLATFORM_SEP;
#else
#error "Unsupported platform"
#endif // PLATFORM
#else
// Already included in the GameBin path(s), if required
return "";
#endif // defined( KE_ARCH_X64 ) && SOURCE_ENGINE >= SE_BLADE
}
} fs_wrapper;
class VPlayerInfo_Logic : public IPlayerInfoBridge

View File

@ -724,11 +724,10 @@ static cell_t GetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
static cell_t LoadEntityFromHandleAddress(IPluginContext *pContext, const cell_t *params)
{
#ifdef KE_ARCH_X86
void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = g_SourceMod.FromPseudoAddress(params[1]);
#endif
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
addr = g_SourceMod.FromPseudoAddress(params[1]);
}
if (addr == NULL)
{
@ -835,11 +834,10 @@ static cell_t SetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
static cell_t StoreEntityToHandleAddress(IPluginContext *pContext, const cell_t *params)
{
#ifdef KE_ARCH_X86
void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = g_SourceMod.FromPseudoAddress(params[1]);
#endif
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
addr = g_SourceMod.FromPseudoAddress(params[1]);
}
if (addr == NULL)
{
@ -2772,11 +2770,10 @@ static cell_t GetEntityAddress(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
}
#ifdef KE_ARCH_X86
return reinterpret_cast<cell_t>(pEntity);
#else
return g_SourceMod.ToPseudoAddress(pEntity);
#endif
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
return g_SourceMod.ToPseudoAddress(pEntity);
}
return reinterpret_cast<uintptr_t>(pEntity);
}
REGISTER_NATIVES(entityNatives)

View File

@ -30,8 +30,12 @@
#include "sourcemod.h"
#include "sourcemm_api.h"
#ifndef VPROF_ENABLED
#define VPROF_ENABLED
#endif
#ifndef RAD_TELEMETRY_DISABLED
#define RAD_TELEMETRY_DISABLED
#endif
#include <tier0/vprof.h>
VProfTool sVProfTool;

View File

@ -376,7 +376,7 @@ ReturnAction_t HandleDetour(HookType_t hookType, CHook* pDetour)
{
// The this pointer is implicitly always the first argument.
void *thisPtr = pDetour->GetArgument<void *>(0);
cell_t thisAddr = GetThisPtr(thisPtr, pWrapper->thisType);
cell_t thisAddr = GetThisPtr(pCallback->GetParentContext(), thisPtr, pWrapper->thisType);
pCallback->PushCell(thisAddr);
}
@ -532,6 +532,7 @@ CDynamicHooksSourcePawn::CDynamicHooksSourcePawn(HookSetup *setup, CHook *pDetou
this->hookType = setup->hookType;
this->m_pDetour = pDetour;
this->callConv = setup->callConv;
this->thisFuncCallConv = setup->callConv;
}
HookReturnStruct *CDynamicHooksSourcePawn::GetReturnStruct()

View File

@ -42,6 +42,8 @@ enum SDKFuncConfSource
SDKConf_Address
};
using ParamVector = SourceHook::CVector<ParamInfo>;
bool GetHandleIfValidOrError(HandleType_t type, void **object, IPluginContext *pContext, cell_t param)
{
if(param == BAD_HANDLE)
@ -81,6 +83,56 @@ bool GetCallbackArgHandleIfValidOrError(HandleType_t type, HandleType_t otherTyp
return true;
}
bool GetObjectAddrOrThis(IPluginContext *pContext, const cell_t *params, void *&retAddr)
{
HookParamsStruct *paramStruct = NULL;
retAddr = NULL;
if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)&paramStruct, pContext, params[1]))
{
return false;
}
if(params[2] != 0)
{
const ParamVector &paramsVec = paramStruct->dg->params;
if(params[2] < 0 || params[2] > static_cast<int>(paramsVec.size()))
{
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramsVec.size());
}
int index = params[2] - 1;
const ParamInfo &param = paramsVec.at(index);
if(param.type != HookParamType_ObjectPtr && param.type != HookParamType_Object)
{
return pContext->ThrowNativeError("Invalid object value type %i", param.type);
}
size_t offset = GetParamOffset(paramStruct, index);
retAddr = GetObjectAddr(param.type, param.flags, paramStruct->orgParams, offset);
return true;
}
const DHooksInfo* dgInfo = paramStruct->dg;
if(dgInfo->thisFuncCallConv != CallConv_THISCALL)
{
return pContext->ThrowNativeError("Parameter 'this' is only available in member functions");
}
if(dgInfo->thisType != ThisPointer_Address
&& dgInfo->thisType != ThisPointer_CBaseEntity
&& dgInfo->hookType != HookType_GameRules)
{
return pContext->ThrowNativeError("Parameter 'this' is not specified as an address, it is not available");
}
retAddr = g_SHPtr->GetIfacePtr();
return true;
}
IPluginFunction *GetCallback(IPluginContext *pContext, HookSetup * setup, const cell_t *params, cell_t callback_index)
{
IPluginFunction *ret = NULL;
@ -122,7 +174,12 @@ cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params)
//native Handle:DHookCreateDetour(Address:funcaddr, CallingConvention:callConv, ReturnType:returntype, ThisPointerType:thistype);
cell_t Native_CreateDetour(IPluginContext *pContext, const cell_t *params)
{
HookSetup *setup = new HookSetup((ReturnType)params[3], PASSFLAG_BYVAL, (CallingConvention)params[2], (ThisPointerType)params[4], (void *)params[1]);
void* addr = reinterpret_cast<void*>(params[1]);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
addr = g_pSM->FromPseudoAddress(params[1]);
}
HookSetup *setup = new HookSetup((ReturnType)params[3], PASSFLAG_BYVAL, (CallingConvention)params[2], (ThisPointerType)params[4], addr);
Handle_t hndl = handlesys->CreateHandle(g_HookSetupHandle, setup, pContext->GetIdentity(), myself->GetIdentity(), NULL);
@ -589,7 +646,10 @@ cell_t HookRawImpl(IPluginContext *pContext, const cell_t *params, int callbackI
if (removalcbIndex > 0)
removalcb = pContext->GetFunctionById(params[removalcbIndex]);
void *iface = (void *)(params[3]);
void* iface = reinterpret_cast<void*>(params[3]);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
iface = g_pSM->FromPseudoAddress(params[3]);
}
for(int i = g_pHooks.size() -1; i >= 0; i--)
{
@ -1089,28 +1149,12 @@ cell_t Native_RemoveEntityListener(IPluginContext *pContext, const cell_t *param
//native any:DHookGetParamObjectPtrVar(Handle:hParams, num, offset, ObjectValueType:type);
cell_t Native_GetParamObjectPtrVar(IPluginContext *pContext, const cell_t *params)
{
HookParamsStruct *paramStruct;
if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)&paramStruct, pContext, params[1]))
void *addr = NULL;
if(!GetObjectAddrOrThis(pContext, params, addr))
{
return 0;
}
if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size())
{
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size());
}
int index = params[2] - 1;
if(paramStruct->dg->params.at(index).type != HookParamType_ObjectPtr && paramStruct->dg->params.at(index).type != HookParamType_Object)
{
return pContext->ThrowNativeError("Invalid object value type %i", paramStruct->dg->params.at(index).type);
}
size_t offset = GetParamOffset(paramStruct, index);
void *addr = GetObjectAddr(paramStruct->dg->params.at(index).type, paramStruct->dg->params.at(index).flags, paramStruct->orgParams, offset);
switch((ObjectValueType)params[4])
{
case ObjectValueType_Int:
@ -1160,28 +1204,12 @@ cell_t Native_GetParamObjectPtrVar(IPluginContext *pContext, const cell_t *param
//native DHookSetParamObjectPtrVar(Handle:hParams, num, offset, ObjectValueType:type, value)
cell_t Native_SetParamObjectPtrVar(IPluginContext *pContext, const cell_t *params)
{
HookParamsStruct *paramStruct;
if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)&paramStruct, pContext, params[1]))
void *addr = NULL;
if(!GetObjectAddrOrThis(pContext, params, addr))
{
return 0;
}
if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size())
{
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size());
}
int index = params[2] - 1;
if(paramStruct->dg->params.at(index).type != HookParamType_ObjectPtr && paramStruct->dg->params.at(index).type != HookParamType_Object)
{
return pContext->ThrowNativeError("Invalid object value type %i", paramStruct->dg->params.at(index).type);
}
size_t offset = GetParamOffset(paramStruct, index);
void *addr = GetObjectAddr(paramStruct->dg->params.at(index).type, paramStruct->dg->params.at(index).flags, paramStruct->orgParams, offset);
switch((ObjectValueType)params[4])
{
case ObjectValueType_Int:
@ -1245,28 +1273,12 @@ cell_t Native_SetParamObjectPtrVar(IPluginContext *pContext, const cell_t *param
//native DHookGetParamObjectPtrVarVector(Handle:hParams, num, offset, ObjectValueType:type, Float:buffer[3]);
cell_t Native_GetParamObjectPtrVarVector(IPluginContext *pContext, const cell_t *params)
{
HookParamsStruct *paramStruct;
if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)&paramStruct, pContext, params[1]))
void *addr = NULL;
if(!GetObjectAddrOrThis(pContext, params, addr))
{
return 0;
}
if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size())
{
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size());
}
int index = params[2] - 1;
if(paramStruct->dg->params.at(index).type != HookParamType_ObjectPtr && paramStruct->dg->params.at(index).type != HookParamType_Object)
{
return pContext->ThrowNativeError("Invalid object value type %i", paramStruct->dg->params.at(index).type);
}
size_t offset = GetParamOffset(paramStruct, index);
void *addr = GetObjectAddr(paramStruct->dg->params.at(index).type, paramStruct->dg->params.at(index).flags, paramStruct->orgParams, offset);
cell_t *buffer;
pContext->LocalToPhysAddr(params[5], &buffer);
@ -1299,28 +1311,12 @@ cell_t Native_GetParamObjectPtrVarVector(IPluginContext *pContext, const cell_t
//native DHookSetParamObjectPtrVarVector(Handle:hParams, num, offset, ObjectValueType:type, Float:value[3]);
cell_t Native_SetParamObjectPtrVarVector(IPluginContext *pContext, const cell_t *params)
{
HookParamsStruct *paramStruct;
if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)&paramStruct, pContext, params[1]))
void *addr = NULL;
if(!GetObjectAddrOrThis(pContext, params, addr))
{
return 0;
}
if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size())
{
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size());
}
int index = params[2] - 1;
if(paramStruct->dg->params.at(index).type != HookParamType_ObjectPtr && paramStruct->dg->params.at(index).type != HookParamType_Object)
{
return pContext->ThrowNativeError("Invalid object value type %i", paramStruct->dg->params.at(index).type);
}
size_t offset = GetParamOffset(paramStruct, index);
void *addr = GetObjectAddr(paramStruct->dg->params.at(index).type, paramStruct->dg->params.at(index).flags, paramStruct->orgParams, offset);
cell_t *buffer;
pContext->LocalToPhysAddr(params[5], &buffer);
@ -1352,28 +1348,12 @@ cell_t Native_SetParamObjectPtrVarVector(IPluginContext *pContext, const cell_t
//native DHookGetParamObjectPtrString(Handle:hParams, num, offset, ObjectValueType:type, String:buffer[], size)
cell_t Native_GetParamObjectPtrString(IPluginContext *pContext, const cell_t *params)
{
HookParamsStruct *paramStruct;
if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)&paramStruct, pContext, params[1]))
void *addr = NULL;
if (!GetObjectAddrOrThis(pContext, params, addr))
{
return 0;
}
if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size())
{
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size());
}
int index = params[2] - 1;
if(paramStruct->dg->params.at(index).type != HookParamType_ObjectPtr && paramStruct->dg->params.at(index).type != HookParamType_Object)
{
return pContext->ThrowNativeError("Invalid object value type %i", paramStruct->dg->params.at(index).type);
}
size_t offset = GetParamOffset(paramStruct, index);
void *addr = GetObjectAddr(paramStruct->dg->params.at(index).type, paramStruct->dg->params.at(index).flags, paramStruct->orgParams, offset);
switch((ObjectValueType)params[4])
{
case ObjectValueType_CharPtr:
@ -1510,6 +1490,10 @@ cell_t Native_GetParamAddress(IPluginContext *pContext, const cell_t *params)
}
size_t offset = GetParamOffset(paramStruct, index);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
return g_pSM->ToPseudoAddress(*(void**)((intptr_t)paramStruct->orgParams + offset));
}
return *(cell_t *)((intptr_t)paramStruct->orgParams + offset);
}

View File

@ -465,19 +465,18 @@ HookReturnStruct *GetReturnStruct(DHooksCallback *dg)
return res;
}
cell_t GetThisPtr(void *iface, ThisPointerType type)
cell_t GetThisPtr(IPluginContext* pContext, void *iface, ThisPointerType type)
{
if(type == ThisPointer_CBaseEntity)
if (type == ThisPointer_CBaseEntity)
{
if (!iface)
return -1;
return gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
}
#ifdef KE_ARCH_X64
return g_pSM->ToPseudoAddress(iface);
#else
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
return g_pSM->ToPseudoAddress(iface);
}
return (cell_t)iface;
#endif
}
#if defined( WIN32 ) && !defined( KE_ARCH_X64 )
@ -500,7 +499,7 @@ void *Callback(DHooksCallback *dg, void **argStack)
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
}
if(dg->returnType != ReturnType_Void)
{
@ -684,7 +683,7 @@ float Callback_float(DHooksCallback *dg, void **argStack)
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
}
returnStruct = GetReturnStruct(dg);
@ -841,7 +840,7 @@ SDKVector *Callback_vector(DHooksCallback *dg, void **argStack)
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
}
returnStruct = GetReturnStruct(dg);
@ -995,7 +994,7 @@ string_t *Callback_stringt(DHooksCallback *dg, void **argStack)
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
dg->plugin_callback->PushCell(GetThisPtr(dg->plugin_callback->GetParentContext(), g_SHPtr->GetIfacePtr(), dg->thisType));
}
returnStruct = GetReturnStruct(dg);

View File

@ -162,6 +162,7 @@ public:
int entity;
ThisPointerType thisType;
HookType hookType;
CallingConvention thisFuncCallConv;
};
class DHooksCallback : public SourceHook::ISHDelegate, public DHooksInfo
@ -338,7 +339,7 @@ public:
};
size_t GetStackArgsSize(DHooksCallback *dg);
cell_t GetThisPtr(void *iface, ThisPointerType type);
cell_t GetThisPtr(IPluginContext* pContext, void *iface, ThisPointerType type);
extern IBinTools *g_pBinTools;
extern HandleType_t g_HookParamsHandle;

View File

@ -1,6 +1,8 @@
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#include "takedamageinfohack.h"
#include "smsdk_ext.h"
#include <ISDKHooks.h>
#include <convar.h>
@ -15,8 +17,6 @@
#include <itoolentity.h>
#endif
#include "takedamageinfohack.h"
#if SOURCE_ENGINE >= SE_CSS && SOURCE_ENGINE != SE_LEFT4DEAD
#define GETMAXHEALTH_IS_VIRTUAL
#endif

View File

@ -34,7 +34,7 @@
#include <datamap.h>
variant_t g_Variant_t;
char g_Variant_str_Value[128];
char g_Variant_str_Value[1024];
// copy this definition as the original file includes cbase.h which explodes in a shower of compile errors
void variant_t::SetEntity( CBaseEntity *val )

View File

@ -63,7 +63,8 @@ inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &ty
type = PassType_Basic;
if (vtype == Valve_POD
|| vtype == Valve_Float
|| vtype == Valve_Bool)
|| vtype == Valve_Bool
|| vtype == Valve_VirtualAddress)
{
flags = PASSFLAG_BYVAL | PASSFLAG_ASPOINTER;
} else {
@ -86,6 +87,13 @@ inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &ty
static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params)
{
auto call_type = (ValveCallType)params[1];
if (call_type == ValveCall_Raw && pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
return pContext->ThrowNativeError("SDKCall_Raw is unavailable for plugins that have enabled virtual address.");
}
if (call_type == ValveCall_VirtualAddress && pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) != SP_ERROR_NONE) {
return pContext->ThrowNativeError("SDKCall_VirtualAddress is unavailable for plugins that haven't enabled virtual address.");
}
s_numparams = 0;
s_vtbl_index = -1;
s_call_addr = NULL;
@ -172,11 +180,10 @@ static cell_t PrepSDKCall_SetSignature(IPluginContext *pContext, const cell_t *p
static cell_t PrepSDKCall_SetAddress(IPluginContext *pContext, const cell_t *params)
{
#ifdef KE_ARCH_X86
s_call_addr = reinterpret_cast<void *>(params[1]);
#else
s_call_addr = g_pSM->FromPseudoAddress(params[1]);
#endif
s_call_addr = reinterpret_cast<void*>(params[1]);
if (pContext->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) == SP_ERROR_NONE) {
s_call_addr = g_pSM->FromPseudoAddress(params[1]);
}
return (s_call_addr != NULL) ? 1 : 0;
}
@ -413,6 +420,36 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
startparam++;
}
break;
case ValveCall_VirtualAddress:
{
//params[startparam] is an address to a pointer to THIS
//params following this are params to the method we will invoke later
if (startparam > numparams)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("Expected a ThisPtr address, it wasn't found");
}
//note: varargs pawn args are passed by-ref
cell_t *cell;
pContext->LocalToPhysAddr(params[startparam], &cell);
void* thisptr = reinterpret_cast<void*>(g_pSM->FromPseudoAddress(*cell));
if (thisptr == nullptr)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("ThisPtr address cannot be null");
}
else if (reinterpret_cast<uintptr_t>(thisptr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
vc->stk_put(ptr);
return pContext->ThrowNativeError("Invalid ThisPtr address %p is pointing to reserved memory.", thisptr);
}
*(void **)ptr = thisptr;
startparam++;
}
break;
default:
{
vc->stk_put(ptr);
@ -536,6 +573,13 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
addr = *(bool **)addr;
}
return *addr ? 1 : 0;
} else if (vc->retinfo->vtype == Valve_VirtualAddress) {
void *addr = *(void **)vc->retbuf;
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
{
addr = *(void **)addr;
}
return g_pSM->ToPseudoAddress(addr);
} else {
cell_t *addr = (cell_t *)vc->retbuf;
if (vc->retinfo->flags & PASSFLAG_ASPOINTER)

View File

@ -164,6 +164,21 @@ size_t ValveParamToBinParam(ValveType type,
return sizeof(float);
}
}
case Valve_VirtualAddress:
{
info->flags = flags;
if (flags & PASSFLAG_ASPOINTER)
{
needs_extra = true;
info->type = PassType_Basic;
info->size = sizeof(void**);
return sizeof(void**) + sizeof(void*);
} else {
info->type = PassType_Basic;
info->size = sizeof(void*);
return sizeof(void*);
}
}
}
return 0;
@ -276,6 +291,19 @@ DataStatus EncodeValveParam(IPluginContext *pContext,
*addr = *(bool *)buffer ? 1 : 0;
return Data_Okay;
}
case Valve_VirtualAddress:
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
if (data->flags & PASSFLAG_ASPOINTER)
{
buffer = *(void **)buffer;
}
*addr = g_pSM->ToPseudoAddress(*(void**)buffer);
return Data_Okay;
}
}
@ -585,6 +613,29 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
*(char **)buffer = addr;
return Data_Okay;
}
case Valve_VirtualAddress:
{
if (data->decflags & VDECODE_FLAG_BYREF)
{
cell_t *addr;
pContext->LocalToPhysAddr(param, &addr);
param = *addr;
}
if (data->flags & PASSFLAG_ASPOINTER)
{
*(void **)buffer = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
buffer = *(void **)buffer;
}
void* addr = g_pSM->FromPseudoAddress(param);
if (addr == nullptr && (data->decflags & VDECODE_FLAG_ALLOWNULL) == 0)
{
pContext->ThrowNativeError("NULL Address not allowed");
return Data_Fail;
}
*(void **)buffer = addr;
return Data_Okay;
}
}
return Data_Fail;

View File

@ -53,6 +53,7 @@ enum ValveType
Valve_Edict, /**< Edict */
Valve_String, /**< String */
Valve_Bool, /**< Boolean */
Valve_VirtualAddress, /**< SM Virtual Address */
Valve_Object, /**< Object, not matching one of the above types */
};
@ -84,6 +85,7 @@ enum ValveCallType
ValveCall_Raw, /**< Thiscall (address explicit first parameter) */
ValveCall_Server, /**< Thiscall (CBaseServer implicit first parameter) */
ValveCall_Engine, /**< Thiscall (CVEngineServer implicit first parameter) */
ValveCall_VirtualAddress /**< Thiscall (address explicit first parameter) */
};
/**

View File

@ -57,25 +57,9 @@ void PlayerConditionsMgr::ProcessCondChange(CondChangeData_t *pCondData)
return;
int client = pCondData->hPlayer.GetEntryIndex();
int newConds = 0;
int prevConds = 0;
CondVar var = pCondData->var;
if (var == m_nPlayerCond)
{
prevConds = m_OldConds[client][_condition_bits] | m_OldConds[client][var];
newConds = m_OldConds[client][_condition_bits] | pCondData->newConds;
}
else if (var == _condition_bits)
{
prevConds = m_OldConds[client][m_nPlayerCond] | m_OldConds[client][var];
newConds = m_OldConds[client][m_nPlayerCond] | pCondData->newConds;
}
else
{
prevConds = m_OldConds[client][var];
newConds = pCondData->newConds;
}
int newConds = pCondData->newConds;
int prevConds = m_OldConds[client][var];
if (prevConds != newConds)
{

View File

@ -16,131 +16,125 @@
{
"Offsets"
{
"CanBeAutobalanced"
{
"windows" "464"
"linux" "465"
}
"EndTouch"
{
"windows" "101"
"linux" "102"
"mac" "102"
}
"FireBullets"
{
"windows" "113"
"linux" "114"
"mac" "114"
}
"GetMaxHealth"
{
"windows" "118"
"linux" "119"
}
"GroundEntChanged"
{
"windows" "178"
"linux" "179"
"mac" "179"
}
"OnTakeDamage"
{
"windows" "62"
"linux" "63"
"mac" "63"
}
"OnTakeDamage_Alive"
{
"windows" "273"
"linux" "274"
}
"PreThink"
{
"windows" "336"
"linux" "337"
"mac" "337"
}
"PostThink"
{
"windows" "337"
"linux" "338"
"mac" "338"
}
"Reload"
{
"windows" "271"
"linux" "272"
"mac" "272"
}
"SetTransmit"
{
"windows" "20"
"linux" "21"
"mac" "21"
}
"ShouldCollide"
{
"windows" "16"
"linux" "17"
"mac" "17"
}
"Spawn"
{
"windows" "22"
"linux" "23"
"mac" "23"
}
"StartTouch"
{
"windows" "99"
"linux" "100"
"mac" "100"
}
"Think"
{
"windows" "47"
"linux" "48"
"mac" "48"
}
"Touch"
{
"windows" "100"
"linux" "101"
"mac" "101"
}
"TraceAttack"
{
"windows" "60"
"linux" "61"
"mac" "61"
}
"Use"
{
"windows" "98"
"linux" "99"
"mac" "99"
}
"VPhysicsUpdate"
{
"windows" "158"
"linux" "159"
"mac" "159"
}
"Weapon_CanSwitchTo"
{
"windows" "267"
"linux" "268"
"mac" "268"
}
"Weapon_CanUse"
{
"windows" "261"
"linux" "262"
"mac" "262"
}
"Weapon_Drop"
{
"windows" "264"
"linux" "265"
"mac" "265"
}
"Weapon_Equip"
{
"windows" "262"
"linux" "263"
"mac" "263"
}
"Weapon_Switch"
{
"windows" "265"
"linux" "266"
"mac" "266"
}
}
}

View File

@ -4,26 +4,32 @@
{
"Offsets"
{
"CanBeAutobalanced"
{
"windows" "465"
"linux" "466"
}
"GroundEntChanged"
{
"windows" "188"
"linux" "190"
"windows" "178"
"linux" "180"
}
"OnTakeDamage_Alive"
{
"windows" "287"
"linux" "288"
"windows" "283"
"linux" "284"
}
"GetMaxHealth"
{
"windows" "126"
"linux" "127"
"windows" "118"
"linux" "119"
}
"Blocked"
{
"windows" "109"
"linux" "110"
"windows" "101"
"linux" "102"
}
/* CBaseCombatWeapon::Reload */
"Reload"
{
"windows" "287"
@ -31,18 +37,19 @@
}
"EndTouch"
{
"windows" "107"
"linux" "108"
"windows" "99"
"linux" "100"
}
/* CBaseEntity::FireBullets(FireBulletsInfo_t const&) */
"FireBullets"
{
"windows" "121"
"linux" "121"
"windows" "113"
"linux" "113"
}
"OnTakeDamage"
{
"windows" "69"
"linux" "70"
"windows" "61"
"linux" "62"
}
"PreThink"
{
@ -56,8 +63,8 @@
}
"SetTransmit"
{
"windows" "28"
"linux" "29"
"windows" "20"
"linux" "21"
}
"ShouldCollide"
{
@ -66,64 +73,64 @@
}
"Spawn"
{
"windows" "30"
"linux" "31"
"windows" "22"
"linux" "23"
}
"StartTouch"
{
"windows" "105"
"linux" "106"
"windows" "97"
"linux" "98"
}
"Think"
{
"windows" "57"
"linux" "58"
"windows" "49"
"linux" "50"
}
"Touch"
{
"windows" "106"
"linux" "107"
"windows" "98"
"linux" "99"
}
"TraceAttack"
{
"windows" "67"
"linux" "68"
"windows" "59"
"linux" "60"
}
"Use"
{
"windows" "104"
"linux" "105"
"windows" "96"
"linux" "97"
}
"VPhysicsUpdate"
{
"windows" "168"
"linux" "169"
"windows" "158"
"linux" "159"
}
"Weapon_CanSwitchTo"
{
"windows" "278"
"linux" "279"
"windows" "277"
"linux" "278"
}
"Weapon_CanUse"
{
"windows" "271"
"linux" "272"
}
"Weapon_Drop"
{
"windows" "274"
"linux" "275"
}
"Weapon_Equip"
{
"windows" "272"
"linux" "273"
}
"Weapon_Drop"
"Weapon_Switch"
{
"windows" "275"
"linux" "276"
}
"Weapon_Equip"
{
"windows" "273"
"linux" "274"
}
"Weapon_Switch"
{
"windows" "276"
"linux" "277"
}
}
}
}

View File

@ -121,6 +121,13 @@
"linux" "259"
"linux64" "259"
}
"GetAttachment"
{
"windows" "211"
"windows64" "211"
"linux" "212"
"linux64" "212"
}
}
"Keys"

View File

@ -81,10 +81,10 @@
}
"Teleport"
{
"windows" "111"
"windows64" "111"
"linux" "110"
"linux64" "110"
"windows" "110"
"windows64" "110"
"linux" "111"
"linux64" "111"
}
"CommitSuicide"
{
@ -151,10 +151,10 @@
}
"GetAttachment"
{
"windows" "258"
"windows64" "258"
"linux" "259"
"linux64" "259"
"windows" "211"
"windows64" "211"
"linux" "212"
"linux64" "212"
}
}

View File

@ -26,19 +26,16 @@
{
"windows" "4"
"linux" "4"
"mac" "4"
}
"GetTENext"
{
"windows" "8"
"linux" "8"
"mac" "8"
}
"TE_GetServerClass"
{
"windows" "0"
"linux" "0"
"mac" "0"
}
}
@ -53,7 +50,7 @@
"s_pTempEntities"
{
"library" "server"
"mac" "@_ZN15CBaseTempEntity15s_pTempEntitiesE"
"linux" "@_ZN15CBaseTempEntity15s_pTempEntitiesE"
}
}
}
@ -64,12 +61,12 @@
"Signatures"
{
/* Functions in CGlobalEntityList */
/* Search any functions with the "CAI_StandoffBehavior::PrescheduleThink" string, FindEntityByClassname is called with "ai_battle_line" string as a parameter */
"FindEntityByClassname"
{
"library" "server"
"windows" "\x55\x89\xE5\x53\x57\x56\x83\xEC\x08\x8B\x45\x08\x85\xC0\x0F\x85\x2A\x2A\x2A\x2A"
"windows" "\x55\x89\xE5\x53\x57\x56\x83\xEC\x08\x8B\x45\x2A\x85\xC0\x0F\x85"
"linux" "@_ZN17CGlobalEntityList21FindEntityByClassnameEP11CBaseEntityPKc"
"mac" "@_ZN17CGlobalEntityList21FindEntityByClassnameEP11CBaseEntityPKc"
}
}
}
@ -82,9 +79,19 @@
"FireOutput"
{
"library" "server"
"windows" "\x55\x89\xE5\x53\x57\x56\x81\xEC\x10\x01\x00\x00\x8B\x71\x14"
"windows" "\x55\x89\xE5\x53\x57\x56\x81\xEC\x10\x01\x00\x00\x8B\x71"
"linux" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
"mac" "@_ZN17CBaseEntityOutput10FireOutputE9variant_tP11CBaseEntityS2_f"
}
"LookupAttachment"
{
/* CBaseAnimating::LookupAttachment */
/* Called in a function that has the "zipline" and "cable/cable.vmt" strings.
* Inside this function, search for a function call that passes the "zipline" string as the only parameter.
* That function is CBaseAnimating::LookupAttachment.
*/
"library" "server"
"windows" "\x31\xC0\x80\xB9\x2A\x2A\x2A\x2A\x00\x0F\x85"
"linux" "@_ZN14CBaseAnimating16LookupAttachmentEPKc"
}
}
}
@ -93,96 +100,96 @@
{
"Offsets"
{
"SetOwnerEntity"
{
"windows" "17"
"linux" "18"
}
/* CBasePlayer */
"GiveNamedItem"
{
"windows" "408"
"linux" "409"
"mac" "409"
}
"RemovePlayerItem"
{
"windows" "271"
"linux" "272"
"mac" "272"
}
"Weapon_GetSlot"
{
"windows" "269"
"linux" "270"
"mac" "270"
}
"Ignite"
{
"windows" "210"
"linux" "211"
"mac" "211"
}
"Extinguish"
{
"windows" "214"
"linux" "215"
"mac" "215"
}
"Teleport"
{
"windows" "109"
"linux" "110"
"mac" "110"
}
"CommitSuicide"
{
"windows" "446"
"linux" "447"
"mac" "447"
}
"GetVelocity"
{
"windows" "141"
"linux" "142"
"mac" "142"
}
"EyeAngles"
{
"windows" "132"
"linux" "133"
"mac" "133"
}
"AcceptInput"
{
"windows" "36"
"linux" "37"
"mac" "37"
}
"SetEntityModel"
{
"windows" "24"
"linux" "25"
"mac" "25"
}
"WeaponEquip"
{
"windows" "262"
"linux" "263"
"mac" "263"
}
"Activate"
{
"windows" "33"
"linux" "34"
"mac" "34"
}
"RemoveAllItems"
{
"windows" "349"
"linux" "350"
"mac" "350"
}
"PlayerRunCmd"
{
"windows" "426"
"linux" "427"
"mac" "427"
}
"GiveAmmo"
{
"windows" "253"
"linux" "254"
}
"GetAttachment"
{
"windows" "206"
"linux" "207"
}
}

View File

@ -23,13 +23,13 @@
}
"RemovePlayerItem"
{
"windows" "285"
"linux" "286"
"windows" "281"
"linux" "282"
}
"Weapon_GetSlot"
{
"windows" "280"
"linux" "281"
"windows" "279"
"linux" "280"
}
"Ignite"
{
@ -43,8 +43,8 @@
}
"Teleport"
{
"windows" "115"
"linux" "116"
"windows" "107"
"linux" "108"
}
"CommitSuicide"
{
@ -53,33 +53,33 @@
}
"GetVelocity"
{
"windows" "151"
"linux" "152"
"windows" "141"
"linux" "142"
}
"EyeAngles"
{
"windows" "142"
"linux" "143"
"windows" "132"
"linux" "133"
}
"AcceptInput"
{
"windows" "44"
"linux" "45"
"windows" "36"
"linux" "37"
}
"SetEntityModel"
{
"windows" "32"
"linux" "33"
"windows" "24"
"linux" "25"
}
"WeaponEquip"
{
"windows" "273"
"linux" "274"
"windows" "272"
"linux" "273"
}
"Activate"
{
"windows" "41"
"linux" "42"
"windows" "33"
"linux" "34"
}
"PlayerRunCmd"
{
@ -93,13 +93,13 @@
}
"SetOwnerEntity"
{
"windows" "25"
"linux" "26"
"windows" "17"
"linux" "18"
}
"GiveAmmo"
{
"windows" "264"
"linux" "265"
"windows" "263"
"linux" "264"
}
}
"Signatures"

@ -1 +1 @@
Subproject commit 38b4f3670826bbfe7c536ef33ec53f5971d419e2
Subproject commit c018a994478d6c31f70ded7adec7aa9e2c40bb1a

View File

@ -207,19 +207,28 @@ methodmap ArrayList < Handle {
// Returns the index for the first occurrence of the provided string. If
// the string cannot be located, -1 will be returned.
//
// @param item String to search for
// @param block Optionally which block to search in
// @param item String to search for.
// @param block Optionally which block to search in.
// @param start Index to start searching from (exclusive), or -1 for direction default.
// Valid numbers are in the interval [-1..Length].
// @param reverse Whether the search direction should be reversed.
// @param caseSensitive If true (default), comparison is case sensitive.
// If false, comparison is case insensitive.
// @return Array index, or -1 on failure
public native int FindString(const char[] item, int block=0);
// @error Invalid block, or invalid start index.
public native int FindString(const char[] item, int block=0, int start=-1, bool reverse=false, bool caseSensitive=true);
// Returns the index for the first occurrence of the provided value. If the
// value cannot be located, -1 will be returned.
//
// @param item Value to search for
// @param block Optionally which block to search in
// @return Array index, or -1 on failure
// @error Invalid block index
public native int FindValue(any item, int block=0);
// @param item Value to search for.
// @param block Optionally which block to search in.
// @param start Index to start searching from (exclusive), or -1 for direction default.
// Valid numbers are in the interval [-1..Length].
// @param reverse Whether the search direction should be reversed.
// @return Array index, or -1 on failure.
// @error Invalid block, or invalid start index.
public native int FindValue(any item, int block=0, int start=-1, bool reverse=false);
// Sort an ADT Array. Specify the type as Integer, Float, or String.
//

View File

@ -310,7 +310,7 @@ methodmap DHookParam < Handle
// Gets an object's variable value.
//
// @param num Parameter number to get, starting at 1.
// @param num Parameter number to get, 0 for param "this", other parameters start from 1
// @param offset Byte offset within the object to the var to get.
// @param type Type of var it is.
//
@ -320,7 +320,7 @@ methodmap DHookParam < Handle
// Gets an object's vector variable value.
//
// @param num Parameter number to get, starting at 1.
// @param num Parameter number to get, 0 for param "this", other parameters start from 1.
// @param offset Byte offset within the object to the var to get.
// @param type Type of var it is.
// @param vec Buffer to store the result vector.
@ -330,7 +330,7 @@ methodmap DHookParam < Handle
// Gets an object's string variable value.
//
// @param num Parameter number to get, starting at 1.
// @param num Parameter number to get, 0 for param "this", other parameters start from 1.
// @param offset Byte offset within the object to the var to get.
// @param type Type of var it is.
// @param buffer Buffer to store the result string.
@ -344,7 +344,7 @@ methodmap DHookParam < Handle
// The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride
// is returned in the callback.
//
// @param num Parameter number to set, starting at 1.
// @param num Parameter number to set, 0 for param "this", other parameters start from 1.
// @param offset Byte offset within the object to the var to set.
// @param type Type of var it is.
// @param value The value to set the var to.
@ -357,7 +357,7 @@ methodmap DHookParam < Handle
// The changes are only applied when MRES_ChangedHandled or MRES_ChangedOverride
// is returned in the callback.
//
// @param num Parameter number to set, starting at 1.
// @param num Parameter number to set, 0 for param "this", other parameters start from 1.
// @param offset Byte offset within the object to the var to set.
// @param type Type of var it is.
// @param vec The value to set the vector var to.
@ -928,7 +928,7 @@ native void DHookSetReturnString(Handle hReturn, char[] value);
* Gets an objects variable value
*
* @param hParams Handle to params structure
* @param num Param number to get.
* @param num Param number to get, 0 for param "this".
* @param offset Offset within the object to the var to get.
* @param type Type of var it is
*
@ -941,7 +941,7 @@ native any DHookGetParamObjectPtrVar(Handle hParams, int num, int offset, Object
* Sets an objects variable value
*
* @param hParams Handle to params structure
* @param num Param number to set.
* @param num Param number to set, 0 for param "this".
* @param offset Offset within the object to the var to set.
* @param type Type of var it is
* @param value The value to set the var to.
@ -954,7 +954,7 @@ native void DHookSetParamObjectPtrVar(Handle hParams, int num, int offset, Objec
* Gets an objects vector variable value
*
* @param hParams Handle to params structure
* @param num Param number to get.
* @param num Param number to get, 0 for param "this".
* @param offset Offset within the object to the var to get.
* @param type Type of var it is
* @param buffer Buffer to store the result vector
@ -967,7 +967,7 @@ native void DHookGetParamObjectPtrVarVector(Handle hParams, int num, int offset,
* Sets an objects vector variable value
*
* @param hParams Handle to params structure
* @param num Param number to set.
* @param num Param number to set, 0 for param "this".
* @param offset Offset within the object to the var to set.
* @param type Type of var it is
* @param value The value to set the vector var to.
@ -980,7 +980,7 @@ native void DHookSetParamObjectPtrVarVector(Handle hParams, int num, int offset,
* Gets an objects string variable value
*
* @param hParams Handle to params structure
* @param num Param number to get.
* @param num Param number to get, 0 for param "this".
* @param offset Offset within the object to the var to get.
* @param type Type of var it is
* @param buffer Buffer to store the result vector

View File

@ -60,9 +60,10 @@ enum SDKCallType
SDKCall_Player, /**< CBasePlayer call */
SDKCall_GameRules, /**< CGameRules call */
SDKCall_EntityList, /**< CGlobalEntityList call */
SDKCall_Raw, /**< |this| pointer with an arbitrary address */
SDKCall_Raw, /**< |this| pointer with an arbitrary address. This is not available if SM's virtual addresses are enabled */
SDKCall_Server, /**< CBaseServer call */
SDKCall_Engine /**< CVEngineServer call */
SDKCall_Engine, /**< CVEngineServer call */
SDKCall_VirtualAddress /**< |this| pointer with an arbitrary SM virtual address */
};
enum SDKLibrary
@ -88,7 +89,8 @@ enum SDKType
SDKType_Float, /**< Float (any) */
SDKType_Edict, /**< edict_t (always as pointer) */
SDKType_String, /**< NULL-terminated string (always as pointer) */
SDKType_Bool /**< Boolean (any) */
SDKType_Bool, /**< Boolean (any) */
SDKType_VirtualAddress, /**< SM Virtual Address */
};
enum SDKPassMethod

View File

@ -754,6 +754,26 @@ native any LoadFromAddress(Address addr, NumberType size);
*/
native void StoreToAddress(Address addr, any data, NumberType size, bool updateMemAccess = true);
/**
* Load sizeof(void*) from a memory address.
*
* @param addr Address to a memory location.
* @return The address that is stored at that address.
* @error Address is null or pointing to reserved memory.
*/
native Address LoadAddressFromAddress(Address addr);
/**
* Store sizeof(void*) bytes to a memory address.
*
* @param addr Address to a memory location.
* @param data Address to store at that location.
* @param updateMemAccess If true, SourceMod will set read / write / exec permissions
* on the memory page being written to.
* @error Address is null or pointing to reserved memory.
*/
native void StoreAddressToAddress(Address addr, Address data, bool updateMemAccess = true);
methodmap FrameIterator < Handle {
// Creates a stack frame iterator to build your own stack traces.
// @return New handle to a FrameIterator.

View File

@ -166,7 +166,10 @@ enum {
TF_CUSTOM_SLAP_KILL,
TF_CUSTOM_CROC,
TF_CUSTOM_TAUNTATK_GASBLAST,
TF_CUSTOM_AXTINGUISHER_BOOSTED
TF_CUSTOM_AXTINGUISHER_BOOSTED,
TF_CUSTOM_KRAMPUS_MELEE,
TF_CUSTOM_KRAMPUS_RANGED,
TF_CUSTOM_TAUNTATK_TRICKSHOT
};
// Weapon codes as used in some events, such as player_death

View File

@ -0,0 +1,39 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod (C)2004-2025 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This file is part of the SourceMod/SourcePawn SDK.
*
* 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$
*/
#if defined _virtual_address_included
#endinput
#endif
#define _virtual_address_included
public const Address __Virtual_Address__ = view_as<Address>(0);
public const Address PointerSize = view_as<Address>(0); /**< Size of a pointer in bytes (same as `sizeof(void*)`) */

View File

@ -62,7 +62,8 @@ ConVar g_Cvar_ExtendTimeStep;
ConVar g_Cvar_ExtendRoundStep;
ConVar g_Cvar_ExtendFragStep;
ConVar g_Cvar_ExcludeMaps;
ConVar g_Cvar_IncludeMaps;
ConVar g_Cvar_IncludeMinMaps;
ConVar g_Cvar_IncludeMaxMaps;
ConVar g_Cvar_PersistentMaps;
ConVar g_Cvar_NoVoteMode;
ConVar g_Cvar_Extend;
@ -127,7 +128,8 @@ public void OnPluginStart()
g_Cvar_ExtendRoundStep = CreateConVar("sm_extendmap_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 1.0);
g_Cvar_ExtendFragStep = CreateConVar("sm_extendmap_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0);
g_Cvar_ExcludeMaps = CreateConVar("sm_mapvote_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0);
g_Cvar_IncludeMaps = CreateConVar("sm_mapvote_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 6.0);
g_Cvar_IncludeMinMaps = CreateConVar("sm_mapvote_include_min", "4", "Specifies the minimum number of maps to include in the vote.", _, true, 2.0, true, 6.0);
g_Cvar_IncludeMaxMaps = CreateConVar("sm_mapvote_include_max", "6", "Specifies the maximum number of maps to include in the vote.", _, true, 2.0, true, 6.0);
g_Cvar_PersistentMaps = CreateConVar("sm_mapvote_persistentmaps", "0", "Specifies if previous maps should be stored persistently.", _, true, 0.0, true, 1.0);
g_Cvar_NoVoteMode = CreateConVar("sm_mapvote_novote", "1", "Specifies whether or not MapChooser should pick a map if no votes are received.", _, true, 0.0, true, 1.0);
g_Cvar_Extend = CreateConVar("sm_mapvote_extend", "0", "Number of extensions allowed each map.", _, true, 0.0);
@ -609,7 +611,7 @@ void InitiateVote(MapChange when, ArrayList inputlist=null)
if (inputlist == null)
{
int nominateCount = g_NominateList.Length;
int voteSize = g_Cvar_IncludeMaps.IntValue;
int voteSize = g_Cvar_IncludeMaxMaps.IntValue;
/* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */
int nominationsToAdd = nominateCount >= voteSize ? voteSize : nominateCount;
@ -993,16 +995,20 @@ void CreateNextVote()
GetCurrentMap(map, sizeof(map));
RemoveStringFromArray(tempMaps, map);
if (g_Cvar_ExcludeMaps.IntValue && tempMaps.Length > g_Cvar_ExcludeMaps.IntValue)
// Start excluding the most recently played maps first
for (int i = g_OldMapList.Length-1; i >= 0; i--)
{
for (int i = 0; i < g_OldMapList.Length; i++)
if (tempMaps.Length <= g_Cvar_IncludeMinMaps.IntValue)
{
g_OldMapList.GetString(i, map, sizeof(map));
RemoveStringFromArray(tempMaps, map);
// Exit if we hit the minimum option count
break;
}
g_OldMapList.GetString(i, map, sizeof(map));
RemoveStringFromArray(tempMaps, map);
}
int limit = (g_Cvar_IncludeMaps.IntValue < tempMaps.Length ? g_Cvar_IncludeMaps.IntValue : tempMaps.Length);
int limit = (g_Cvar_IncludeMaxMaps.IntValue < tempMaps.Length ? g_Cvar_IncludeMaxMaps.IntValue : tempMaps.Length);
for (int i = 0; i < limit; i++)
{
int b = GetRandomInt(0, tempMaps.Length - 1);
@ -1054,7 +1060,7 @@ NominateResult InternalNominateMap(char[] map, bool force, int owner)
}
/* Too many nominated maps. */
if (g_NominateList.Length >= g_Cvar_IncludeMaps.IntValue && !force)
if (g_NominateList.Length >= g_Cvar_IncludeMaxMaps.IntValue && !force)
{
return Nominate_VoteFull;
}
@ -1062,7 +1068,7 @@ NominateResult InternalNominateMap(char[] map, bool force, int owner)
g_NominateList.PushString(map);
g_NominateOwners.Push(owner);
while (g_NominateList.Length > g_Cvar_IncludeMaps.IntValue)
while (g_NominateList.Length > g_Cvar_IncludeMaxMaps.IntValue)
{
char oldmap[PLATFORM_MAX_PATH];
g_NominateList.GetString(0, oldmap, sizeof(oldmap));

View File

@ -0,0 +1,141 @@
#pragma semicolon 1
#pragma newdecls required
#include <testing>
enum struct TestStruct
{
int intval;
char strval[32];
}
public void OnPluginStart()
{
ArrayList list = new ArrayList(sizeof(TestStruct));
// --------------------------------------------------------------------------------
SetTestContext("EmptyArrayTest");
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, -1, false), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, -1, true), -1);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, -1, false), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, -1, true), -1);
// --------------------------------------------------------------------------------
// Fill
TestStruct ts;
for (int i = 0; i < 10; i++)
{
ts.intval = i;
Format(ts.strval, sizeof(ts.strval), "index%d", i);
list.PushArray(ts);
}
// --------------------------------------------------------------------------------
SetTestContext("FindString");
AssertEq("test_defaults", list.FindString("index3", TestStruct::strval), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, -1, false), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 0, false), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 2, false), 3);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 3, false), -1);
AssertEq("test_forward", list.FindString("index3", TestStruct::strval, 10, false), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, -1, true), 3);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 0, true), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 3, true), -1);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 4, true), 3);
AssertEq("test_reverse", list.FindString("index3", TestStruct::strval, 10, true), 3);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, -1, false), 0);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, -1, true), 0);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, 1, true), 0);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, 10, false), -1);
AssertEq("test_bottom", list.FindString("index0", TestStruct::strval, 10, true), 0);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, -1, false), 9);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, -1, true), 9);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, 8, false), 9);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, 10, false), -1);
AssertEq("test_top", list.FindString("index9", TestStruct::strval, 10, true), 9);
AssertEq("test_case_sensitive", list.FindString("INDEX0", TestStruct::strval, .caseSensitive = true), -1);
AssertEq("test_case_sensitive", list.FindString("INDEX0", TestStruct::strval, .caseSensitive = false), 0);
// --------------------------------------------------------------------------------
SetTestContext("FindValue");
AssertEq("test_defaults", list.FindValue(3, TestStruct::intval), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, -1, false), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 0, false), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 2, false), 3);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 3, false), -1);
AssertEq("test_forward", list.FindValue(3, TestStruct::intval, 10, false), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, -1, true), 3);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 0, true), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 3, true), -1);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 4, true), 3);
AssertEq("test_reverse", list.FindValue(3, TestStruct::intval, 10, true), 3);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, -1, false), 0);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, -1, true), 0);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, 1, true), 0);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, 10, false), -1);
AssertEq("test_bottom", list.FindValue(0, TestStruct::intval, 10, true), 0);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, -1, false), 9);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, -1, true), 9);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, 8, false), 9);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, 10, false), -1);
AssertEq("test_top", list.FindValue(9, TestStruct::intval, 10, true), 9);
// --------------------------------------------------------------------------------
SetTestContext("IterateOverFindString");
int found, index;
// Duplicate last entry
list.PushArray(ts);
found = 0; index = -1;
while ((index = list.FindString("index9", TestStruct::strval, index, false)) != -1)
{
found++;
}
AssertEq("test_find_all_strings_forward", found, 2);
found = 0; index = -1;
while ((index = list.FindString("index9", TestStruct::strval, index, true)) != -1)
{
found++;
}
AssertEq("test_find_all_strings_reverse", found, 2);
// --------------------------------------------------------------------------------
SetTestContext("IterateOverFindValue");
found = 0, index = -1;
while ((index = list.FindValue(9, TestStruct::intval, index, false)) != -1)
{
found++;
}
AssertEq("test_find_all_values_forward", found, 2);
found = 0; index = -1;
while ((index = list.FindValue(9, TestStruct::intval, index, true)) != -1)
{
found++;
}
AssertEq("test_find_all_values_reverse", found, 2);
// --------------------------------------------------------------------------------
PrintToServer("OK");
}

@ -1 +1 @@
Subproject commit ab76f94ee4ef28187cc08030599577996fcba3be
Subproject commit 8c6692c85a6c41f5d89f744da57b5ba43515b4ec