Compare commits

..

248 Commits

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

Copy it over to CreateValveVCall so that ValveParamToBinParam stops
writing to a null pointer.

Fixes #1059 (Hopefully.)
2019-10-18 00:23:45 +01:00
nosoop
024ae2b9ed Use map display name for admin map chooser menu (#1097) 2019-10-07 19:15:36 +01:00
Headline
8a4295d699 NPOTB: Correct GitHub's Linguist inaccuracies (#1096) 2019-10-07 19:14:09 +01:00
David Anderson
f05e39afe1
Merge pull request #1090 from alliedmodders/update-sp
Update SourcePawn to 1.10-dev tip.
2019-10-01 09:50:25 -07:00
Headline
3b1fb85bb8
Fix quote mismatch (#1092) 2019-09-30 22:43:18 -07:00
Playa
a405f85eee Remove SourcePawn JIT license references (#1091) 2019-09-30 15:09:40 -07:00
David Anderson
78511afa4c Update SourcePawn to 1.10-dev tip. 2019-09-28 18:32:47 -07:00
David Anderson
c37c4f830f
Merge pull request #1088 from alliedmodders/update-sp
Update SourcePawn to the tip of 1.10-dev.
2019-09-26 13:14:29 -07:00
David Anderson
4fe2ae780b Update SourcePawn to the tip of 1.10-dev. 2019-09-25 21:59:32 -07:00
Einyux
e02e6bcb4f Add TR_GetHitBoxIndex() native (#1085)
Fixes #1080
2019-09-17 21:24:36 +01:00
David Anderson
c7392aeded Fully convert dynamicmenu to transitional enum structs. (#1082) 2019-09-15 14:02:46 -07:00
David Anderson
14247af323
Merge pull request #1081 from alliedmodders/enum-structs
Update SourcePawn.
2019-09-15 11:55:56 -07:00
David Anderson
32cb00a4c6 Update SourcePawn. 2019-09-15 11:38:21 -07:00
BotoX
d93f6984cc cstrike: Fix wrong timeleft calculation (#1072)
* Fix wrong timeleft calculation

* reorder function calls
2019-09-02 15:33:28 -07:00
42
207584818f Add RequestFrameCallback optional data param (#1068) 2019-09-02 14:00:22 -07:00
Asher Baker
7a42d6b564 Fix build with latest hl2sdk-csgo 2019-09-02 21:45:04 +01:00
David Anderson
94b3ca08a2 Update SourcePawn & amtl submodules (#1067) 2019-09-01 13:24:39 -07:00
RumbleFrog
ab5f00b65b Correct FrameIterator retval regression (#1066) 2019-08-26 19:26:51 -07:00
JoinedSenses
b8fd7db58d Create menu if multiple nom matches found (#983)
This change checks the nomination against the map arraylist. If the nomination matches multiple results, those results are then added to a menu to allow the client to select available maps. The maps added to the menu go against the same checks as the normal nomination menu and wont allow nomination of disabled maps.

Example image of /nominate jump_b
https://i.imgur.com/ZdzB0gk.png

If reply source is console, menus wont be generated and it will attempt to nominate as normal.
2019-08-01 13:48:10 +01:00
hydrogen-mvm
22635d8d35 Add File.Flush methodmap (#1056)
This allows us to do FileHandle.Flush() instead of FlushFile(FileHandle) and maintain consistency in always using methodmaps for file I/O operations.
2019-07-31 22:18:07 +00:00
hydrogen-mvm
fb9b284bcf Correct malformed Regex documentation (#1055) 2019-07-31 10:48:46 -07:00
David Anderson
5868ffd04e
Merge pull request #1050 from alliedmodders/update-sp-093edef
Update SourcePawn to 093edef
2019-07-24 09:38:43 -07:00
Asher Baker
8ce99e0540 Link pthread library for Linux binaries 2019-07-24 14:47:13 +01:00
Asher Baker
efb02755bc Update SourcePawn to 093edef 2019-07-24 13:51:15 +01:00
Asher Baker
fcafd0784c
Workaround CS:GO Stringtable bug (#1046)
The cause of the infamous "Index error writing string table baseline"
error appears to be a timing issue between the engine's network message
processing, the stringtable encoding, and command processing when adding
stringtable entries in OnConfigsExecuted.

When the first client connects the map is re-loaded which causes a full
refresh, the game's stringtable entries are added at tick 65, the client
connection is registered at tick 66, and stringtable entries added in
OnConfigsExecuted are registered as being added in tick 67. The engine
later calls WriteBaselines with the client's signon tick, and neglects
to encode the SM added entries as it considers them from the future.

To avoid this, always pass INT_MAX as the current tick when encoding
the baseline, so all stringtable entries are included regardless of when
they were added. Tested on both Windows and Linux.
2019-07-19 09:13:34 +01:00
42
199802150b Update TF2_IgnitePlayer to support setting duration of fire (#1038)
Related to #713
2019-07-05 22:37:25 +01:00
MartLegion
e47c1a840a Pad plugin ID based on the total plugin count (#1027)
Closes #994
2019-06-17 01:06:03 +01:00
Nicholas Hastings
14227c04b8
Fix matchmaking_ds bin not being found for gamedata (#1006). (#1028) 2019-06-01 14:30:22 -04:00
Batfoxkid
cf0a49881e TFCond Descriptions (#1005)
This is mainly for API (https://sm.alliedmods.net/new-api/tf2/TFCond) to show description of the condition.
2019-06-01 15:43:06 +01:00
JoinedSenses
527a998740 Fix whitespace regression from #1012 (#1026) 2019-05-30 20:11:43 -07:00
JoinedSenses
352f078b07 Add Cookie methodmap (#1012) 2019-05-30 18:27:14 -07:00
JoinedSenses
4f3c3175e6 Create GlobalForward & PrivateForward methodmaps (#1004) 2019-05-29 14:17:42 -07:00
JoinedSenses
81dc80fbd1 Correct Plugin API Documentation Formatting (#1019) 2019-05-28 18:38:58 -07:00
Headline
28036966a6
Fix Miscellaneous Regressions and UBs (#1022) 2019-05-28 18:04:08 -07:00
Headline
2164f5191e
Fix GCC 9 Builds (#1024) 2019-05-28 17:57:40 -07:00
Asher Baker
216ba8b4e9
Create FUNDING.yml 2019-05-27 17:15:04 +01:00
Bara
9c55eed549 Add Shield and Bumpmine to cstrike.inc (#991) 2019-05-24 06:03:42 -07:00
Amine B
f9ce25a7fe PassType typo fixup (#1018)
* PassType typo fixup

Just some little observations, I will look up for more in other files whenever I can

* Update natives.cpp

* Update outputnatives.cpp
2019-05-15 07:22:34 -04:00
Nicholas Hastings
7e418933e7
Re-add missing GetEconItemView param (fixes #1001). (#1017) 2019-05-14 20:55:44 -04:00
Nicholas Hastings
05b3fc0fb9
Re-add float cast on TF2_AddCondition param (fixes #1013). (#1016)
Broken by ArgScuffer
2019-05-14 19:22:43 -04:00
Bruno Ronning
d7990596f9 Update CS:GO "Reload" offset. (#1011) 2019-05-14 18:56:14 -04:00
Kyle Sanderson
86f974f242
NPOTB: Enable cstrike builds w/ Travis-CI. (#1014)
Travis-CI seems to have finally improved their environment so we should be okay to test this unique code-path now with CI.
2019-05-14 11:38:20 -07:00
Loïc
6addc5c8dd Fix wrong formatting to "Vote Delay Minutes" when delay above 60s (#1009)
Fixes #1007
2019-05-13 00:20:47 +01:00
David Anderson
15a7faeafd
Merge pull request #1008 from alliedmodders/update-sp
Update SourcePawn to 4cba235.
2019-05-11 14:13:28 -07:00
David Anderson
626963fc49 Update SourcePawn to 4cba235. 2019-05-11 13:53:09 -07:00
JoinedSenses
2e72fc115d Fix malformed documentation indentation in Array.FindValue (#1002)
Modified indention for uniformity
2019-05-09 16:56:17 -07:00
JoinedSenses
26462f2848 Add Sort and SortCustom to ArrayList methodmap (#1003) 2019-05-09 18:44:31 +01:00
Michael Flaherty
9cd2a74271
Fix ArgBuffer String Serialization (#999) 2019-05-04 01:46:55 -07:00
iNilo
e1648ba8f9 Add missing semicolon to profiler.inc (#996) 2019-05-03 02:11:03 -07:00
Michael Flaherty
dae6d13f06 Fix CSS Builds (#992) 2019-05-01 17:29:55 -04:00
PerfectLaugh
ccf1d7abbd Remove unneeded paramter in CS_DropWeapon (#988)
Updated in 4/30/2019 csgo update
2019-05-01 11:38:02 -04:00
Nick Hastings
b92381505a Update Linux CSWeaponDropBB signature. 2019-05-01 11:35:13 -04:00
Nicholas Hastings
5ba6b1426b
Revert "Update CS:GO CSWeaponDrop Signature (#985)" (#990)
This reverts commit fc7453a6c7.
2019-05-01 11:31:26 -04:00
Anthony
fc7453a6c7 Update CS:GO CSWeaponDrop Signature (#985) 2019-04-30 23:36:39 -07:00
404UNF
ae00144e84 Add new custom kill identifier for TF2 (#972) 2019-04-22 22:53:31 +01:00
Playa
59baaf1123 Fix param order in CancelClientMenu documentation (#982) 2019-04-22 20:33:27 +01:00
Michael Flaherty
e2eac382c0
Add templated helper class to promote type-safety (#965) 2019-04-12 12:10:37 -07:00
Michael Flaherty
dd81d7c78f
Incorperate Licensing Into Project Tree (#961) 2019-04-12 12:10:13 -07:00
peace-maker
e3f4d239f1 IBinTools: Block loading incompatible interface versions (#979)
In #705 SourceMod received support for x64 binaries. The `IBinTools` interface was updated to call functions in 64bit binaries. The `PassInfo` struct's size was increased and the `Create(V)Call()` functions signatures changed, thus making the interface incompatible for consumers which were compiled against an earlier version.

`SMInterface::IsVersionCompatible` wasn't adjusted to that fact, so extensions compiled against pre SM 1.10 could request an `IBinTools` interface pointer, but crash when they try to use it.

This change makes requests to older interface versions invalid, thus letting `RequestInterface` return `NULL` for older extensions. It doesn't fix the backwards incompatibility, but at least makes the problem more blatant, so extensions can handle it themselves.
2019-04-11 14:51:38 -07:00
⭐ B3none
8f0527487f SQL-Admin-Manager: style clean-up (#974)
* Switched to sizeof instead of hard-coding for loop size

* Switched back to pre-increment.

* Dynamically pad variables
2019-04-06 11:47:21 -07:00
Nicholas Hastings
318b36cdcf
Trigger build for hl2sdk-csgo update. 2019-03-28 20:00:20 -04:00
TheRandomLabs
f4b9dfb2e7 Fix misspelling of "runoff" in mapchooser (#973) 2019-03-23 18:21:54 -07:00
David Anderson
2e11d3400e Fix MSVC2015 build. 2019-03-16 17:25:36 -07:00
David Anderson
364cd094d9 Trigger a build. 2019-03-16 16:57:22 -07:00
David Anderson
2af7600057 Switch to MSVC2015 builders. 2019-03-16 16:21:57 -07:00
komashchenko
8031e42bda pb: Add natives to work with 64 bit values (#943)
* Add natives to work with 64 bit Protobuf values

* Fix linux build

* FIX alignment requirements

* FIX alignment requirements V2

* Remove legacy API

* Inattention
2019-03-04 09:06:43 -08:00
Ҝờţأķ
7f9ceaac06 basevotes: Fix buffer size for workshop obtained levels. (#956) 2019-03-03 15:00:24 -08:00
David Anderson
ae0a03d438
Merge pull request #964 from Bara/patch-5
Add missing semicolon
2019-02-19 21:49:07 -08:00
Bara
d105ce778d
Add missing semicolon
Otherwise you'll get this error:
regex.inc(182) : error 001: expected token: ";", but found "<newline>"

[Example with latest sourcemod (1.10.6383) version](https://travis-ci.org/Bara/TroubleinTerroristTown/jobs/495529570#L640)
2019-02-19 17:21:17 +01:00
David Anderson
653e9325fc
Merge pull request #963 from alliedmodders/update-sp
Update SourcePawn.
2019-02-18 12:53:21 -08:00
David Anderson
5d7d7c122e Update SourcePawn. 2019-02-17 21:21:43 -08:00
Ross Bemrose
45fb26d282 Change MultiTargetFilter to a typeset that allows ArrayList as its second argument. (#955) 2019-02-03 13:27:26 -08:00
Asher Baker
c501c837d0
Ignore SM site certificate when downloading GeoIP
Build servers don't have a root for it, and the address is internal
2019-01-19 12:34:23 +00:00
Asher Baker
590f71436f
Get GeoIP data from SM site for now 2019-01-19 12:18:36 +00:00
Michael Flaherty
b7e252dfd6
Prevent FrameIterator OOB Errors (#949) 2019-01-13 13:36:35 -08:00
Nicholas Hastings
a2246af121
Unify map lookup logic across tf2esque engines. (fixes #927) (#931) 2019-01-07 18:17:28 -05:00
Bara
3e454db2d8 Add snowball to CSWeaponID (#936) 2019-01-05 14:56:07 -05:00
OkyHp
b88e0d7875 Add getter for Event.BroadcastDisabled (#946)
In a pre-hook, the hook param is not reliable if multiple plugins have hooked the same event.
2019-01-03 19:42:42 +00:00
Nick Hastings
821251b176 Fix BfRead.BytesLeft not being able to be optional. (fixes #945). 2019-01-01 15:34:26 -05:00
Deathreus
1b3599c189 Bump non-critical versioning to 1.10 (#939) 2018-12-27 21:02:14 -05:00
Nicholas Hastings
5e7596dea6
Upgrade SQLite from v3.22.0 to v3.26.0. (#935) 2018-12-19 17:26:29 -05:00
David Anderson
ab7519530e
Merge pull request #934 from alliedmodders/enum-structs
Inauguration of SourcePawn enum structs
2018-12-16 22:43:43 -08:00
David Anderson
faa10f52a8 Move dynamicmenu.sp enum structs to transitional syntax. 2018-12-16 18:49:36 -08:00
David Anderson
53df09fbb7 Fix dynamicmenu.sp indentation. 2018-12-16 18:41:55 -08:00
Michael Flaherty
c8f3035cb0
Introduce enum structs to core sm plugins 2018-12-15 13:51:03 -08:00
David Anderson
f465985370 Update SourcePawn and AMTL to master.
This brings in enum struct support.
2018-12-15 12:17:11 -08:00
David Anderson
470486ba7e
Don't double-format in ReplyToCommand. (#932) 2018-12-12 23:30:27 -08:00
Nick Hastings
9a4fe1c475 Fix signed/unsigned compare on Windows. 2018-12-12 20:02:23 -05:00
Ruben Gonzalez
dd61223c0b Add new CSGO weapon id's/itemdefs. (#929) 2018-12-12 11:35:36 -08:00
Nick Hastings
c196082988 Typo fix for CS:GO POSIX Extinguish gamedata. 2018-12-08 09:05:10 -05:00
Nick Hastings
9e58476631 Update CS:GO contribution score offset. 2018-12-07 07:24:30 -05:00
Nick Hastings
4bebdc18a2 Hmm... 2018-12-06 20:31:29 -05:00
Nick Hastings
a01529b210 Add new GiveNamedItem param for CS:GO. 2018-12-06 20:18:21 -05:00
Nick Hastings
0b35c84bf0 Update CS:GO SDKTools and SDKHooks offsets. 2018-12-06 19:23:32 -05:00
Ruben Gonzalez
846a99e57f Merge branch 'master' of github.com:alliedmodders/sourcemod 2018-12-06 18:49:15 -05:00
Ruben Gonzalez
c28f957fb3 Update csgo gamedata part 1 2018-12-06 18:47:44 -05:00
peace-maker
f0aec6b0b6 Fix typo in fallback to "default" maplists section (#923)
When lookup of a more specialized entry in the maplists.cfg failed, it wouldn't fallback to the "default" section, but just try to parse the same section again.
2018-11-13 16:32:18 +00:00
Ruben Gonzalez
d79c5e0dfa Switch CS:GO Clantag set/get to use netprops + offset over sig + offset. (#922)
* Switch CS:GO Clantag set/get to use netprops + offset over sig+offset.

* Make sure the new functions are defined before using them...

* Fix offset name

* Fix incorrectly dereferencing.
2018-11-09 07:13:17 -05:00
Kyle Sanderson
cb8d92edeb
SDKHooks: Reset global hookid when unhooking in SH. (#916)
Fixes https://github.com/alliedmodders/sourcemod/issues/912
2018-10-28 11:06:57 -07:00
Asher Baker
db9925493a
Update game.empires.txt 2018-10-14 13:06:30 +01:00
peace-maker
1b795a70b0 Add GameData methodmap (#766) 2018-10-11 20:27:56 -07:00
Kruzya
ccfd2ffe38 Added sm_reload_databases (#773)
Added command sm_reload_databases for refreshing "registered" Databases Configurations cache.

Closes #772
2018-10-11 17:36:52 +01:00
Asher Baker
c1d235a59c
Use natural sorting for map lists (Fixes #892) (#907)
This produces consistently better results, especially for games such as L4D(2).
2018-10-11 15:20:10 +01:00
Asher Baker
b5320a4f8a
Add a note about FormatTime platform dependence (#908)
This has been another constant source of confusion since the C99 ones were added to the strftime documentation we link.

It'd be nice to have a consistent implementation inside SM in the future.
2018-10-11 11:07:07 +01:00
Asher Baker
a1271ec3a8
Handle NULLs in SDKCall string return (Fixes #874) (#906)
`SDKCall` has existing semantics that a `-1` retval indicates null, so use that and writes an empty string to the buffer.

Consumers can tell the difference between `""` and `NULL` by checking if the return value is `0` or `-1`.
2018-10-11 00:18:03 +01:00
Asher Baker
a659896f8a Revert "Use natural sorting for map lists (Fixes #892)"
This reverts commit a4e169aa8f.
2018-10-11 00:04:46 +01:00
Asher Baker
a4e169aa8f Use natural sorting for map lists (Fixes #892) 2018-10-11 00:03:34 +01:00
Asher Baker
7dd733cf46
Improve CreateNative failure message (#903)
This confuses everyone.
2018-10-10 13:35:17 +01:00
Ruben Gonzalez
6eb319f46e
Update CS:GO gamedata. (#904) 2018-10-09 20:18:53 -04:00
SlidyBat
3add38f665 Add additional TraceRay natives (#885)
* More TR natives

* Fix small typo

* Fix another typo

* Fix TR_AllSolid description

* Change Disp to Displacement

* Reorder params in TR_GetSurfaceName

* Fix TR_GetSurfaceName

* Another fix for TR_GetSurfaceName -_-

* Change if block to switch

* Make handle first param in TR_GetSurfaceName

* Reorder TR_GetStartPosition params

* Make TranslatePartitionFlags static

* Change tabs used for formatting to spaces

* Change inline comment style to be consistent with rest of file
2018-10-07 14:15:54 -07:00
Michael Flaherty
34e91fbd81 Restore SQL_CheckConfig Behavior (#873)
* Change lookup strategy for SQL_CheckConfig

* Ensure db conf lookup failures default to ..default

* Revert "Ensure db conf lookup failures default to ..default"

This reverts commit 03dc703daeeeadaa134e2160bf2c7cd812402758.
2018-10-07 14:08:11 -07:00
Michael Flaherty
a9ca1a2fd6
NPOTB: Clarify preprocessor logic (#900) 2018-10-05 04:22:29 -07:00
Michael Flaherty
a21c7564c1 [NMRiH] Gamedata update (Fixes #898) (#899) 2018-10-05 07:09:19 -04:00
Asher Baker
1ca4517f46 Revert "Remove arch loops from build scripts. (#889)"
This reverts commit 7ed329c11f.
2018-10-04 17:59:40 +00:00
Michael Flaherty
22b43e3869 Fix regression in vstk size (#894)
* Fix regression in vstk size

* Fix macro comment mistake

* More macro comment removals
2018-10-04 08:08:29 -04:00
Michael Flaherty
fc14e37d0f Fix CS_TerminateRound calls & detour (#893) 2018-10-03 22:50:31 -04:00
David Anderson
7ed329c11f
Remove arch loops from build scripts. (#889)
This simplifies non-sdk build scripts by removing their loops over SM.archs. Instead the top-level
build script will re-evaluate them for each architecture.
2018-09-30 09:59:28 -07:00
Michael Flaherty
6ad6abd319
Update sourcepawn submodule 2018-09-29 21:12:40 -07:00
SlidyBat
bece74491d NPOTB: Update sample extension params to be sourcehook-friendly (#886) 2018-09-22 21:55:05 -07:00
Michael Flaherty
990a02dbe0
Fix grammar error in File docs (#883) 2018-09-22 12:27:05 -07:00
Ruben Gonzalez
75193e9ee9
Add new weapons to CSWeaponID enum. (#869) 2018-09-12 10:13:39 -04:00
JoinedSenses
a5b22498ce Update to sm_ban, sm_kick, & sm_map in chat with no args to display menu (#838)
This change makes it so /kick, /ban, and /map open the already created methods for displaying their menus when there are no args.

The reason for the feature is to take advantage of menus that already exist and to make the commands easier to use.

The client == 0 check prevents them from opening if it was ran via rcon, sm_rcon, or server command. Client auth is also checked because its a registered admin command.

Usage params will display if client == 0 and args < min

For example, a moderator wants to change a map, instead of running through the admin menu, they can instead type just /map to display available maps and choose one.

If a mod wants to quickly ban or kick someone without having to either run through the admin menu or type it out, they could then type the corresponding commands with no args to open the menus.
2018-09-04 00:41:22 +01:00
Maxim Telezhenko
398522712e Add missing MarkNativeAsOptional for SetAuthIdCookie native (#879) 2018-09-01 00:19:48 +01:00
Asher Baker
caf0914289
Remove MAPLIST_FLAG_NO_DEFAULT misuses (#870)
These two base plugins are using the MAPLIST_FLAG_NO_DEFAULT when they shouldn't, which causes much user (and SM developer) confusion as it is completely counter to the documentation.
2018-08-19 12:41:53 +01:00
Michael Flaherty
17700e45b0
Fix SetClanTag CS:GO Windows Signature (#868) 2018-08-15 17:56:04 -07:00
Asher Baker
ba8b42ef1b
Burninate IDataPack (#864)
This doesn't break any extensions NOT using IDataPack, and we do not know of any that are.

* The extension storage utility of this interface has been broken for the last 9 months, with ISourceMod::CreateDataPack being disabled.
* The plugin interop utility of this interface (its stated purpose) has been broken for the last 11+ years, with ISourceMod::GetDataPackHandleType being disabled.

I imagine it only survived the first cleanup 11 years ago because CSS:DM was using it internally, which it has now been migrated away from.

Compiled all the included extensions without changes (API compat), and loaded extensions build pre-change without issue (ABI compat).
2018-08-13 23:03:48 +01:00
SlidyBat
144fb907f1 Add new Traceray natives (#754) 2018-08-13 23:02:12 +01:00
Asher Baker
e7c6b23439
Update blacklist.plugins.txt 2018-08-12 22:32:59 +01:00
Michael Flaherty
a65c215217 Fix DataPack Overwrite Regression (#862)
Some tests passed with the implementation prior to this commit, but those were edge cases. Good older behavior is now fully restored
2018-08-11 13:31:33 +01:00
peace-maker
7e3b1c395b Mark new methodmap natives as optional (#867)
The `TopMenu` methodmap natives weren't marked as optional if the extension was optional like the other normal natives.

The `Regex` natives weren't marked as optional at all before if the regex extension was included optionally.

This makes the error message cleaner in case topmenus aren't loaded.
```
adminmenu.smx (Admin Menu): Required extension "TopMenus" file("topmenus.ext") not running
basebans.smx (Basic Ban Commands): Native "TopMenu.Display" was not found
```
2018-08-06 20:11:01 +01:00
Nick Hastings
3511d2a44d Trigger build against hl2sdk-tf2 update. 2018-08-02 17:29:09 -04:00
ddhoward
beaf812909 Deprecate FormatUserLogText (#856)
Allow client index 0, too. (Console)
2018-07-31 19:19:18 -07:00
Michael Flaherty
7068c3e865
Fix LogStackTrace Anomaly (#863) 2018-07-31 04:17:36 -07:00
Kyle Sanderson
255b9323cc
Flip sm_debug_connect to "1" (#860) 2018-07-27 22:02:31 -07:00
hydrogen-mvm
d14c94c353 Add missing return value documentation (#854) 2018-07-26 18:33:22 -07:00
Michael Flaherty
11abe77eed
Allow any returns in native callbacks (#857) 2018-07-25 21:46:44 -07:00
hydrogen-mvm
7d8dfb09d8 Fix English style in CONTRIBUTING.md (#855) 2018-07-21 23:17:35 -06:00
Kyle Sanderson
3baa703256
NPOTB: Fix clang-3.9 failures with Travis-CI (#851)
fix clang-3.9 failures, maybe; hopefully. I forget why this was broken.
2018-07-17 13:07:55 -07:00
Kyle Sanderson
2b3159f418
NPOTB: Add Discord and IRC Server to README.md 2018-07-17 10:43:23 -07:00
Kyle Sanderson
72acca4b9e
Fix DataPack memory leak regression from #848. (#850)
* Fix memory leak regression from https://github.com/alliedmodders/sourcemod/pull/848.
2018-07-16 08:34:49 -07:00
Michael Flaherty
32d12ea4a6 Preserve old DataPack behavior when overwriting data (#848)
* Match old DataPack behavior when overwriting data

* Make RemoveItem more flexible

* Ditch implied RemoveItem behavior & asher fixes

* KyleS nits - but fixed before he says them

* Add back implicit behavior

* Update CDataPack.cpp

Committing to the spec.

* Update CDataPack.h

* fixup removing last item if explicitly requested

* Fix logic for accepting pack pos, rather than index

* Fixup IsReadable

* headache is over now
2018-07-14 17:00:17 -07:00
Ruben Gonzalez
e4862dade8 Update CS:GO mac64/linux64 gamedata. 2018-07-13 19:44:40 -04:00
Ruben Gonzalez
ed908b6545 Fix CS:GO weaponPrice offset. 2018-07-13 07:47:53 -04:00
KliPPy
a81b52a787 Add move semantics for StringHashMap (#589)
* Move semantics for StringHashMap

* style

* Update sm_stringhashmap.h
2018-07-12 11:25:22 -07:00
komashchenko
52cdbb4fc1 Fix sm_help erroring out if invoked during the connection process (#723)
* Fix "Exception reported: Client 12 is not in game"

* Fix

* Update adminhelp.sp
2018-07-12 11:18:57 -07:00
Kyle Sanderson
d0bf26135c
Collection of plugin cleanups (#777)
* Fix rockthevote not clearing g_Voted on fakeclients.

* remove g_RTVAllowed in rockthevote as it's unused.

* Fix basebans using the wrong forward for configs.

* Prevent sm_addban from banning an immune steam adminid.

* Sprinkle in IsChatTrigger checks to plugins with plaintext chat hooks.

* fixup g_Voted[client] in OnClientDisconnect
2018-07-12 11:16:18 -07:00
Nick Hastings
4f2bb62ff9 Enable radio menus for IOSoccer. 2018-07-10 20:19:36 -04:00
Michael Flaherty
28f1ea82b6 Add base CommandIterator implementation (#819)
* Add base CommandIterator implementation

* Add check for invalid pos & finalize pr
2018-07-10 17:39:31 -04:00
Michael Flaherty
aaac0b9eb2 Individualize NameHashSet Hashing & Revisit #709 (#740)
* Make mac/win lookups lowercase'd

* Revert #709 & 81042cc

* Adjust HashPolicy implementation across sourcemod

Basically, in order to implement our own (actual) hash policy in
`PluginSys.h`, we needed to remove the blanket implementation of `hash`
that was used before. Now, each policy must implement `hash` along with
`matches` in order to be used with `NameHashSet`. While this does force
us to change every implementation of policies across the entirety of
sourcemod, it allows core to use flexible implementations of `hash`.

* Remove logic duplication

* Improve lowercase checks
2018-07-10 17:38:40 -04:00
Alfred Llagas
daee19d502 Changed "entiy" to "entity" in IsEntNetworkable (#847)
* Changed "entiy" to "entity" in IsEntNetworkable

* Update entity.inc
2018-07-08 11:11:35 -04:00
Mattia
70145dfd74 Make SQL_QuoteString deprecated (#792)
* Make SQL_QuoteString deprecated

* Fix message
2018-07-08 11:06:06 -04:00
Michael Flaherty
c09b32010f Add Profiler methodmap (#814)
* Add profiler methodmap

* No tag mismatches here

thanks pm

* Lets fix some documentation while we're here.

* Use proper methodmap documentation style

Across sm we use `//` for methodmap docs, so lets just keep this consistent
2018-07-08 11:05:29 -04:00
Mattia
85a1d3e78a "sound" folder instead "sounds" (#790)
The folder is actually "sound" and not "sounds"
2018-07-08 11:04:20 -04:00
Nick Hastings
a9c9da1066 Update SDKTools sound functionality for hl2sdk-csgo changes. 2018-07-07 08:57:00 -04:00
Nick Hastings
2860f31cb0 Trigger build for hl2sdk-csgo update. 2018-07-06 20:54:36 -04:00
Ruben Gonzalez
54cf1337c1 Merge branch 'master' of github.com:alliedmodders/sourcemod 2018-07-06 19:18:44 -04:00
Ruben Gonzalez
dcde5927b1 Update SetClanTag signature 2018-07-06 19:18:14 -04:00
Nick Hastings
c458d1e600 Trigger build for hl2sdk-csgo update. 2018-07-06 19:08:58 -04:00
Mr. Silence
aae7161273 Updated some offsets and all signatures for ZPS. (#839)
Signed-off-by: Mr.Silence <Silenci0@users.noreply.github.com>
2018-06-27 17:15:27 -04:00
Nick Hastings
6287774d69 Update SDKTools gamedata for IOSoccer (fixes #833). 2018-06-22 16:30:22 -04:00
voed
dc4d597fb9 Add link to SourceMod plugin API reference in project readme (#830) 2018-06-22 08:08:00 -06:00
Michael Flaherty
9ceb1af4fe Add LogStackTrace native (#685) 2018-06-19 23:18:37 -07:00
Michael Flaherty
b9b6832a11 Streamline ConfDb loading proceedure (#791)
* Create DatabaseConfBuilder & remove locking
* Remove all refcounting

This is part 1/n in regards to this PR's rework
* Move db conf lookup out of RunThreadPart
* Return default configuration for failed lookups
* RefPtr members & stop leaks
* fix uint comparison warning
2018-06-19 09:35:37 -07:00
Nick Hastings
53c63def07 Use env vars to find MySQL src on Linux, macOS. 2018-06-07 20:40:14 -04:00
Asher Baker
4f70185aef Fix amtl submodule pin 2018-06-05 19:06:04 +01:00
peace-maker
6fcb411fe4 MySQL: Support multiple result sets in prepared queries (#825)
Prepared statements can return multiple result sets since MySQL 5.5. That can happen when calling stored procedures using `CALL x();`.

This change removes the previous caching of result bindings, since the number of fields in a result can differ from result set to result set. This could potentially have a negative impact on prepared statements always only returning one result set, since the result binding buffers are recreated everytime the statement is executed instead of once. That difference should be negligible.

Fixes #823.
2018-06-05 18:33:33 +01:00
peace-maker
9cc518e408 Fix MySQL extension build using vs2015 (#824)
MySQL defines its own timespec_t. Official mysql builds are built using VS2013, so you still need to compile the client library yourself to be able to link it, but this change makes the dbi extension compatible with future versions already.
2018-06-05 09:29:11 -04:00
Nick Hastings
ddebc2a075 Fix oops with SetConVarBounds. 2018-06-03 12:36:58 -04:00
David Anderson
fe6abb0c48
Merge pull request #822 from alliedmodders/update-sourcepawn
Update SourcePawn.
2018-05-31 23:32:51 -07:00
David Anderson
90e66cbeef Update SourcePawn. 2018-05-31 23:13:36 -07:00
David Anderson
487e01e4ed
Merge pull request #821 from alliedmodders/update-amtl
Update AMTL.
2018-05-31 21:44:09 -07:00
David Anderson
25b3d8f354 Update AMTL. 2018-05-31 21:23:59 -07:00
Ruben Gonzalez
d430bd2f5c
Fix CompileRegex not actually setting a valid error code. (#775)
Fix CompileRegex not actually setting a valid error code.
2018-05-28 13:59:43 -04:00
Ruben Gonzalez
e2767a3c80
Remove goto from ExtensionSys.cpp (#729) 2018-05-25 09:49:10 -04:00
RumbleFrog
7f552e4d75 Deprecate GetMaxClients (#818) 2018-05-23 12:58:36 +01:00
Nick Hastings
cbcda61135 Swap _XKEYCHECK_H for _ALLOW_KEYWORD_MACROS, in case it moves to a
different header.
2018-05-21 19:54:12 -04:00
jason-e
2904c87b62 Send ShowActivity messages to TV clients (#813)
`ShowActivity` and related functions are used to inform all clients about the usage of admin commands (such as bans or mutes). These messages are not sent to any fake clients, however they _should_ be sent to SourceTV/GOTV fake clients because messages they receive are actually visible to broadcast viewers and in demos recorded with `tv_record`. 

Player chat messages as well as SM functions like `PrintToChat`/`PrintToChatAll` broadcast to TV clients, but `ShowActivity` does not.
2018-05-09 09:13:49 +01:00
Nick Hastings
cfdedce362 Missed converting a GetFlags instance. 2018-05-06 13:18:04 -04:00
Nick Hastings
467d57059a Out with the old ConVar accessibility hacks, in with the new. 2018-05-06 12:59:33 -04:00
Nick Hastings
c993712438 Update BM:S gamedata. 2018-05-06 12:17:47 -04:00
Nick Hastings
a69d18ae1c Fix warning/error on newer Clang versions from abort not being defined. 2018-05-06 10:28:24 -04:00
Nick Hastings
95dae67d5b Fix wrong matchmaking_ds bin path being used in some instances. 2018-05-06 10:26:43 -04:00
Nick Hastings
f6a64da672 Update Insurgency FireOutput gamedata. 2018-05-05 11:35:06 -04:00
Nick Hastings
11b23a6d07 Update ConVar hacks for BMS.
This is also to trigger an MM:S build for hl2sdk changes in multiple branches.
2018-05-05 11:01:55 -04:00
Spirrwell
82f1c5a20b Update Function Offsets For PVKII (#808)
* Update Function Offsets For PVKII

-Updates offsets
-Removes "Reload" as no corresponding function actually exists

* Offset Fixes

-Re-add "Reload" as it's defined for CBaseCombatWeapon
-Fix Linux\Mac offsets for GroundEntChanged
2018-05-01 20:28:54 -04:00
404
7e080d259e Update helpers.inc (#805)
Update GetClientAuthString to GetClientAuthId
2018-04-28 11:18:12 +01:00
Kyle Sanderson
1ab6ab1e5c
NPOTB: Add basic issue template for new GH issues. 2018-04-05 22:20:49 -07:00
Nick Hastings
b0e7bab980 Merge branch 'master' of https://github.com/alliedmodders/sourcemod 2018-03-28 21:11:14 -04:00
Nick Hastings
9b8d28de56 Allow -1/null for attacker and inflictor for OTD (bug 6494). 2018-03-28 21:10:32 -04:00
Michael Flaherty
5611ec54a2 Migrate extensions to common AMTL string funcs (#785) 2018-03-25 13:00:53 -07:00
Hexah
6c7e29cbdb Documentation fixes from methodmap implementation (#788)
* There is no "menu" param

* No "menu" param on GetTitle()

* Misspell "Replies"
2018-03-25 12:58:11 -07:00
Michael Flaherty
118d6dc9b1 Improve error message for EmitSound (#787)
Improve some error messages in sdktools.
2018-03-20 19:42:43 -06:00
Nicholas Hastings
08fe840bfd Probably fix Windows build. 2018-03-20 17:25:48 -04:00
Nicholas Hastings
4637cf9221
Use MySQL 5.5 for MySQL extension. (#786) 2018-03-20 17:12:30 -04:00
Joël Troch
4fd68939d3 [ZPS] Update gamedata and engine migration (#782)
* Migrate ZPS from EP2 to SDK 2013 engine

* Update ZPS gamedata (for version 3.0.7-Hotfix3)
2018-03-19 19:19:01 -04:00
peace-maker
be6a930e82 Update SQLite to version 3.22.0 (#783)
This includes numerous bug fixes, optimizations and new features from releases over the past 5 years.

http://sqlite.org/chronology.html
2018-03-19 19:09:12 -04:00
Michael Flaherty
956f264b85 Replace ke::SafeSprintf with ke::SafeStrcpy (#784) 2018-03-19 20:12:51 +00:00
Nicholas Hastings
0a91b1f5b1 Increase MAX_NAME_LENGTH to match CS:GO MAX_PLAYER_NAME_LENGTH. 2018-02-25 10:51:18 -05:00
Nicholas Hastings
a17b47a2dc Add Protobuf.HasField native. 2018-02-25 10:49:37 -05:00
Michael Flaherty
2a8c390498 Un-const string retrievals (#769) 2018-02-20 18:38:17 +00:00
Asher Baker
41ffe975fd
Update blacklist.plugins.txt 2018-02-15 22:35:56 +00:00
Ruben Gonzalez
5ac3390656
Add new regex natives. (#767)
Add new regex natives to get multiple/all matches.
2018-02-15 15:31:24 -05:00
peace-maker
f9faf9e48c Allow different values per platform in "Keys" gamedata section (#765)
This adds support for platform specific custom key values in the `Keys` section in game config files. Now you can have different values for the same key per platform.

Previously you could only add general key values in gamedata files that were the same on all platforms like
```
"Keys"
{
	"key"	"value"
}
```

This patch allows you to set the value per platform in a subsection like
```
"Keys"
{
	"key"
	{
		"windows"	"value1"
		"linux"	"value2"
		"mac"	"value3"
	}
}
```

Looking up the `key` will return the value matching the host platform.
2018-02-06 14:40:51 +00:00
Michael Flaherty
e57dce76e1 Add support for msvc 1912 (Fixes #761) (#764)
* Add support for msvc 1912

* Default new msvc versions to VS 2017

* Use 2015 lib with 2017
2018-02-04 17:06:22 -05:00
Michael Flaherty
64a6972757 Fix description for CharToLower and CharToUpper v2 (#750) 2018-02-02 23:30:12 +00:00
StrangeThings
1293d15f72 Remove the @brief tag in sdktools_hooks.inc (#759) 2018-02-02 23:28:20 +00:00
Michael Flaherty
12fca79006 Prevent use of primitive float operation functions (#763)
Apparently people use the float natives for actual float arithmetic; they're not really intended to be used directly.

* Prevent use of primitive float operation functions
* Deprecate float operation functs
* Alias Float natives to internal names
* Add clarifying note
* Remove use of internal FloatDiv native
2018-02-02 23:27:38 +00:00
thewavelength
55b8371fa8 Add VS Preview 2017 as valid compiler (msvc-1911) (#678) 2018-01-28 11:39:23 +00:00
peace-maker
a8080c0bbb Fix description of nominations convars (#758) 2018-01-27 12:00:04 +00:00
JRiipinen
8c61fdc99d Add more TF2 specific DMG_ definitions (#756)
* Add more TF2 DMG_ definitions

* Guard them all

* Inline doccomments
2018-01-26 14:06:54 +00:00
Nicholas Hastings
9374620b8b
Add RemoveEntity native. (bug 5714) (#745) 2018-01-07 13:52:36 -05:00
Ruben Gonzalez
5a35760215
Merge pull request #744 from alliedmodders/show-required-exts
Address issue #737
2017-12-31 11:06:35 -05:00
Alex
6b257de75a Add internationalization to basechat and fix CS:GO colours (#674)
* Added translation more to basechat

Also fixed colors, because it didn't work without `\x01` at begin of string.

* Fixed cs:go colors, thanks Bara20

* Added 'space' at the start of string.

* Added check for Engine_CSGO, to remove offset on other games

* forgot one row
2017-12-30 12:25:32 -08:00
Ruben Gonzalez
40356fc9db Address issue #737 2017-12-30 14:08:56 -05:00
Kyle Sanderson
de108cca44
Simplify Logger internals (Fixes Issue #663). (#691)
* Simplify Logger internals (Issue #663).

* Avoid reformatting strings on every call.
2017-12-29 19:56:25 -08:00
Kyle Sanderson
5f5a6b3a16
Migrate CDataPack from a Compact Cassette tape. (#688)
* Migrate CDataPack from a Cassette Tape.

Tested-By: Headline22.

* Remove last IsReadable param pass.

* populate len still if CDataPack::ReadString is unreadable or the wrong type.

* Fyren Fixes(TM)(R)(C).

* Deprecate IDataPack.
2017-12-29 19:56:02 -08:00
Nicholas Hastings
29b1926432 A couple of fixups to last commit (NPOTB). 2017-12-29 04:55:56 -08:00
Nicholas Hastings
e0a154faa0 Add TF2 NextBot symbol data from Pelipoka to GDC (NPOTB). 2017-12-29 04:38:47 -08:00
Byte
1706fdfed9 Fix typo and update CSGOBadList (#738)
* Fix typo

* Update CSGOBadList
2017-12-28 18:43:49 -05:00
Byte
945df342d8 Fix typo in SwitchTeam Linux Signature (#743) 2017-12-28 17:39:30 -05:00
Scott Ehlert
bfb11c7712
Remove extra CS:GO Mac offset for GetItemInLoadout 2017-12-20 04:17:29 -06:00
Scott Ehlert
fa7d8757dc Rebuild 64-bit Linux libpcre with -Wa,-mrelax-relocations=no 2017-12-20 03:50:12 -06:00
Scott Ehlert
3c7978153b Rebuild 64-bit Linux libpcre with -fPIC. 2017-12-20 03:15:57 -06:00
Scott Ehlert
7cb3d4d8ff Fix Linux and macOS builds. 2017-12-20 02:13:56 -06:00
Scott Ehlert
870e118150 Fix BreakpadSymbols script for 64-bit builds. 2017-12-20 02:07:30 -06:00
Scott Ehlert
e27f8fba1a Hopefully fix Windows build. 2017-12-20 02:04:05 -06:00
Scott Ehlert
ce1a4dcac0
64-bit support for CSGO on Linux and macOS (#705) 2017-12-20 01:56:23 -06:00
Scott Ehlert
057a5790e2 Update CS:GO TerminateRound signature for Linux. 2017-12-19 23:23:29 -06:00
Nicholas Hastings
87858ef264 Test build. 2017-12-18 21:00:04 -05:00
Nicholas Hastings
98fea02eaa Roll version. >_> 2017-12-18 20:39:57 -05:00
279 changed files with 152499 additions and 47845 deletions

12
.gitattributes vendored Normal file
View File

@ -0,0 +1,12 @@
# GitHub views all .h files as C, let's assume it's C++
*.h linguist-language=c++
# Internal tools overriding
tools/* linguist-vendored
editor/* linguist-vendored
# Third-party overriding
extensions/curl/curl-src/* linguist-vendored
extensions/geoip/GeoIP.c linguist-vendored
extensions/geoip/GeoIP.h linguist-vendored
extensions/sqlite/sqlite-source/* linguist-vendored

View File

@ -7,17 +7,17 @@ Please consider the following guidelines when reporting an issue.
#### Not for general support #### Not for general support
This is not the right place to get help with using or installing SourceMod, or for issues with specific, third-party SourceMod plugins or extensions. This is not the right place to get help with using or installing SourceMod, or for issues with specific, third-party SourceMod plugins or extensions.
For help with SourceMod, please consult the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52). Similary, for assistance with, or to report issues with third-party SourceMod plugins or extension, you should post in the existing thread for the plugin or extension at the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52). For help with SourceMod, please consult the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52). Similarly, for assistance with, or to report issues with, third-party SourceMod plugins or extensions, you should post in the existing thread for that plugin or extension on the [AlliedModders forums](https://forums.alliedmods.net/forumdisplay.php?f=52).
#### Details, details, details #### Details, details, details
Provide as much detail as possible when reporting an issue. Provide as much detail as possible when reporting an issue.
For bugs or other undesired behavior, answers to the follow questions are a great start. For bugs or other undesired behavior, answers to the following questions are a great start:
* What is the issue? * What is the issue?
* What behavior are you expecting instead? * What behavior are you expecting instead?
* On what operating system is the game server running? * On what operating system is the game server running?
* What game is the game server running? * What game is the game server running?
* What exact (full x.y.z.a version number) version of Metamod:Source and SourceMod are installed on the game server? * What exact version (full x.y.z.a version number) of Metamod:Source and SourceMod are installed on the game server?
* What is the specific, shortest path to reproducing this issue? If this issue can be reproduced with plugin code, please try to shorten it to the minimum required to trigger the problem. * What is the specific, shortest path to reproducing this issue? If this issue can be reproduced with plugin code, please try to shorten it to the minimum required to trigger the problem.
If this is a feature request, the following are helpful. Generally, not all will apply, but whatever you can answer ahead of time will shorten back and forth conversation. If this is a feature request, the following are helpful. Generally, not all will apply, but whatever you can answer ahead of time will shorten back and forth conversation.
@ -29,18 +29,18 @@ If this is a feature request, the following are helpful. Generally, not all will
Please report any security bugs to [security@alliedmods.net](mailto:security@alliedmods.net) rather than to this public issue tracker. Please report any security bugs to [security@alliedmods.net](mailto:security@alliedmods.net) rather than to this public issue tracker.
#### We're only human #### We're only human
Please keep in mind that we maintain the project in our spare time, at no cost. There is no SLA, and you are not owed a response or fix. Please keep in mind that we maintain this project in our spare time, at no cost. There is no SLA, and you are not owed a response or a fix.
#### Conduct #### Conduct
Please refer to the [AlliedModders forum rules.](https://forums.alliedmods.net/misc.php?do=showrules) Please refer to the [AlliedModders forum rules.](https://forums.alliedmods.net/misc.php?do=showrules)
## Pull Requests ## Pull Requests
Firstly, thank you for considering to contribute changes to the project! Firstly, thank you for considering contributing changes to the project!
However, if this is anything more than a small fix such an a gamedata update, a glaring code flaw, or a simple typo in a file like this one, please file an issue first so that it can be discussed, unless you have already spoken to multiple members of the development team about it on IRC or the AlliedModders forums. However, if this is anything more than a small fix such as a gamedata update, a glaring code flaw, or a simple typo in a file like this one, please file an issue first so that it can be discussed, unless you have already spoken to multiple members of the development team about it on IRC or the AlliedModders forums.
We don't like to have to reject pull requests, so we want to avoid those scenarios. We wouldn't want you to feel that you wasted your time writing something only for us to have it then be shot down. We don't like to have to reject pull requests, so we want to avoid those scenarios. We wouldn't want you to feel like you wasted your time writing something only for us to shoot it down.
#### Rejection #### Rejection
*Copied from Phabricator's [Contributing Code guidelines](https://secure.phabricator.com/book/phabcontrib/article/contributing_code/#rejecting-patches), as we largely feel the same way about this.* *Copied from Phabricator's [Contributing Code guidelines](https://secure.phabricator.com/book/phabcontrib/article/contributing_code/#rejecting-patches), as we largely feel the same way about this.*

8
.github/FUNDING.yml vendored Normal file
View File

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

26
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

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

View File

@ -9,6 +9,7 @@ addons:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-3.9
- llvm-toolchain-trusty-4.0 - llvm-toolchain-trusty-4.0
- llvm-toolchain-trusty-5.0 - llvm-toolchain-trusty-5.0
packages: packages:
@ -23,6 +24,7 @@ addons:
# - clang-5.0 # - clang-5.0
# - g++-6 # - g++-6
# - g++-6-multilib # - g++-6-multilib
- clang-3.9
- g++-4.8-multilib - g++-4.8-multilib
- g++-4.8 - g++-4.8
- g++-4.9-multilib - g++-4.9-multilib
@ -112,5 +114,5 @@ script:
- mkdir build && cd build - mkdir build && cd build
- PATH="~/.local/bin:$PATH" - PATH="~/.local/bin:$PATH"
- eval "${MATRIX_EVAL}" - eval "${MATRIX_EVAL}"
- python ../configure.py --enable-optimize --sdks=episode1,tf2,l4d2,csgo,dota - python ../configure.py --enable-optimize --sdks=episode1,css,tf2,l4d2,csgo,dota
- ambuild - ambuild

View File

@ -11,10 +11,29 @@ class SDK(object):
self.platform = platform self.platform = platform
self.name = dir self.name = dir
self.path = None # Actual path self.path = None # Actual path
self.platformSpec = platform
# By default, nothing supports x64.
if type(platform) is list:
self.platformSpec = {p: ['x86'] for p in platform}
else:
self.platformSpec = platform
def shouldBuild(self, target, archs):
if target.platform not in self.platformSpec:
return False
if not len([i for i in self.platformSpec[target.platform] if i in archs]):
return False
return True
WinOnly = ['windows'] WinOnly = ['windows']
WinLinux = ['windows', 'linux'] WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac'] WinLinuxMac = ['windows', 'linux', 'mac']
CSGO = {
'windows': ['x86'],
'linux': ['x86', 'x64'],
'mac': ['x64']
}
PossibleSDKs = { PossibleSDKs = {
'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'), 'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
@ -31,7 +50,7 @@ PossibleSDKs = {
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'), 'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'),
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'), 'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'), 'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', WinLinux, 'csgo'), 'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, 'csgo'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'), 'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'),
'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'), 'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'),
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'), 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
@ -60,6 +79,28 @@ def ResolveEnvPath(env, folder):
def Normalize(path): def Normalize(path):
return os.path.abspath(os.path.normpath(path)) return os.path.abspath(os.path.normpath(path))
def SetArchFlags(compiler, arch, platform):
if compiler.behavior == 'gcc':
if arch == 'x86':
compiler.cflags += ['-m32']
compiler.linkflags += ['-m32']
if platform == 'mac':
compiler.linkflags += ['-arch', 'i386']
elif arch == 'x64':
compiler.cflags += ['-m64', '-fPIC']
compiler.linkflags += ['-m64']
if platform == 'mac':
compiler.linkflags += ['-arch', 'x86_64']
elif compiler.like('msvc'):
if builder.target.arch == 'x86':
compiler.linkflags += ['/MACHINE:X86']
elif builder.target.arch == 'x64':
compiler.linkflags += ['/MACHINE:X64']
def AppendArchSuffix(binary, name, arch):
if arch == 'x64':
binary.localFolder = name + '.x64'
class SMConfig(object): class SMConfig(object):
def __init__(self): def __init__(self):
@ -68,10 +109,12 @@ class SMConfig(object):
self.extensions = [] self.extensions = []
self.generated_headers = None self.generated_headers = None
self.mms_root = None self.mms_root = None
self.mysql_root = None self.mysql_root = {}
self.spcomp = None self.spcomp = None
self.spcomp_bins = None
self.smx_files = {} self.smx_files = {}
self.versionlib = None self.versionlib = None
self.archs = builder.target.arch.replace('x86_64', 'x64').split(',')
def use_auto_versioning(self): def use_auto_versioning(self):
if builder.backend != 'amb2': if builder.backend != 'amb2':
@ -105,7 +148,7 @@ class SMConfig(object):
for sdk_name in PossibleSDKs: for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name] sdk = PossibleSDKs[sdk_name]
if builder.target.platform in sdk.platform: if sdk.shouldBuild(builder.target, self.archs):
if builder.options.hl2sdk_root: if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder) sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
else: else:
@ -118,8 +161,9 @@ class SMConfig(object):
sdk.path = Normalize(sdk_path) sdk.path = Normalize(sdk_path)
self.sdks[sdk_name] = sdk self.sdks[sdk_name] = sdk
if len(self.sdks) < 1: if len(self.sdks) < 1 and len(sdk_list):
raise Exception('At least one SDK must be available.') raise Exception('No SDKs were found that build on {0}-{1}, nothing to do.'.format(
builder.target.platform, builder.target.arch))
if builder.options.mms_path: if builder.options.mms_path:
self.mms_root = builder.options.mms_path self.mms_root = builder.options.mms_path
@ -136,20 +180,39 @@ class SMConfig(object):
if builder.options.hasMySql: if builder.options.hasMySql:
if builder.options.mysql_path: if builder.options.mysql_path:
self.mysql_root = builder.options.mysql_path self.mysql_root['x86'] = builder.options.mysql_path
else: else:
for i in range(7): for i in range(10):
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i)) self.mysql_root['x86'] = ResolveEnvPath('MYSQL55', 'mysql-5.' + str(i))
if self.mysql_root: if self.mysql_root['x86']:
break break
if not self.mysql_root or not os.path.isdir(self.mysql_root): if not self.mysql_root['x86'] or not os.path.isdir(self.mysql_root['x86']):
raise Exception('Could not find a path to MySQL!') raise Exception('Could not find a path to MySQL!')
self.mysql_root = Normalize(self.mysql_root) self.mysql_root['x86'] = Normalize(self.mysql_root['x86'])
# For now, ignore 64-bit MySQL on Windows
if 'x64' in self.archs and builder.target.platform != 'windows':
if builder.options.mysql64_path:
self.mysql_root['x64'] = builder.options.mysql64_path
else:
for i in range(10):
self.mysql_root['x64'] = ResolveEnvPath('MYSQL55_64', 'mysql-5.' + str(i) + '-x86_64')
if self.mysql_root['x64']:
break
if not self.mysql_root['x64'] or not os.path.isdir(self.mysql_root['x64']):
raise Exception('Could not find a path to 64-bit MySQL!')
self.mysql_root['x64'] = Normalize(self.mysql_root['x64'])
def configure(self): def configure(self):
builder.AddConfigureFile('pushbuild.txt') builder.AddConfigureFile('pushbuild.txt')
if not set(self.archs).issubset(['x86', 'x64']):
raise Exception('Unknown target architecture: {0}'.format(builder.target.arch))
cxx = builder.DetectCxx() cxx = builder.DetectCxx()
if cxx.like('msvc') and len(self.archs) > 1:
raise Exception('Building multiple archs with MSVC is not currently supported')
if cxx.like('gcc'): if cxx.like('gcc'):
self.configure_gcc(cxx) self.configure_gcc(cxx)
@ -200,12 +263,11 @@ class SMConfig(object):
'-pipe', '-pipe',
'-fno-strict-aliasing', '-fno-strict-aliasing',
'-Wall', '-Wall',
# '-Werror', '-Werror',
'-Wno-unused', '-Wno-unused',
'-Wno-switch', '-Wno-switch',
'-Wno-array-bounds', '-Wno-array-bounds',
'-msse', '-msse',
'-m32',
'-fvisibility=hidden', '-fvisibility=hidden',
] ]
cxx.cxxflags += [ cxx.cxxflags += [
@ -216,7 +278,6 @@ class SMConfig(object):
'-Wno-overloaded-virtual', '-Wno-overloaded-virtual',
'-fvisibility-inlines-hidden', '-fvisibility-inlines-hidden',
] ]
cxx.linkflags += ['-m32']
have_gcc = cxx.family == 'gcc' have_gcc = cxx.family == 'gcc'
have_clang = cxx.family == 'clang' have_clang = cxx.family == 'clang'
@ -234,7 +295,8 @@ class SMConfig(object):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if cxx.version >= 'gcc-4.8': if cxx.version >= 'gcc-4.8':
cxx.cflags += ['-Wno-unused-result'] cxx.cflags += ['-Wno-unused-result']
if cxx.version >= 'gcc-9.0':
cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned']
if have_clang: if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
@ -271,7 +333,6 @@ class SMConfig(object):
'/TP', '/TP',
] ]
cxx.linkflags += [ cxx.linkflags += [
'/MACHINE:X86',
'kernel32.lib', 'kernel32.lib',
'user32.lib', 'user32.lib',
'gdi32.lib', 'gdi32.lib',
@ -310,7 +371,6 @@ class SMConfig(object):
cxx.cflags += ['-mmacosx-version-min=10.5'] cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [ cxx.linkflags += [
'-mmacosx-version-min=10.5', '-mmacosx-version-min=10.5',
'-arch', 'i386',
'-lstdc++', '-lstdc++',
'-stdlib=libstdc++', '-stdlib=libstdc++',
] ]
@ -319,7 +379,7 @@ class SMConfig(object):
def configure_windows(self, cxx): def configure_windows(self, cxx):
cxx.defines += ['WIN32', '_WINDOWS'] cxx.defines += ['WIN32', '_WINDOWS']
def AddVersioning(self, binary): def AddVersioning(self, binary, arch):
if builder.target.platform == 'windows': if builder.target.platform == 'windows':
binary.sources += ['version.rc'] binary.sources += ['version.rc']
binary.compiler.rcdefines += [ binary.compiler.rcdefines += [
@ -335,45 +395,51 @@ class SMConfig(object):
'-current_version', self.productVersion '-current_version', self.productVersion
] ]
if self.use_auto_versioning(): if self.use_auto_versioning():
binary.compiler.linkflags += [self.versionlib] binary.compiler.linkflags += [self.versionlib[arch]]
binary.compiler.sourcedeps += SM.generated_headers binary.compiler.sourcedeps += SM.generated_headers
return binary return binary
def LibraryBuilder(self, compiler, name): def LibraryBuilder(self, compiler, name, arch):
binary = compiler.Library(name) binary = compiler.Library(name)
self.AddVersioning(binary) AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
if binary.compiler.like('msvc'): if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS'] binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
return binary return binary
def ProgramBuilder(self, compiler, name): def ProgramBuilder(self, compiler, name, arch):
binary = compiler.Program(name) binary = compiler.Program(name)
self.AddVersioning(binary) AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
if '-static-libgcc' in binary.compiler.linkflags: if '-static-libgcc' in binary.compiler.linkflags:
binary.compiler.linkflags.remove('-static-libgcc') binary.compiler.linkflags.remove('-static-libgcc')
if '-lgcc_eh' in binary.compiler.linkflags: if '-lgcc_eh' in binary.compiler.linkflags:
binary.compiler.linkflags.remove('-lgcc_eh') binary.compiler.linkflags.remove('-lgcc_eh')
if binary.compiler.like('gcc'): if binary.compiler.like('gcc'):
binary.compiler.linkflags += ['-lstdc++'] binary.compiler.linkflags += ['-lstdc++', '-lpthread']
if binary.compiler.like('msvc'): if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE'] binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE']
return binary return binary
def StaticLibraryBuilder(self, compiler, name): def StaticLibraryBuilder(self, compiler, name, arch):
binary = compiler.StaticLibrary(name) binary = compiler.StaticLibrary(name)
AppendArchSuffix(binary, name, arch)
return binary; return binary;
def Library(self, context, name): def Library(self, context, name, arch):
compiler = context.cxx.clone() compiler = context.cxx.clone()
return self.LibraryBuilder(compiler, name) SetArchFlags(compiler, arch, builder.target.platform)
return self.LibraryBuilder(compiler, name, arch)
def Program(self, context, name): def Program(self, context, name, arch):
compiler = context.cxx.clone() compiler = context.cxx.clone()
return self.ProgramBuilder(compiler, name) SetArchFlags(compiler, arch, builder.target.platform)
return self.ProgramBuilder(compiler, name, arch)
def StaticLibrary(self, context, name): def StaticLibrary(self, context, name, arch):
compiler = context.cxx.clone() compiler = context.cxx.clone()
return self.StaticLibraryBuilder(compiler, name) SetArchFlags(compiler, arch, builder.target.platform)
return self.StaticLibraryBuilder(compiler, name, arch)
def ConfigureForExtension(self, context, compiler): def ConfigureForExtension(self, context, compiler):
compiler.cxxincludes += [ compiler.cxxincludes += [
@ -386,13 +452,15 @@ class SMConfig(object):
] ]
return compiler return compiler
def ExtLibrary(self, context, name): def ExtLibrary(self, context, name, arch):
binary = self.Library(context, name) binary = self.Library(context, name, arch)
self.ConfigureForExtension(context, binary.compiler) self.ConfigureForExtension(context, binary.compiler)
return binary return binary
def ConfigureForHL2(self, binary, sdk): def ConfigureForHL2(self, binary, sdk, arch):
compiler = binary.compiler compiler = binary.compiler
SetArchFlags(compiler, arch, builder.target.platform)
compiler.cxxincludes += [ compiler.cxxincludes += [
os.path.join(self.mms_root, 'core'), os.path.join(self.mms_root, 'core'),
@ -435,6 +503,9 @@ class SMConfig(object):
else: else:
compiler.defines += ['COMPILER_GCC'] compiler.defines += ['COMPILER_GCC']
if arch == 'x64':
compiler.defines += ['X64BITS', 'PLATFORM_64BITS']
# For everything after Swarm, this needs to be defined for entity networking # For everything after Swarm, this needs to be defined for entity networking
# to work properly with sendprop value changes. # to work properly with sendprop value changes.
if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']: if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']:
@ -446,6 +517,7 @@ class SMConfig(object):
if sdk.name == 'csgo' and builder.target.platform == 'linux': if sdk.name == 'csgo' and builder.target.platform == 'linux':
compiler.linkflags += ['-lstdc++'] compiler.linkflags += ['-lstdc++']
compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
for path in paths: for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)] compiler.cxxincludes += [os.path.join(sdk.path, *path)]
@ -455,16 +527,20 @@ class SMConfig(object):
lib_folder = os.path.join(sdk.path, 'linux_sdk') lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name in ['sdk2013', 'bms']: elif sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
elif arch == 'x64':
lib_folder = os.path.join(sdk.path, 'lib', 'linux64')
else: else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux') lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target.platform == 'mac': elif builder.target.platform == 'mac':
if sdk.name in ['sdk2013', 'bms']: if sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
elif arch == 'x64':
lib_folder = os.path.join(sdk.path, 'lib', 'osx64')
else: else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac') lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target.platform in ['linux', 'mac']: if builder.target.platform in ['linux', 'mac']:
if sdk.name in ['sdk2013', 'bms']: if sdk.name in ['sdk2013', 'bms'] or arch == 'x64':
compiler.postlink += [ compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')), compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a')) compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
@ -476,12 +552,17 @@ class SMConfig(object):
] ]
if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']: if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))] if arch == 'x64':
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces.a'))]
else:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
dynamic_libs = [] dynamic_libs = []
if builder.target.platform == 'linux': if builder.target.platform == 'linux':
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']: if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so'] dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
elif arch == 'x64' and sdk.name == 'csgo':
dynamic_libs = ['libtier0_client.so', 'libvstdlib_client.so']
elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo']: elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo']:
dynamic_libs = ['libtier0.so', 'libvstdlib.so'] dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else: else:
@ -512,20 +593,21 @@ class SMConfig(object):
return binary return binary
def HL2Library(self, context, name, sdk): def HL2Library(self, context, name, sdk, arch):
binary = self.Library(context, name) binary = self.Library(context, name, arch)
self.ConfigureForExtension(context, binary.compiler) self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(binary, sdk) return self.ConfigureForHL2(binary, sdk, arch)
def HL2Project(self, context, name): def HL2Project(self, context, name):
project = context.cxx.LibraryProject(name) project = context.cxx.LibraryProject(name)
self.ConfigureForExtension(context, project.compiler) self.ConfigureForExtension(context, project.compiler)
return project return project
def HL2Config(self, project, name, sdk): def HL2Config(self, project, name, sdk, arch):
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name)) binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
self.AddVersioning(binary) AppendArchSuffix(binary, name, arch)
return self.ConfigureForHL2(binary, sdk) self.AddVersioning(binary, arch)
return self.ConfigureForHL2(binary, sdk, arch)
SM = SMConfig() SM = SMConfig()
SM.detectProductVersion() SM.detectProductVersion()
@ -548,10 +630,15 @@ SP = builder.Build('sourcepawn/AMBuildScript', {
'external_amtl': os.path.join(builder.sourcePath, 'public', 'amtl'), 'external_amtl': os.path.join(builder.sourcePath, 'public', 'amtl'),
'external_build': ['core'], 'external_build': ['core'],
}) })
SM.spcomp = SP.spcomp if len(SP.spcomp) > 1:
SM.binaries += [ SM.spcomp = SP.spcomp['x86']
SP.libsourcepawn else:
] SM.spcomp = SP.spcomp[list(SP.spcomp.keys())[0]]
SM.spcomp_bins = list(SP.spcomp.values())
for arch in SM.archs:
SM.binaries += [
SP.libsourcepawn[arch]
]
BuildScripts = [ BuildScripts = [
'loader/AMBuilder', 'loader/AMBuilder',

View File

@ -14,4 +14,14 @@ Development
- [Issue tracker](https://github.com/alliedmodders/sourcemod/issues): Issues that require back and forth communication - [Issue tracker](https://github.com/alliedmodders/sourcemod/issues): Issues that require back and forth communication
- [Building SourceMod](https://wiki.alliedmods.net/Building_SourceMod): Instructions on how to build SourceMod itself using [AMBuild](https://github.com/alliedmodders/ambuild) - [Building SourceMod](https://wiki.alliedmods.net/Building_SourceMod): Instructions on how to build SourceMod itself using [AMBuild](https://github.com/alliedmodders/ambuild)
- [SourcePawn scripting](https://wiki.alliedmods.net/Category:SourceMod_Scripting): SourcePawn examples and introduction to the language - [SourcePawn scripting](https://wiki.alliedmods.net/Category:SourceMod_Scripting): SourcePawn examples and introduction to the language
- [SourceMod plugin API](https://sm.alliedmods.net/new-api): Online SourceMod plugin API reference generated from the include files
- [SourceMod extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces - [SourceMod extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces
Contact
-------
- Connect with us on [GameSurge](https://gamesurge.net) IRC in #sourcemod
- Alternatively feel free to join our [Discord](https://discord.gg/HgZctSS) server
License
-------
SourceMod is licensed under the GNU General Public License version 3. Special exceptions are outlined in the LICENSE.txt file inside of the licenses folder.

View File

@ -35,7 +35,7 @@ namespace SourceMod {
// Add 1 to the RHS of this expression to bump the intercom file // Add 1 to the RHS of this expression to bump the intercom file
// This is to prevent mismatching core/logic binaries // This is to prevent mismatching core/logic binaries
static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 55; static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 57;
} // namespace SourceMod } // namespace SourceMod

View File

@ -50,7 +50,6 @@ class IProviderCallbacks;
class IExtensionSys; class IExtensionSys;
class ITextParsers; class ITextParsers;
class ILogger; class ILogger;
class IDataPack;
class ICellArray; class ICellArray;
struct sm_logic_t struct sm_logic_t
@ -70,10 +69,10 @@ struct sm_logic_t
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...); void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
void (*AddNatives)(sp_nativeinfo_t *natives); void (*AddNatives)(sp_nativeinfo_t *natives);
void (*RegisterProfiler)(IProfilingTool *tool); void (*RegisterProfiler)(IProfilingTool *tool);
IDataPack * (*CreateDataPack)();
void (*FreeDataPack)(IDataPack *pack);
ICellArray * (*CreateCellArray)(size_t blocksize); ICellArray * (*CreateCellArray)(size_t blocksize);
void (*FreeCellArray)(ICellArray *arr); void (*FreeCellArray)(ICellArray *arr);
void * (*FromPseudoAddress)(uint32_t pseudoAddr);
uint32_t (*ToPseudoAddress)(void *addr);
IScriptManager *scripts; IScriptManager *scripts;
IShareSys *sharesys; IShareSys *sharesys;
IExtensionSys *extsys; IExtensionSys *extsys;

View File

@ -22,6 +22,8 @@ parser.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default
help='Root search folder for HL2SDKs') help='Root search folder for HL2SDKs')
parser.options.add_option('--mysql-path', type=str, dest='mysql_path', default=None, parser.options.add_option('--mysql-path', type=str, dest='mysql_path', default=None,
help='Path to MySQL 5') help='Path to MySQL 5')
parser.options.add_option('--mysql64-path', type=str, dest='mysql64_path', default=None,
help='Path to 64-bit MySQL 5')
parser.options.add_option('--mms-path', type=str, dest='mms_path', default=None, parser.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source') help='Path to Metamod:Source')
parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',

View File

@ -1,4 +1,4 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os import os
project = SM.HL2Project(builder, 'sourcemod') project = SM.HL2Project(builder, 'sourcemod')
@ -44,61 +44,70 @@ project.sources += [
for sdk_name in SM.sdks: for sdk_name in SM.sdks:
sdk = SM.sdks[sdk_name] sdk = SM.sdks[sdk_name]
binary_name = 'sourcemod.' + sdk.ext for arch in SM.archs:
if not arch in sdk.platformSpec[builder.target.platform]:
continue
binary = SM.HL2Config(project, binary_name, sdk) binary_name = 'sourcemod.' + sdk.ext
compiler = binary.compiler
compiler.cxxincludes += [ binary = SM.HL2Config(project, binary_name, sdk, arch)
builder.sourcePath compiler = binary.compiler
]
if sdk.name == 'csgo':
compiler.cxxincludes += [ compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'), builder.sourcePath
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
] ]
if compiler.like('msvc'): if sdk.name == 'csgo':
compiler.defines += ['_XKEYCHECK_H'] compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
]
if builder.target.platform == 'linux': if compiler.like('msvc'):
compiler.postlink += ['-lpthread', '-lrt'] compiler.defines += ['_ALLOW_KEYWORD_MACROS']
if sdk.name == 'csgo':
if builder.target.platform == 'linux': if builder.target.platform == 'linux':
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a') compiler.postlink += ['-lpthread', '-lrt']
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
elif builder.target.platform == 'mac':
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
elif builder.target.platform == 'windows':
msvc_ver = compiler.version
vs_year = ''
if msvc_ver == 1800:
vs_year = '2013'
elif 1900 <= msvc_ver < 2000:
vs_year = '2015'
else:
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
if 'DEBUG' in compiler.defines: if sdk.name == 'csgo':
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib') if builder.target.platform == 'linux':
else: if arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib') lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
compiler.linkflags.insert(0, binary.Dep(lib_path)) elif arch == 'x64':
lib_path = os.path.join(sdk.path, 'lib', 'linux64', 'release', 'libprotobuf.a')
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
elif builder.target.platform == 'mac':
if arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
elif arch == 'x64':
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
elif builder.target.platform == 'windows':
msvc_ver = compiler.version
vs_year = ''
if msvc_ver == 1800:
vs_year = '2013'
elif 1900 <= msvc_ver < 2000:
vs_year = '2015'
else:
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
if 'DEBUG' in compiler.defines:
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
else:
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
compiler.linkflags.insert(0, binary.Dep(lib_path))
if sdk.name == 'csgo': if sdk.name == 'csgo':
binary.sources += ['smn_protobuf.cpp'] binary.sources += ['smn_protobuf.cpp']
else: else:
binary.sources += ['smn_bitbuffer.cpp'] binary.sources += ['smn_bitbuffer.cpp']
if sdk.name == 'csgo': if sdk.name == 'csgo':
binary.sources += [ binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'), os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'), os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'), os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
] ]
SM.binaries += builder.Add(project) SM.binaries += builder.Add(project)

View File

@ -317,7 +317,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
char buffer[128]; char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client)) if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
{ {
ke::SafeSprintf(buffer, sizeof(buffer), "You do not have access to this command"); ke::SafeStrcpy(buffer, sizeof(buffer), "You do not have access to this command");
} }
unsigned int replyto = g_ChatTriggers.GetReplyTo(); unsigned int replyto = g_ChatTriggers.GetReplyTo();
@ -342,9 +342,10 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
const char *group, const char *group,
int adminflags, int adminflags,
const char *description, const char *description,
int flags) int flags,
IPlugin *pPlugin)
{ {
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags); ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
if (!pInfo) if (!pInfo)
return false; return false;
@ -388,10 +389,11 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction, bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
const char *name, const char *name,
const char *description, const char *description,
int flags) int flags,
IPlugin *pPlugin)
{ {
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags); ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
if (!pInfo) if (!pInfo)
return false; return false;
@ -555,7 +557,7 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
return true; return true;
} }
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags) ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin)
{ {
ConCmdInfo *pInfo; ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(name, &pInfo)) if (!m_Cmds.retrieve(name, &pInfo))
@ -580,6 +582,7 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
char *new_name = sm_strdup(name); char *new_name = sm_strdup(name);
char *new_help = sm_strdup(description); char *new_help = sm_strdup(description);
pCmd = new ConCommand(new_name, CommandCallback, new_help, flags); pCmd = new ConCommand(new_name, CommandCallback, new_help, flags);
pInfo->pPlugin = pPlugin;
pInfo->sourceMod = true; pInfo->sourceMod = true;
} }
else else

View File

@ -41,6 +41,7 @@
#include <IAdminSystem.h> #include <IAdminSystem.h>
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include "GameHooks.h" #include "GameHooks.h"
#include <am-autoptr.h>
#include <sm_stringhashmap.h> #include <sm_stringhashmap.h>
#include <am-utility.h> #include <am-utility.h>
#include <am-inlinelist.h> #include <am-inlinelist.h>
@ -98,8 +99,9 @@ struct ConCmdInfo
{ {
ConCmdInfo() ConCmdInfo()
{ {
pPlugin = nullptr;
sourceMod = false; sourceMod = false;
pCmd = NULL; pCmd = nullptr;
eflags = 0; eflags = 0;
} }
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */ bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
@ -107,6 +109,7 @@ struct ConCmdInfo
CmdHookList hooks; /**< Hook list */ CmdHookList hooks; /**< Hook list */
FlagBits eflags; /**< Effective admin flags */ FlagBits eflags; /**< Effective admin flags */
ke::RefPtr<CommandHook> sh_hook; /**< SourceHook hook, if any. */ ke::RefPtr<CommandHook> sh_hook; /**< SourceHook hook, if any. */
IPlugin *pPlugin; /**< Owning plugin handle. */
}; };
typedef List<ConCmdInfo *> ConCmdList; typedef List<ConCmdInfo *> ConCmdList;
@ -131,13 +134,14 @@ public: //IRootConsoleCommand
public: //IConCommandTracker public: //IConCommandTracker
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override; void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override;
public: public:
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags); bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags, IPlugin *pPlugin);
bool AddAdminCommand(IPluginFunction *pFunction, bool AddAdminCommand(IPluginFunction *pFunction,
const char *name, const char *name,
const char *group, const char *group,
int adminflags, int adminflags,
const char *description, const char *description,
int flags); int flags,
IPlugin *pPlugin);
ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type); ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type);
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove); void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool LookForSourceModCommand(const char *cmd); bool LookForSourceModCommand(const char *cmd);
@ -145,7 +149,7 @@ public:
private: private:
bool InternalDispatch(int client, const ICommandArgs *args); bool InternalDispatch(int client, const ICommandArgs *args);
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args); ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags); ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin);
void AddToCmdList(ConCmdInfo *info); void AddToCmdList(ConCmdInfo *info);
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool untrack); void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool untrack);
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);

View File

@ -364,8 +364,8 @@ void EventManager::FireEvent(EventInfo *pInfo, bool bDontBroadcast)
void EventManager::FireEventToClient(EventInfo *pInfo, IClient *pClient) void EventManager::FireEventToClient(EventInfo *pInfo, IClient *pClient)
{ {
// The IClient vtable is +4 from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance. // The IClient vtable is +sizeof(void *) from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - 4); IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - sizeof(void *));
pGameClient->FireGameEvent(pInfo->pEvent); pGameClient->FireGameEvent(pInfo->pEvent);
} }

View File

@ -50,8 +50,8 @@
typedef ICommandLine *(*FakeGetCommandLine)(); typedef ICommandLine *(*FakeGetCommandLine)();
#define TIER0_NAME SOURCE_BIN_PREFIX "tier0" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT #define TIER0_NAME FORMAT_SOURCE_BIN_NAME("tier0")
#define VSTDLIB_NAME SOURCE_BIN_PREFIX "vstdlib" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT #define VSTDLIB_NAME FORMAT_SOURCE_BIN_NAME("vstdlib")
CHalfLife2 g_HL2; CHalfLife2 g_HL2;
ConVar *sv_lan = NULL; ConVar *sv_lan = NULL;
@ -139,6 +139,7 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
m_CSGOBadList.add("m_flFallbackWear"); m_CSGOBadList.add("m_flFallbackWear");
m_CSGOBadList.add("m_nFallbackStatTrak"); m_CSGOBadList.add("m_nFallbackStatTrak");
m_CSGOBadList.add("m_iCompetitiveRanking"); m_CSGOBadList.add("m_iCompetitiveRanking");
m_CSGOBadList.add("m_iCompetitiveRankType");
m_CSGOBadList.add("m_nActiveCoinRank"); m_CSGOBadList.add("m_nActiveCoinRank");
m_CSGOBadList.add("m_nMusicID"); m_CSGOBadList.add("m_nMusicID");
#endif #endif
@ -162,7 +163,7 @@ ConfigResult CHalfLife2::OnSourceModConfigChanged(const char *key, const char *v
} }
else else
{ {
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"yes\" or \"no\""); ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
return ConfigResult_Reject; return ConfigResult_Reject;
} }
#endif #endif
@ -227,7 +228,12 @@ void CHalfLife2::InitLogicalEntData()
return; return;
} }
#ifdef PLATFORM_X86
g_EntList = *reinterpret_cast<void **>(addr + offset); g_EntList = *reinterpret_cast<void **>(addr + offset);
#elif defined PLATFORM_X64
int32_t varOffset = *reinterpret_cast<int32_t *>(addr + offset);
g_EntList = reinterpret_cast<void *>(addr + offset + sizeof(int32_t) + varOffset);
#endif
} }
} }
@ -827,7 +833,7 @@ void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
kick.client = client; kick.client = client;
kick.userid = userid; kick.userid = userid;
ke::SafeSprintf(kick.buffer, sizeof(kick.buffer), "%s", msg); ke::SafeStrcpy(kick.buffer, sizeof(kick.buffer), msg);
m_DelayedKicks.push(kick); m_DelayedKicks.push(kick);
} }
@ -1194,7 +1200,7 @@ bool IsWindowsReservedDeviceName(const char *pMapname)
}; };
size_t reservedCount = sizeof(reservedDeviceNames) / sizeof(reservedDeviceNames[0]); size_t reservedCount = sizeof(reservedDeviceNames) / sizeof(reservedDeviceNames[0]);
for (int i = 0; i < reservedCount; ++i) for (size_t i = 0; i < reservedCount; ++i)
{ {
if (CheckReservedFilename(pMapname, reservedDeviceNames[i])) if (CheckReservedFilename(pMapname, reservedDeviceNames[i]))
{ {
@ -1260,19 +1266,26 @@ SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_
return SMFindMapResult::FuzzyMatch; return SMFindMapResult::FuzzyMatch;
} }
#elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_BMS #elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM \
static char szTemp[PLATFORM_MAX_PATH]; || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS
if (pFoundMap == NULL) static IVEngineServer *engine23 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer023", nullptr));
if (engine23)
{ {
ke::SafeStrcpy(szTemp, SM_ARRAYSIZE(szTemp), pMapName); static char szTemp[PLATFORM_MAX_PATH];
pFoundMap = szTemp; if (pFoundMap == NULL)
nMapNameMax = 0; {
} ke::SafeStrcpy(szTemp, SM_ARRAYSIZE(szTemp), pMapName);
pFoundMap = szTemp;
nMapNameMax = 0;
}
return static_cast<SMFindMapResult>(engine->FindMap(pFoundMap, static_cast<int>(nMapNameMax))); return static_cast<SMFindMapResult>(engine->FindMap(pFoundMap, static_cast<int>(nMapNameMax)));
#elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_SDK2013 }
static IVEngineServer *engine21 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer021", nullptr)); else
return engine21->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found; {
static IVEngineServer *engine21 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer021", nullptr));
return engine21->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
}
#else #else
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found; return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
#endif #endif
@ -1300,7 +1313,7 @@ bool CHalfLife2::IsMapValid(const char *map)
if (!map || !map[0]) if (!map || !map[0])
return false; return false;
return FindMap(map) != SMFindMapResult::NotFound; return FindMap(map) == SMFindMapResult::Found;
} }
// TODO: Add ep1 support for this. (No IServerTools available there) // TODO: Add ep1 support for this. (No IServerTools available there)
@ -1339,7 +1352,7 @@ string_t CHalfLife2::AllocPooledString(const char *pszValue)
bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const
{ {
CSteamID sid(GetServerSteamId64()); CSteamID sid((uint64)GetServerSteamId64());
switch (sid.GetEAccountType()) switch (sid.GetEAccountType())
{ {

View File

@ -70,8 +70,8 @@ using namespace SourceMod;
#define SOURCE_BIN_EXT ".dylib" #define SOURCE_BIN_EXT ".dylib"
#elif defined __linux__ #elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \ #if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \ || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI
#define SOURCE_BIN_PREFIX "lib" #define SOURCE_BIN_PREFIX "lib"
#define SOURCE_BIN_SUFFIX "_srv" #define SOURCE_BIN_SUFFIX "_srv"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD #elif SOURCE_ENGINE >= SE_LEFT4DEAD
@ -84,6 +84,9 @@ using namespace SourceMod;
#define SOURCE_BIN_EXT ".so" #define SOURCE_BIN_EXT ".so"
#endif #endif
#define FORMAT_SOURCE_BIN_NAME(basename) \
(SOURCE_BIN_PREFIX basename SOURCE_BIN_SUFFIX SOURCE_BIN_EXT)
struct DataTableInfo struct DataTableInfo
{ {
struct SendPropPolicy struct SendPropPolicy

View File

@ -34,6 +34,7 @@
#include <IMenuManager.h> #include <IMenuManager.h>
#include <IPlayerHelpers.h> #include <IPlayerHelpers.h>
#include <am-autoptr.h>
#include <am-string.h> #include <am-string.h>
#include <am-vector.h> #include <am-vector.h>
#include "sm_fastlink.h" #include "sm_fastlink.h"

View File

@ -458,9 +458,8 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
} }
else else
{ {
display_len = ke::SafeSprintf(display_pkt, display_len = ke::SafeStrcpy(display_pkt,
sizeof(display_pkt), sizeof(display_pkt),
"%s",
text); text);
} }
display_keys = keys; display_keys = keys;

View File

@ -138,8 +138,8 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
logger->LogMessage("[SM] Changed map to \"%s\"", newmap); logger->LogMessage("[SM] Changed map to \"%s\"", newmap);
ke::SafeSprintf(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap); ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
ke::SafeSprintf(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change"); ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
#if SOURCE_ENGINE != SE_DARKMESSIAH #if SOURCE_ENGINE != SE_DARKMESSIAH
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown)); RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
@ -184,14 +184,14 @@ void NextMapManager::OnSourceModLevelChange( const char *mapName )
m_tempChangeInfo.m_mapName[0] ='\0'; m_tempChangeInfo.m_mapName[0] ='\0';
m_tempChangeInfo.m_changeReason[0] = '\0'; m_tempChangeInfo.m_changeReason[0] = '\0';
m_tempChangeInfo.startTime = time(NULL); m_tempChangeInfo.startTime = time(NULL);
ke::SafeSprintf(lastMap, sizeof(lastMap), "%s", mapName); ke::SafeStrcpy(lastMap, sizeof(lastMap), mapName);
} }
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason ) void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
{ {
/* Store the mapname and reason */ /* Store the mapname and reason */
ke::SafeSprintf(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), "%s", mapName); ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName);
ke::SafeSprintf(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "%s", changeReason); ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), changeReason);
/* Change level and skip our hook */ /* Change level and skip our hook */
g_forcedChange = true; g_forcedChange = true;
@ -221,7 +221,7 @@ void CmdChangeLevelCallback()
if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0') if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0')
{ {
ke::SafeSprintf(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1)); ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
ke::SafeSprintf(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command"); ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
} }
} }

View File

@ -64,7 +64,7 @@ const unsigned int *g_NumPlayersToAuth = NULL;
int lifestate_offset = -1; int lifestate_offset = -1;
List<ICommandTargetProcessor *> target_processors; List<ICommandTargetProcessor *> target_processors;
ConVar sm_debug_connect("sm_debug_connect", "0", 0, "Log Debug information about potential connection issues."); ConVar sm_debug_connect("sm_debug_connect", "1", 0, "Log Debug information about potential connection issues.");
SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int); SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *); SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
@ -109,7 +109,7 @@ class KickPlayerTimer : public ITimedEvent
public: public:
ResultType OnTimer(ITimer *pTimer, void *pData) ResultType OnTimer(ITimer *pTimer, void *pData)
{ {
int userid = (int)pData; int userid = (int)(intptr_t)pData;
int client = g_Players.GetClientOfUserId(userid); int client = g_Players.GetClientOfUserId(userid);
if (client) if (client)
{ {
@ -212,6 +212,9 @@ void PlayerManager::OnSourceModAllInitialized()
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdMaxplayersCallback), true); SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdMaxplayersCallback), true);
maxplayersCmd = pCmd; maxplayersCmd = pCmd;
} }
gameevents->AddListener(this, "player_connect", true);
gameevents->AddListener(this, "player_disconnect", true);
} }
void PlayerManager::OnSourceModShutdown() void PlayerManager::OnSourceModShutdown()
@ -259,6 +262,8 @@ void PlayerManager::OnSourceModShutdown()
{ {
SH_REMOVE_HOOK(ConCommand, Dispatch, maxplayersCmd, SH_STATIC(CmdMaxplayersCallback), true); SH_REMOVE_HOOK(ConCommand, Dispatch, maxplayersCmd, SH_STATIC(CmdMaxplayersCallback), true);
} }
gameevents->RemoveListener(this);
} }
ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key, ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
@ -281,7 +286,7 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
} else if (strcasecmp(value, "off") == 0) { } else if (strcasecmp(value, "off") == 0) {
m_QueryLang = false; m_QueryLang = false;
} else { } else {
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"on\" or \"off\""); ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
return ConfigResult_Reject; return ConfigResult_Reject;
} }
return ConfigResult_Accept; return ConfigResult_Accept;
@ -292,7 +297,7 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
} else if ( strcasecmp(value, "no") == 0) { } else if ( strcasecmp(value, "no") == 0) {
m_bAuthstringValidation = false; m_bAuthstringValidation = false;
} else { } else {
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"yes\" or \"no\""); ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
return ConfigResult_Reject; return ConfigResult_Reject;
} }
return ConfigResult_Accept; return ConfigResult_Accept;
@ -1424,6 +1429,11 @@ int PlayerManager::GetNumPlayers()
return m_PlayerCount; return m_PlayerCount;
} }
int PlayerManager::GetNumClients()
{
return m_ClientCount;
}
int PlayerManager::GetClientOfUserId(int userid) int PlayerManager::GetClientOfUserId(int userid)
{ {
if (userid < 0 || userid > USHRT_MAX) if (userid < 0 || userid > USHRT_MAX)
@ -2019,6 +2029,27 @@ bool PlayerManager::HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQue
} }
#endif #endif
/* IGameEventListener2::FireGameEvent */
void PlayerManager::FireGameEvent(IGameEvent *pEvent)
{
const char *name = pEvent->GetName();
if (strcmp(name, "player_connect") == 0)
{
const int client = pEvent->GetInt("index") + 1;
const int userid = pEvent->GetInt("userid");
m_ClientCount++;
}
else if (strcmp(name, "player_disconnect") == 0)
{
const int userid = pEvent->GetInt("userid");
const int client = m_UserIdLookUp[userid];
m_ClientCount--;
}
}
/******************* /*******************
*** PLAYER CODE *** *** PLAYER CODE ***
@ -2141,18 +2172,18 @@ void CPlayer::UpdateAuthIds()
} }
char szAuthBuffer[64]; char szAuthBuffer[64];
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "STEAM_%u:%u:%u", steam2universe, m_SteamId.GetAccountID() & 1, m_SteamId.GetAccountID() >> 1); ke::SafeSprintf(szAuthBuffer, sizeof(szAuthBuffer), "STEAM_%u:%u:%u", steam2universe, m_SteamId.GetAccountID() & 1, m_SteamId.GetAccountID() >> 1);
m_Steam2Id = szAuthBuffer; m_Steam2Id = szAuthBuffer;
// TODO: make sure all hl2sdks' steamclientpublic.h have k_unSteamUserDesktopInstance. // TODO: make sure all hl2sdks' steamclientpublic.h have k_unSteamUserDesktopInstance.
if (m_SteamId.GetUnAccountInstance() == 1 /* k_unSteamUserDesktopInstance */) if (m_SteamId.GetUnAccountInstance() == 1 /* k_unSteamUserDesktopInstance */)
{ {
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID()); ke::SafeSprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID());
} }
else else
{ {
snprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID(), m_SteamId.GetUnAccountInstance()); ke::SafeSprintf(szAuthBuffer, sizeof(szAuthBuffer), "[U:%u:%u:%u]", m_SteamId.GetEUniverse(), m_SteamId.GetAccountID(), m_SteamId.GetUnAccountInstance());
} }
m_Steam3Id = szAuthBuffer; m_Steam3Id = szAuthBuffer;
@ -2578,7 +2609,7 @@ void CPlayer::DoBasicAdminChecks()
if (!g_Players.CheckSetAdminName(client, this, id)) if (!g_Players.CheckSetAdminName(client, this, id))
{ {
int userid = engine->GetPlayerUserId(m_pEdict); int userid = engine->GetPlayerUserId(m_pEdict);
g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)userid, 0); g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)(intptr_t)userid, 0);
} }
return; return;
} }

View File

@ -159,7 +159,8 @@ private:
class PlayerManager : class PlayerManager :
public SMGlobalClass, public SMGlobalClass,
public IPlayerManager public IPlayerManager,
public IGameEventListener2
{ {
friend class CPlayer; friend class CPlayer;
public: public:
@ -202,6 +203,7 @@ public: //IPlayerManager
IGamePlayer *GetGamePlayer(edict_t *pEdict); IGamePlayer *GetGamePlayer(edict_t *pEdict);
int GetMaxClients(); int GetMaxClients();
int GetNumPlayers(); int GetNumPlayers();
int GetNumClients();
int GetClientOfUserId(int userid); int GetClientOfUserId(int userid);
bool IsServerActivated(); bool IsServerActivated();
int FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags); int FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags);
@ -212,6 +214,8 @@ public: //IPlayerManager
int GetClientFromSerial(unsigned int serial); int GetClientFromSerial(unsigned int serial);
void ClearAdminId(AdminId id); void ClearAdminId(AdminId id);
void RecheckAnyAdmins(); void RecheckAnyAdmins();
public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent);
public: public:
inline int MaxClients() inline int MaxClients()
{ {
@ -272,6 +276,7 @@ private:
int m_SourceTVUserId; int m_SourceTVUserId;
int m_ReplayUserId; int m_ReplayUserId;
bool m_bInCCKVHook; bool m_bInCCKVHook;
int m_ClientCount;
private: private:
static const int NETMSG_TYPE_BITS = 5; // SVC_Print overhead for netmsg type static const int NETMSG_TYPE_BITS = 5; // SVC_Print overhead for netmsg type
static const int SVC_Print_BufferSize = 2048 - 1; // -1 for terminating \0 static const int SVC_Print_BufferSize = 2048 - 1; // -1 for terminating \0

View File

@ -118,6 +118,13 @@ public:
return msg; return msg;
} }
inline bool HasField(const char *pszFieldName)
{
GETCHECK_FIELD();
CHECK_FIELD_NOT_REPEATED();
return msg->GetReflection()->HasField(*msg, field);
}
inline bool GetInt32(const char *pszFieldName, int32 *out) inline bool GetInt32(const char *pszFieldName, int32 *out)
{ {
GETCHECK_FIELD(); GETCHECK_FIELD();
@ -341,6 +348,20 @@ public:
return true; return true;
} }
inline bool GetInt64OrUnsigned(const char *pszFieldName, int64 *out)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
*out = (int64)msg->GetReflection()->GetUInt64(*msg, field);
else
*out = msg->GetReflection()->GetInt64(*msg, field);
return true;
}
inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value) inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
{ {
@ -367,6 +388,24 @@ public:
return true; return true;
} }
inline bool SetInt64OrUnsigned(const char *pszFieldName, int64 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
{
msg->GetReflection()->SetUInt64(msg, field, (uint64)value);
}
else
{
msg->GetReflection()->SetInt64(msg, field, value);
}
return true;
}
inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out) inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out)
{ {
@ -384,6 +423,21 @@ public:
return true; return true;
} }
inline bool GetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 *out)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
*out = (int64)msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
else
*out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
return true;
}
inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value) inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value)
{ {
@ -411,6 +465,25 @@ public:
return true; return true;
} }
inline bool SetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
{
msg->GetReflection()->SetRepeatedUInt64(msg, field, index, (uint64)value);
}
else
{
msg->GetReflection()->SetRepeatedInt64(msg, field, index, value);
}
return true;
}
inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value) inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
{ {
@ -437,6 +510,24 @@ public:
return true; return true;
} }
inline bool AddInt64OrUnsigned(const char *pszFieldName, int64 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
{
msg->GetReflection()->AddUInt64(msg, field, (uint64)value);
}
else
{
msg->GetReflection()->AddInt64(msg, field, value);
}
return true;
}
inline bool GetBool(const char *pszFieldName, bool *out) inline bool GetBool(const char *pszFieldName, bool *out)
{ {

View File

@ -1,94 +1,99 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os import os
binary = SM.Library(builder, 'sourcemod.logic') for arch in SM.archs:
binary.compiler.cxxincludes += [ binary = SM.Library(builder, 'sourcemod.logic', arch)
builder.sourcePath, binary.compiler.cxxincludes += [
os.path.join(builder.sourcePath, 'core', 'logic'), builder.sourcePath,
os.path.join(builder.sourcePath, 'public'), os.path.join(builder.sourcePath, 'core', 'logic'),
os.path.join(builder.sourcePath, 'sourcepawn', 'include'), os.path.join(builder.sourcePath, 'public'),
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'), os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
os.path.join(builder.sourcePath, 'public', 'amtl'), os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
os.path.join(SM.mms_root, 'core', 'sourcehook') os.path.join(builder.sourcePath, 'public', 'amtl'),
] os.path.join(SM.mms_root, 'core', 'sourcehook')
binary.compiler.defines += [ ]
'SM_DEFAULT_THREADER', binary.compiler.defines += [
'SM_LOGIC' 'SM_DEFAULT_THREADER',
] 'SM_LOGIC'
]
if builder.target.platform == 'linux': if builder.target.platform == 'linux':
binary.compiler.postlink += ['-lpthread', '-lrt'] binary.compiler.postlink += ['-lpthread', '-lrt']
elif builder.target.platform == 'mac': elif builder.target.platform == 'mac':
binary.compiler.cflags += ['-Wno-deprecated-declarations'] binary.compiler.cflags += ['-Wno-deprecated-declarations']
binary.compiler.postlink += ['-framework', 'CoreServices'] binary.compiler.postlink += ['-framework', 'CoreServices']
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang': if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
binary.compiler.cxxflags += ['-fno-rtti'] binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.family == 'msvc': elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-'] binary.compiler.cxxflags += ['/GR-']
binary.sources += [ binary.sources += [
'common_logic.cpp', 'common_logic.cpp',
'smn_adt_array.cpp', 'smn_adt_array.cpp',
'smn_sorting.cpp', 'smn_sorting.cpp',
'smn_maplists.cpp', 'smn_maplists.cpp',
'ADTFactory.cpp', 'ADTFactory.cpp',
'smn_adt_stack.cpp', 'smn_adt_stack.cpp',
'thread/ThreadWorker.cpp', 'thread/ThreadWorker.cpp',
'thread/BaseWorker.cpp', 'thread/BaseWorker.cpp',
'ThreadSupport.cpp', 'ThreadSupport.cpp',
'smn_float.cpp', 'smn_float.cpp',
'TextParsers.cpp', 'TextParsers.cpp',
'smn_textparse.cpp', 'smn_textparse.cpp',
'smn_adt_trie.cpp', 'smn_adt_trie.cpp',
'smn_functions.cpp', 'smn_functions.cpp',
'smn_timers.cpp', 'smn_timers.cpp',
'smn_players.cpp', 'smn_players.cpp',
'MemoryUtils.cpp', 'MemoryUtils.cpp',
'smn_admin.cpp', 'smn_admin.cpp',
'smn_banning.cpp', 'smn_banning.cpp',
'smn_filesystem.cpp', 'smn_filesystem.cpp',
'stringutil.cpp', 'stringutil.cpp',
'Translator.cpp', 'Translator.cpp',
'PhraseCollection.cpp', 'PhraseCollection.cpp',
'smn_lang.cpp', 'smn_lang.cpp',
'smn_string.cpp', 'smn_string.cpp',
'smn_handles.cpp', 'smn_handles.cpp',
'smn_datapacks.cpp', 'smn_datapacks.cpp',
'smn_gameconfigs.cpp', 'smn_gameconfigs.cpp',
'smn_fakenatives.cpp', 'smn_fakenatives.cpp',
'GameConfigs.cpp', 'GameConfigs.cpp',
'sm_crc32.cpp', 'sm_crc32.cpp',
'smn_profiler.cpp', 'smn_profiler.cpp',
'ShareSys.cpp', 'ShareSys.cpp',
'PluginSys.cpp', 'PluginSys.cpp',
'HandleSys.cpp', 'HandleSys.cpp',
'NativeOwner.cpp', 'NativeOwner.cpp',
'ExtensionSys.cpp', 'ExtensionSys.cpp',
'DebugReporter.cpp', 'DebugReporter.cpp',
'Database.cpp', 'Database.cpp',
'smn_database.cpp', 'smn_database.cpp',
'ForwardSys.cpp', 'ForwardSys.cpp',
'AdminCache.cpp', 'AdminCache.cpp',
'sm_trie.cpp', 'sm_trie.cpp',
'smn_console.cpp', 'smn_console.cpp',
'ProfileTools.cpp', 'ProfileTools.cpp',
'Logger.cpp', 'Logger.cpp',
'smn_core.cpp', 'smn_core.cpp',
'smn_menus.cpp', 'smn_menus.cpp',
'sprintf.cpp', 'sprintf.cpp',
'LibrarySys.cpp', 'LibrarySys.cpp',
'RootConsoleMenu.cpp', 'RootConsoleMenu.cpp',
'CDataPack.cpp', 'CDataPack.cpp',
'frame_tasks.cpp', 'frame_tasks.cpp',
'smn_halflife.cpp', 'smn_halflife.cpp',
'FrameIterator.cpp', 'FrameIterator.cpp',
'NativeInvoker.cpp', 'DatabaseConfBuilder.cpp',
] 'NativeInvoker.cpp',
if builder.target.platform == 'windows': ]
binary.sources += ['thread/WinThreads.cpp']
else:
binary.sources += ['thread/PosixThreads.cpp']
if arch == 'x64':
binary.sources += ['PseudoAddrManager.cpp']
SM.binaries += [builder.Add(binary)] if builder.target.platform == 'windows':
binary.sources += ['thread/WinThreads.cpp']
else:
binary.sources += ['thread/PosixThreads.cpp']
SM.binaries += [builder.Add(binary)]

View File

@ -1090,14 +1090,14 @@ bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t ma
else if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_') else if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_')
{ {
// non-bot/lan Steam2 Id, strip off the STEAM_* part // non-bot/lan Steam2 Id, strip off the STEAM_* part
snprintf(out, maxlen, "%s", &ident[8]); ke::SafeStrcpy(out, maxlen, &ident[8]);
return true; return true;
} }
else if (len >= 7 && !strncmp(ident, "[U:", 3) && ident[len-1] == ']') else if (len >= 7 && !strncmp(ident, "[U:", 3) && ident[len-1] == ']')
{ {
// Steam3 Id, replicate the Steam2 Post-"STEAM_" part // Steam3 Id, replicate the Steam2 Post-"STEAM_" part
uint32_t accountId = strtoul(&ident[5], nullptr, 10); uint32_t accountId = strtoul(&ident[5], nullptr, 10);
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1); ke::SafeSprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
return true; return true;
} }
else else
@ -1124,7 +1124,7 @@ bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t ma
&& accountType == k_EAccountTypeIndividual && accountInstance <= k_unSteamUserWebInstance && accountType == k_EAccountTypeIndividual && accountInstance <= k_unSteamUserWebInstance
) )
{ {
snprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1); ke::SafeSprintf(out, maxlen, "%u:%u", accountId & 1, accountId >> 1);
return true; return true;
} }
} }

View File

@ -33,27 +33,20 @@
#include <string.h> #include <string.h>
#include "CDataPack.h" #include "CDataPack.h"
#include <amtl/am-autoptr.h> #include <amtl/am-autoptr.h>
#include <amtl/am-vector.h>
using namespace ke;
#define DATAPACK_INITIAL_SIZE 64
CDataPack::CDataPack() CDataPack::CDataPack()
{ {
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
m_capacity = DATAPACK_INITIAL_SIZE;
Initialize(); Initialize();
} }
CDataPack::~CDataPack() CDataPack::~CDataPack()
{ {
free(m_pBase); Initialize();
} }
static Vector<AutoPtr<CDataPack>> sDataPackCache; static ke::Vector<ke::AutoPtr<CDataPack>> sDataPackCache;
IDataPack * CDataPack::New() CDataPack *CDataPack::New()
{ {
if (sDataPackCache.empty()) if (sDataPackCache.empty())
return new CDataPack(); return new CDataPack();
@ -65,293 +58,187 @@ IDataPack * CDataPack::New()
} }
void void
CDataPack::Free(IDataPack *pack) CDataPack::Free(CDataPack *pack)
{ {
sDataPackCache.append(static_cast<CDataPack *>(pack)); sDataPackCache.append(static_cast<CDataPack *>(pack));
} }
void CDataPack::Initialize() void CDataPack::Initialize()
{ {
m_curptr = m_pBase;
m_size = 0;
}
void CDataPack::CheckSize(size_t typesize)
{
if (m_curptr - m_pBase + typesize <= m_capacity)
{
return;
}
size_t pos = m_curptr - m_pBase;
do do
{ {
m_capacity *= 2; } while (this->RemoveItem());
} while (pos + typesize > m_capacity);
elements.clear();
m_pBase = (char *)realloc(m_pBase, m_capacity); position = 0;
m_curptr = m_pBase + pos;
} }
void CDataPack::ResetSize() void CDataPack::ResetSize()
{ {
m_size = 0; Initialize();
} }
size_t CDataPack::CreateMemory(size_t size, void **addr) size_t CDataPack::CreateMemory(size_t size, void **addr)
{ {
CheckSize(sizeof(char) + sizeof(size_t) + size); InternalPack val;
size_t pos = m_curptr - m_pBase; val.type = CDataPackType::Raw;
val.pData.vval = new uint8_t[size + sizeof(size)];
reinterpret_cast<size_t *>(val.pData.vval)[0] = size;
elements.insert(position, val);
*(char *)m_curptr = Raw; return position++;
m_curptr += sizeof(char);
*(size_t *)m_curptr = size;
m_curptr += sizeof(size_t);
if (addr)
{
*addr = m_curptr;
}
m_curptr += size;
m_size += sizeof(char) + sizeof(size_t) + size;
return pos;
} }
void CDataPack::PackCell(cell_t cell) void CDataPack::PackCell(cell_t cell)
{ {
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t)); InternalPack val;
val.type = CDataPackType::Cell;
*(char *)m_curptr = Cell; val.pData.cval = cell;
m_curptr += sizeof(char); elements.insert(position++, val);
*(size_t *)m_curptr = sizeof(cell_t);
m_curptr += sizeof(size_t);
*(cell_t *)m_curptr = cell;
m_curptr += sizeof(cell_t);
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
} }
void CDataPack::PackFloat(float val) void CDataPack::PackFunction(cell_t function)
{ {
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float)); InternalPack val;
val.type = CDataPackType::Function;
val.pData.cval = function;
elements.insert(position++, val);
}
*(char *)m_curptr = Float; void CDataPack::PackFloat(float floatval)
m_curptr += sizeof(char); {
InternalPack val;
*(size_t *)m_curptr = sizeof(float); val.type = CDataPackType::Float;
m_curptr += sizeof(size_t); val.pData.fval = floatval;
elements.insert(position++, val);
*(float *)m_curptr = val;
m_curptr += sizeof(float);
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
} }
void CDataPack::PackString(const char *string) void CDataPack::PackString(const char *string)
{ {
size_t len = strlen(string); InternalPack val;
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1; val.type = CDataPackType::String;
CheckSize(maxsize); ke::AString *sval = new ke::AString(string);
val.pData.sval = sval;
*(char *)m_curptr = String; elements.insert(position++, val);
m_curptr += sizeof(char);
// Pack the string length first for buffer overrun checking.
*(size_t *)m_curptr = len;
m_curptr += sizeof(size_t);
// Now pack the string.
memcpy(m_curptr, string, len);
m_curptr[len] = '\0';
m_curptr += len + 1;
m_size += maxsize;
} }
void CDataPack::Reset() const void CDataPack::Reset() const
{ {
m_curptr = m_pBase; position = 0;
} }
size_t CDataPack::GetPosition() const size_t CDataPack::GetPosition() const
{ {
return static_cast<size_t>(m_curptr - m_pBase); return position;
} }
bool CDataPack::SetPosition(size_t pos) const bool CDataPack::SetPosition(size_t pos) const
{ {
if (pos > m_size) if (pos > elements.length())
{
return false; return false;
}
m_curptr = m_pBase + pos;
position = pos;
return true; return true;
} }
cell_t CDataPack::ReadCell() const cell_t CDataPack::ReadCell() const
{ {
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t))) if (!IsReadable() || elements[position].type != CDataPackType::Cell)
{
return 0; return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Cell) return elements[position++].pData.cval;
{
return 0;
}
m_curptr += sizeof(char);
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
{
return 0;
}
m_curptr += sizeof(size_t);
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
m_curptr += sizeof(cell_t);
return val;
}
float CDataPack::ReadFloat() const
{
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
{
return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Float)
{
return 0;
}
m_curptr += sizeof(char);
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
{
return 0;
}
m_curptr += sizeof(size_t);
float val = *reinterpret_cast<float *>(m_curptr);
m_curptr += sizeof(float);
return val;
}
bool CDataPack::IsReadable(size_t bytes) const
{
return (bytes + (m_curptr - m_pBase) > m_size) ? false : true;
}
const char *CDataPack::ReadString(size_t *len) const
{
if (!IsReadable(sizeof(char) + sizeof(size_t)))
{
return NULL;
}
if (*reinterpret_cast<char *>(m_curptr) != String)
{
return NULL;
}
m_curptr += sizeof(char);
size_t real_len = *(size_t *)m_curptr;
m_curptr += sizeof(size_t);
char *str = (char *)m_curptr;
if ((strlen(str) != real_len) || !(IsReadable(real_len+1)))
{
return NULL;
}
if (len)
{
*len = real_len;
}
m_curptr += real_len + 1;
return str;
}
void *CDataPack::GetMemory() const
{
return m_curptr;
}
void *CDataPack::ReadMemory(size_t *size) const
{
if (!IsReadable(sizeof(size_t)))
{
return NULL;
}
if (*reinterpret_cast<char *>(m_curptr) != Raw)
{
return NULL;
}
m_curptr += sizeof(char);
size_t bytecount = *(size_t *)m_curptr;
m_curptr += sizeof(size_t);
if (!IsReadable(bytecount))
{
return NULL;
}
void *ptr = m_curptr;
if (size)
{
*size = bytecount;
}
m_curptr += bytecount;
return ptr;
}
void CDataPack::PackFunction(cell_t function)
{
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
*(char *)m_curptr = Function;
m_curptr += sizeof(char);
*(size_t *)m_curptr = sizeof(cell_t);
m_curptr += sizeof(size_t);
*(cell_t *)m_curptr = function;
m_curptr += sizeof(cell_t);
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
} }
cell_t CDataPack::ReadFunction() const cell_t CDataPack::ReadFunction() const
{ {
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t))) if (!IsReadable() || elements[position].type != CDataPackType::Function)
{
return 0; return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Function) return elements[position++].pData.cval;
{ }
return 0;
} float CDataPack::ReadFloat() const
m_curptr += sizeof(char); {
if (!IsReadable() || elements[position].type != CDataPackType::Float)
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t)) return 0;
{
return 0; return elements[position++].pData.fval;
} }
m_curptr += sizeof(size_t); bool CDataPack::IsReadable(size_t bytes) const
{
cell_t val = *reinterpret_cast<cell_t *>(m_curptr); return (position < elements.length());
m_curptr += sizeof(cell_t); }
return val;
const char *CDataPack::ReadString(size_t *len) const
{
if (!IsReadable() || elements[position].type != CDataPackType::String)
{
if (len)
*len = 0;
return nullptr;
}
const ke::AString &val = *elements[position++].pData.sval;
if (len)
*len = val.length();
return val.chars();
}
void *CDataPack::ReadMemory(size_t *size) const
{
void *ptr = nullptr;
if (!IsReadable() || elements[position].type != CDataPackType::Raw)
return ptr;
size_t *val = reinterpret_cast<size_t *>(elements[position].pData.vval);
ptr = &(val[1]);
++position;
if (size)
*size = val[0]; /* Egor!!!! */
return ptr;
}
bool CDataPack::RemoveItem(size_t pos)
{
if (!elements.length())
{
return false;
}
if (pos == static_cast<size_t>(-1))
{
pos = position;
}
if (pos >= elements.length())
{
return false;
}
if (pos < position) // we're deleting under us, step back
{
--position;
}
switch (elements[pos].type)
{
case CDataPackType::Raw:
{
delete elements[pos].pData.vval;
break;
}
case CDataPackType::String:
{
delete elements[pos].pData.sval;
break;
}
}
elements.remove(pos);
return true;
} }

View File

@ -32,54 +32,165 @@
#ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_ #ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_ #define _INCLUDE_SOURCEMOD_CDATAPACK_H_
#include <IDataPack.h> #include <ISourceMod.h>
#include <amtl/am-vector.h>
#include <amtl/am-string.h>
using namespace SourceMod; using namespace SourceMod;
class CDataPack : public IDataPack enum CDataPackType {
Raw,
Cell,
Float,
String,
Function
};
class CDataPack
{ {
public: public:
CDataPack(); CDataPack();
~CDataPack(); ~CDataPack();
static IDataPack *New(); static CDataPack *New();
static void Free(IDataPack *pack); static void Free(CDataPack *pack);
public: //IDataReader
public: // Originally IDataReader
/**
* @brief Resets the position in the data stream to the beginning.
*/
void Reset() const; void Reset() const;
/**
* @brief Retrieves the current stream position.
*
* @return Index into the stream.
*/
size_t GetPosition() const; size_t GetPosition() const;
/**
* @brief Sets the current stream position.
*
* @param pos Index to set the stream at.
* @return True if succeeded, false if out of bounds.
*/
bool SetPosition(size_t pos) const; bool SetPosition(size_t pos) const;
/**
* @brief Reads one cell from the data stream.
*
* @return A cell read from the current position.
*/
cell_t ReadCell() const; cell_t ReadCell() const;
/**
* @brief Reads one float from the data stream.
*
* @return A float read from the current position.
*/
float ReadFloat() const; float ReadFloat() const;
bool IsReadable(size_t bytes) const;
/**
* @brief Returns whether or not a specified number of bytes from the current stream
* position to the end can be read.
*
* @param bytes Number of bytes to simulate reading.
* @return True if can be read, false otherwise.
*/
bool IsReadable(size_t bytes = 0) const;
/**
* @brief Reads a string from the data stream.
*
* @param len Optional pointer to store the string length.
* @return Pointer to the string, or NULL if out of bounds.
*/
const char *ReadString(size_t *len) const; const char *ReadString(size_t *len) const;
void *GetMemory() const;
/**
* @brief Reads the current position as a generic data type.
*
* @param size Optional pointer to store the size of the data type.
* @return Pointer to the data, or NULL if out of bounds.
*/
void *ReadMemory(size_t *size) const; void *ReadMemory(size_t *size) const;
/**
* @brief Reads a function pointer from the data stream.
*
* @return A function pointer read from the current position.
*/
cell_t ReadFunction() const; cell_t ReadFunction() const;
public: //IDataPack
public: // Originally IDataPack
/**
* @brief Resets the used size of the stream back to zero.
*/
void ResetSize(); void ResetSize();
/**
* @brief Packs one cell into the data stream.
*
* @param cell Cell value to write.
*/
void PackCell(cell_t cell); void PackCell(cell_t cell);
/**
* @brief Packs one float into the data stream.
*
* @param val Float value to write.
*/
void PackFloat(float val); void PackFloat(float val);
/**
* @brief Packs one string into the data stream.
* The length is recorded as well for buffer overrun protection.
*
* @param string String to write.
*/
void PackString(const char *string); void PackString(const char *string);
/**
* @brief Creates a generic block of memory in the stream.
*
* Note that the pointer it returns can be invalidated on further
* writing, since the stream size may grow. You may need to double back
* and fetch the pointer again.
*
* @param size Size of the memory to create in the stream.
* @param addr Optional pointer to store the relocated memory address.
* @return Current position of the stream beforehand.
*/
size_t CreateMemory(size_t size, void **addr); size_t CreateMemory(size_t size, void **addr);
/**
* @brief Packs one function pointer into the data stream.
*
* @param function The function pointer to write.
*/
void PackFunction(cell_t function); void PackFunction(cell_t function);
public: public:
void Initialize(); void Initialize();
inline size_t GetCapacity() const { return m_capacity; } inline size_t GetCapacity() const { return this->elements.length(); };
private: inline CDataPackType GetCurrentType(void) const { return this->elements[this->position].type; };
void CheckSize(size_t sizetype); bool RemoveItem(size_t pos = -1);
private:
char *m_pBase;
mutable char *m_curptr;
size_t m_capacity;
size_t m_size;
enum DataPackType { private:
Raw, typedef union {
Cell, cell_t cval;
Float, float fval;
String, uint8_t *vval;
Function ke::AString *sval;
}; } InternalPackValue;
typedef struct {
InternalPackValue pData;
CDataPackType type;
} InternalPack;
ke::Vector<InternalPack> elements;
mutable size_t position;
}; };
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_ #endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_

View File

@ -227,11 +227,17 @@ private:
/* finally, allocate the new block */ /* finally, allocate the new block */
if (m_Data) if (m_Data)
{ {
m_Data = (cell_t *)realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize); cell_t *data = static_cast<cell_t*>(realloc(m_Data, sizeof(cell_t) * m_BlockSize * m_AllocSize));
if (!data) // allocation failure
{
return false;
}
m_Data = data;
} else { } else {
m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize); m_Data = static_cast<cell_t*>(malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize));
} }
return (m_Data != NULL); return (m_Data != nullptr);
} }
private: private:
cell_t *m_Data; cell_t *m_Data;

View File

@ -37,6 +37,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <IThreader.h> #include <IThreader.h>
#include <bridge/include/ILogger.h> #include <bridge/include/ILogger.h>
#include <bridge/include/CoreProvider.h>
#define DBPARSE_LEVEL_NONE 0 #define DBPARSE_LEVEL_NONE 0
#define DBPARSE_LEVEL_MAIN 1 #define DBPARSE_LEVEL_MAIN 1
@ -47,8 +48,6 @@ static bool s_OneTimeThreaderErrorMsg = false;
DBManager::DBManager() DBManager::DBManager()
: m_Terminate(false), : m_Terminate(false),
m_ParseLevel(0),
m_ParseState(0),
m_pDefault(NULL) m_pDefault(NULL)
{ {
} }
@ -65,38 +64,29 @@ void DBManager::OnSourceModAllInitialized()
g_HandleSys.InitAccessDefaults(NULL, &sec); g_HandleSys.InitAccessDefaults(NULL, &sec);
sec.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY; sec.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY;
sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY; sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY;
m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL); m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL);
m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL); m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL);
g_ShareSys.AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg"); g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
m_Builder.SetPath(m_Filename);
g_PluginSys.AddPluginsListener(this);
g_PluginSys.AddPluginsListener(this);
g_pSM->AddGameFrameHook(&FrameHook); g_pSM->AddGameFrameHook(&FrameHook);
auto sm_reload_databases = [this] (int client, const ICommandArgs *args) -> bool {
m_Builder.StartParse();
return true;
};
bridge->DefineCommand("sm_reload_databases", "Reparse database configurations file", sm_reload_databases);
} }
void DBManager::OnSourceModLevelChange(const char *mapName) void DBManager::OnSourceModLevelChange(const char *mapName)
{ {
SMCError err; m_Builder.StartParse();
SMCStates states = {0, 0};
/* We lock and don't give up the lock until we're done.
* This way the thread's search won't be searching through a
* potentially empty/corrupt list, which would be very bad.
*/
ke::AutoLock lock(&m_ConfigLock);
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
{
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
if (err != SMCError_Custom)
{
const char *txt = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Line %d: %s", states.line, txt);
}
}
} }
void DBManager::OnSourceModShutdown() void DBManager::OnSourceModShutdown()
@ -106,7 +96,6 @@ void DBManager::OnSourceModShutdown()
g_PluginSys.RemovePluginsListener(this); g_PluginSys.RemovePluginsListener(this);
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent); g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent); g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
ClearConfigs();
} }
unsigned int DBManager::GetInterfaceVersion() unsigned int DBManager::GetInterfaceVersion()
@ -134,136 +123,10 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
} }
} }
void DBManager::ReadSMC_ParseStart()
{
ClearConfigs();
m_ParseLevel = 0;
m_ParseState = DBPARSE_LEVEL_NONE;
m_DefDriver.clear();
}
void DBManager::ClearConfigs()
{
List<ConfDbInfo *>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
delete (*iter);
m_confs.clear();
}
ConfDbInfo s_CurInfo;
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
{
if (m_ParseLevel)
{
m_ParseLevel++;
return SMCResult_Continue;
}
if (m_ParseState == DBPARSE_LEVEL_NONE)
{
if (strcmp(name, "Databases") == 0)
{
m_ParseState = DBPARSE_LEVEL_MAIN;
} else {
m_ParseLevel++;
}
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
s_CurInfo = ConfDbInfo();
s_CurInfo.name = name;
m_ParseState = DBPARSE_LEVEL_DATABASE;
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
m_ParseLevel++;
}
return SMCResult_Continue;
}
SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{
if (m_ParseLevel)
{
return SMCResult_Continue;
}
if (m_ParseState == DBPARSE_LEVEL_MAIN)
{
if (strcmp(key, "driver_default") == 0)
{
m_DefDriver.assign(value);
}
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
if (strcmp(key, "driver") == 0)
{
if (strcmp(value, "default") != 0)
{
s_CurInfo.driver = value;
}
} else if (strcmp(key, "database") == 0) {
s_CurInfo.database = value;
} else if (strcmp(key, "host") == 0) {
s_CurInfo.host = value;
} else if (strcmp(key, "user") == 0) {
s_CurInfo.user = value;
} else if (strcmp(key, "pass") == 0) {
s_CurInfo.pass = value;
} else if (strcmp(key, "timeout") == 0) {
s_CurInfo.info.maxTimeout = atoi(value);
} else if (strcmp(key, "port") == 0) {
s_CurInfo.info.port = atoi(value);
}
}
return SMCResult_Continue;
}
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
{
if (m_ParseLevel)
{
m_ParseLevel--;
return SMCResult_Continue;
}
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
{
ConfDbInfo *cdb = new ConfDbInfo();
cdb->name = s_CurInfo.name;
cdb->driver = s_CurInfo.driver;
cdb->host = s_CurInfo.host;
cdb->user = s_CurInfo.user;
cdb->pass = s_CurInfo.pass;
cdb->database = s_CurInfo.database;
cdb->realDriver = s_CurInfo.realDriver;
cdb->info.maxTimeout = s_CurInfo.info.maxTimeout;
cdb->info.port = s_CurInfo.info.port;
cdb->info.driver = cdb->driver.c_str();
cdb->info.database = cdb->database.c_str();
cdb->info.host = cdb->host.c_str();
cdb->info.user = cdb->user.c_str();
cdb->info.pass = cdb->pass.c_str();
/* Save it.. */
m_confs.push_back(cdb);
/* Go up one level */
m_ParseState = DBPARSE_LEVEL_MAIN;
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
m_ParseState = DBPARSE_LEVEL_NONE;
return SMCResult_Halt;
}
return SMCResult_Continue;
}
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
{
}
bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength) bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength)
{ {
ConfDbInfo *pInfo = GetDatabaseConf(name); ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> pInfo = list->GetDatabaseConf(name);
if (!pInfo) if (!pInfo)
{ {
@ -282,11 +145,12 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
/* Try to assign a real driver pointer */ /* Try to assign a real driver pointer */
if (pInfo->info.driver[0] == '\0') if (pInfo->info.driver[0] == '\0')
{ {
if (!m_pDefault && m_DefDriver.size() > 0) ke::AString defaultDriver = list->GetDefaultDriver();
if (!m_pDefault && defaultDriver.length() > 0)
{ {
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str()); m_pDefault = FindOrLoadDriver(defaultDriver.chars());
} }
dname = m_DefDriver.size() ? m_DefDriver.c_str() : "default"; dname = defaultDriver.length() ? defaultDriver.chars() : "default";
pInfo->realDriver = m_pDefault; pInfo->realDriver = m_pDefault;
} else { } else {
pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver); pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
@ -310,7 +174,6 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
*pdb = NULL; *pdb = NULL;
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname); g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname);
return false; return false;
} }
@ -323,7 +186,7 @@ void DBManager::AddDriver(IDBDriver *pDriver)
*/ */
KillWorkerThread(); KillWorkerThread();
m_drivers.push_back(pDriver); m_drivers.push_back(pDriver);
} }
void DBManager::RemoveDriver(IDBDriver *pDriver) void DBManager::RemoveDriver(IDBDriver *pDriver)
@ -343,17 +206,17 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
} }
} }
/* Make sure NOTHING references this! */ ConfDbInfoList *list = m_Builder.GetConfigList();
List<ConfDbInfo *>::iterator iter; for (size_t i = 0; i < list->length(); i++)
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
{ {
ConfDbInfo &db = *(*iter); ke::RefPtr<ConfDbInfo> current = list->at(i);
if (db.realDriver == pDriver) if (current->realDriver == pDriver)
{ {
db.realDriver = NULL; current->realDriver = NULL;
} }
} }
/* Someone unloaded the default driver? Silly.. */ /* Someone unloaded the default driver? Silly.. */
if (pDriver == m_pDefault) if (pDriver == m_pDefault)
{ {
@ -389,9 +252,11 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
IDBDriver *DBManager::GetDefaultDriver() IDBDriver *DBManager::GetDefaultDriver()
{ {
if (!m_pDefault && m_DefDriver.size() > 0) ConfDbInfoList *list = m_Builder.GetConfigList();
ke::AString defaultDriver = list->GetDefaultDriver();
if (!m_pDefault && defaultDriver.length() > 0)
{ {
m_pDefault = FindOrLoadDriver(m_DefDriver.c_str()); m_pDefault = FindOrLoadDriver(defaultDriver.chars());
} }
return m_pDefault; return m_pDefault;
@ -454,10 +319,16 @@ IDBDriver *DBManager::GetDriver(unsigned int index)
const DatabaseInfo *DBManager::FindDatabaseConf(const char *name) const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
{ {
ConfDbInfo *info = GetDatabaseConf(name); ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> info = list->GetDatabaseConf(name);
if (!info) if (!info)
{ {
return NULL; // couldn't find requested conf, return default if exists
info = list->GetDefaultConfiguration();
if (!info)
{
return NULL;
}
} }
return &info->info; return &info->info;
@ -465,18 +336,9 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
ConfDbInfo *DBManager::GetDatabaseConf(const char *name) ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
{ {
List<ConfDbInfo *>::iterator iter; ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> info(list->GetDatabaseConf(name));
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++) return info;
{
ConfDbInfo &conf = *(*iter);
if (conf.name == name)
{
return &conf;
}
}
return NULL;
} }
IDBDriver *DBManager::FindOrLoadDriver(const char *name) IDBDriver *DBManager::FindOrLoadDriver(const char *name)
@ -729,23 +591,13 @@ void DBManager::OnPluginWillUnload(IPlugin *plugin)
} }
} }
void DBManager::LockConfig() ke::AString DBManager::GetDefaultDriverName()
{ {
m_ConfigLock.Lock(); ConfDbInfoList *list = m_Builder.GetConfigList();
} return list->GetDefaultDriver();
void DBManager::UnlockConfig()
{
m_ConfigLock.Unlock();
}
const char *DBManager::GetDefaultDriverName()
{
return m_DefDriver.c_str();
} }
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver) void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)
{ {
g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver); g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver);
} }

View File

@ -32,39 +32,24 @@
#ifndef _INCLUDE_DATABASE_MANAGER_H_ #ifndef _INCLUDE_DATABASE_MANAGER_H_
#define _INCLUDE_DATABASE_MANAGER_H_ #define _INCLUDE_DATABASE_MANAGER_H_
#include <IDBDriver.h>
#include "common_logic.h" #include "common_logic.h"
#include <sh_vector.h> #include <sh_vector.h>
#include <sh_string.h> #include <am-string.h>
#include <sh_list.h> #include <sh_list.h>
#include <ITextParsers.h>
#include <IThreader.h> #include <IThreader.h>
#include <IPluginSys.h> #include <IPluginSys.h>
#include <am-thread-utils.h> #include <am-thread-utils.h>
#include "sm_simple_prioqueue.h" #include "sm_simple_prioqueue.h"
#include <am-refcounting.h>
#include "DatabaseConfBuilder.h"
using namespace SourceHook; using namespace SourceHook;
struct ConfDbInfo
{
ConfDbInfo() : realDriver(NULL)
{
}
String name;
String driver;
String host;
String user;
String pass;
String database;
IDBDriver *realDriver;
DatabaseInfo info;
};
class DBManager : class DBManager :
public IDBManager, public IDBManager,
public SMGlobalClass, public SMGlobalClass,
public IHandleTypeDispatch, public IHandleTypeDispatch,
public ITextListener_SMC,
public IPluginsListener public IPluginsListener
{ {
public: public:
@ -83,6 +68,7 @@ public: //IDBManager
void AddDriver(IDBDriver *pDrivera); void AddDriver(IDBDriver *pDrivera);
void RemoveDriver(IDBDriver *pDriver); void RemoveDriver(IDBDriver *pDriver);
const DatabaseInfo *FindDatabaseConf(const char *name); const DatabaseInfo *FindDatabaseConf(const char *name);
ConfDbInfo *GetDatabaseConf(const char *name);
bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength); bool Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool persistent, char *error, size_t maxlength);
unsigned int GetDriverCount(); unsigned int GetDriverCount();
IDBDriver *GetDriver(unsigned int index); IDBDriver *GetDriver(unsigned int index);
@ -90,25 +76,16 @@ public: //IDBManager
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr); HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token); HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
void AddDependency(IExtension *myself, IDBDriver *driver); void AddDependency(IExtension *myself, IDBDriver *driver);
public: //ITextListener_SMC
void ReadSMC_ParseStart();
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
void ReadSMC_ParseEnd(bool halted, bool failed);
public: //ke::IRunnable public: //ke::IRunnable
void Run(); void Run();
void ThreadMain(); void ThreadMain();
public: //IPluginsListener public: //IPluginsListener
void OnPluginWillUnload(IPlugin *plugin); void OnPluginWillUnload(IPlugin *plugin);
public: public:
ConfDbInfo *GetDatabaseConf(const char *name);
IDBDriver *FindOrLoadDriver(const char *name); IDBDriver *FindOrLoadDriver(const char *name);
IDBDriver *GetDefaultDriver(); IDBDriver *GetDefaultDriver();
const char *GetDefaultDriverName(); ke::AString GetDefaultDriverName();
bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio); bool AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio);
void LockConfig();
void UnlockConfig();
void RunFrame(); void RunFrame();
inline HandleType_t GetDatabaseType() inline HandleType_t GetDatabaseType()
{ {
@ -126,17 +103,13 @@ private:
CVector<bool> m_drSafety; /* which drivers are safe? */ CVector<bool> m_drSafety; /* which drivers are safe? */
ke::AutoPtr<ke::Thread> m_Worker; ke::AutoPtr<ke::Thread> m_Worker;
ke::ConditionVariable m_QueueEvent; ke::ConditionVariable m_QueueEvent;
ke::Mutex m_ConfigLock;
ke::Mutex m_ThinkLock; ke::Mutex m_ThinkLock;
bool m_Terminate; bool m_Terminate;
List<ConfDbInfo *> m_confs; DatabaseConfBuilder m_Builder;
HandleType_t m_DriverType; HandleType_t m_DriverType;
HandleType_t m_DatabaseType; HandleType_t m_DatabaseType;
String m_DefDriver;
char m_Filename[PLATFORM_MAX_PATH]; char m_Filename[PLATFORM_MAX_PATH];
unsigned int m_ParseLevel;
unsigned int m_ParseState;
IDBDriver *m_pDefault; IDBDriver *m_pDefault;
}; };

View File

@ -0,0 +1,184 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2018 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "DatabaseConfBuilder.h"
#include <bridge/include/ILogger.h>
#define DBPARSE_LEVEL_NONE 0
#define DBPARSE_LEVEL_MAIN 1
#define DBPARSE_LEVEL_DATABASE 2
DatabaseConfBuilder::DatabaseConfBuilder()
: m_ParseList(nullptr),
m_InfoList(new ConfDbInfoList())
{
}
void DatabaseConfBuilder::SetPath(char *str)
{
m_Filename = str;
}
DatabaseConfBuilder::~DatabaseConfBuilder()
{
}
ConfDbInfoList *DatabaseConfBuilder::GetConfigList()
{
return m_InfoList;
}
void DatabaseConfBuilder::StartParse()
{
SMCError err;
SMCStates states = {0, 0};
if ((err = textparsers->ParseFile_SMC(m_Filename.chars(), this, &states)) != SMCError_Okay)
{
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename.chars());
if (err != SMCError_Custom)
{
const char *txt = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Line %d: %s", states.line, txt);
}
}
}
void DatabaseConfBuilder::ReadSMC_ParseStart()
{
m_ParseLevel = 0;
m_ParseState = DBPARSE_LEVEL_NONE;
m_ParseList = new ConfDbInfoList();
}
SMCResult DatabaseConfBuilder::ReadSMC_NewSection(const SMCStates *states, const char *name)
{
if (m_ParseLevel)
{
m_ParseLevel++;
return SMCResult_Continue;
}
if (m_ParseState == DBPARSE_LEVEL_NONE)
{
if (strcmp(name, "Databases") == 0)
{
m_ParseState = DBPARSE_LEVEL_MAIN;
} else {
m_ParseLevel++;
}
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
m_ParseCurrent = new ConfDbInfo();
m_ParseCurrent->name = name;
m_ParseState = DBPARSE_LEVEL_DATABASE;
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
m_ParseLevel++;
}
return SMCResult_Continue;
}
SMCResult DatabaseConfBuilder::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{
if (m_ParseLevel)
{
return SMCResult_Continue;
}
if (m_ParseState == DBPARSE_LEVEL_MAIN)
{
if (strcmp(key, "driver_default") == 0)
{
m_ParseList->SetDefaultDriver(value);
}
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
if (strcmp(key, "driver") == 0)
{
if (strcmp(value, "default") != 0)
{
m_ParseCurrent->driver = value;
}
} else if (strcmp(key, "database") == 0) {
m_ParseCurrent->database = value;
} else if (strcmp(key, "host") == 0) {
m_ParseCurrent->host = value;
} else if (strcmp(key, "user") == 0) {
m_ParseCurrent->user = value;
} else if (strcmp(key, "pass") == 0) {
m_ParseCurrent->pass = value;
} else if (strcmp(key, "timeout") == 0) {
m_ParseCurrent->info.maxTimeout = atoi(value);
} else if (strcmp(key, "port") == 0) {
m_ParseCurrent->info.port = atoi(value);
}
}
return SMCResult_Continue;
}
SMCResult DatabaseConfBuilder::ReadSMC_LeavingSection(const SMCStates *states)
{
if (m_ParseLevel)
{
m_ParseLevel--;
return SMCResult_Continue;
}
if (m_ParseState == DBPARSE_LEVEL_DATABASE)
{
m_ParseCurrent->info.driver = m_ParseCurrent->driver.chars();
m_ParseCurrent->info.database = m_ParseCurrent->database.chars();
m_ParseCurrent->info.host = m_ParseCurrent->host.chars();
m_ParseCurrent->info.user = m_ParseCurrent->user.chars();
m_ParseCurrent->info.pass = m_ParseCurrent->pass.chars();
/* Save it.. */
m_ParseCurrent->AddRef();
m_ParseList->append(m_ParseCurrent);
m_ParseCurrent = nullptr;
/* Go up one level */
m_ParseState = DBPARSE_LEVEL_MAIN;
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
m_ParseState = DBPARSE_LEVEL_NONE;
return SMCResult_Halt;
}
return SMCResult_Continue;
}
void DatabaseConfBuilder::ReadSMC_ParseEnd(bool halted, bool failed)
{
m_InfoList->ReleaseMembers();
delete m_InfoList;
m_InfoList = m_ParseList;
m_ParseList = nullptr;
}

View File

@ -0,0 +1,129 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2018 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_DATABASE_CONF_BUILDER_H_
#define _INCLUDE_DATABASE_CONF_BUILDER_H_
#include <IDBDriver.h>
#include <ITextParsers.h>
#include "common_logic.h"
#include <am-vector.h>
#include <am-string.h>
#include <am-refcounting-threadsafe.h>
class ConfDbInfo : public ke::RefcountedThreadsafe<ConfDbInfo>
{
public:
ConfDbInfo() : realDriver(NULL)
{
}
ke::AString name;
ke::AString driver;
ke::AString host;
ke::AString user;
ke::AString pass;
ke::AString database;
IDBDriver *realDriver;
DatabaseInfo info;
};
class ConfDbInfoList : public ke::Vector<ConfDbInfo *>
{
/* Allow internal usage of ConfDbInfoList */
friend class DBManager;
friend class DatabaseConfBuilder;
private:
ke::AString& GetDefaultDriver() {
return m_DefDriver;
}
ConfDbInfo *GetDatabaseConf(const char *name) {
for (size_t i = 0; i < this->length(); i++)
{
ConfDbInfo *current = this->at(i);
/* If we run into the default configuration, then we'll save it
* for the next call to GetDefaultConfiguration */
if (strcmp(current->name.chars(), "default") == 0)
{
m_DefaultConfig = current;
}
if (strcmp(current->name.chars(), name) == 0)
{
return current;
}
}
return nullptr;
}
ConfDbInfo *GetDefaultConfiguration() {
return m_DefaultConfig;
}
void SetDefaultDriver(const char *input) {
m_DefDriver = ke::AString(input);
}
void ReleaseMembers() {
for (size_t i = 0; i < this->length(); i++) {
ConfDbInfo *current = this->at(i);
current->Release();
}
}
private:
ConfDbInfo *m_DefaultConfig;
ke::AString m_DefDriver;
};
class DatabaseConfBuilder : public ITextListener_SMC
{
public:
DatabaseConfBuilder();
~DatabaseConfBuilder();
void StartParse();
void SetPath(char* path);
ConfDbInfoList *GetConfigList();
public: //ITextListener_SMC
void ReadSMC_ParseStart();
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
void ReadSMC_ParseEnd(bool halted, bool failed);
private:
unsigned int m_ParseLevel;
unsigned int m_ParseState;
ConfDbInfo *m_ParseCurrent;
ConfDbInfoList *m_ParseList;
private:
ke::AString m_Filename;
ConfDbInfoList *m_InfoList;
};
#endif //_INCLUDE_DATABASE_CONF_BUILDER_H_

View File

@ -29,11 +29,11 @@
* Version: $Id$ * Version: $Id$
*/ */
#include <ISourceMod.h>
#include <IPluginSys.h> #include <IPluginSys.h>
#include <stdarg.h> #include <stdarg.h>
#include "DebugReporter.h" #include "DebugReporter.h"
#include "Logger.h" #include "Logger.h"
#include <am-string.h>
DebugReport g_DbgReporter; DebugReport g_DbgReporter;
@ -194,35 +194,53 @@ void DebugReport::ReportError(const IErrorReport &report, IFrameIterator &iter)
g_Logger.LogError("[SM] Blaming: %s", blame); g_Logger.LogError("[SM] Blaming: %s", blame);
} }
if (!iter.Done()) ke::Vector<ke::AString> arr = GetStackTrace(&iter);
for (size_t i = 0; i < arr.length(); i++)
{ {
g_Logger.LogError("[SM] Call stack trace:"); g_Logger.LogError("%s", arr[i].chars());
}
}
for (int index = 0; !iter.Done(); iter.Next(), index++) ke::Vector<ke::AString> DebugReport::GetStackTrace(IFrameIterator *iter)
{
char temp[3072];
ke::Vector<ke::AString> trace;
iter->Reset();
if (!iter->Done())
{
trace.append("[SM] Call stack trace:");
for (int index = 0; !iter->Done(); iter->Next(), index++)
{ {
const char *fn = iter.FunctionName(); const char *fn = iter->FunctionName();
if (!fn) if (!fn)
{ {
fn = "<unknown function>"; fn = "<unknown function>";
} }
if (iter.IsNativeFrame()) if (iter->IsNativeFrame())
{ {
g_Logger.LogError("[SM] [%d] %s", index, fn); g_pSM->Format(temp, sizeof(temp), "[SM] [%d] %s", index, fn);
trace.append(temp);
continue; continue;
} }
if (iter.IsScriptedFrame()) if (iter->IsScriptedFrame())
{ {
const char *file = iter.FilePath(); const char *file = iter->FilePath();
if (!file) if (!file)
{ {
file = "<unknown>"; file = "<unknown>";
} }
g_Logger.LogError("[SM] [%d] Line %d, %s::%s", g_pSM->Format(temp, sizeof(temp), "[SM] [%d] Line %d, %s::%s",
index, index,
iter.LineNumber(), iter->LineNumber(),
file, file,
fn); fn);
trace.append(temp);
} }
} }
} }
return trace;
} }

View File

@ -34,6 +34,8 @@
#include "sp_vm_api.h" #include "sp_vm_api.h"
#include "common_logic.h" #include "common_logic.h"
#include <am-vector.h>
#include <am-string.h>
class DebugReport : class DebugReport :
public SMGlobalClass, public SMGlobalClass,
@ -48,6 +50,7 @@ public:
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...); void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap); void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...); void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
ke::Vector<ke::AString> GetStackTrace(IFrameIterator *iter);
private: private:
int _GetPluginIndex(IPluginContext *ctx); int _GetPluginIndex(IPluginContext *ctx);
}; };

View File

@ -73,73 +73,68 @@ CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
/* Special case for new bintools binary */ /* Special case for new bintools binary */
if (strcmp(filename, "bintools.ext") == 0) if (strcmp(filename, "bintools.ext") == 0)
{ {
goto normal;
}
/* Zeroth, see if there is an engine specific build in the new place. */
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
if (libsys->IsPathFile(path))
{
goto found;
}
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
if (strcmp(bridge->gamesuffix, "2.tf2") == 0
|| strcmp(bridge->gamesuffix, "2.dods") == 0
|| strcmp(bridge->gamesuffix, "2.hl2dm") == 0
)
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
if (libsys->IsPathFile(path))
{
goto found;
}
}
else if (strcmp(bridge->gamesuffix, "2.nd") == 0)
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
if (libsys->IsPathFile(path))
{
goto found;
}
}
/* First see if there is an engine specific build! */
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
/* Try the "normal" version */
if (!libsys->IsPathFile(path))
{
normal:
g_pSM->BuildPath(Path_SM, g_pSM->BuildPath(Path_SM,
path, path,
PLATFORM_MAX_PATH, PLATFORM_MAX_PATH,
"extensions/%s." PLATFORM_LIB_EXT, "extensions/%s." PLATFORM_LIB_EXT,
filename); filename);
} }
else
{
/* Zeroth, see if there is an engine specific build in the new place. */
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
found: if (!libsys->IsPathFile(path))
{
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
if (strcmp(bridge->gamesuffix, "2.tf2") == 0
|| strcmp(bridge->gamesuffix, "2.dods") == 0
|| strcmp(bridge->gamesuffix, "2.hl2dm") == 0
)
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
}
else if (strcmp(bridge->gamesuffix, "2.nd") == 0)
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
}
//Try further
if (!libsys->IsPathFile(path))
{
/* First see if there is an engine specific build! */
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
filename,
bridge->gamesuffix);
/* Try the "normal" version */
if (!libsys->IsPathFile(path))
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s." PLATFORM_LIB_EXT,
filename);
}
}
}
}
Initialize(filename, path, bRequired); Initialize(filename, path, bRequired);
} }
@ -176,7 +171,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
{ {
m_pLib->CloseLibrary(); m_pLib->CloseLibrary();
m_pLib = NULL; m_pLib = NULL;
snprintf(error, maxlength, "Unable to find extension entry point"); ke::SafeStrcpy(error, maxlength, "Unable to find extension entry point");
return false; return false;
} }
@ -246,7 +241,7 @@ void CLocalExtension::Unload()
bool CRemoteExtension::Reload(char *error, size_t maxlength) bool CRemoteExtension::Reload(char *error, size_t maxlength)
{ {
snprintf(error, maxlength, "Remote extensions do not support reloading"); ke::SafeStrcpy(error, maxlength, "Remote extensions do not support reloading");
return false; return false;
} }
@ -280,13 +275,13 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
{ {
if (!m_pAPI) if (!m_pAPI)
{ {
snprintf(error, maxlength, "No IExtensionInterface instance provided"); ke::SafeStrcpy(error, maxlength, "No IExtensionInterface instance provided");
return false; return false;
} }
if (m_pAPI->GetExtensionVersion() > SMINTERFACE_EXTENSIONAPI_VERSION) if (m_pAPI->GetExtensionVersion() > SMINTERFACE_EXTENSIONAPI_VERSION)
{ {
snprintf(error, maxlength, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION); ke::SafeSprintf(error, maxlength, "Extension version is too new to load (%d, max is %d)", m_pAPI->GetExtensionVersion(), SMINTERFACE_EXTENSIONAPI_VERSION);
return false; return false;
} }
@ -421,65 +416,20 @@ void CExtension::AddChildDependent(CExtension *pOther, SMInterface *iface)
m_ChildDeps.push_back(info); m_ChildDeps.push_back(info);
} }
// note: dependency iteration deprecated since 1.10
ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface)
{ {
List<IfaceInfo>::iterator iter = m_Deps.begin(); return nullptr;
if (iter == m_Deps.end())
{
return NULL;
}
if (pOwner)
{
*pOwner = (*iter).owner;
}
if (pInterface)
{
*pInterface = (*iter).iface;
}
List<IfaceInfo>::iterator *pIter = new List<IfaceInfo>::iterator(iter);
return (ITERATOR *)pIter;
} }
bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface)
{ {
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter; return false;
List<IfaceInfo>::iterator _iter;
if (_iter == m_Deps.end())
{
return false;
}
_iter++;
if (pOwner)
{
*pOwner = (*_iter).owner;
}
if (pInterface)
{
*pInterface = (*_iter).iface;
}
*pIter = _iter;
if (_iter == m_Deps.end())
{
return false;
}
return true;
} }
void CExtension::FreeDependencyIterator(ITERATOR *iter) void CExtension::FreeDependencyIterator(ITERATOR *iter)
{ {
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
delete pIter;
} }
void CExtension::AddInterface(SMInterface *pInterface) void CExtension::AddInterface(SMInterface *pInterface)
@ -493,7 +443,7 @@ bool CExtension::IsRunning(char *error, size_t maxlength)
{ {
if (error) if (error)
{ {
snprintf(error, maxlength, "%s", m_Error.c_str()); ke::SafeStrcpy(error, maxlength, m_Error.c_str());
} }
return false; return false;
} }
@ -575,7 +525,7 @@ void CExtensionManager::TryAutoload()
} }
char file[PLATFORM_MAX_PATH]; char file[PLATFORM_MAX_PATH];
len = ke::SafeSprintf(file, sizeof(file), "%s", lfile); len = ke::SafeStrcpy(file, sizeof(file), lfile);
strcpy(&file[len - 9], ".ext"); strcpy(&file[len - 9], ".ext");
LoadAutoExtension(file); LoadAutoExtension(file);
@ -591,7 +541,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
if (strcmp(ext, PLATFORM_LIB_EXT) == 0) if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{ {
char path2[PLATFORM_MAX_PATH]; char path2[PLATFORM_MAX_PATH];
ke::SafeSprintf(path2, sizeof(path2), "%s", path); ke::SafeStrcpy(path2, sizeof(path2), path);
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0'; path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadAutoExtension(path2, bErrorOnMissing); return LoadAutoExtension(path2, bErrorOnMissing);
} }
@ -683,7 +633,7 @@ IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size
if (strcmp(ext, PLATFORM_LIB_EXT) == 0) if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{ {
char path2[PLATFORM_MAX_PATH]; char path2[PLATFORM_MAX_PATH];
ke::SafeSprintf(path2, sizeof(path2), "%s", file); ke::SafeStrcpy(path2, sizeof(path2), file);
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0'; path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadExtension(path2, error, maxlength); return LoadExtension(path2, error, maxlength);
} }
@ -1136,7 +1086,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
if (pExt->unload_code == (unsigned)atoi(unload)) if (pExt->unload_code == (unsigned)atoi(unload))
{ {
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename()); ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
UnloadExtension(pExt); UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename); rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
} }
@ -1151,7 +1101,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
|| (!pExt->m_ChildDeps.size() && !pExt->m_Dependents.size())) || (!pExt->m_ChildDeps.size() && !pExt->m_Dependents.size()))
{ {
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename()); ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
UnloadExtension(pExt); UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename); rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
return; return;
@ -1252,7 +1202,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
char error[255]; char error[255];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename()); ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
if (pExt->Reload(error, sizeof(error))) if (pExt->Reload(error, sizeof(error)))
{ {

View File

@ -66,26 +66,33 @@ static const char *g_pParseEngine = NULL;
#define PSTATE_GAMEDEFS_OFFSETS 3 #define PSTATE_GAMEDEFS_OFFSETS 3
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4 #define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4
#define PSTATE_GAMEDEFS_KEYS 5 #define PSTATE_GAMEDEFS_KEYS 5
#define PSTATE_GAMEDEFS_SUPPORTED 6 #define PSTATE_GAMEDEFS_KEYS_PLATFORM 6
#define PSTATE_GAMEDEFS_SIGNATURES 7 #define PSTATE_GAMEDEFS_SUPPORTED 7
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 8 #define PSTATE_GAMEDEFS_SIGNATURES 8
#define PSTATE_GAMEDEFS_CRC 9 #define PSTATE_GAMEDEFS_SIGNATURES_SIG 9
#define PSTATE_GAMEDEFS_CRC_BINARY 10 #define PSTATE_GAMEDEFS_CRC 10
#define PSTATE_GAMEDEFS_CUSTOM 11 #define PSTATE_GAMEDEFS_CRC_BINARY 11
#define PSTATE_GAMEDEFS_ADDRESSES 12 #define PSTATE_GAMEDEFS_CUSTOM 12
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 13 #define PSTATE_GAMEDEFS_ADDRESSES 13
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 14 #define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 14
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 15
#if defined PLATFORM_X86
#define PLATFORM_ARCH_SUFFIX ""
#elif defined PLATFORM_X64
#define PLATFORM_ARCH_SUFFIX "64"
#endif
#if defined PLATFORM_WINDOWS #if defined PLATFORM_WINDOWS
#define PLATFORM_NAME "windows" #define PLATFORM_NAME "windows" PLATFORM_ARCH_SUFFIX
#define PLATFORM_SERVER_BINARY "server.dll" #define PLATFORM_SERVER_BINARY "server.dll"
#elif defined PLATFORM_LINUX #elif defined PLATFORM_LINUX
#define PLATFORM_NAME "linux" #define PLATFORM_NAME "linux" PLATFORM_ARCH_SUFFIX
#define PLATFORM_COMPAT_ALT "mac" /* Alternate platform name if game data is missing for primary one */ #define PLATFORM_COMPAT_ALT "mac" PLATFORM_ARCH_SUFFIX /* Alternate platform name if game data is missing for primary one */
#define PLATFORM_SERVER_BINARY "server_i486.so" #define PLATFORM_SERVER_BINARY "server_i486.so"
#elif defined PLATFORM_APPLE #elif defined PLATFORM_APPLE
#define PLATFORM_NAME "mac" #define PLATFORM_NAME "mac" PLATFORM_ARCH_SUFFIX
#define PLATFORM_COMPAT_ALT "linux" #define PLATFORM_COMPAT_ALT "linux" PLATFORM_ARCH_SUFFIX
#define PLATFORM_SERVER_BINARY "server.dylib" #define PLATFORM_SERVER_BINARY "server.dylib"
#endif #endif
@ -252,6 +259,13 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
} }
break; break;
} }
case PSTATE_GAMEDEFS_KEYS:
{
strncopy(m_Key, name, sizeof(m_Key));
m_ParseState = PSTATE_GAMEDEFS_KEYS_PLATFORM;
matched_platform = false;
break;
}
case PSTATE_GAMEDEFS_OFFSETS: case PSTATE_GAMEDEFS_OFFSETS:
{ {
m_Prop[0] = '\0'; m_Prop[0] = '\0';
@ -338,7 +352,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
} }
else else
{ {
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0) if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0 &&
strcmp(name, "linux64") != 0 && strcmp(name, "windows64") != 0 && strcmp(name, "mac64") != 0)
{ {
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile); logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
logger->LogError("[SM] Unrecognized platform \"%s\"", name); logger->LogError("[SM] Unrecognized platform \"%s\"", name);
@ -349,7 +364,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
} }
/* No sub-sections allowed: /* No sub-sections allowed:
case PSTATE_GAMEDEFS_OFFSETS_OFFSET: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
case PSTATE_GAMEDEFS_KEYS: case PSTATE_GAMEDEFS_KEYS_PLATFORM:
case PSTATE_GAMEDEFS_SUPPORTED: case PSTATE_GAMEDEFS_SUPPORTED:
case PSTATE_GAMEDEFS_SIGNATURES_SIG: case PSTATE_GAMEDEFS_SIGNATURES_SIG:
case PSTATE_GAMEDEFS_CRC_BINARY: case PSTATE_GAMEDEFS_CRC_BINARY:
@ -386,6 +401,13 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { } else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
ke::AString vstr(value); ke::AString vstr(value);
m_Keys.replace(key, ke::Move(vstr)); m_Keys.replace(key, ke::Move(vstr));
}
else if (m_ParseState == PSTATE_GAMEDEFS_KEYS_PLATFORM) {
if (IsPlatformCompatible(key, &matched_platform))
{
ke::AString vstr(value);
m_Keys.replace(m_Key, ke::Move(vstr));
}
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) { } else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
if (strcmp(key, "game") == 0) if (strcmp(key, "game") == 0)
{ {
@ -499,6 +521,11 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
m_ParseState = PSTATE_GAMEDEFS; m_ParseState = PSTATE_GAMEDEFS;
break; break;
} }
case PSTATE_GAMEDEFS_KEYS_PLATFORM:
{
m_ParseState = PSTATE_GAMEDEFS_KEYS;
break;
}
case PSTATE_GAMEDEFS_OFFSETS_OFFSET: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
{ {
/* Parse the offset... */ /* Parse the offset... */

View File

@ -90,6 +90,7 @@ private:
char m_Prop[64]; char m_Prop[64];
char m_offset[64]; char m_offset[64];
char m_Game[256]; char m_Game[256];
char m_Key[64];
bool bShouldBeReadingDefault; bool bShouldBeReadingDefault;
bool had_game; bool had_game;
bool matched_game; bool matched_game;

View File

@ -35,6 +35,7 @@
#include <IHandleSys.h> #include <IHandleSys.h>
#include <stdio.h> #include <stdio.h>
#include <sm_namehashset.h> #include <sm_namehashset.h>
#include <amtl/am-autoptr.h>
#include <amtl/am-string.h> #include <amtl/am-string.h>
#include <amtl/am-function.h> #include <amtl/am-function.h>
#include "common_logic.h" #include "common_logic.h"

View File

@ -66,7 +66,7 @@ CDirectory::CDirectory(const char *path)
{ {
#if defined PLATFORM_WINDOWS #if defined PLATFORM_WINDOWS
char newpath[PLATFORM_MAX_PATH]; char newpath[PLATFORM_MAX_PATH];
snprintf(newpath, sizeof(newpath), "%s\\*.*", path); ke::SafeSprintf(newpath, sizeof(newpath), "%s\\*.*", path);
m_dir = FindFirstFileA(newpath, &m_fd); m_dir = FindFirstFileA(newpath, &m_fd);
if (!IsValid()) if (!IsValid())
{ {
@ -78,7 +78,7 @@ CDirectory::CDirectory(const char *path)
{ {
/* :TODO: we need to read past "." and ".."! */ /* :TODO: we need to read past "." and ".."! */
ep = readdir(m_dir); ep = readdir(m_dir);
snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path); ke::SafeStrcpy(m_origpath, PLATFORM_MAX_PATH, path);
} else { } else {
ep = NULL; ep = NULL;
} }
@ -125,7 +125,9 @@ bool CDirectory::IsEntryDirectory()
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY); return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
#elif defined PLATFORM_POSIX #elif defined PLATFORM_POSIX
char temppath[PLATFORM_MAX_PATH]; char temppath[PLATFORM_MAX_PATH];
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName()); int ret = ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
if (static_cast<size_t>(ret) >= sizeof(temppath))
return false;
return ke::file::IsDirectory(temppath); return ke::file::IsDirectory(temppath);
#endif #endif
} }
@ -136,7 +138,9 @@ bool CDirectory::IsEntryFile()
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE)); return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
#elif defined PLATFORM_POSIX #elif defined PLATFORM_POSIX
char temppath[PLATFORM_MAX_PATH]; char temppath[PLATFORM_MAX_PATH];
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName()); int ret = ke::SafeSprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
if (static_cast<size_t>(ret) >= sizeof(temppath))
return false;
return ke::file::IsFile(temppath); return ke::file::IsFile(temppath);
#endif #endif
} }
@ -226,7 +230,7 @@ void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
const char *ae = strerror_r(code, error, maxlength); const char *ae = strerror_r(code, error, maxlength);
if (ae != error) if (ae != error)
{ {
ke::SafeSprintf(error, maxlength, "%s", ae); ke::SafeStrcpy(error, maxlength, ae);
} }
#elif defined PLATFORM_POSIX #elif defined PLATFORM_POSIX
strerror_r(code, error, maxlength); strerror_r(code, error, maxlength);
@ -305,12 +309,12 @@ size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char
#endif #endif
) )
{ {
return ke::SafeSprintf(buffer, maxlength, "%s", &path[i+1]); return ke::SafeStrcpy(buffer, maxlength, &path[i+1]);
} }
} }
/* We scanned and found no path separator */ /* We scanned and found no path separator */
return ke::SafeSprintf(buffer, maxlength, "%s", path); return ke::SafeStrcpy(buffer, maxlength, path);
} }
bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime) bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime)

View File

@ -40,10 +40,6 @@
Logger g_Logger; Logger g_Logger;
/**
* :TODO: This should be creating the log folder if it doesn't exist
*/
ConfigResult Logger::OnSourceModConfigChanged(const char *key, ConfigResult Logger::OnSourceModConfigChanged(const char *key,
const char *value, const char *value,
ConfigSource source, ConfigSource source,
@ -60,7 +56,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
} else if (strcasecmp(value, "off") == 0) { } else if (strcasecmp(value, "off") == 0) {
state = false; state = false;
} else { } else {
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"on\" or \"off\""); ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
return ConfigResult_Reject; return ConfigResult_Reject;
} }
@ -68,7 +64,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
{ {
state ? EnableLogging() : DisableLogging(); state ? EnableLogging() : DisableLogging();
} else { } else {
m_InitialState = state; m_Active = state;
} }
return ConfigResult_Accept; return ConfigResult_Accept;
@ -81,7 +77,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
} else if (strcasecmp(value, "game") == 0) { } else if (strcasecmp(value, "game") == 0) {
m_Mode = LoggingMode_Game; m_Mode = LoggingMode_Game;
} else { } else {
ke::SafeSprintf(error, maxlength, "Invalid value: must be [daily|map|game]"); ke::SafeStrcpy(error, maxlength, "Invalid value: must be [daily|map|game]");
return ConfigResult_Reject; return ConfigResult_Reject;
} }
@ -93,7 +89,12 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
void Logger::OnSourceModStartup(bool late) void Logger::OnSourceModStartup(bool late)
{ {
InitLogger(m_Mode); char buff[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs");
if (!libsys->IsPathDirectory(buff))
{
libsys->CreateFolder(buff);
}
} }
void Logger::OnSourceModAllShutdown() void Logger::OnSourceModAllShutdown()
@ -103,127 +104,7 @@ void Logger::OnSourceModAllShutdown()
void Logger::OnSourceModLevelChange(const char *mapName) void Logger::OnSourceModLevelChange(const char *mapName)
{ {
MapChange(mapName); _MapChange(mapName);
}
void Logger::_NewMapFile()
{
if (!m_Active)
{
return;
}
/* Append "Log file closed" to previous log file */
_CloseFile();
char _filename[256];
int i = 0;
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
while (true)
{
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
FILE *fp = fopen(_filename, "r");
if (!fp)
{
break;
}
fclose(fp);
i++;
}
m_NrmFileName.assign(_filename);
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
if (!fp)
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return;
} else {
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
fclose(fp);
}
}
void Logger::_CloseFile()
{
if (!m_Active)
{
return;
}
FILE *fp = NULL;
if (!m_NrmFileName.empty())
{
fp = fopen(m_NrmFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogMessage("Log file closed.");
fclose(fp);
}
m_NrmFileName.clear();
}
if (!m_ErrMapStart)
{
return;
}
fp = fopen(m_ErrFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogError("Error log file session closed.");
fclose(fp);
}
m_ErrFileName.clear();
}
void Logger::InitLogger(LoggingMode mode)
{
m_Mode = mode;
m_Active = m_InitialState;
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
m_NrmCurDay = curtime->tm_mday;
m_ErrCurDay = curtime->tm_mday;
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrFileName.assign(_filename);
switch (m_Mode)
{
case LoggingMode_PerMap:
{
if (!m_Active)
{
m_DelayedStart = true;
}
break;
}
case LoggingMode_Daily:
{
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_NrmFileName.assign(_filename);
m_DailyPrintHdr = true;
break;
}
default:
{
/* do nothing... */
break;
}
}
} }
void Logger::CloseLogger() void Logger::CloseLogger()
@ -231,6 +112,13 @@ void Logger::CloseLogger()
_CloseFile(); _CloseFile();
} }
void Logger::_CloseFile()
{
_CloseNormal();
_CloseError();
_CloseFatal();
}
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...) void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
{ {
if (!m_Active) if (!m_Active)
@ -259,11 +147,6 @@ void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap) void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
{ {
if (!m_Active)
{
return;
}
static ConVar *sv_logecho = bridge->FindConVar("sv_logecho"); static ConVar *sv_logecho = bridge->FindConVar("sv_logecho");
char buffer[3072]; char buffer[3072];
@ -282,15 +165,12 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
ke::SafeSprintf(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer); ke::SafeSprintf(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
bridge->ConPrint(conBuffer); bridge->ConPrint(conBuffer);
} }
fflush(fp);
} }
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap) void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
{ {
if (!m_Active)
{
return;
}
char buffer[3072]; char buffer[3072];
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap); ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
@ -298,8 +178,8 @@ void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
time_t t = g_pSM->GetAdjustedTime(); time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t); tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer); fprintf(fp, "L %s: %s\n", date, buffer);
fflush(fp); fflush(fp);
} }
@ -324,63 +204,14 @@ void Logger::LogMessageEx(const char *vafmt, va_list ap)
return; return;
} }
if (m_DelayedStart) FILE *pFile = _OpenNormal();
if (!pFile)
{ {
m_DelayedStart = false; return;
_NewMapFile();
} }
time_t t = g_pSM->GetAdjustedTime(); LogToOpenFileEx(pFile, vafmt, ap);
tm *curtime = localtime(&t); fclose(pFile);
FILE *fp = NULL;
if (m_Mode == LoggingMode_PerMap)
{
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
_NewMapFile();
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
goto print_error;
}
}
} else {
if (m_NrmCurDay != curtime->tm_mday)
{
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_NrmFileName.assign(_filename);
m_NrmCurDay = curtime->tm_mday;
m_DailyPrintHdr = true;
}
fp = fopen(m_NrmFileName.c_str(), "a+");
}
if (fp)
{
if (m_DailyPrintHdr)
{
char date[32];
m_DailyPrintHdr = false;
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
} else {
goto print_error;
}
return;
print_error:
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
} }
void Logger::LogError(const char *vafmt, ...) void Logger::LogError(const char *vafmt, ...)
@ -398,72 +229,20 @@ void Logger::LogErrorEx(const char *vafmt, va_list ap)
return; return;
} }
time_t t = g_pSM->GetAdjustedTime(); FILE *pFile = _OpenError();
tm *curtime = localtime(&t); if (!pFile)
if (curtime->tm_mday != m_ErrCurDay)
{ {
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrFileName.assign(_filename);
m_ErrCurDay = curtime->tm_mday;
m_ErrMapStart = false;
}
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
if (fp)
{
if (!m_ErrMapStart)
{
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod error session started\n", date);
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrMapStart = true;
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
}
else
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return; return;
} }
LogToOpenFileEx(pFile, vafmt, ap);
fclose(pFile);
} }
void Logger::MapChange(const char *mapname) void Logger::_MapChange(const char *mapname)
{ {
m_CurMapName.assign(mapname); m_CurrentMapName = mapname;
_UpdateFiles(true);
switch (m_Mode)
{
case LoggingMode_Daily:
{
LogMessage("-------- Mapchange to %s --------", mapname);
break;
}
case LoggingMode_PerMap:
{
_NewMapFile();
break;
}
default:
{
/* Do nothing... */
break;
}
}
if (m_ErrMapStart)
{
LogError("Error log file session closed.");
}
m_ErrMapStart = false;
} }
void Logger::_PrintToGameLog(const char *fmt, va_list ap) void Logger::_PrintToGameLog(const char *fmt, va_list ap)
@ -480,30 +259,6 @@ void Logger::_PrintToGameLog(const char *fmt, va_list ap)
bridge->LogToGame(msg); bridge->LogToGame(msg);
} }
const char *Logger::GetLogFileName(LogType type) const
{
switch (type)
{
case LogType_Normal:
{
return m_NrmFileName.c_str();
}
case LogType_Error:
{
return m_ErrFileName.c_str();
}
default:
{
return "";
}
}
}
LoggingMode Logger::GetLoggingMode() const
{
return m_Mode;
}
void Logger::EnableLogging() void Logger::EnableLogging()
{ {
if (m_Active) if (m_Active)
@ -539,16 +294,161 @@ void Logger::LogFatalEx(const char *msg, va_list ap)
* It's already implemented twice which is bad. * It's already implemented twice which is bad.
*/ */
char path[PLATFORM_MAX_PATH]; FILE *pFile = _OpenFatal();
if (!pFile)
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
FILE *fp = fopen(path, "at");
if (fp)
{ {
m_Active = true; return;
LogToOpenFileEx(fp, msg, ap); }
m_Active = false;
fclose(fp); LogToOpenFileEx(pFile, msg, ap);
fclose(pFile);
}
void Logger::_UpdateFiles(bool bLevelChange)
{
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
if (!bLevelChange && curtime->tm_mday == m_Day)
{
return;
}
m_Day = curtime->tm_mday;
char buff[PLATFORM_MAX_PATH];
ke::SafeSprintf(buff, sizeof(buff), "%04d%02d%02d", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
ke::AString currentDate(buff);
if (m_Mode == LoggingMode_PerMap)
{
if (bLevelChange)
{
for (size_t iter = 0; iter < static_cast<size_t>(-1); ++iter)
{
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s%u.log", currentDate.chars(), iter);
if (!libsys->IsPathFile(buff))
{
break;
}
}
}
else
{
ke::SafeStrcpy(buff, sizeof(buff), m_NormalFileName.chars());
}
}
else
{
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/L%s.log", currentDate.chars());
}
if (m_NormalFileName.compare(buff))
{
_CloseNormal();
m_NormalFileName = buff;
}
else
{
if (bLevelChange)
{
LogMessage("-------- Mapchange to %s --------", m_CurrentMapName.chars());
}
}
g_pSM->BuildPath(Path_SM, buff, sizeof(buff), "logs/errors_%s.log", currentDate.chars());
if (bLevelChange || m_ErrorFileName.compare(buff))
{
_CloseError();
m_ErrorFileName = buff;
} }
} }
FILE *Logger::_OpenNormal()
{
_UpdateFiles();
FILE *pFile = fopen(m_NormalFileName.chars(), "a+");
if (pFile == NULL)
{
_LogFatalOpen(m_NormalFileName);
return pFile;
}
if (!m_DamagedNormalFile)
{
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(pFile, "L %s: SourceMod log file session started (file \"%s\") (Version \"%s\")\n", date, m_NormalFileName.chars(), SOURCEMOD_VERSION);
m_DamagedNormalFile = true;
}
return pFile;
}
FILE *Logger::_OpenError()
{
_UpdateFiles();
FILE *pFile = fopen(m_ErrorFileName.chars(), "a+");
if (pFile == NULL)
{
_LogFatalOpen(m_ErrorFileName);
return pFile;
}
if (!m_DamagedErrorFile)
{
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(pFile, "L %s: SourceMod error session started\n", date);
fprintf(pFile, "L %s: Info (map \"%s\") (file \"%s\")\n", date, m_CurrentMapName.chars(), m_ErrorFileName.chars());
m_DamagedErrorFile = true;
}
return pFile;
}
FILE *Logger::_OpenFatal()
{
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
return fopen(path, "at");
}
void Logger::_LogFatalOpen(ke::AString &str)
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", str.chars());
LogFatal("[SM] Platform returned error: \"%s\"", error);
}
void Logger::_CloseNormal()
{
if (m_DamagedNormalFile)
{
LogMessage("Log file closed.");
m_DamagedNormalFile = false;
}
}
void Logger::_CloseError()
{
if (m_DamagedErrorFile)
{
LogError("Error log file session closed.");
m_DamagedErrorFile = false;
}
}
void Logger::_CloseFatal()
{
}

View File

@ -34,11 +34,9 @@
#include "common_logic.h" #include "common_logic.h"
#include <stdio.h> #include <stdio.h>
#include <sh_string.h> #include <amtl/am-string.h>
#include <bridge/include/ILogger.h> #include <bridge/include/ILogger.h>
using namespace SourceHook;
enum LogType enum LogType
{ {
LogType_Normal, LogType_Normal,
@ -55,9 +53,7 @@ enum LoggingMode
class Logger : public SMGlobalClass, public ILogger class Logger : public SMGlobalClass, public ILogger
{ {
public: public:
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), Logger() : m_Day(-1), m_Mode(LoggingMode_Daily), m_Active(true), m_DamagedNormalFile(false), m_DamagedErrorFile(false)
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
m_InitialState(true)
{ {
} }
public: //SMGlobalClass public: //SMGlobalClass
@ -70,7 +66,6 @@ public: //SMGlobalClass
void OnSourceModAllShutdown(); void OnSourceModAllShutdown();
void OnSourceModLevelChange(const char *mapName); void OnSourceModLevelChange(const char *mapName);
public: public:
void InitLogger(LoggingMode mode);
void CloseLogger(); void CloseLogger();
void EnableLogging(); void EnableLogging();
void DisableLogging(); void DisableLogging();
@ -85,25 +80,32 @@ public:
/* This version does not print to console, and is thus thread-safe */ /* This version does not print to console, and is thus thread-safe */
void LogToFileOnly(FILE *fp, const char *msg, ...); void LogToFileOnly(FILE *fp, const char *msg, ...);
void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap); void LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap);
void MapChange(const char *mapname);
const char *GetLogFileName(LogType type) const;
LoggingMode GetLoggingMode() const;
private: private:
void _MapChange(const char *mapname);
void _CloseFile(); void _CloseFile();
void _NewMapFile(); void _CloseNormal();
void _CloseError();
void _CloseFatal();
FILE *_OpenNormal();
FILE *_OpenError();
FILE *_OpenFatal();
void _LogFatalOpen(ke::AString &str);
void _PrintToGameLog(const char *fmt, va_list ap); void _PrintToGameLog(const char *fmt, va_list ap);
void _UpdateFiles(bool bLevelChange = false);
private: private:
String m_NrmFileName; ke::AString m_NormalFileName;
String m_ErrFileName; ke::AString m_ErrorFileName;
String m_CurMapName; ke::AString m_CurrentMapName;
int m_Day;
LoggingMode m_Mode; LoggingMode m_Mode;
int m_NrmCurDay;
int m_ErrCurDay;
bool m_ErrMapStart;
bool m_Active; bool m_Active;
bool m_DelayedStart; bool m_DamagedNormalFile;
bool m_DailyPrintHdr; bool m_DamagedErrorFile;
bool m_InitialState;
}; };
extern Logger g_Logger; extern Logger g_Logger;

View File

@ -43,18 +43,6 @@
#include <mach-o/dyld_images.h> #include <mach-o/dyld_images.h>
#include <mach-o/loader.h> #include <mach-o/loader.h>
#include <mach-o/nlist.h> #include <mach-o/nlist.h>
/* Define things from 10.6 SDK for older SDKs */
#ifndef MAC_OS_X_VERSION_10_6
struct task_dyld_info
{
mach_vm_address_t all_image_info_addr;
mach_vm_size_t all_image_info_size;
};
typedef struct task_dyld_info task_dyld_info_data_t;
#define TASK_DYLD_INFO 17
#define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
#endif // MAC_OS_X_VERSION_10_6
#endif // PLATFORM_APPLE #endif // PLATFORM_APPLE
MemoryUtils g_MemUtils; MemoryUtils g_MemUtils;
@ -63,25 +51,10 @@ MemoryUtils::MemoryUtils()
{ {
#ifdef PLATFORM_APPLE #ifdef PLATFORM_APPLE
Gestalt(gestaltSystemVersionMajor, &m_OSXMajor); task_dyld_info_data_t dyld_info;
Gestalt(gestaltSystemVersionMinor, &m_OSXMinor); mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
/* Get pointer to struct that describes all loaded mach-o images in process */ m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
{
task_dyld_info_data_t dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
}
else
{
struct nlist list[2];
memset(list, 0, sizeof(list));
list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
nlist("/usr/lib/dyld", list);
m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
}
#endif #endif
} }
@ -147,13 +120,25 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
#elif defined PLATFORM_LINUX #elif defined PLATFORM_LINUX
#ifdef PLATFORM_X86
typedef Elf32_Ehdr ElfHeader;
typedef Elf32_Shdr ElfSHeader;
typedef Elf32_Sym ElfSymbol;
#define ELF_SYM_TYPE ELF32_ST_TYPE
#else
typedef Elf64_Ehdr ElfHeader;
typedef Elf64_Shdr ElfSHeader;
typedef Elf64_Sym ElfSymbol;
#define ELF_SYM_TYPE ELF64_ST_TYPE
#endif
struct link_map *dlmap; struct link_map *dlmap;
struct stat dlstat; struct stat dlstat;
int dlfile; int dlfile;
uintptr_t map_base; uintptr_t map_base;
Elf32_Ehdr *file_hdr; ElfHeader *file_hdr;
Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr; ElfSHeader *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
Elf32_Sym *symtab; ElfSymbol *symtab;
const char *shstrtab, *strtab; const char *shstrtab, *strtab;
uint16_t section_count; uint16_t section_count;
uint32_t symbol_count; uint32_t symbol_count;
@ -204,7 +189,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
} }
/* Map library file into memory */ /* Map library file into memory */
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0); file_hdr = (ElfHeader *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
map_base = (uintptr_t)file_hdr; map_base = (uintptr_t)file_hdr;
if (file_hdr == MAP_FAILED) if (file_hdr == MAP_FAILED)
{ {
@ -219,7 +204,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
return NULL; return NULL;
} }
sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff); sections = (ElfSHeader *)(map_base + file_hdr->e_shoff);
section_count = file_hdr->e_shnum; section_count = file_hdr->e_shnum;
/* Get ELF section header string table */ /* Get ELF section header string table */
shstrtab_hdr = &sections[file_hdr->e_shstrndx]; shstrtab_hdr = &sections[file_hdr->e_shstrndx];
@ -228,7 +213,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
/* Iterate sections while looking for ELF symbol table and string table */ /* Iterate sections while looking for ELF symbol table and string table */
for (uint16_t i = 0; i < section_count; i++) for (uint16_t i = 0; i < section_count; i++)
{ {
Elf32_Shdr &hdr = sections[i]; ElfSHeader &hdr = sections[i];
const char *section_name = shstrtab + hdr.sh_name; const char *section_name = shstrtab + hdr.sh_name;
if (strcmp(section_name, ".symtab") == 0) if (strcmp(section_name, ".symtab") == 0)
@ -248,15 +233,15 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
return NULL; return NULL;
} }
symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset); symtab = (ElfSymbol *)(map_base + symtab_hdr->sh_offset);
strtab = (const char *)(map_base + strtab_hdr->sh_offset); strtab = (const char *)(map_base + strtab_hdr->sh_offset);
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize; symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
/* Iterate symbol table starting from the position we were at last time */ /* Iterate symbol table starting from the position we were at last time */
for (uint32_t i = libtable->last_pos; i < symbol_count; i++) for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
{ {
Elf32_Sym &sym = symtab[i]; ElfSymbol &sym = symtab[i];
unsigned char sym_type = ELF32_ST_TYPE(sym.st_info); unsigned char sym_type = ELF_SYM_TYPE(sym.st_info);
const char *sym_name = strtab + sym.st_name; const char *sym_name = strtab + sym.st_name;
Symbol *cur_sym; Symbol *cur_sym;
@ -280,14 +265,29 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
return symbol_entry ? symbol_entry->address : NULL; return symbol_entry ? symbol_entry->address : NULL;
#elif defined PLATFORM_APPLE #elif defined PLATFORM_APPLE
#ifdef PLATFORM_X86
typedef struct mach_header MachHeader;
typedef struct segment_command MachSegment;
typedef struct nlist MachSymbol;
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
#else
typedef struct mach_header_64 MachHeader;
typedef struct segment_command_64 MachSegment;
typedef struct nlist_64 MachSymbol;
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
#endif
typedef struct load_command MachLoadCmd;
typedef struct symtab_command MachSymHeader;
uintptr_t dlbase, linkedit_addr; uintptr_t dlbase, linkedit_addr;
uint32_t image_count; uint32_t image_count;
struct mach_header *file_hdr; MachHeader *file_hdr;
struct load_command *loadcmds; MachLoadCmd *loadcmds;
struct segment_command *linkedit_hdr; MachSegment *linkedit_hdr;
struct symtab_command *symtab_hdr; MachSymHeader *symtab_hdr;
struct nlist *symtab; MachSymbol *symtab;
const char *strtab; const char *strtab;
uint32_t loadcmd_count; uint32_t loadcmd_count;
uint32_t symbol_count; uint32_t symbol_count;
@ -357,16 +357,16 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
/* If symbol isn't in our table, then we have to locate it in memory */ /* If symbol isn't in our table, then we have to locate it in memory */
file_hdr = (struct mach_header *)dlbase; file_hdr = (MachHeader *)dlbase;
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header)); loadcmds = (MachLoadCmd *)(dlbase + sizeof(MachHeader));
loadcmd_count = file_hdr->ncmds; loadcmd_count = file_hdr->ncmds;
/* Loop through load commands until we find the ones for the symbol table */ /* Loop through load commands until we find the ones for the symbol table */
for (uint32_t i = 0; i < loadcmd_count; i++) for (uint32_t i = 0; i < loadcmd_count; i++)
{ {
if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr) if (loadcmds->cmd == MACH_LOADCMD_SEGMENT && !linkedit_hdr)
{ {
struct segment_command *seg = (struct segment_command *)loadcmds; MachSegment *seg = (MachSegment *)loadcmds;
if (strcmp(seg->segname, "__LINKEDIT") == 0) if (strcmp(seg->segname, "__LINKEDIT") == 0)
{ {
linkedit_hdr = seg; linkedit_hdr = seg;
@ -378,7 +378,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
} }
else if (loadcmds->cmd == LC_SYMTAB) else if (loadcmds->cmd == LC_SYMTAB)
{ {
symtab_hdr = (struct symtab_command *)loadcmds; symtab_hdr = (MachSymHeader *)loadcmds;
if (linkedit_hdr) if (linkedit_hdr)
{ {
break; break;
@ -386,7 +386,7 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
} }
/* Load commands are not of a fixed size which is why we add the size */ /* Load commands are not of a fixed size which is why we add the size */
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize); loadcmds = (MachLoadCmd *)((uintptr_t)loadcmds + loadcmds->cmdsize);
} }
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff) if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
@ -396,14 +396,14 @@ void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
} }
linkedit_addr = dlbase + linkedit_hdr->vmaddr; linkedit_addr = dlbase + linkedit_hdr->vmaddr;
symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff); symtab = (MachSymbol *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff); strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
symbol_count = symtab_hdr->nsyms; symbol_count = symtab_hdr->nsyms;
/* Iterate symbol table starting from the position we were at last time */ /* Iterate symbol table starting from the position we were at last time */
for (uint32_t i = libtable->last_pos; i < symbol_count; i++) for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
{ {
struct nlist &sym = symtab[i]; MachSymbol &sym = symtab[i];
/* Ignore the prepended underscore on all symbols, so +1 here */ /* Ignore the prepended underscore on all symbols, so +1 here */
const char *sym_name = strtab + sym.n_un.n_strx + 1; const char *sym_name = strtab + sym.n_un.n_strx + 1;
Symbol *cur_sym; Symbol *cur_sym;
@ -440,6 +440,12 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
#ifdef PLATFORM_X86
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_I386;
#else
const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_AMD64;
#endif
MEMORY_BASIC_INFORMATION info; MEMORY_BASIC_INFORMATION info;
IMAGE_DOS_HEADER *dos; IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *pe; IMAGE_NT_HEADERS *pe;
@ -465,10 +471,8 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
return false; return false;
} }
/* Check architecture, which is 32-bit/x86 right now /* Check architecture */
* Should change this for 64-bit if Valve gets their act together if (file->Machine != PE_FILE_MACHINE)
*/
if (file->Machine != IMAGE_FILE_MACHINE_I386)
{ {
return false; return false;
} }
@ -484,9 +488,21 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
#elif defined PLATFORM_LINUX #elif defined PLATFORM_LINUX
#ifdef PLATFORM_X86
typedef Elf32_Ehdr ElfHeader;
typedef Elf32_Phdr ElfPHeader;
const unsigned char ELF_CLASS = ELFCLASS32;
const uint16_t ELF_MACHINE = EM_386;
#else
typedef Elf64_Ehdr ElfHeader;
typedef Elf64_Phdr ElfPHeader;
const unsigned char ELF_CLASS = ELFCLASS64;
const uint16_t ELF_MACHINE = EM_X86_64;
#endif
Dl_info info; Dl_info info;
Elf32_Ehdr *file; ElfHeader *file;
Elf32_Phdr *phdr; ElfPHeader *phdr;
uint16_t phdrCount; uint16_t phdrCount;
if (!dladdr(libPtr, &info)) if (!dladdr(libPtr, &info))
@ -501,7 +517,7 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
/* This is for our insane sanity checks :o */ /* This is for our insane sanity checks :o */
baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase); baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase);
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr); file = reinterpret_cast<ElfHeader *>(baseAddr);
/* Check ELF magic */ /* Check ELF magic */
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0) if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
@ -514,11 +530,15 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
{ {
return false; return false;
} }
/* Check ELF endianness */
if (file->e_ident[EI_DATA] != ELFDATA2LSB)
{
return false;
}
/* Check ELF architecture, which is 32-bit/x86 right now /* Check ELF architecture */
* Should change this for 64-bit if Valve gets their act together if (file->e_ident[EI_CLASS] != ELF_CLASS || file->e_machine != ELF_MACHINE)
*/
if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
{ {
return false; return false;
} }
@ -530,11 +550,11 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
} }
phdrCount = file->e_phnum; phdrCount = file->e_phnum;
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff); phdr = reinterpret_cast<ElfPHeader *>(baseAddr + file->e_phoff);
for (uint16_t i = 0; i < phdrCount; i++) for (uint16_t i = 0; i < phdrCount; i++)
{ {
Elf32_Phdr &hdr = phdr[i]; ElfPHeader &hdr = phdr[i];
/* We only really care about the segment with executable code */ /* We only really care about the segment with executable code */
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R)) if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
@ -553,9 +573,25 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
#elif defined PLATFORM_APPLE #elif defined PLATFORM_APPLE
#ifdef PLATFORM_X86
typedef struct mach_header MachHeader;
typedef struct segment_command MachSegment;
const uint32_t MACH_MAGIC = MH_MAGIC;
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT;
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_I386;
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_I386_ALL;
#else
typedef struct mach_header_64 MachHeader;
typedef struct segment_command_64 MachSegment;
const uint32_t MACH_MAGIC = MH_MAGIC_64;
const uint32_t MACH_LOADCMD_SEGMENT = LC_SEGMENT_64;
const cpu_type_t MACH_CPU_TYPE = CPU_TYPE_X86_64;
const cpu_subtype_t MACH_CPU_SUBTYPE = CPU_SUBTYPE_X86_64_ALL;
#endif
Dl_info info; Dl_info info;
struct mach_header *file; MachHeader *file;
struct segment_command *seg; MachSegment *seg;
uint32_t cmd_count; uint32_t cmd_count;
if (!dladdr(libPtr, &info)) if (!dladdr(libPtr, &info))
@ -570,16 +606,16 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
/* This is for our insane sanity checks :o */ /* This is for our insane sanity checks :o */
baseAddr = (uintptr_t)info.dli_fbase; baseAddr = (uintptr_t)info.dli_fbase;
file = (struct mach_header *)baseAddr; file = (MachHeader *)baseAddr;
/* Check Mach-O magic */ /* Check Mach-O magic */
if (file->magic != MH_MAGIC) if (file->magic != MACH_MAGIC)
{ {
return false; return false;
} }
/* Check architecture (32-bit/x86) */ /* Check architecture */
if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL) if (file->cputype != MACH_CPU_TYPE || file->cpusubtype != MACH_CPU_SUBTYPE)
{ {
return false; return false;
} }
@ -591,17 +627,17 @@ bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
} }
cmd_count = file->ncmds; cmd_count = file->ncmds;
seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header)); seg = (MachSegment *)(baseAddr + sizeof(MachHeader));
/* Add up memory sizes of mapped segments */ /* Add up memory sizes of mapped segments */
for (uint32_t i = 0; i < cmd_count; i++) for (uint32_t i = 0; i < cmd_count; i++)
{ {
if (seg->cmd == LC_SEGMENT) if (seg->cmd == MACH_LOADCMD_SEGMENT)
{ {
lib.memorySize += seg->vmsize; lib.memorySize += seg->vmsize;
} }
seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize); seg = (MachSegment *)((uintptr_t)seg + seg->cmdsize);
} }
#endif #endif

View File

@ -33,6 +33,7 @@
#include <IShareSys.h> #include <IShareSys.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <am-autoptr.h>
#include <am-string.h> #include <am-string.h>
#include <am-utility.h> #include <am-utility.h>
#include <am-refcounting.h> #include <am-refcounting.h>

View File

@ -75,7 +75,7 @@ CPlugin::CPlugin(const char *file)
m_serial = ++MySerial; m_serial = ++MySerial;
m_errormsg[0] = '\0'; m_errormsg[0] = '\0';
m_DateTime[0] = '\0'; m_DateTime[0] = '\0';
ke::SafeSprintf(m_filename, sizeof(m_filename), "%s", file); ke::SafeStrcpy(m_filename, sizeof(m_filename), file);
memset(&m_info, 0, sizeof(m_info)); memset(&m_info, 0, sizeof(m_info));
@ -905,7 +905,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
if (localpath == NULL) if (localpath == NULL)
{ {
/* If no path yet, don't add a former slash */ /* If no path yet, don't add a former slash */
ke::SafeSprintf(new_local, sizeof(new_local), "%s", dir->GetEntryName()); ke::SafeStrcpy(new_local, sizeof(new_local), dir->GetEntryName());
} else { } else {
libsys->PathFormat(new_local, sizeof(new_local), "%s/%s", localpath, dir->GetEntryName()); libsys->PathFormat(new_local, sizeof(new_local), "%s/%s", localpath, dir->GetEntryName());
} }
@ -920,7 +920,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
char plugin[PLATFORM_MAX_PATH]; char plugin[PLATFORM_MAX_PATH];
if (localpath == NULL) if (localpath == NULL)
{ {
ke::SafeSprintf(plugin, sizeof(plugin), "%s", name); ke::SafeStrcpy(plugin, sizeof(plugin), name);
} else { } else {
libsys->PathFormat(plugin, sizeof(plugin), "%s/%s", localpath, name); libsys->PathFormat(plugin, sizeof(plugin), "%s/%s", localpath, name);
} }
@ -994,9 +994,9 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
if (res == LoadRes_NeverLoad) { if (res == LoadRes_NeverLoad) {
if (m_LoadingLocked) if (m_LoadingLocked)
ke::SafeSprintf(error, maxlength, "There is a global plugin loading lock in effect"); ke::SafeStrcpy(error, maxlength, "There is a global plugin loading lock in effect");
else else
ke::SafeSprintf(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)"); ke::SafeStrcpy(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
return NULL; return NULL;
} }
@ -1277,7 +1277,7 @@ bool CPluginManager::MalwareCheckPass(CPlugin *pPlugin)
unsigned char *pCodeHash = pPlugin->GetRuntime()->GetCodeHash(); unsigned char *pCodeHash = pPlugin->GetRuntime()->GetCodeHash();
char codeHashBuf[40]; char codeHashBuf[40];
ke::SafeSprintf(codeHashBuf, 40, "plugin_"); ke::SafeStrcpy(codeHashBuf, sizeof(codeHashBuf), "plugin_");
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
ke::SafeSprintf(codeHashBuf + 7 + (i * 2), 3, "%02x", pCodeHash[i]); ke::SafeSprintf(codeHashBuf + 7 + (i * 2), 3, "%02x", pCodeHash[i]);
@ -1607,7 +1607,7 @@ ConfigResult CPluginManager::OnSourceModConfigChanged(const char *key,
} else if (strcasecmp(value, "no") == 0) { } else if (strcasecmp(value, "no") == 0) {
m_bBlockBadPlugins = false; m_bBlockBadPlugins = false;
} else { } else {
ke::SafeSprintf(error, maxlength, "Invalid value: must be \"yes\" or \"no\""); ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
return ConfigResult_Reject; return ConfigResult_Reject;
} }
return ConfigResult_Accept; return ConfigResult_Accept;
@ -1701,6 +1701,9 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
char buffer[256]; char buffer[256];
unsigned int id = 1; unsigned int id = 1;
int plnum = GetPluginCount(); int plnum = GetPluginCount();
char plstr[10];
ke::SafeSprintf(plstr, sizeof(plstr), "%d", plnum);
int plpadding = strlen(plstr);
if (!plnum) if (!plnum)
{ {
@ -1709,7 +1712,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
} }
else else
{ {
rootmenu->ConsolePrint("[SM] Listing %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : ""); rootmenu->ConsolePrint("[SM] Listing %d plugin%s:", plnum, (plnum > 1) ? "s" : "");
} }
ke::LinkedList<CPlugin *> fail_list; ke::LinkedList<CPlugin *> fail_list;
@ -1721,19 +1724,19 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
const sm_plugininfo_t *info = pl->GetPublicInfo(); const sm_plugininfo_t *info = pl->GetPublicInfo();
if (pl->GetStatus() != Plugin_Running && !pl->IsSilentlyFailed()) if (pl->GetStatus() != Plugin_Running && !pl->IsSilentlyFailed())
{ {
len += ke::SafeSprintf(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetDisplayStatus())); len += ke::SafeSprintf(buffer, sizeof(buffer), " %0*d <%s>", plpadding, id, GetStatusText(pl->GetDisplayStatus()));
/* Plugin has failed to load. */ /* Plugin has failed to load. */
fail_list.append(pl); fail_list.append(pl);
} }
else else
{ {
len += ke::SafeSprintf(buffer, sizeof(buffer), " %02d", id); len += ke::SafeSprintf(buffer, sizeof(buffer), " %0*d", plpadding, id);
} }
if (pl->GetStatus() < Plugin_Created || pl->GetStatus() == Plugin_Evicted) if (pl->GetStatus() < Plugin_Created || pl->GetStatus() == Plugin_Evicted)
{ {
if (pl->IsSilentlyFailed()) if (pl->IsSilentlyFailed())
len += ke::SafeSprintf(&buffer[len], sizeof(buffer)-len, " Disabled:"); len += ke::SafeStrcpy(&buffer[len], sizeof(buffer)-len, " Disabled:");
len += ke::SafeSprintf(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename()); len += ke::SafeSprintf(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
if (IS_STR_FILLED(info->version)) if (IS_STR_FILLED(info->version))
{ {
@ -1842,11 +1845,11 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
if (pl->GetStatus() < Plugin_Created) if (pl->GetStatus() < Plugin_Created)
{ {
const sm_plugininfo_t *info = pl->GetPublicInfo(); const sm_plugininfo_t *info = pl->GetPublicInfo();
ke::SafeSprintf(name, sizeof(name), (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename()); ke::SafeStrcpy(name, sizeof(name), (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
} }
else else
{ {
ke::SafeSprintf(name, sizeof(name), "%s", pl->GetFilename()); ke::SafeStrcpy(name, sizeof(name), pl->GetFilename());
} }
if (UnloadPlugin(pl)) if (UnloadPlugin(pl))
@ -1958,11 +1961,11 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const ICommandArg
if (IPluginRuntime *runtime = pl->GetRuntime()) { if (IPluginRuntime *runtime = pl->GetRuntime()) {
unsigned char *pCodeHash = runtime->GetCodeHash(); unsigned char *pCodeHash = runtime->GetCodeHash();
unsigned char *pDataHash = runtime->GetDataHash(); unsigned char *pDataHash = runtime->GetDataHash();
char combinedHash[33]; char combinedHash[33];
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
ke::SafeSprintf(combinedHash + (i * 2), 3, "%02x", pCodeHash[i] ^ pDataHash[i]); ke::SafeSprintf(combinedHash + (i * 2), 3, "%02x", pCodeHash[i] ^ pDataHash[i]);
rootmenu->ConsolePrint(" Hash: %s", combinedHash); rootmenu->ConsolePrint(" Hash: %s", combinedHash);
} }
} else { } else {
@ -2090,7 +2093,7 @@ void CPluginManager::ReloadPluginImpl(int id, const char filename[], PluginType
char error[128]; char error[128];
bool wasloaded; bool wasloaded;
IPlugin *newpl = LoadPlugin(filename, true, ptype, error, sizeof(error), &wasloaded); IPlugin *newpl = LoadPlugin(filename, true, ptype, error, sizeof(error), &wasloaded);
if (!newpl) if (!newpl)
{ {
rootmenu->ConsolePrint("[SM] Plugin %s failed to reload: %s.", filename, error); rootmenu->ConsolePrint("[SM] Plugin %s failed to reload: %s.", filename, error);
return; return;

View File

@ -55,9 +55,6 @@
#include <bridge/include/IScriptManager.h> #include <bridge/include/IScriptManager.h>
#include <am-function.h> #include <am-function.h>
#include <ReentrantList.h> #include <ReentrantList.h>
#ifdef PLATFORM_APPLE
#include <cctype>
#endif
class CPlayer; class CPlayer;
@ -487,17 +484,10 @@ private:
{ {
/* For windows & mac, we convert the path to lower-case in order to avoid duplicate plugin loading */ /* For windows & mac, we convert the path to lower-case in order to avoid duplicate plugin loading */
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE #if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
const char *original = key.chars(); ke::AString original(key.chars());
char *copy = strdup(original); ke::AString lower = original.lowercase();
for (size_t i = 0; copy[i]; ++i) return detail::CharsAndLength(lower.chars()).hash();
{
copy[i] = tolower(copy[i]);
}
uint32_t hash = detail::CharsAndLength(copy).hash();
free(copy);
return hash;
#else #else
return key.hash(); return key.hash();
#endif #endif
@ -505,25 +495,14 @@ private:
static inline bool matches(const char *file, const CPlugin *plugin) static inline bool matches(const char *file, const CPlugin *plugin)
{ {
const char *pluginFile = const_cast<CPlugin*>(plugin)->GetFilename(); const char *pluginFileChars = const_cast<CPlugin*>(plugin)->GetFilename();
#if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE #if defined PLATFORM_WINDOWS || defined PLATFORM_APPLE
size_t fileLen = strlen(file); ke::AString pluginFile = ke::AString(pluginFileChars).lowercase();
if (fileLen != strlen(pluginFile)) ke::AString input = ke::AString(file).lowercase();
{
return false;
}
for (size_t i = 0; i < fileLen; ++i) return pluginFile == input;
{
if (tolower(file[i]) != tolower(pluginFile[i]))
{
return false;
}
}
return true;
#else #else
return strcmp(pluginFile, file) == 0; return strcmp(pluginFileChars, file) == 0;
#endif #endif
} }
}; };

View File

@ -0,0 +1,169 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2017 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*/
#include "PseudoAddrManager.h"
#ifdef PLATFORM_APPLE
#include <mach/mach.h>
#include <mach/vm_region.h>
#endif
#ifdef PLATFORM_LINUX
#include <inttypes.h>
#endif
PseudoAddressManager::PseudoAddressManager() : m_NumEntries(0)
{
}
// A pseudo address consists of a table index in the upper 6 bits and an offset in the
// lower 26 bits. The table consists of memory allocation base addresses.
void *PseudoAddressManager::FromPseudoAddress(uint32_t paddr)
{
#ifdef PLATFORM_X64
uint8_t index = paddr >> PSEUDO_OFFSET_BITS;
uint32_t offset = paddr & ((1 << PSEUDO_OFFSET_BITS) - 1);
if (index >= m_NumEntries)
return nullptr;
return reinterpret_cast<void *>(uintptr_t(m_AllocBases[index]) + offset);
#else
return nullptr;
#endif
}
uint32_t PseudoAddressManager::ToPseudoAddress(void *addr)
{
#ifdef PLATFORM_X64
uint8_t index = 0;
uint32_t offset = 0;
bool hasEntry = false;
void *base = GetAllocationBase(addr);
if (base) {
for (int i = 0; i < m_NumEntries; i++) {
if (m_AllocBases[i] == base) {
index = i;
hasEntry = true;
break;
}
}
} else {
return 0;
}
if (!hasEntry) {
index = m_NumEntries;
if (m_NumEntries < SM_ARRAYSIZE(m_AllocBases))
m_AllocBases[m_NumEntries++] = base;
else
return 0; // Table is full
}
ptrdiff_t diff = uintptr_t(addr) - uintptr_t(base);
// Ensure difference fits in 26 bits
if (diff > (UINT32_MAX >> PSEUDO_INDEX_BITS))
return 0;
return (index << PSEUDO_OFFSET_BITS) | diff;
#else
return 0;
#endif
}
void *PseudoAddressManager::GetAllocationBase(void *ptr)
{
#if defined PLATFORM_WINDOWS
MEMORY_BASIC_INFORMATION info;
if (!VirtualQuery(ptr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
return nullptr;
return info.AllocationBase;
#elif defined PLATFORM_APPLE
#ifdef PLATFORM_X86
typedef vm_region_info_t mach_vm_region_info_t;
typedef vm_region_basic_info_data_t mach_vm_region_basic_info_data_t;
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO;
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT;
#define mach_vm_region vm_region
#elif defined PLATFORM_X64
typedef vm_region_info_64_t mach_vm_region_info_t ;
typedef vm_region_basic_info_data_64_t mach_vm_region_basic_info_data_t;
const vm_region_flavor_t MACH_VM_REGION_BASIC_INFO = VM_REGION_BASIC_INFO_64;
const mach_msg_type_number_t MACH_VM_REGION_BASIC_INFO_COUNT = VM_REGION_BASIC_INFO_COUNT_64;
#define mach_vm_region vm_region_64
#endif
vm_size_t size;
vm_address_t vmaddr = reinterpret_cast<vm_address_t>(ptr);
mach_vm_region_basic_info_data_t info;
memory_object_name_t obj;
vm_region_flavor_t flavor = MACH_VM_REGION_BASIC_INFO;
mach_msg_type_number_t count = MACH_VM_REGION_BASIC_INFO_COUNT;
kern_return_t kr = mach_vm_region(mach_task_self(), &vmaddr, &size, flavor,
reinterpret_cast<mach_vm_region_info_t>(&info),
&count, &obj);
if (kr != KERN_SUCCESS)
return nullptr;
return reinterpret_cast<void *>(vmaddr);
#elif defined PLATFORM_LINUX
uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
// Format:
// lower upper prot stuff path
// 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat
FILE *fp = fopen("/proc/self/maps", "r");
if (fp) {
uintptr_t lower, upper;
while (fscanf(fp, "%" PRIxPTR "-%" PRIxPTR, &lower, &upper) != EOF) {
if (addr >= lower && addr <= upper) {
fclose(fp);
return reinterpret_cast<void *>(lower);
}
// Read to end of line
int c;
while ((c = fgetc(fp)) != '\n') {
if (c == EOF)
break;
}
if (c == EOF)
break;
}
fclose(fp);
}
return nullptr;
#endif
}

View File

@ -0,0 +1,51 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2017 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*/
#ifndef _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
#define _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_
#include "common_logic.h"
class PseudoAddressManager
{
public:
PseudoAddressManager();
public:
void *FromPseudoAddress(uint32_t paddr);
uint32_t ToPseudoAddress(void *addr);
private:
void *GetAllocationBase(void *ptr);
private:
static constexpr uint8_t PSEUDO_OFFSET_BITS = 26;
static constexpr uint8_t PSEUDO_INDEX_BITS = sizeof(uint32_t) * 8 - PSEUDO_OFFSET_BITS;
void *m_AllocBases[1 << PSEUDO_INDEX_BITS];
uint8_t m_NumEntries;
};
#endif // _INCLUDE_SOURCEMOD_PSEUDOADDRESSMANAGER_H_

View File

@ -166,7 +166,7 @@ void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
{ {
buffer[len++] = ' '; buffer[len++] = ' ';
} }
len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text); len += ke::SafeSprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
ConsolePrint("%s", buffer); ConsolePrint("%s", buffer);
} }
} }
@ -256,7 +256,7 @@ static bool sm_dump_handles(int client, const ICommandArgs *args)
auto write_handles_to_game = [] (const char *str) -> void auto write_handles_to_game = [] (const char *str) -> void
{ {
char buffer[1024]; char buffer[1024];
size_t len = ke::SafeSprintf(buffer, sizeof(buffer)-2, "%s", str); size_t len = ke::SafeStrcpy(buffer, sizeof(buffer)-2, str);
buffer[len] = '\n'; buffer[len] = '\n';
buffer[len+1] = '\0'; buffer[len+1] = '\0';

View File

@ -162,18 +162,16 @@ bool ShareSystem::RequestInterface(const char *iface_name,
SMInterface **pIface) SMInterface **pIface)
{ {
/* See if the interface exists */ /* See if the interface exists */
List<IfaceInfo>::iterator iter;
SMInterface *iface; SMInterface *iface;
IExtension *iface_owner; IExtension *iface_owner = nullptr;
bool found = false; bool found = false;
for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++) for (auto iter = m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
{ {
IfaceInfo &info = (*iter); IfaceInfo &info = *iter;
iface = info.iface; iface = info.iface;
if (strcmp(iface->GetInterfaceName(), iface_name) == 0) if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
{ {
if (iface->GetInterfaceVersion() == iface_vers if (iface->GetInterfaceVersion() == iface_vers || iface->IsVersionCompatible(iface_vers))
|| iface->IsVersionCompatible(iface_vers))
{ {
iface_owner = info.owner; iface_owner = info.owner;
found = true; found = true;

View File

@ -144,7 +144,7 @@ SMCError TextParsers::ParseSMCFile(const char *file,
fclose(fp); fclose(fp);
errstr = GetSMCErrorString(result); errstr = GetSMCErrorString(result);
ke::SafeSprintf(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error"); ke::SafeStrcpy(buffer, maxsize, errstr != NULL ? errstr : "Unknown error");
return result; return result;
} }
@ -195,7 +195,7 @@ SMCError TextParsers::ParseSMCStream(const char *stream,
result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states); result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states);
const char *errstr = GetSMCErrorString(result); const char *errstr = GetSMCErrorString(result);
ke::SafeSprintf(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error"); ke::SafeStrcpy(buffer, maxsize, errstr != NULL ? errstr : "Unknown error");
return result; return result;
} }

View File

@ -940,7 +940,7 @@ bool Translator::AddLanguage(const char *langcode, const char *description)
Language *pLanguage = new Language; Language *pLanguage = new Language;
idx = m_Languages.size(); idx = m_Languages.size();
ke::SafeSprintf(pLanguage->m_code2, sizeof(pLanguage->m_code2), "%s", langcode); ke::SafeStrcpy(pLanguage->m_code2, sizeof(pLanguage->m_code2), langcode);
pLanguage->m_CanonicalName = m_pStringTab->AddString(lower); pLanguage->m_CanonicalName = m_pStringTab->AddString(lower);
m_LCodeLookup.insert(langcode, idx); m_LCodeLookup.insert(langcode, idx);

View File

@ -55,7 +55,6 @@
#include "sprintf.h" #include "sprintf.h"
#include "LibrarySys.h" #include "LibrarySys.h"
#include "RootConsoleMenu.h" #include "RootConsoleMenu.h"
#include "CDataPack.h"
#include "CellArray.h" #include "CellArray.h"
#include <bridge/include/BridgeAPI.h> #include <bridge/include/BridgeAPI.h>
#include <bridge/include/IProviderCallbacks.h> #include <bridge/include/IProviderCallbacks.h>
@ -86,6 +85,9 @@ IScriptManager *scripts = &g_PluginSys;
IExtensionSys *extsys = &g_Extensions; IExtensionSys *extsys = &g_Extensions;
ILogger *logger = &g_Logger; ILogger *logger = &g_Logger;
CNativeOwner g_CoreNatives; CNativeOwner g_CoreNatives;
#ifdef PLATFORM_X64
PseudoAddressManager pseudoAddr;
#endif
static void AddCorePhraseFile(const char *filename) static void AddCorePhraseFile(const char *filename)
{ {
@ -115,6 +117,24 @@ static void RegisterProfiler(IProfilingTool *tool)
g_ProfileToolManager.RegisterTool(tool); g_ProfileToolManager.RegisterTool(tool);
} }
static void *FromPseudoAddress(uint32_t paddr)
{
#ifdef PLATFORM_X64
return pseudoAddr.FromPseudoAddress(paddr);
#else
return nullptr;
#endif
}
static uint32_t ToPseudoAddress(void *addr)
{
#ifdef PLATFORM_X64
return pseudoAddr.ToPseudoAddress(addr);
#else
return 0;
#endif
}
// Defined in smn_filesystem.cpp. // Defined in smn_filesystem.cpp.
extern bool OnLogPrint(const char *msg); extern bool OnLogPrint(const char *msg);
@ -146,10 +166,10 @@ static sm_logic_t logic =
GenerateError, GenerateError,
AddNatives, AddNatives,
RegisterProfiler, RegisterProfiler,
CDataPack::New,
CDataPack::Free,
CellArray::New, CellArray::New,
CellArray::Free, CellArray::Free,
FromPseudoAddress,
ToPseudoAddress,
&g_PluginSys, &g_PluginSys,
&g_ShareSys, &g_ShareSys,
&g_Extensions, &g_Extensions,

View File

@ -33,6 +33,9 @@
#define _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ #define _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
#include "../sm_globals.h" #include "../sm_globals.h"
#ifdef PLATFORM_X64
#include "PseudoAddrManager.h"
#endif
namespace SourceMod { namespace SourceMod {
class CoreProvider; class CoreProvider;
@ -57,6 +60,7 @@ class IVEngineServerBridge;
#endif #endif
} // namespace SourceMod } // namespace SourceMod
struct ServerGlobals; struct ServerGlobals;
class PseudoAddressManager;
extern SourceMod::CoreProvider *bridge; extern SourceMod::CoreProvider *bridge;
extern SourceMod::IHandleSys *handlesys; extern SourceMod::IHandleSys *handlesys;
@ -76,6 +80,7 @@ extern SourceMod::IScriptManager *scripts;
extern SourceMod::IExtensionSys *extsys; extern SourceMod::IExtensionSys *extsys;
extern SourceMod::ILogger *logger; extern SourceMod::ILogger *logger;
extern SourceMod::IMenuManager *menus; extern SourceMod::IMenuManager *menus;
extern PseudoAddressManager pseudoAddr;
#if defined SM_LOGIC #if defined SM_LOGIC
extern SourceMod::IVEngineServerBridge *engine; extern SourceMod::IVEngineServerBridge *engine;

View File

@ -31,6 +31,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "common_logic.h" #include "common_logic.h"
#include <am-autoptr.h>
#include <am-moveable.h> #include <am-moveable.h>
#include <am-refcounting.h> #include <am-refcounting.h>
#include <sm_stringhashmap.h> #include <sm_stringhashmap.h>

View File

@ -708,7 +708,11 @@ enum NumberType
static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params) static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
{ {
#ifdef PLATFORM_X86
void *addr = reinterpret_cast<void*>(params[1]); void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
#endif
if (addr == NULL) if (addr == NULL)
{ {
@ -736,7 +740,11 @@ static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params) static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
{ {
#ifdef PLATFORM_X86
void *addr = reinterpret_cast<void*>(params[1]); void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = pseudoAddr.FromPseudoAddress(params[1]);
#endif
if (addr == NULL) if (addr == NULL)
{ {
@ -929,6 +937,26 @@ static cell_t FrameIterator_GetFilePath(IPluginContext *pContext, const cell_t *
return 0; return 0;
} }
static cell_t LogStackTrace(IPluginContext *pContext, const cell_t *params)
{
char buffer[512];
g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 1);
IFrameIterator *it = pContext->CreateFrameIterator();
ke::Vector<ke::AString> arr = g_DbgReporter.GetStackTrace(it);
pContext->DestroyFrameIterator(it);
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
g_Logger.LogError("[SM] Stack trace requested: %s", buffer);
g_Logger.LogError("[SM] Called from: %s", pPlugin->GetFilename());
for (size_t i = 0; i < arr.length(); ++i)
{
g_Logger.LogError("%s", arr[i].chars());
}
return 0;
}
REGISTER_NATIVES(coreNatives) REGISTER_NATIVES(coreNatives)
{ {
{"ThrowError", ThrowError}, {"ThrowError", ThrowError},
@ -959,6 +987,7 @@ REGISTER_NATIVES(coreNatives)
{"StoreToAddress", StoreToAddress}, {"StoreToAddress", StoreToAddress},
{"IsNullVector", IsNullVector}, {"IsNullVector", IsNullVector},
{"IsNullString", IsNullString}, {"IsNullString", IsNullString},
{"LogStackTrace", LogStackTrace},
{"FrameIterator.FrameIterator", FrameIterator_Create}, {"FrameIterator.FrameIterator", FrameIterator_Create},
{"FrameIterator.Next", FrameIterator_Next}, {"FrameIterator.Next", FrameIterator_Next},

View File

@ -314,6 +314,12 @@ public:
error[0] = '\0'; error[0] = '\0';
strncopy(dbname, _dbname, sizeof(dbname)); strncopy(dbname, _dbname, sizeof(dbname));
me = scripts->FindPluginByContext(m_pFunction->GetParentContext()->GetContext()); me = scripts->FindPluginByContext(m_pFunction->GetParentContext()->GetContext());
m_pInfo = g_DBMan.GetDatabaseConf(dbname);
if (!m_pInfo)
{
g_pSM->Format(error, sizeof(error), "Could not find database config \"%s\"", dbname);
}
} }
IdentityToken_t *GetOwner() IdentityToken_t *GetOwner()
{ {
@ -325,15 +331,10 @@ public:
} }
void RunThreadPart() void RunThreadPart()
{ {
g_DBMan.LockConfig(); if (m_pInfo)
const DatabaseInfo *pInfo = g_DBMan.FindDatabaseConf(dbname);
if (!pInfo)
{ {
g_pSM->Format(error, sizeof(error), "Could not find database config \"%s\"", dbname); m_pDatabase = m_pDriver->Connect(&m_pInfo->info, false, error, sizeof(error));
} else {
m_pDatabase = m_pDriver->Connect(pInfo, false, error, sizeof(error));
} }
g_DBMan.UnlockConfig();
} }
void CancelThinkPart() void CancelThinkPart()
{ {
@ -383,6 +384,7 @@ public:
delete this; delete this;
} }
private: private:
ke::RefPtr<ConfDbInfo> m_pInfo;
IPlugin *me; IPlugin *me;
IPluginFunction *m_pFunction; IPluginFunction *m_pFunction;
IDBDriver *m_pDriver; IDBDriver *m_pDriver;
@ -453,7 +455,7 @@ static cell_t ConnectToDbAsync(IPluginContext *pContext, const cell_t *params, A
g_pSM->Format(error, g_pSM->Format(error,
sizeof(error), sizeof(error),
"Could not find driver \"%s\"", "Could not find driver \"%s\"",
pInfo->driver[0] == '\0' ? g_DBMan.GetDefaultDriverName() : pInfo->driver); pInfo->driver[0] == '\0' ? g_DBMan.GetDefaultDriverName().chars() : pInfo->driver);
} else if (!driver->IsThreadSafe()) { } else if (!driver->IsThreadSafe()) {
g_pSM->Format(error, g_pSM->Format(error,
sizeof(error), sizeof(error),
@ -1423,7 +1425,7 @@ static cell_t SQL_CheckConfig(IPluginContext *pContext, const cell_t *params)
char *name; char *name;
pContext->LocalToString(params[1], &name); pContext->LocalToString(params[1], &name);
return (g_DBMan.FindDatabaseConf(name) != NULL) ? 1 : 0; return (g_DBMan.GetDatabaseConf(name) != nullptr) ? 1 : 0;
} }
static cell_t SQL_ConnectCustom(IPluginContext *pContext, const cell_t *params) static cell_t SQL_ConnectCustom(IPluginContext *pContext, const cell_t *params)

View File

@ -61,7 +61,7 @@ public:
} }
void OnHandleDestroy(HandleType_t type, void *object) void OnHandleDestroy(HandleType_t type, void *object)
{ {
CDataPack::Free(reinterpret_cast<IDataPack *>(object)); CDataPack::Free(reinterpret_cast<CDataPack *>(object));
} }
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize) bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
{ {
@ -73,7 +73,7 @@ public:
static cell_t smn_CreateDataPack(IPluginContext *pContext, const cell_t *params) static cell_t smn_CreateDataPack(IPluginContext *pContext, const cell_t *params)
{ {
IDataPack *pDataPack = CDataPack::New(); CDataPack *pDataPack = CDataPack::New();
if (!pDataPack) if (!pDataPack)
{ {
@ -88,7 +88,7 @@ static cell_t smn_WritePackCell(IPluginContext *pContext, const cell_t *params)
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -96,7 +96,13 @@ static cell_t smn_WritePackCell(IPluginContext *pContext, const cell_t *params)
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
}
bool insert = (params[0] >= 3) ? params[3] : false;
if (!insert)
{
pDataPack->RemoveItem();
} }
pDataPack->PackCell(params[2]); pDataPack->PackCell(params[2]);
@ -109,7 +115,7 @@ static cell_t smn_WritePackFloat(IPluginContext *pContext, const cell_t *params)
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -117,7 +123,13 @@ static cell_t smn_WritePackFloat(IPluginContext *pContext, const cell_t *params)
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
}
bool insert = (params[0] >= 3) ? params[3] : false;
if (!insert)
{
pDataPack->RemoveItem();
} }
pDataPack->PackFloat(sp_ctof(params[2])); pDataPack->PackFloat(sp_ctof(params[2]));
@ -130,7 +142,7 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -138,7 +150,13 @@ static cell_t smn_WritePackString(IPluginContext *pContext, const cell_t *params
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
}
bool insert = (params[0] >= 3) ? params[3] : false;
if (!insert)
{
pDataPack->RemoveItem();
} }
char *str; char *str;
@ -153,7 +171,7 @@ static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *para
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -161,7 +179,13 @@ static cell_t smn_WritePackFunction(IPluginContext *pContext, const cell_t *para
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
}
bool insert = (params[0] >= 3) ? params[3] : false;
if (!insert)
{
pDataPack->RemoveItem();
} }
pDataPack->PackFunction(params[2]); pDataPack->PackFunction(params[2]);
@ -174,7 +198,7 @@ static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -182,12 +206,17 @@ static cell_t smn_ReadPackCell(IPluginContext *pContext, const cell_t *params)
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t))) if (!pDataPack->IsReadable())
{ {
return pContext->ThrowNativeError("DataPack operation is out of bounds."); return pContext->ThrowNativeError("Data pack operation is out of bounds.");
}
if (pDataPack->GetCurrentType() != CDataPackType::Cell)
{
return pContext->ThrowNativeError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::Cell);
} }
return pDataPack->ReadCell(); return pDataPack->ReadCell();
@ -198,7 +227,7 @@ static cell_t smn_ReadPackFloat(IPluginContext *pContext, const cell_t *params)
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -206,12 +235,17 @@ static cell_t smn_ReadPackFloat(IPluginContext *pContext, const cell_t *params)
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float))) if (!pDataPack->IsReadable())
{ {
return pContext->ThrowNativeError("DataPack operation is out of bounds."); return pContext->ThrowNativeError("Data pack operation is out of bounds.");
}
if (pDataPack->GetCurrentType() != CDataPackType::Float)
{
return pContext->ThrowNativeError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::Float);
} }
return sp_ftoc(pDataPack->ReadFloat()); return sp_ftoc(pDataPack->ReadFloat());
@ -222,7 +256,7 @@ static cell_t smn_ReadPackString(IPluginContext *pContext, const cell_t *params)
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -230,15 +264,20 @@ static cell_t smn_ReadPackString(IPluginContext *pContext, const cell_t *params)
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
const char *str; if (!pDataPack->IsReadable())
if (!(str=pDataPack->ReadString(NULL)))
{ {
return pContext->ThrowNativeError("DataPack operation is out of bounds."); return pContext->ThrowNativeError("Data pack operation is out of bounds.");
} }
if (pDataPack->GetCurrentType() != CDataPackType::String)
{
return pContext->ThrowNativeError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::String);
}
const char *str = pDataPack->ReadString(NULL);
pContext->StringToLocal(params[2], params[3], str); pContext->StringToLocal(params[2], params[3], str);
return 1; return 1;
@ -249,7 +288,7 @@ static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *param
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -257,12 +296,17 @@ static cell_t smn_ReadPackFunction(IPluginContext *pContext, const cell_t *param
if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr = handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
if (!pDataPack->IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t))) if (!pDataPack->IsReadable())
{ {
return pContext->ThrowNativeError("DataPack operation is out of bounds."); return pContext->ThrowNativeError("Data pack operation is out of bounds.");
}
if (pDataPack->GetCurrentType() != CDataPackType::Function)
{
return pContext->ThrowNativeError("Invalid data pack type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::Function);
} }
return pDataPack->ReadFunction(); return pDataPack->ReadFunction();
@ -273,7 +317,7 @@ static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -281,14 +325,17 @@ static cell_t smn_ResetPack(IPluginContext *pContext, const cell_t *params)
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
pDataPack->Reset();
if (params[2]) if (params[2])
{ {
pDataPack->ResetSize(); pDataPack->ResetSize();
} }
else
{
pDataPack->Reset();
}
return 1; return 1;
} }
@ -298,7 +345,7 @@ static cell_t smn_GetPackPosition(IPluginContext *pContext, const cell_t *params
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -306,7 +353,7 @@ static cell_t smn_GetPackPosition(IPluginContext *pContext, const cell_t *params
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
return static_cast<cell_t>(pDataPack->GetPosition()); return static_cast<cell_t>(pDataPack->GetPosition());
@ -317,7 +364,7 @@ static cell_t smn_SetPackPosition(IPluginContext *pContext, const cell_t *params
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -325,12 +372,12 @@ static cell_t smn_SetPackPosition(IPluginContext *pContext, const cell_t *params
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
if (!pDataPack->SetPosition(params[2])) if (!pDataPack->SetPosition(params[2]))
{ {
return pContext->ThrowNativeError("Invalid DataPack position, %d is out of bounds", params[2]); return pContext->ThrowNativeError("Invalid data pack position, %d is out of bounds (%d)", params[2], pDataPack->GetCapacity());
} }
return 1; return 1;
@ -341,7 +388,7 @@ static cell_t smn_IsPackReadable(IPluginContext *pContext, const cell_t *params)
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError herr; HandleError herr;
HandleSecurity sec; HandleSecurity sec;
IDataPack *pDataPack; CDataPack *pDataPack;
sec.pOwner = pContext->GetIdentity(); sec.pOwner = pContext->GetIdentity();
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
@ -349,7 +396,7 @@ static cell_t smn_IsPackReadable(IPluginContext *pContext, const cell_t *params)
if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack)) if ((herr=handlesys->ReadHandle(hndl, g_DataPackType, &sec, (void **)&pDataPack))
!= HandleError_None) != HandleError_None)
{ {
return pContext->ThrowNativeError("Invalid data pack handle %x (error %d)", hndl, herr); return pContext->ThrowNativeError("Invalid data pack handle %x (error %d).", hndl, herr);
} }
return pDataPack->IsReadable(params[2]) ? 1 : 0; return pDataPack->IsReadable(params[2]) ? 1 : 0;

View File

@ -113,14 +113,14 @@ static cell_t CreateNative(IPluginContext *pContext, const cell_t *params)
IPluginFunction *pFunction = pContext->GetFunctionById(params[2]); IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
if (!pFunction) if (!pFunction)
{ {
return pContext->ThrowNativeError("Function %x is not a valid function", params[2]); return pContext->ThrowNativeError("Failed to create native \"%s\", function %x is not a valid function", name, params[2]);
} }
pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext()); pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
if (!pPlugin->AddFakeNative(pFunction, name, FakeNativeRouter)) if (!pPlugin->AddFakeNative(pFunction, name, FakeNativeRouter))
{ {
return pContext->ThrowNativeError("Fatal error creating dynamic native!"); return pContext->ThrowNativeError("Failed to create native \"%s\", name is probably already in use", name);
} }
return 1; return 1;

View File

@ -321,7 +321,7 @@ static cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params)
{ {
size_t len = strlen(path); size_t len = strlen(path);
char wildcardedPath[PLATFORM_MAX_PATH]; char wildcardedPath[PLATFORM_MAX_PATH];
snprintf(wildcardedPath, sizeof(wildcardedPath), "%s%s*", path, (path[len-1] != '/' && path[len-1] != '\\') ? "/" : ""); ke::SafeSprintf(wildcardedPath, sizeof(wildcardedPath), "%s%s*", path, (path[len-1] != '/' && path[len-1] != '\\') ? "/" : "");
char *pathID; char *pathID;
if ((err=pContext->LocalToStringNULL(params[3], &pathID)) != SP_ERROR_NONE) if ((err=pContext->LocalToStringNULL(params[3], &pathID)) != SP_ERROR_NONE)
@ -1195,6 +1195,7 @@ REGISTER_NATIVES(filesystem)
{"File.WriteLine", sm_WriteFileLine}, {"File.WriteLine", sm_WriteFileLine},
{"File.EndOfFile", sm_IsEndOfFile}, {"File.EndOfFile", sm_IsEndOfFile},
{"File.Seek", sm_FileSeek}, {"File.Seek", sm_FileSeek},
{"File.Flush", sm_FlushFile},
{"File.Position.get", sm_FilePosition}, {"File.Position.get", sm_FilePosition},
{"File.ReadInt8", File_ReadTyped<int8_t>}, {"File.ReadInt8", File_ReadTyped<int8_t>},
{"File.ReadUint8", File_ReadTyped<uint8_t>}, {"File.ReadUint8", File_ReadTyped<uint8_t>},

View File

@ -793,29 +793,38 @@ static cell_t sm_AddFrameAction(IPluginContext *pContext, const cell_t *params)
REGISTER_NATIVES(functionNatives) REGISTER_NATIVES(functionNatives)
{ {
{"GetFunctionByName", sm_GetFunctionByName}, {"GetFunctionByName", sm_GetFunctionByName},
{"CreateGlobalForward", sm_CreateGlobalForward}, {"CreateGlobalForward", sm_CreateGlobalForward},
{"CreateForward", sm_CreateForward}, {"CreateForward", sm_CreateForward},
{"GetForwardFunctionCount", sm_GetForwardFunctionCount}, {"GetForwardFunctionCount", sm_GetForwardFunctionCount},
{"AddToForward", sm_AddToForward}, {"AddToForward", sm_AddToForward},
{"RemoveFromForward", sm_RemoveFromForward}, {"RemoveFromForward", sm_RemoveFromForward},
{"RemoveAllFromForward", sm_RemoveAllFromForward}, {"RemoveAllFromForward", sm_RemoveAllFromForward},
{"Call_StartFunction", sm_CallStartFunction}, {"Call_StartFunction", sm_CallStartFunction},
{"Call_StartForward", sm_CallStartForward}, {"Call_StartForward", sm_CallStartForward},
{"Call_StartNative", sm_CallStartNative}, {"Call_StartNative", sm_CallStartNative},
{"Call_PushCell", sm_CallPushCell}, {"Call_PushCell", sm_CallPushCell},
{"Call_PushCellRef", sm_CallPushCellRef}, {"Call_PushCellRef", sm_CallPushCellRef},
{"Call_PushFloat", sm_CallPushFloat}, {"Call_PushFloat", sm_CallPushFloat},
{"Call_PushFloatRef", sm_CallPushFloatRef}, {"Call_PushFloatRef", sm_CallPushFloatRef},
{"Call_PushArray", sm_CallPushArray}, {"Call_PushArray", sm_CallPushArray},
{"Call_PushArrayEx", sm_CallPushArrayEx}, {"Call_PushArrayEx", sm_CallPushArrayEx},
{"Call_PushString", sm_CallPushString}, {"Call_PushString", sm_CallPushString},
{"Call_PushStringEx", sm_CallPushStringEx}, {"Call_PushStringEx", sm_CallPushStringEx},
{"Call_PushNullVector", sm_CallPushNullVector}, {"Call_PushNullVector", sm_CallPushNullVector},
{"Call_PushNullString", sm_CallPushNullString}, {"Call_PushNullString", sm_CallPushNullString},
{"Call_Finish", sm_CallFinish}, {"Call_Finish", sm_CallFinish},
{"Call_FinishEx", sm_CallFinishEx}, {"Call_FinishEx", sm_CallFinishEx},
{"Call_Cancel", sm_CallCancel}, {"Call_Cancel", sm_CallCancel},
{"RequestFrame", sm_AddFrameAction}, {"RequestFrame", sm_AddFrameAction},
{NULL, NULL},
{"GlobalForward.GlobalForward", sm_CreateGlobalForward},
{"GlobalForward.FunctionCount.get", sm_GetForwardFunctionCount},
{"PrivateForward.PrivateForward", sm_CreateForward},
{"PrivateForward.AddFunction", sm_AddToForward},
{"PrivateForward.RemoveFunction", sm_RemoveFromForward},
{"PrivateForward.RemoveAllFunctions", sm_RemoveAllFromForward},
{NULL, NULL},
}; };

View File

@ -67,7 +67,10 @@ static cell_t smn_LoadGameConfigFile(IPluginContext *pCtx, const cell_t *params)
return pCtx->ThrowNativeError("Unable to open %s: %s", filename, error); return pCtx->ThrowNativeError("Unable to open %s: %s", filename, error);
} }
return handlesys->CreateHandle(g_GameConfigsType, gc, pCtx->GetIdentity(), g_pCoreIdent, NULL); Handle_t hndl = handlesys->CreateHandle(g_GameConfigsType, gc, pCtx->GetIdentity(), g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE)
g_GameConfigs.CloseGameConfigFile(gc);
return hndl;
} }
static cell_t smn_GameConfGetOffset(IPluginContext *pCtx, const cell_t *params) static cell_t smn_GameConfGetOffset(IPluginContext *pCtx, const cell_t *params)
@ -152,7 +155,11 @@ static cell_t smn_GameConfGetAddress(IPluginContext *pCtx, const cell_t *params)
if (!gc->GetAddress(key, &val)) if (!gc->GetAddress(key, &val))
return 0; return 0;
#ifdef PLATFORM_X86
return (cell_t)val; return (cell_t)val;
#else
return pseudoAddr.ToPseudoAddress(val);
#endif
} }
static GameConfigsNatives s_GameConfigsNatives; static GameConfigsNatives s_GameConfigsNatives;
@ -163,5 +170,11 @@ REGISTER_NATIVES(gameconfignatives)
{"GameConfGetOffset", smn_GameConfGetOffset}, {"GameConfGetOffset", smn_GameConfGetOffset},
{"GameConfGetKeyValue", smn_GameConfGetKeyValue}, {"GameConfGetKeyValue", smn_GameConfGetKeyValue},
{"GameConfGetAddress", smn_GameConfGetAddress}, {"GameConfGetAddress", smn_GameConfGetAddress},
// Transitional syntax support.
{"GameData.GameData", smn_LoadGameConfigFile},
{"GameData.GetOffset", smn_GameConfGetOffset},
{"GameData.GetKeyValue", smn_GameConfGetKeyValue},
{"GameData.GetAddress", smn_GameConfGetAddress},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -68,7 +68,7 @@ static cell_t sm_LoadTranslations(IPluginContext *pCtx, const cell_t *params)
IPlugin *pl = pluginsys->FindPluginByContext(pCtx->GetContext()); IPlugin *pl = pluginsys->FindPluginByContext(pCtx->GetContext());
pCtx->LocalToString(params[1], &filename); pCtx->LocalToString(params[1], &filename);
ke::SafeSprintf(buffer, sizeof(buffer), "%s", filename); ke::SafeStrcpy(buffer, sizeof(buffer), filename);
/* Make sure there is no extension */ /* Make sure there is no extension */
if ((ext = strstr(buffer, ".txt")) != NULL if ((ext = strstr(buffer, ".txt")) != NULL

View File

@ -321,9 +321,109 @@ public:
delete m_pCurMapList; delete m_pCurMapList;
m_pCurMapList = NULL; m_pCurMapList = NULL;
} }
static bool alphanum_isdigit(const char c)
{
return c >= '0' && c <= '9';
}
static int alphanum_impl(const char *l, const char *r)
{
/**
* http://www.davekoelle.com/files/alphanum.hpp
*
* compare l and r with strcmp() semantics, but using
* the "Alphanum Algorithm". This function is designed to read
* through the l and r strings only one time, for
* maximum performance. It does not allocate memory for
* substrings.
*
* Released under the MIT License - https://opensource.org/licenses/MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
enum mode_t { STRING, NUMBER } mode = STRING;
while (*l && *r)
{
if (mode == STRING)
{
char l_char, r_char;
while ((l_char = *l) && (r_char = *r))
{
// check if this are digit characters
const bool l_digit = alphanum_isdigit(l_char), r_digit = alphanum_isdigit(r_char);
// if both characters are digits, we continue in NUMBER mode
if (l_digit && r_digit)
{
mode = NUMBER;
break;
}
// if only the left character is a digit, we have a result
if (l_digit) return -1;
// if only the right character is a digit, we have a result
if (r_digit) return +1;
// compute the difference of both characters
const int diff = l_char - r_char;
// if they differ we have a result
if (diff != 0) return diff;
// otherwise process the next characters
++l;
++r;
}
}
else // mode == NUMBER
{
// get the left number
unsigned long l_int = 0;
while (*l && alphanum_isdigit(*l))
{
// TODO: this can overflow
l_int = l_int * 10 + *l - '0';
++l;
}
// get the right number
unsigned long r_int = 0;
while (*r && alphanum_isdigit(*r))
{
// TODO: this can overflow
r_int = r_int * 10 + *r - '0';
++r;
}
// if the difference is not equal to zero, we have a comparison result
const long diff = l_int - r_int;
if (diff != 0)
return diff;
// otherwise we process the next substring in STRING mode
mode = STRING;
}
}
if (*r) return -1;
if (*l) return +1;
return 0;
}
static int sort_maps_in_adt_array(const void *str1, const void *str2) static int sort_maps_in_adt_array(const void *str1, const void *str2)
{ {
return strcmp((char *)str1, (char *)str2); return alphanum_impl(static_cast<const char *>(str1), static_cast<const char *>(str2));
} }
ICellArray *UpdateMapList(ICellArray *pUseArray, const char *name, int *pSerial, unsigned int flags) ICellArray *UpdateMapList(ICellArray *pUseArray, const char *name, int *pSerial, unsigned int flags)
{ {
@ -341,7 +441,7 @@ public:
*/ */
if (strcmp(name, "default") != 0) if (strcmp(name, "default") != 0)
{ {
success = GetMapList(&pNewArray, name, &change_serial); success = GetMapList(&pNewArray, "default", &change_serial);
} }
/* If either of the last two conditions failed, try again if we can. */ /* If either of the last two conditions failed, try again if we can. */
if (!success && strcmp(name, "mapcyclefile") != 0) if (!success && strcmp(name, "mapcyclefile") != 0)

View File

@ -64,10 +64,13 @@ static const int kActivityAdmins = 4; // Show admin activity to admins anonymo
static const int kActivityAdminsNames = 8; // If 4 is specified, admin names will be shown. static const int kActivityAdminsNames = 8; // If 4 is specified, admin names will be shown.
static const int kActivityRootNames = 16; // Always show admin names to root users. static const int kActivityRootNames = 16; // Always show admin names to root users.
#define FEATURECAP_MULTITARGETFILTER_CLIENTPARAM "SourceMod MultiTargetFilter ClientParam"
class PlayerLogicHelpers : class PlayerLogicHelpers :
public SMGlobalClass, public SMGlobalClass,
public IPluginsListener, public IPluginsListener,
public ICommandTargetProcessor public ICommandTargetProcessor,
public IFeatureProvider
{ {
struct SimpleMultiTargetFilter struct SimpleMultiTargetFilter
{ {
@ -186,6 +189,7 @@ public: //SMGlobalClass
void OnSourceModAllInitialized() void OnSourceModAllInitialized()
{ {
pluginsys->AddPluginsListener(this); pluginsys->AddPluginsListener(this);
sharesys->AddCapabilityProvider(NULL, this, FEATURECAP_MULTITARGETFILTER_CLIENTPARAM);
} }
void OnSourceModShutdown() void OnSourceModShutdown()
@ -195,6 +199,7 @@ public: //SMGlobalClass
playerhelpers->UnregisterCommandTargetProcessor(this); playerhelpers->UnregisterCommandTargetProcessor(this);
filterEnabled = false; filterEnabled = false;
} }
sharesys->DropCapabilityProvider(NULL, this, FEATURECAP_MULTITARGETFILTER_CLIENTPARAM);
} }
public: //IPluginsListener public: //IPluginsListener
@ -212,6 +217,13 @@ public: //IPluginsListener
} }
} }
} }
public: //IFeatureProvider
FeatureStatus GetFeatureStatus(FeatureType type, const char *name)
{
return FeatureStatus_Available;
}
} s_PlayerLogicHelpers; } s_PlayerLogicHelpers;
static cell_t static cell_t
@ -258,18 +270,7 @@ static cell_t sm_GetClientCount(IPluginContext *pCtx, const cell_t *params)
return playerhelpers->GetNumPlayers(); return playerhelpers->GetNumPlayers();
} }
int maxplayers = playerhelpers->GetMaxClients(); return playerhelpers->GetNumClients();
int count = 0;
for (int i = 1; i <= maxplayers; ++i)
{
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
if ((pPlayer->IsConnected()) && !(pPlayer->IsInGame()))
{
count++;
}
}
return (playerhelpers->GetNumPlayers() + count);
} }
static cell_t sm_GetMaxClients(IPluginContext *pCtx, const cell_t *params) static cell_t sm_GetMaxClients(IPluginContext *pCtx, const cell_t *params)
@ -398,7 +399,7 @@ static cell_t SteamIdToLocal(IPluginContext *pCtx, int index, AuthIdType authTyp
} }
char szAuth[64]; char szAuth[64];
snprintf(szAuth, sizeof(szAuth), "%" PRIu64, steamId); ke::SafeSprintf(szAuth, sizeof(szAuth), "%" PRIu64, steamId);
pCtx->StringToLocal(local_addr, bytes, szAuth); pCtx->StringToLocal(local_addr, bytes, szAuth);
} }
@ -1124,7 +1125,6 @@ static cell_t _ShowActivity(IPluginContext *pContext,
{ {
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i); IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
if (!pPlayer->IsInGame() if (!pPlayer->IsInGame()
|| pPlayer->IsFakeClient()
|| (display_in_chat && i == client)) || (display_in_chat && i == client))
{ {
continue; continue;
@ -1251,7 +1251,6 @@ static cell_t _ShowActivity2(IPluginContext *pContext,
{ {
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i); IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
if (!pPlayer->IsInGame() if (!pPlayer->IsInGame()
|| pPlayer->IsFakeClient()
|| i == client) || i == client)
{ {
continue; continue;

View File

@ -223,6 +223,11 @@ REGISTER_NATIVES(profilerNatives)
{"EnterProfilingEvent", EnterProfilingEvent}, {"EnterProfilingEvent", EnterProfilingEvent},
{"LeaveProfilingEvent", LeaveProfilingEvent}, {"LeaveProfilingEvent", LeaveProfilingEvent},
{"IsProfilingActive", IsProfilingActive}, {"IsProfilingActive", IsProfilingActive},
{"Profiler.Profiler", CreateProfiler},
{"Profiler.Time.get", GetProfilerTime},
{"Profiler.Start", StartProfiling},
{"Profiler.Stop", StopProfiling},
{NULL, NULL}, {NULL, NULL},
}; };

View File

@ -584,12 +584,16 @@ static cell_t sm_SortADTArrayCustom(IPluginContext *pContext, const cell_t *para
REGISTER_NATIVES(sortNatives) REGISTER_NATIVES(sortNatives)
{ {
{"SortIntegers", sm_SortIntegers}, {"SortIntegers", sm_SortIntegers},
{"SortFloats", sm_SortFloats}, {"SortFloats", sm_SortFloats},
{"SortStrings", sm_SortStrings}, {"SortStrings", sm_SortStrings},
{"SortCustom1D", sm_SortCustom1D}, {"SortCustom1D", sm_SortCustom1D},
{"SortCustom2D", sm_SortCustom2D}, {"SortCustom2D", sm_SortCustom2D},
{"SortADTArray", sm_SortADTArray}, {"SortADTArray", sm_SortADTArray},
{"SortADTArrayCustom", sm_SortADTArrayCustom}, {"SortADTArrayCustom", sm_SortADTArrayCustom},
{NULL, NULL},
{"ArrayList.Sort", sm_SortADTArray},
{"ArrayList.SortCustom", sm_SortADTArrayCustom},
{NULL, NULL},
}; };

View File

@ -1171,18 +1171,12 @@ reswitch:
int userid; int userid;
if (!bridge->DescribePlayer(*value, &name, &auth, &userid)) if (!bridge->DescribePlayer(*value, &name, &auth, &userid))
return pCtx->ThrowNativeError("Client index %d is invalid (arg %d)", *value, arg); return pCtx->ThrowNativeError("Client index %d is invalid (arg %d)", *value, arg);
ke::SafeSprintf(buffer,
sizeof(buffer), ke::SafeSprintf(buffer, sizeof(buffer), "%s<%d><%s><>", name, userid, auth);
"%s<%d><%s><>",
name,
userid,
auth);
} }
else else
{ {
ke::SafeSprintf(buffer, ke::SafeStrcpy(buffer, sizeof(buffer), "Console<0><Console><Console>");
sizeof(buffer),
"Console<0><Console><Console>");
} }
if (!AddString(&buf_p, llen, buffer, width, prec, flags)) if (!AddString(&buf_p, llen, buffer, width, prec, flags))
return pCtx->ThrowNativeError("Escaped string would be truncated (arg %d)", arg); return pCtx->ThrowNativeError("Escaped string would be truncated (arg %d)", arg);

View File

@ -381,7 +381,11 @@ public:
{ {
if (len > max_size) if (len > max_size)
{ {
buffer = (char *)realloc(buffer, len); auto *newbuffer = static_cast<char *>(realloc(buffer, len));
if (!newbuffer)
return nullptr;
buffer = newbuffer;
max_size = len; max_size = len;
} }
return buffer; return buffer;
@ -420,7 +424,11 @@ cell_t InternalFormat(IPluginContext *pCtx, const cell_t *params, int start)
{ {
if (maxlen > sizeof(g_formatbuf)) if (maxlen > sizeof(g_formatbuf))
{ {
__copy_buf = g_extrabuf.GetWithSize(maxlen); char *tmpbuff = g_extrabuf.GetWithSize(maxlen);
if (!tmpbuff)
return pCtx->ThrowNativeError("Unable to allocate buffer with a size of \"%u\"", maxlen);
__copy_buf = tmpbuff;
} }
else else
{ {

View File

@ -52,8 +52,6 @@
#include <bridge/include/IPlayerInfoBridge.h> #include <bridge/include/IPlayerInfoBridge.h>
#include <bridge/include/IFileSystemBridge.h> #include <bridge/include/IFileSystemBridge.h>
#define MATCHMAKINGDS_NAME "matchmaking_ds" SOURCE_BIN_SUFFIX SOURCE_BIN_EXT
sm_logic_t logicore; sm_logic_t logicore;
IThreader *g_pThreader = nullptr; IThreader *g_pThreader = nullptr;
@ -629,13 +627,7 @@ void CoreProviderImpl::InitializeBridge()
this->serverFactory = (void *)g_SMAPI->GetServerFactory(false); this->serverFactory = (void *)g_SMAPI->GetServerFactory(false);
this->listeners = SMGlobalClass::head; this->listeners = SMGlobalClass::head;
char path[PLATFORM_MAX_PATH]; if (ke::RefPtr<ke::SharedLib> mmlib = ke::SharedLib::Open(FORMAT_SOURCE_BIN_NAME("matchmaking_ds"), NULL, 0)) {
ke::path::Format(path, sizeof(path),
"%s/bin/" MATCHMAKINGDS_NAME,
g_SMAPI->GetBaseDir());
if (ke::RefPtr<ke::SharedLib> mmlib = ke::SharedLib::Open(path, NULL, 0)) {
this->matchmakingDSFactory = this->matchmakingDSFactory =
mmlib->get<decltype(sCoreProviderImpl.matchmakingDSFactory)>("CreateInterface"); mmlib->get<decltype(sCoreProviderImpl.matchmakingDSFactory)>("CreateInterface");
} }
@ -668,7 +660,7 @@ bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength)
/* Now it's time to load the logic binary */ /* Now it's time to load the logic binary */
g_SMAPI->PathFormat(file, g_SMAPI->PathFormat(file,
sizeof(file), sizeof(file),
"%s/bin/sourcemod.logic." PLATFORM_LIB_EXT, "%s/bin/" PLATFORM_ARCH_FOLDER "sourcemod.logic." PLATFORM_LIB_EXT,
g_SourceMod.GetSourceModPath()); g_SourceMod.GetSourceModPath());
char myerror[255]; char myerror[255];
@ -681,7 +673,7 @@ bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength)
LogicLoadFunction llf = logic_->get<decltype(llf)>("logic_load"); LogicLoadFunction llf = logic_->get<decltype(llf)>("logic_load");
if (!llf) { if (!llf) {
logic_ = nullptr; logic_ = nullptr;
ke::SafeSprintf(error, maxlength, "could not find logic_load function"); ke::SafeStrcpy(error, maxlength, "could not find logic_load function");
return false; return false;
} }
@ -690,7 +682,7 @@ bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength)
logic_init_ = llf(SM_LOGIC_MAGIC); logic_init_ = llf(SM_LOGIC_MAGIC);
if (!logic_init_) { if (!logic_init_) {
ke::SafeSprintf(error, maxlength, "component version mismatch"); ke::SafeStrcpy(error, maxlength, "component version mismatch");
return false; return false;
} }
return true; return true;

View File

@ -712,7 +712,8 @@ static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
} }
if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4])) IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
if (!g_ConCmds.AddServerCommand(pFunction, name, help, params[4], pPlugin))
{ {
return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name); return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
} }
@ -742,7 +743,7 @@ static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext()); IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
const char *group = pPlugin->GetFilename(); const char *group = pPlugin->GetFilename();
if (!g_ConCmds.AddAdminCommand(pFunction, name, group, 0, help, params[4])) if (!g_ConCmds.AddAdminCommand(pFunction, name, group, 0, help, params[4], pPlugin))
{ {
return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name); return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
} }
@ -769,9 +770,9 @@ static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
pContext->LocalToString(params[5], (char **)&group); pContext->LocalToString(params[5], (char **)&group);
pFunction = pContext->GetFunctionById(params[2]); pFunction = pContext->GetFunctionById(params[2]);
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
if (group[0] == '\0') if (group[0] == '\0')
{ {
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
group = pPlugin->GetFilename(); group = pPlugin->GetFilename();
} }
@ -780,7 +781,7 @@ static cell_t sm_RegAdminCmd(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
} }
if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags)) if (!g_ConCmds.AddAdminCommand(pFunction, name, group, flags, help, cmdflags, pPlugin))
{ {
return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name); return pContext->ThrowNativeError("Command \"%s\" could not be created. A convar with the same name already exists.", name);
} }
@ -1317,6 +1318,141 @@ static cell_t FakeClientCommandKeyValues(IPluginContext *pContext, const cell_t
#endif #endif
} }
static cell_t sm_CommandIterator(IPluginContext *pContext, const cell_t *params)
{
GlobCmdIter *iter = new GlobCmdIter;
iter->started = false;
Handle_t hndl = handlesys->CreateHandle(hCmdIterType, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE)
{
delete iter;
}
return hndl;
}
static cell_t sm_CommandIteratorNext(IPluginContext *pContext, const cell_t *params)
{
GlobCmdIter *iter;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
}
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
if (!iter->started)
{
iter->iter = cmds.begin();
iter->started = true;
}
else
{
iter->iter++;
}
// iterate further, skip non-sourcemod cmds
while (iter->iter != cmds.end() && !(*(iter->iter))->sourceMod)
{
iter->iter++;
}
return iter->iter != cmds.end();
}
static cell_t sm_CommandIteratorFlags(IPluginContext *pContext, const cell_t *params)
{
GlobCmdIter *iter;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
}
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
if (!iter->started || iter->iter == cmds.end())
{
return pContext->ThrowNativeError("Invalid CommandIterator position");
}
ConCmdInfo *pInfo = (*(iter->iter));
return pInfo->eflags;
}
static cell_t sm_CommandIteratorGetDesc(IPluginContext *pContext, const cell_t *params)
{
GlobCmdIter *iter;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
}
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
if (!iter->started || iter->iter == cmds.end())
{
return pContext->ThrowNativeError("Invalid CommandIterator position");
}
ConCmdInfo *pInfo = (*(iter->iter));
pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetHelpText(), NULL);
return 1;
}
static cell_t sm_CommandIteratorGetName(IPluginContext *pContext, const cell_t *params)
{
GlobCmdIter *iter;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
}
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
if (!iter->started || iter->iter == cmds.end())
{
return pContext->ThrowNativeError("Invalid CommandIterator position");
}
ConCmdInfo *pInfo = (*(iter->iter));
pContext->StringToLocalUTF8(params[2], params[3], pInfo->pCmd->GetName(), NULL);
return 1;
}
static cell_t sm_CommandIteratorPlugin(IPluginContext *pContext, const cell_t *params)
{
GlobCmdIter *iter;
HandleError err;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
if ((err = handlesys->ReadHandle(params[1], hCmdIterType, &sec, (void **)&iter))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]);
}
const List<ConCmdInfo *> &cmds = g_ConCmds.GetCommandList();
if (!iter->started || iter->iter == cmds.end())
{
return pContext->ThrowNativeError("Invalid CommandIterator position");
}
ConCmdInfo *pInfo = (*(iter->iter));
return pInfo->pPlugin->GetMyHandle();
}
REGISTER_NATIVES(consoleNatives) REGISTER_NATIVES(consoleNatives)
{ {
{"CreateConVar", sm_CreateConVar}, {"CreateConVar", sm_CreateConVar},
@ -1383,5 +1519,12 @@ REGISTER_NATIVES(consoleNatives)
{"ConVar.AddChangeHook", sm_HookConVarChange}, {"ConVar.AddChangeHook", sm_HookConVarChange},
{"ConVar.RemoveChangeHook", sm_UnhookConVarChange}, {"ConVar.RemoveChangeHook", sm_UnhookConVarChange},
{"CommandIterator.CommandIterator", sm_CommandIterator},
{"CommandIterator.Next", sm_CommandIteratorNext},
{"CommandIterator.GetDescription", sm_CommandIteratorGetDesc},
{"CommandIterator.GetName", sm_CommandIteratorGetName},
{"CommandIterator.Flags.get", sm_CommandIteratorFlags},
{"CommandIterator.Plugin.get", sm_CommandIteratorPlugin},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -2595,7 +2595,7 @@ static cell_t GetEntityFlags(IPluginContext *pContext, const cell_t *params)
for (int32_t i = 0; i < 32; i++) for (int32_t i = 0; i < 32; i++)
{ {
int32_t flag = (1<<i); int32_t flag = (1U<<i);
if ((actual_flags & flag) == flag) if ((actual_flags & flag) == flag)
{ {
sm_flags |= SDKEntFlagToSMEntFlag(flag); sm_flags |= SDKEntFlagToSMEntFlag(flag);
@ -2641,7 +2641,7 @@ static cell_t SetEntityFlags(IPluginContext *pContext, const cell_t *params)
for (int32_t i = 0; i < 32; i++) for (int32_t i = 0; i < 32; i++)
{ {
int32_t flag = (1<<i); int32_t flag = (1U<<i);
if ((sm_flags & flag) == flag) if ((sm_flags & flag) == flag)
{ {
actual_flags |= SMEntFlagToSDKEntFlag(flag); actual_flags |= SMEntFlagToSDKEntFlag(flag);
@ -2660,7 +2660,12 @@ 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]); return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
} }
#ifdef PLATFORM_X86
return reinterpret_cast<cell_t>(pEntity); return reinterpret_cast<cell_t>(pEntity);
#else
return g_SourceMod.ToPseudoAddress(pEntity);
#endif
} }
REGISTER_NATIVES(entityNatives) REGISTER_NATIVES(entityNatives)

View File

@ -438,6 +438,22 @@ static cell_t sm_SetEventBroadcast(IPluginContext *pContext, const cell_t *param
return 1; return 1;
} }
static cell_t sm_GetEventBroadcast(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
EventInfo *pInfo;
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
if ((err=handlesys->ReadHandle(hndl, g_EventManager.GetHandleType(), &sec, (void **)&pInfo))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid game event handle %x (error %d)", hndl, err);
}
return pInfo->bDontBroadcast;
}
REGISTER_NATIVES(gameEventNatives) REGISTER_NATIVES(gameEventNatives)
{ {
{"HookEvent", sm_HookEvent}, {"HookEvent", sm_HookEvent},
@ -471,6 +487,7 @@ REGISTER_NATIVES(gameEventNatives)
{"Event.SetFloat", sm_SetEventFloat}, {"Event.SetFloat", sm_SetEventFloat},
{"Event.SetString", sm_SetEventString}, {"Event.SetString", sm_SetEventString},
{"Event.BroadcastDisabled.set", sm_SetEventBroadcast}, {"Event.BroadcastDisabled.set", sm_SetEventBroadcast},
{"Event.BroadcastDisabled.get", sm_GetEventBroadcast},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -1104,7 +1104,7 @@ static cell_t smn_KvGetSectionSymbol(IPluginContext *pCtx, const cell_t *params)
static cell_t KeyValues_Import(IPluginContext *pContext, const cell_t *params) static cell_t KeyValues_Import(IPluginContext *pContext, const cell_t *params)
{ {
// This version takes (dest, src). The original is (src, dest). // This version takes (dest, src). The original is (src, dest).
cell_t new_params[3] = { const cell_t new_params[3] = {
2, 2,
params[2], params[2],
params[1], params[1],

View File

@ -82,6 +82,38 @@ static cell_t smn_PbReadInt(IPluginContext *pCtx, const cell_t *params)
return ret; return ret;
} }
static cell_t smn_PbReadInt64(IPluginContext *pCtx, const cell_t *params)
{
GET_MSG_FROM_HANDLE_OR_ERR();
GET_FIELD_NAME_OR_ERR();
cell_t *ret;
pCtx->LocalToPhysAddr(params[3], &ret);
int64 temp;
((cell_t *)&temp)[0] = ret[0];
((cell_t *)&temp)[1] = ret[1];
if (params[4] < 0)
{
if (!msg->GetInt64OrUnsigned(strField, &temp))
{
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName().c_str());
}
}
else
{
if (!msg->GetRepeatedInt64OrUnsigned(strField, params[4], &temp))
{
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[4], msg->GetProtobufMessage()->GetTypeName().c_str());
}
}
ret[0] = ((cell_t *)&temp)[0];
ret[1] = ((cell_t *)&temp)[1];
return 1;
}
static cell_t smn_PbReadFloat(IPluginContext *pCtx, const cell_t *params) static cell_t smn_PbReadFloat(IPluginContext *pCtx, const cell_t *params)
{ {
GET_MSG_FROM_HANDLE_OR_ERR(); GET_MSG_FROM_HANDLE_OR_ERR();
@ -304,6 +336,14 @@ static cell_t smn_PbGetRepeatedFieldCount(IPluginContext *pCtx, const cell_t *pa
return cnt; return cnt;
} }
static cell_t smn_PbHasField(IPluginContext *pCtx, const cell_t *params)
{
GET_MSG_FROM_HANDLE_OR_ERR();
GET_FIELD_NAME_OR_ERR();
return msg->HasField(strField) ? 1 : 0;
}
static cell_t smn_PbSetInt(IPluginContext *pCtx, const cell_t *params) static cell_t smn_PbSetInt(IPluginContext *pCtx, const cell_t *params)
{ {
GET_MSG_FROM_HANDLE_OR_ERR(); GET_MSG_FROM_HANDLE_OR_ERR();
@ -328,6 +368,35 @@ static cell_t smn_PbSetInt(IPluginContext *pCtx, const cell_t *params)
return 1; return 1;
} }
static cell_t smn_PbSetInt64(IPluginContext *pCtx, const cell_t *params)
{
GET_MSG_FROM_HANDLE_OR_ERR();
GET_FIELD_NAME_OR_ERR();
cell_t *value;
pCtx->LocalToPhysAddr(params[3], &value);
int64 temp;
((cell_t *)&temp)[0] = value[0];
((cell_t *)&temp)[1] = value[1];
if (params[4] < 0)
{
if (!msg->SetInt64OrUnsigned(strField, temp))
{
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName().c_str());
}
}
else
{
if (!msg->SetRepeatedInt64OrUnsigned(strField, params[4], temp))
{
return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, params[4], msg->GetProtobufMessage()->GetTypeName().c_str());
}
}
return 1;
}
static cell_t smn_PbSetFloat(IPluginContext *pCtx, const cell_t *params) static cell_t smn_PbSetFloat(IPluginContext *pCtx, const cell_t *params)
{ {
GET_MSG_FROM_HANDLE_OR_ERR(); GET_MSG_FROM_HANDLE_OR_ERR();
@ -545,6 +614,25 @@ static cell_t smn_PbAddInt(IPluginContext *pCtx, const cell_t *params)
return 1; return 1;
} }
static cell_t smn_PbAddInt64(IPluginContext *pCtx, const cell_t *params)
{
GET_MSG_FROM_HANDLE_OR_ERR();
GET_FIELD_NAME_OR_ERR();
cell_t *value;
pCtx->LocalToPhysAddr(params[3], &value);
int64 temp;
((cell_t *)&temp)[0] = value[0];
((cell_t *)&temp)[1] = value[1];
if (!msg->AddInt64OrUnsigned(strField, temp))
{
return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName().c_str());
}
return 1;
}
static cell_t smn_PbAddFloat(IPluginContext *pCtx, const cell_t *params) static cell_t smn_PbAddFloat(IPluginContext *pCtx, const cell_t *params)
{ {
GET_MSG_FROM_HANDLE_OR_ERR(); GET_MSG_FROM_HANDLE_OR_ERR();
@ -770,6 +858,7 @@ REGISTER_NATIVES(protobufnatives)
// Transitional syntax. // Transitional syntax.
{"Protobuf.ReadInt", smn_PbReadInt}, {"Protobuf.ReadInt", smn_PbReadInt},
{"Protobuf.ReadInt64", smn_PbReadInt64},
{"Protobuf.ReadFloat", smn_PbReadFloat}, {"Protobuf.ReadFloat", smn_PbReadFloat},
{"Protobuf.ReadBool", smn_PbReadBool}, {"Protobuf.ReadBool", smn_PbReadBool},
{"Protobuf.ReadString", smn_PbReadString}, {"Protobuf.ReadString", smn_PbReadString},
@ -778,7 +867,9 @@ REGISTER_NATIVES(protobufnatives)
{"Protobuf.ReadVector", smn_PbReadVector}, {"Protobuf.ReadVector", smn_PbReadVector},
{"Protobuf.ReadVector2D", smn_PbReadVector2D}, {"Protobuf.ReadVector2D", smn_PbReadVector2D},
{"Protobuf.GetRepeatedFieldCount", smn_PbGetRepeatedFieldCount}, {"Protobuf.GetRepeatedFieldCount", smn_PbGetRepeatedFieldCount},
{"Protobuf.HasField", smn_PbHasField},
{"Protobuf.SetInt", smn_PbSetInt}, {"Protobuf.SetInt", smn_PbSetInt},
{"Protobuf.SetInt64", smn_PbSetInt64},
{"Protobuf.SetFloat", smn_PbSetFloat}, {"Protobuf.SetFloat", smn_PbSetFloat},
{"Protobuf.SetBool", smn_PbSetBool}, {"Protobuf.SetBool", smn_PbSetBool},
{"Protobuf.SetString", smn_PbSetString}, {"Protobuf.SetString", smn_PbSetString},
@ -787,6 +878,7 @@ REGISTER_NATIVES(protobufnatives)
{"Protobuf.SetVector", smn_PbSetVector}, {"Protobuf.SetVector", smn_PbSetVector},
{"Protobuf.SetVector2D", smn_PbSetVector2D}, {"Protobuf.SetVector2D", smn_PbSetVector2D},
{"Protobuf.AddInt", smn_PbAddInt}, {"Protobuf.AddInt", smn_PbAddInt},
{"Protobuf.AddInt64", smn_PbAddInt64},
{"Protobuf.AddFloat", smn_PbAddFloat}, {"Protobuf.AddFloat", smn_PbAddFloat},
{"Protobuf.AddBool", smn_PbAddBool}, {"Protobuf.AddBool", smn_PbAddBool},
{"Protobuf.AddString", smn_PbAddString}, {"Protobuf.AddString", smn_PbAddString},

View File

@ -110,7 +110,7 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen
{ {
if (error) if (error)
{ {
snprintf(error, maxlen, "Unable to find interface %s", MMIFACE_PLMANAGER); ke::SafeSprintf(error, maxlen, "Unable to find interface %s", MMIFACE_PLMANAGER);
} }
return false; return false;
} }

View File

@ -107,7 +107,7 @@ ConfigResult SourceModBase::OnSourceModConfigChanged(const char *key,
{ {
if (source == ConfigSource_Console) if (source == ConfigSource_Console)
{ {
ke::SafeSprintf(error, maxlength, "Cannot be set at runtime"); ke::SafeStrcpy(error, maxlength, "Cannot be set at runtime");
return ConfigResult_Reject; return ConfigResult_Reject;
} }
@ -185,7 +185,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
/* Attempt to load the JIT! */ /* Attempt to load the JIT! */
char file[PLATFORM_MAX_PATH]; char file[PLATFORM_MAX_PATH];
char myerror[255]; char myerror[255];
g_SMAPI->PathFormat(file, sizeof(file), "%s/bin/sourcepawn.jit.x86.%s", g_SMAPI->PathFormat(file, sizeof(file), "%s/bin/" PLATFORM_ARCH_FOLDER "sourcepawn.jit.x86.%s",
GetSourceModPath(), GetSourceModPath(),
PLATFORM_LIB_EXT PLATFORM_LIB_EXT
); );
@ -195,7 +195,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
{ {
if (error && maxlength) if (error && maxlength)
{ {
ke::SafeSprintf(error, maxlength, "%s (failed to load bin/sourcepawn.jit.x86.%s)", ke::SafeSprintf(error, maxlength, "%s (failed to load bin/" PLATFORM_ARCH_FOLDER "sourcepawn.jit.x86.%s)",
myerror, myerror,
PLATFORM_LIB_EXT); PLATFORM_LIB_EXT);
} }
@ -207,7 +207,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
if (!factoryFn) { if (!factoryFn) {
if (error && maxlength) if (error && maxlength)
snprintf(error, maxlength, "SourcePawn library is out of date"); ke::SafeStrcpy(error, maxlength, "SourcePawn library is out of date");
ShutdownJIT(); ShutdownJIT();
return false; return false;
} }
@ -215,7 +215,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
ISourcePawnFactory *factory = factoryFn(SOURCEPAWN_API_VERSION); ISourcePawnFactory *factory = factoryFn(SOURCEPAWN_API_VERSION);
if (!factory) { if (!factory) {
if (error && maxlength) if (error && maxlength)
snprintf(error, maxlength, "SourcePawn library is out of date"); ke::SafeStrcpy(error, maxlength, "SourcePawn library is out of date");
ShutdownJIT(); ShutdownJIT();
return false; return false;
} }
@ -223,7 +223,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
g_pPawnEnv = factory->NewEnvironment(); g_pPawnEnv = factory->NewEnvironment();
if (!g_pPawnEnv) { if (!g_pPawnEnv) {
if (error && maxlength) if (error && maxlength)
snprintf(error, maxlength, "Could not create a SourcePawn environment!"); ke::SafeStrcpy(error, maxlength, "Could not create a SourcePawn environment!");
ShutdownJIT(); ShutdownJIT();
return false; return false;
} }
@ -617,14 +617,14 @@ unsigned int SourceModBase::GetGlobalTarget() const
return m_target; return m_target;
} }
IDataPack *SourceModBase::CreateDataPack() void *SourceModBase::CreateDataPack()
{ {
return logicore.CreateDataPack(); return nullptr;
} }
void SourceModBase::FreeDataPack(IDataPack *pack) void SourceModBase::FreeDataPack(void *pack)
{ {
logicore.FreeDataPack(pack); return;
} }
Handle_t SourceModBase::GetDataPackHandleType(bool readonly) Handle_t SourceModBase::GetDataPackHandleType(bool readonly)
@ -745,6 +745,16 @@ bool SourceModBase::IsMapRunning()
return g_OnMapStarted; return g_OnMapStarted;
} }
void *SourceModBase::FromPseudoAddress(uint32_t pseudoAddr)
{
return logicore.FromPseudoAddress(pseudoAddr);
}
uint32_t SourceModBase::ToPseudoAddress(void *addr)
{
return logicore.ToPseudoAddress(addr);
}
class ConVarRegistrar : class ConVarRegistrar :
public IConCommandBaseAccessor, public IConCommandBaseAccessor,
public SMGlobalClass public SMGlobalClass

View File

@ -113,8 +113,8 @@ public: // ISourceMod
void LogMessage(IExtension *pExt, const char *format, ...); void LogMessage(IExtension *pExt, const char *format, ...);
void LogError(IExtension *pExt, const char *format, ...); void LogError(IExtension *pExt, const char *format, ...);
size_t FormatString(char *buffer, size_t maxlength, IPluginContext *pContext, const cell_t *params, unsigned int param); size_t FormatString(char *buffer, size_t maxlength, IPluginContext *pContext, const cell_t *params, unsigned int param);
IDataPack *CreateDataPack(); void *CreateDataPack();
void FreeDataPack(IDataPack *pack); void FreeDataPack(void *pack);
HandleType_t GetDataPackHandleType(bool readonly=false); HandleType_t GetDataPackHandleType(bool readonly=false);
KeyValues *ReadKeyValuesHandle(Handle_t hndl, HandleError *err=NULL, bool root=false); KeyValues *ReadKeyValuesHandle(Handle_t hndl, HandleError *err=NULL, bool root=false);
const char *GetGameFolderName() const; const char *GetGameFolderName() const;
@ -135,6 +135,8 @@ public: // ISourceMod
int GetPluginId(); int GetPluginId();
int GetShApiVersion(); int GetShApiVersion();
bool IsMapRunning(); bool IsMapRunning();
void *FromPseudoAddress(uint32_t pseudoAddr);
uint32_t ToPseudoAddress(void *addr);
private: private:
void ShutdownServices(); void ShutdownServices();
private: private:

View File

@ -1,27 +1,30 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os import os
binary = SM.ExtLibrary(builder, 'bintools.ext') for arch in SM.archs:
binary.compiler.defines += ['HOOKING_ENABLED'] binary = SM.ExtLibrary(builder, 'bintools.ext', arch)
binary.compiler.cxxincludes += [ binary.compiler.defines += ['HOOKING_ENABLED']
os.path.join(SM.mms_root, 'core', 'sourcehook'), binary.compiler.cxxincludes += [
os.path.join(builder.sourcePath, 'public', 'jit'), os.path.join(SM.mms_root, 'core', 'sourcehook'),
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'), os.path.join(builder.sourcePath, 'public', 'jit'),
] os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang': ]
binary.compiler.cxxflags += ['-fno-rtti'] if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
elif binary.compiler.family == 'msvc': binary.compiler.cxxflags += ['-fno-rtti']
binary.compiler.cxxflags += ['/GR-'] elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
binary.sources += [ binary.sources += [
'extension.cpp', 'extension.cpp',
'CallMaker.cpp', 'CallMaker.cpp',
'CallWrapper.cpp', 'CallWrapper.cpp',
'HookWrapper.cpp', '../../public/smsdk_ext.cpp'
'jit_call.cpp', ]
'jit_hook.cpp',
'../../public/smsdk_ext.cpp' if arch == 'x64':
] binary.sources += ['jit_call_x64.cpp']
else:
binary.sources += ['jit_call.cpp']
SM.extensions += [builder.Add(binary)] SM.extensions += [builder.Add(binary)]

View File

@ -82,7 +82,8 @@ ICallWrapper *CallMaker::CreateCall(void *address,
CallConvention cv, CallConvention cv,
const PassInfo *retInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], const PassInfo paramInfo[],
unsigned int numParams) unsigned int numParams,
unsigned int fnFlags)
{ {
SourceHook::CProtoInfoBuilder protoInfo(GetSHCallConvention(cv)); SourceHook::CProtoInfoBuilder protoInfo(GetSHCallConvention(cv));
@ -103,7 +104,11 @@ ICallWrapper *CallMaker::CreateCall(void *address,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
} }
#if defined PLATFORM_X64
return g_CallMaker2.CreateCall(address, &(*protoInfo), retInfo, paramInfo, fnFlags);
#else
return g_CallMaker2.CreateCall(address, &(*protoInfo)); return g_CallMaker2.CreateCall(address, &(*protoInfo));
#endif
} }
ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx, ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx,
@ -111,7 +116,8 @@ ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx,
unsigned int thisOffs, unsigned int thisOffs,
const PassInfo *retInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], const PassInfo paramInfo[],
unsigned int numParams) unsigned int numParams,
unsigned int fnFlags)
{ {
SourceHook::MemFuncInfo info; SourceHook::MemFuncInfo info;
info.isVirtual = true; info.isVirtual = true;
@ -138,12 +144,16 @@ ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
} }
#if defined PLATFORM_X64
return g_CallMaker2.CreateVirtualCall(&(*protoInfo), &info, retInfo, paramInfo, fnFlags);
#else
return g_CallMaker2.CreateVirtualCall(&(*protoInfo), &info); return g_CallMaker2.CreateVirtualCall(&(*protoInfo), &info);
#endif
} }
ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo) ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo)
{ {
#ifdef PLATFORM_X86
CallWrapper *pWrapper = new CallWrapper(protoInfo); CallWrapper *pWrapper = new CallWrapper(protoInfo);
pWrapper->SetCalleeAddr(address); pWrapper->SetCalleeAddr(address);
@ -151,11 +161,15 @@ ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo
pWrapper->SetCodeBaseAddr(addr); pWrapper->SetCodeBaseAddr(addr);
return pWrapper; return pWrapper;
#else
return nullptr;
#endif
} }
ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo, ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info) const SourceHook::MemFuncInfo *info)
{ {
#ifdef PLATFORM_X86
CallWrapper *pWrapper = new CallWrapper(protoInfo); CallWrapper *pWrapper = new CallWrapper(protoInfo);
pWrapper->SetMemFuncInfo(info); pWrapper->SetMemFuncInfo(info);
@ -163,9 +177,48 @@ ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoIn
pWrapper->SetCodeBaseAddr(addr); pWrapper->SetCodeBaseAddr(addr);
return pWrapper; return pWrapper;
#else
return nullptr;
#endif
} }
#if defined HOOKING_ENABLED ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo,
const PassInfo *retInfo, const PassInfo paramInfo[],
unsigned int fnFlags)
{
#ifdef PLATFORM_X64
CallWrapper *pWrapper = new CallWrapper(protoInfo, retInfo, paramInfo, fnFlags);
pWrapper->SetCalleeAddr(address);
void *addr = JIT_CallCompile(pWrapper, FuncAddr_Direct);
pWrapper->SetCodeBaseAddr(addr);
return pWrapper;
#else
return nullptr;
#endif
}
ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info,
const PassInfo *retInfo,
const PassInfo paramInfo[],
unsigned int fnFlags)
{
#ifdef PLATFORM_X64
CallWrapper *pWrapper = new CallWrapper(protoInfo, retInfo, paramInfo, fnFlags);
pWrapper->SetMemFuncInfo(info);
void *addr = JIT_CallCompile(pWrapper, FuncAddr_VTable);
pWrapper->SetCodeBaseAddr(addr);
return pWrapper;
#else
return nullptr;
#endif
}
#if 0
IHookWrapper *CallMaker2::CreateVirtualHook(SourceHook::ISourceHook *pSH, IHookWrapper *CallMaker2::CreateVirtualHook(SourceHook::ISourceHook *pSH,
const SourceHook::ProtoInfo *protoInfo, const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info, const SourceHook::MemFuncInfo *info,

View File

@ -34,7 +34,6 @@
#include "CallWrapper.h" #include "CallWrapper.h"
#include "HookWrapper.h"
using namespace SourceMod; using namespace SourceMod;
@ -45,26 +44,30 @@ public: //IBinTools
CallConvention cv, CallConvention cv,
const PassInfo *retInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], const PassInfo paramInfo[],
unsigned int numParams); unsigned int numParams,
unsigned int fnFlags);
ICallWrapper *CreateVCall(unsigned int vtblIdx, ICallWrapper *CreateVCall(unsigned int vtblIdx,
unsigned int vtblOffs, unsigned int vtblOffs,
unsigned int thisOffs, unsigned int thisOffs,
const PassInfo *retInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], const PassInfo paramInfo[],
unsigned int numParams); unsigned int numParams,
unsigned int fnFlags);
}; };
class CallMaker2 class CallMaker2
#if defined HOOKING_ENABLED
: public IBinTools2
#endif
{ {
public: //IBinTools2 public: //IBinTools2
virtual ICallWrapper *CreateCall(void *address, virtual ICallWrapper *CreateCall(void *address,
const SourceHook::ProtoInfo *protoInfo); const SourceHook::ProtoInfo *protoInfo);
virtual ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo, virtual ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info); const SourceHook::MemFuncInfo *info);
#if defined HOOKING_ENABLED ICallWrapper *CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo,
const PassInfo *retInfo, const PassInfo paramInfo[], unsigned int fnFlags);
ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info, const PassInfo *retInfo,
const PassInfo paramInfo[], unsigned int fnFlags);
#if 0
virtual IHookWrapper *CreateVirtualHook(SourceHook::ISourceHook *pSH, virtual IHookWrapper *CreateVirtualHook(SourceHook::ISourceHook *pSH,
const SourceHook::ProtoInfo *protoInfo, const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info, const SourceHook::MemFuncInfo *info,

View File

@ -33,7 +33,7 @@
#include "CallWrapper.h" #include "CallWrapper.h"
#include "CallMaker.h" #include "CallMaker.h"
CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo) CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo) : m_FnFlags(0)
{ {
m_AddrCodeBase = NULL; m_AddrCodeBase = NULL;
m_AddrCallee = NULL; m_AddrCallee = NULL;
@ -77,6 +77,22 @@ CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo)
} }
} }
CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], unsigned int fnFlags) : CallWrapper(protoInfo)
{
m_RetParam->fields = retInfo->fields;
m_RetParam->numFields = retInfo->numFields;
unsigned int argnum = protoInfo->numOfParams;
for (unsigned int i = 0; i < argnum; i++)
{
m_Params[i].info.fields = paramInfo[i].fields;
m_Params[i].info.numFields = paramInfo[i].numFields;
}
m_FnFlags = fnFlags;
}
CallWrapper::~CallWrapper() CallWrapper::~CallWrapper()
{ {
delete [] m_Params; delete [] m_Params;
@ -184,3 +200,8 @@ unsigned int CallWrapper::GetParamOffset(unsigned int num)
return m_Params[num].offset; return m_Params[num].offset;
} }
unsigned int CallWrapper::GetFunctionFlags()
{
return m_FnFlags;
}

View File

@ -47,6 +47,8 @@ class CallWrapper : public ICallWrapper
{ {
public: public:
CallWrapper(const SourceHook::ProtoInfo *protoInfo); CallWrapper(const SourceHook::ProtoInfo *protoInfo);
CallWrapper(const SourceHook::ProtoInfo *protoInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], unsigned int fnFlags);
~CallWrapper(); ~CallWrapper();
public: //ICallWrapper public: //ICallWrapper
CallConvention GetCallConvention(); CallConvention GetCallConvention();
@ -59,6 +61,7 @@ public: //ICallWrapper
SourceHook::ProtoInfo::CallConvention GetSHCallConvention(); SourceHook::ProtoInfo::CallConvention GetSHCallConvention();
const SourceHook::PassInfo *GetSHParamInfo(unsigned int num); const SourceHook::PassInfo *GetSHParamInfo(unsigned int num);
unsigned int GetParamOffset(unsigned int num); unsigned int GetParamOffset(unsigned int num);
unsigned int GetFunctionFlags();
public: public:
void SetCalleeAddr(void *addr); void SetCalleeAddr(void *addr);
void SetCodeBaseAddr(void *addr); void SetCodeBaseAddr(void *addr);
@ -74,6 +77,7 @@ private:
void *m_AddrCallee; void *m_AddrCallee;
void *m_AddrCodeBase; void *m_AddrCodeBase;
SourceHook::MemFuncInfo m_FuncInfo; SourceHook::MemFuncInfo m_FuncInfo;
unsigned int m_FnFlags;
}; };
#endif //_INCLUDE_SOURCEMOD_CALLWRAPPER_H_ #endif //_INCLUDE_SOURCEMOD_CALLWRAPPER_H_

View File

@ -50,12 +50,6 @@ bool BinTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
g_SPEngine = g_pSM->GetScriptingEngine(); g_SPEngine = g_pSM->GetScriptingEngine();
g_pShareSys->AddInterface(myself, &g_CallMaker); g_pShareSys->AddInterface(myself, &g_CallMaker);
/* IBinTools2 is only compatible with SH v5 */
if (g_pSM->GetShApiVersion() >= 5)
{
g_pShareSys->AddInterface(myself, &g_CallMaker2);
}
return true; return true;
} }

File diff suppressed because it is too large Load Diff

View File

@ -34,11 +34,12 @@
#include <jit_helpers.h> #include <jit_helpers.h>
#include <x86_macros.h> #include <x86_macros.h>
#include <sm_platform.h>
#include "CallWrapper.h" #include "CallWrapper.h"
#include "HookWrapper.h"
void *JIT_CallCompile(CallWrapper *pWrapper, FuncAddrMethod method); void *JIT_CallCompile(CallWrapper *pWrapper, FuncAddrMethod method);
#if defined HOOKING_ENABLED
#if 0
void *JIT_HookCompile(HookWrapper *pWrapper); void *JIT_HookCompile(HookWrapper *pWrapper);
void JIT_FreeHook(void *addr); void JIT_FreeHook(void *addr);
#endif #endif

View File

@ -214,7 +214,7 @@ inline void Write_Push_Params(JitWriter *jit,
IA32_Push_Reg(jit, kREG_EBX); IA32_Push_Reg(jit, kREG_EBX);
//push <pWrapper> //push <pWrapper>
IA32_Push_Imm32(jit, (jit_int32_t)pWrapper); IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)pWrapper);
} }
inline void Write_Call_Handler(JitWriter *jit, void *addr) inline void Write_Call_Handler(JitWriter *jit, void *addr)

View File

@ -0,0 +1,656 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod BinTools Extension
* Copyright (C) 2004-2017 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*/
#include <jit_helpers.h>
#include <x86_macros.h>
// 64-bit registers
const jit_uint8_t kREG_RAX = kREG_EAX;
const jit_uint8_t kREG_RCX = kREG_ECX;
const jit_uint8_t kREG_RDX = kREG_EDX;
const jit_uint8_t kREG_RBX = kREG_EBX;
const jit_uint8_t kREG_RSP = kREG_ESP;
const jit_uint8_t kREG_RBP = kREG_EBP;
const jit_uint8_t kREG_RSI = kREG_ESI;
const jit_uint8_t kREG_RDI = kREG_EDI;
const jit_uint8_t kREG_R8 = 8;
const jit_uint8_t kREG_R9 = 9;
const jit_uint8_t kREG_R10 = 10;
const jit_uint8_t kREG_R11 = 11;
const jit_uint8_t kREG_R12 = 12;
const jit_uint8_t kREG_R13 = 13;
const jit_uint8_t kREG_R14 = 14;
const jit_uint8_t kREG_R15 = 15;
const jit_uint8_t kREG_XMM0 = 0;
const jit_uint8_t kREG_XMM1 = 1;
const jit_uint8_t kREG_XMM2 = 2;
const jit_uint8_t kREG_XMM3 = 3;
const jit_uint8_t kREG_XMM4 = 4;
const jit_uint8_t kREG_XMM5 = 5;
const jit_uint8_t kREG_XMM6 = 6;
const jit_uint8_t kREG_XMM7 = 7;
const jit_uint8_t kREG_XMM8 = 8;
const jit_uint8_t kREG_XMM9 = 9;
const jit_uint8_t kREG_XMM10 = 10;
const jit_uint8_t kREG_XMM11 = 11;
const jit_uint8_t kREG_XMM12 = 12;
const jit_uint8_t kREG_XMM13 = 13;
const jit_uint8_t kREG_XMM14 = 14;
const jit_uint8_t kREG_XMM15 = 15;
#define X64_REX_PREFIX 0x40
#define IA32_MOV_REG8_IMM8 0xB0
inline jit_uint8_t x64_rex(bool w, jit_uint8_t r, jit_uint8_t x, jit_uint8_t b)
{
return (X64_REX_PREFIX | ((jit_uint8_t)w << 3) | ((r>>3) << 2) | ((x>>3) << 1) | (b >> 3));
}
inline void X64_Push_Reg(JitWriter *jit, jit_uint8_t reg)
{
if (reg >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, reg));
IA32_Push_Reg(jit, reg & 7);
}
inline void X64_Mov_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Mov_Reg_Rm(jit, dest & 7, src & 7, mode);
}
inline void X64_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Mov_Reg_Rm_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_Reg_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Mov_Reg_Rm_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_Reg32_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
if (src>= kREG_R8 || dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
IA32_Mov_Reg_Rm(jit, dest & 7, src & 7, mode);
}
inline void X64_Mov_Reg32_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (src>= kREG_R8 || dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
IA32_Mov_Reg_Rm_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_Reg32_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (src>= kREG_R8 || dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
IA32_Mov_Reg_Rm_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_And_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value)
{
jit->write_ubyte(x64_rex(true, 0, 0, reg));
IA32_And_Rm_Imm8(jit, reg & 7, mode, value);
}
inline void X64_Sub_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t val, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 5, 0, reg));
IA32_Sub_Rm_Imm8(jit, reg & 7, val, mode);
}
inline void X64_Sub_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t val, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 5, 0, reg));
IA32_Sub_Rm_Imm32(jit, reg & 7, val, mode);
}
inline void X64_Pop_Reg(JitWriter *jit, jit_uint8_t reg)
{
if (reg >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, reg));
IA32_Pop_Reg(jit, reg & 7);
}
inline void X64_Return(JitWriter *jit)
{
IA32_Return(jit);
}
inline void X64_Movzx_Reg64_Rm8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm8_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Movzx_Reg64_Rm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm8(jit, dest & 7, src & 7, mode);
}
inline void X64_Movzx_Reg64_Rm8_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm8_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_RmRSP_Reg(JitWriter *jit, jit_uint8_t src)
{
jit->write_ubyte(x64_rex(true, kREG_RSP, 0, src));
jit->write_ubyte(IA32_MOV_RM_REG);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, kREG_RSP));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, kREG_RSP));
}
inline void X64_Mov_RmRSP_Disp8_Reg(JitWriter *jit, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, src, 0, kREG_RSP));
jit->write_ubyte(IA32_MOV_RM_REG);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, kREG_RSP));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, kREG_RSP));
jit->write_byte(disp);
}
inline void X64_Mov_RmRSP_Disp32_Reg(JitWriter *jit, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, src, 0, kREG_RSP));
jit->write_ubyte(IA32_MOV_RM_REG);
jit->write_ubyte(ia32_modrm(MOD_DISP32, src & 7, kREG_RSP));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, kREG_RSP));
jit->write_byte(disp);
}
inline void X64_Movzx_Reg64_Rm16(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm16(jit, dest & 7, src & 7, mode);
}
inline void X64_Movzx_Reg64_Rm16_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm16_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Movzx_Reg64_Rm16_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm16_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_Lea_DispRegImm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int8_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_base));
IA32_Lea_DispRegImm8(jit, dest & 7, src_base & 7, val);
}
inline void X64_Lea_DispRegImm32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int32_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_base));
IA32_Lea_DispRegImm32(jit, dest & 7, src_base & 7, val);
}
inline void X64_Add_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t value, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 0, 0, reg));
IA32_Add_Rm_Imm8(jit, reg & 7, value, mode);
}
inline void X64_Add_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t value, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 0, 0, reg));
IA32_Add_Rm_Imm32(jit, reg & 7, value, mode);
}
inline void X64_Movaps_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movups_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movaps_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
}
inline void X64_Movapd_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
}
inline void X64_Movups_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
}
inline void X64_Movupd_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
}
inline void X64_Movupd_Rm_Disp8_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(0x66);
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movaps_Rm_Disp8_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp8_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movaps_Rm_Disp32_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_DISP32, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp32_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_DISP32, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movlps_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x12);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movhps_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x16);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movaps_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movlps_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x12);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movhps_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x16);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movaps_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movapd_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movupd_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movapd_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movupd_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movapd_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movupd_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Cld(JitWriter *jit)
{
IA32_Cld(jit);
}
inline void X64_Rep(JitWriter *jit)
{
IA32_Rep(jit);
}
inline void X64_Movsq(JitWriter *jit)
{
jit->write_ubyte(x64_rex(true, 0, 0, 0));
jit->write_ubyte(IA32_MOVSD);
}
inline void X64_Movsb(JitWriter *jit)
{
jit->write_ubyte(IA32_MOVSB);
}
inline void X64_Lea_Reg_DispRegMultImm8(JitWriter *jit,
jit_uint8_t dest,
jit_uint8_t src_base,
jit_uint8_t src_index,
jit_uint8_t scale,
jit_int8_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_index));
IA32_Lea_Reg_DispRegMultImm8(jit, dest & 7, src_base, src_index & 7, scale, val);
}
inline void X64_Lea_Reg_DispRegMultImm32(JitWriter *jit,
jit_uint8_t dest,
jit_uint8_t src_base,
jit_uint8_t src_index,
jit_uint8_t scale,
jit_int32_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_index));
jit->write_ubyte(IA32_LEA_REG_MEM);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, kREG_SIB));
jit->write_ubyte(ia32_sib(scale, src_index & 7, src_base));
jit->write_int32(val);
}
inline jitoffs_t X64_Mov_Reg_Imm32(JitWriter *jit, jit_uint8_t dest, jit_int32_t num)
{
jitoffs_t offs;
jit->write_ubyte(x64_rex(true, 0, 0, dest));
jit->write_ubyte(0xC7);
jit->write_ubyte(ia32_modrm(MOD_REG, 0, dest & 7));
offs = jit->get_outputpos();
jit->write_int32(num);
return offs;
}
inline jitoffs_t X64_Mov_Reg_Imm64(JitWriter *jit, jit_uint8_t dest, jit_int64_t num)
{
jitoffs_t offs;
jit->write_ubyte(x64_rex(true, 0, 0, dest));
jit->write_ubyte(IA32_MOV_REG_IMM+(dest & 7));
offs = jit->get_outputpos();
jit->write_int64(num);
return offs;
}
inline void X64_Mov_Rm8_Reg8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
if (dest >= kREG_R8 || src > kREG_R8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(IA32_MOV_RM8_REG8);
if ((dest & 7) == kREG_RBP) // Using rbp/r13 requires a displacement
mode = MOD_DISP8;
jit->write_ubyte(ia32_modrm(mode, src & 7, dest & 7));
if ((dest & 7) == kREG_RSP) // rsp/r12 needs SIB byte
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
else if ((dest & 7) == kREG_RBP)
jit->write_ubyte(0); // Displacement of 0 needed to use rbp/r13
}
inline void X64_Mov_Rm32_Reg32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
if (dest >= kREG_R8 || src > kREG_R8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(IA32_MOV_RM_REG);
if ((dest & 7) == kREG_RBP) // Using rbp/r13 requires a displacement
mode = MOD_DISP8;
jit->write_ubyte(ia32_modrm(mode, src & 7, dest & 7));
if ((dest & 7) == kREG_RSP) // rsp/r12 needs SIB byte
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
else if ((dest & 7) == kREG_RBP)
jit->write_ubyte(0); // Displacement of 0 needed to use rbp/r13
}
inline void X64_Mov_Rm16_Reg16(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(IA32_16BIT_PREFIX);
X64_Mov_Rm32_Reg32(jit, dest, src, mode);
}
inline void X64_Mov_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, src, 0, dest));
jit->write_ubyte(IA32_MOV_RM_REG);
if ((dest & 7) == kREG_RBP) // Using rbp/r13 requires a displacement
mode = MOD_DISP8;
jit->write_ubyte(ia32_modrm(mode, src & 7, dest & 7));
if ((dest & 7) == kREG_RSP) // rsp/r12 needs SIB byte
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
else if ((dest & 7) == kREG_RBP)
jit->write_ubyte(0); // Displacement of 0 needed to use rbp/r13
}
inline void X64_Mov_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, src, 0, dest));
IA32_Mov_Rm_Reg_Disp8(jit, dest & 7, src & 7, disp);
}
inline jitoffs_t X64_Call_Imm32(JitWriter *jit, jit_int32_t disp)
{
return IA32_Call_Imm32(jit, disp);
}
inline void X64_Write_Jump32_Abs(JitWriter *jit, jitoffs_t jmp, void *target)
{
IA32_Write_Jump32_Abs(jit, jmp, target);
}
inline void X64_Call_Reg(JitWriter *jit, jit_uint8_t reg)
{
if (reg >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, reg));
IA32_Call_Reg(jit, reg & 7);
}
inline jitoffs_t X64_Mov_Reg8_Imm8(JitWriter *jit, jit_uint8_t dest, jit_int8_t value)
{
jitoffs_t offs;
if (dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, dest));
jit->write_ubyte(IA32_MOV_REG8_IMM8+(dest & 7));
offs = jit->get_outputpos();
jit->write_byte(value);
return offs;
}
inline void X64_Movd_Reg32_Xmm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
if (dest >= kREG_R8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x7E);
jit->write_ubyte(ia32_modrm(MOD_REG, src & 7, dest & 7));
}
inline void X64_Movq_Reg_Xmm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
jit->write_ubyte(x64_rex(true, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x7E);
jit->write_ubyte(ia32_modrm(MOD_REG, src & 7, dest & 7));
}

View File

@ -1,23 +1,24 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os import os
binary = SM.ExtLibrary(builder, 'clientprefs.ext') for arch in SM.archs:
binary.compiler.cxxincludes += [ binary = SM.ExtLibrary(builder, 'clientprefs.ext', arch)
os.path.join(SM.mms_root, 'core', 'sourcehook'), binary.compiler.cxxincludes += [
] os.path.join(SM.mms_root, 'core', 'sourcehook'),
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang': ]
binary.compiler.cxxflags += ['-fno-rtti'] if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
elif binary.compiler.family == 'msvc': binary.compiler.cxxflags += ['-fno-rtti']
binary.compiler.cxxflags += ['/GR-'] elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
binary.sources += [ binary.sources += [
'extension.cpp', 'extension.cpp',
'cookie.cpp', 'cookie.cpp',
'menus.cpp', 'menus.cpp',
'natives.cpp', 'natives.cpp',
'query.cpp', 'query.cpp',
'../../public/smsdk_ext.cpp' '../../public/smsdk_ext.cpp'
] ]
SM.extensions += [builder.Add(binary)] SM.extensions += [builder.Add(binary)]

View File

@ -56,20 +56,14 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
if (DBInfo == NULL) if (DBInfo == NULL)
{ {
DBInfo = dbi->FindDatabaseConf("default"); DBInfo = dbi->FindDatabaseConf("storage-local");
if (DBInfo == NULL) if (DBInfo == NULL)
{ {
DBInfo = dbi->FindDatabaseConf("storage-local"); ke::SafeStrcpy(error, maxlength, "Could not find any suitable database configs");
return false;
} }
} }
if (DBInfo == NULL)
{
snprintf(error, maxlength, "Could not find any suitable database configs");
return false;
}
if (DBInfo->driver && DBInfo->driver[0] != '\0') if (DBInfo->driver && DBInfo->driver[0] != '\0')
{ {
Driver = dbi->FindOrLoadDriver(DBInfo->driver); Driver = dbi->FindOrLoadDriver(DBInfo->driver);
@ -81,7 +75,7 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
if (Driver == NULL) if (Driver == NULL)
{ {
snprintf(error, maxlength, "Could not load DB Driver \"%s\"", DBInfo->driver); ke::SafeSprintf(error, maxlength, "Could not load DB Driver \"%s\"", DBInfo->driver);
return false; return false;
} }

View File

@ -471,20 +471,82 @@ cell_t GetClientCookieTime(IPluginContext *pContext, const cell_t *params)
return value; return value;
} }
static cell_t Cookie_Set(IPluginContext *pContext, const cell_t *params)
{
// This version takes (handle, client, value). The original is (client, handle, value).
const cell_t new_params[4] = {
3,
params[2],
params[1],
params[3]
};
return SetClientPrefCookie(pContext, new_params);
}
static cell_t Cookie_Get(IPluginContext *pContext, const cell_t *params)
{
// This verson takes (handle, client, buffer, maxlen). The original is (client, handle, buffer, maxlen).
const cell_t new_params[5] = {
4,
params[2],
params[1],
params[3],
params[4]
};
return GetClientPrefCookie(pContext, new_params);
}
static cell_t Cookie_SetByAuthId(IPluginContext *pContext, const cell_t *params)
{
// This version takes (handle, authid, value). The original is (authid, handle, value).
const cell_t new_params[4] = {
3,
params[2],
params[1],
params[3]
};
return SetAuthIdCookie(pContext, new_params);
}
static cell_t Cookie_GetClientTime(IPluginContext *pContext, const cell_t *params)
{
// This version takes (handle, client). The original is (client, handle)
const cell_t new_params[3] = {
2,
params[2],
params[1],
};
return GetClientCookieTime(pContext, new_params);
}
sp_nativeinfo_t g_ClientPrefNatives[] = sp_nativeinfo_t g_ClientPrefNatives[] =
{ {
{"RegClientCookie", RegClientPrefCookie}, {"RegClientCookie", RegClientPrefCookie},
{"FindClientCookie", FindClientPrefCookie}, {"FindClientCookie", FindClientPrefCookie},
{"SetClientCookie", SetClientPrefCookie}, {"SetClientCookie", SetClientPrefCookie},
{"SetAuthIdCookie", SetAuthIdCookie}, {"SetAuthIdCookie", SetAuthIdCookie},
{"GetClientCookie", GetClientPrefCookie}, {"GetClientCookie", GetClientPrefCookie},
{"AreClientCookiesCached", AreClientCookiesCached}, {"AreClientCookiesCached", AreClientCookiesCached},
{"GetCookieAccess", GetCookieAccess}, {"GetCookieAccess", GetCookieAccess},
{"ReadCookieIterator", ReadCookieIterator}, {"ReadCookieIterator", ReadCookieIterator},
{"GetCookieIterator", GetCookieIterator}, {"GetCookieIterator", GetCookieIterator},
{"ShowCookieMenu", ShowSettingsMenu}, {"ShowCookieMenu", ShowSettingsMenu},
{"SetCookieMenuItem", AddSettingsMenuItem}, {"SetCookieMenuItem", AddSettingsMenuItem},
{"SetCookiePrefabMenu", AddSettingsPrefabMenuItem}, {"SetCookiePrefabMenu", AddSettingsPrefabMenuItem},
{"GetClientCookieTime", GetClientCookieTime}, {"GetClientCookieTime", GetClientCookieTime},
{NULL, NULL}
{"Cookie.Cookie", RegClientPrefCookie},
{"Cookie.Find", FindClientPrefCookie},
{"Cookie.Set", Cookie_Set},
{"Cookie.Get", Cookie_Get},
{"Cookie.SetByAuthId", Cookie_SetByAuthId},
{"Cookie.SetPrefabMenu", AddSettingsPrefabMenuItem},
{"Cookie.GetClientTime", Cookie_GetClientTime},
{"Cookie.AccessLevel.get", GetCookieAccess},
{NULL, NULL}
}; };

View File

@ -11,14 +11,24 @@ project.sources += [
'util_cstrike.cpp', 'util_cstrike.cpp',
'../../public/smsdk_ext.cpp', '../../public/smsdk_ext.cpp',
'../../public/CDetour/detours.cpp', '../../public/CDetour/detours.cpp',
'../../public/asm/asm.c' '../../public/asm/asm.c',
'../../public/libudis86/decode.c',
'../../public/libudis86/itab.c',
'../../public/libudis86/syn-att.c',
'../../public/libudis86/syn-intel.c',
'../../public/libudis86/syn.c',
'../../public/libudis86/udis86.c',
] ]
project.compiler.defines += ['HAVE_STRING_H'];
for sdk_name in ['css', 'csgo']: for sdk_name in ['css', 'csgo']:
if sdk_name not in SM.sdks: if sdk_name not in SM.sdks:
continue continue
sdk = SM.sdks[sdk_name] sdk = SM.sdks[sdk_name]
for arch in SM.archs:
SM.HL2Config(project, 'game.cstrike.ext.' + sdk.ext, sdk) if not arch in sdk.platformSpec[builder.target.platform]:
continue
SM.HL2Config(project, 'game.cstrike.ext.' + sdk.ext, sdk, arch)
SM.extensions += builder.Add(project) SM.extensions += builder.Add(project)

View File

@ -64,7 +64,7 @@ bool CStrike::SDK_OnLoad(char *error, size_t maxlength, bool late)
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE != SE_CSGO
if (strcmp(g_pSM->GetGameFolderName(), "cstrike") != 0) if (strcmp(g_pSM->GetGameFolderName(), "cstrike") != 0)
{ {
snprintf(error, maxlength, "Cannot Load Cstrike Extension on mods other than CS:S and CS:GO"); ke::SafeStrcpy(error, maxlength, "Cannot Load Cstrike Extension on mods other than CS:S and CS:GO");
return false; return false;
} }
#endif #endif
@ -77,7 +77,7 @@ bool CStrike::SDK_OnLoad(char *error, size_t maxlength, bool late)
{ {
if (error) if (error)
{ {
snprintf(error, maxlength, "Could not read sm-cstrike.games: %s", conf_error); ke::SafeSprintf(error, maxlength, "Could not read sm-cstrike.games: %s", conf_error);
} }
return false; return false;
} }

View File

@ -126,7 +126,7 @@ DETOUR_DECL_MEMBER0(DetourWeaponPrice, int)
} }
#endif #endif
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE == SE_CSS
DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason) DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
{ {
if (g_pIgnoreTerminateDetour) if (g_pIgnoreTerminateDetour)
@ -135,7 +135,7 @@ DETOUR_DECL_MEMBER2(DetourTerminateRound, void, float, delay, int, reason)
DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason); DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
return; return;
} }
#elif !defined(WIN32) #elif SOURCE_ENGINE == SE_CSGO && !defined(WIN32)
DETOUR_DECL_MEMBER4(DetourTerminateRound, void, float, delay, int, reason, int, unknown, int, unknown2) DETOUR_DECL_MEMBER4(DetourTerminateRound, void, float, delay, int, reason, int, unknown, int, unknown2)
{ {
if (g_pIgnoreTerminateDetour) if (g_pIgnoreTerminateDetour)
@ -189,12 +189,12 @@ DETOUR_DECL_MEMBER3(DetourTerminateRound, void, int, reason, int, unknown, int,
reason++; reason++;
#endif #endif
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE == SE_CSS
if (result == Pl_Changed) if (result == Pl_Changed)
return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason);
return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason); return DETOUR_MEMBER_CALL(DetourTerminateRound)(orgdelay, orgreason);
#elif !defined(WIN32) #elif SOURCE_ENGINE == SE_CSGO && !defined(WIN32)
if (result == Pl_Changed) if (result == Pl_Changed)
return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason, unknown, unknown2); return DETOUR_MEMBER_CALL(DetourTerminateRound)(delay, reason, unknown, unknown2);

View File

@ -18,7 +18,11 @@ struct HashItemDef_Node
class CHashItemDef class CHashItemDef
{ {
public: public:
#ifdef PLATFORM_X86
unsigned char padding[36]; unsigned char padding[36];
#else
unsigned char padding[56];
#endif
HashItemDef_Node *pMem; HashItemDef_Node *pMem;
int nAllocatedCount; int nAllocatedCount;
int nGrowSize; int nGrowSize;

View File

@ -34,6 +34,7 @@
#include "forwards.h" #include "forwards.h"
#include "util_cstrike.h" #include "util_cstrike.h"
#include <server_class.h> #include <server_class.h>
#include <sm_argbuffer.h>
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_CSGO
#include "itemdef-hash.h" #include "itemdef-hash.h"
@ -178,12 +179,8 @@ static cell_t CS_SwitchTeam(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Client index %d is not valid", params[1]); return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
} }
unsigned char vstk[sizeof(CBaseEntity *) + sizeof(int)]; ArgBuffer<CBaseEntity*, int> vstk(pEntity, params[2]);
unsigned char *vptr = vstk;
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
*(int *)vptr = params[2];
pWrapper->Execute(vstk, NULL); pWrapper->Execute(vstk, NULL);
#else #else
if (g_pSDKTools == NULL) if (g_pSDKTools == NULL)
@ -270,17 +267,9 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
if (params[4] == 1 && g_pCSWeaponDropDetoured) if (params[4] == 1 && g_pCSWeaponDropDetoured)
g_pIgnoreCSWeaponDropDetour = true; g_pIgnoreCSWeaponDropDetour = true;
unsigned char vstk[sizeof(CBaseEntity *) * 2 + sizeof(bool)]; ArgBuffer<CBaseEntity*, CBaseEntity*, bool> vstk(pEntity, pWeapon, (params[3]) ? true : false);
unsigned char *vptr = vstk;
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
*(CBaseEntity **)vptr = pWeapon;
vptr += sizeof(CBaseEntity *);
*(bool *)vptr = (params[3]) ? true : false;
pWrapper->Execute(vstk, NULL);
pWrapper->Execute(vstk, NULL);
return 1; return 1;
} }
@ -308,7 +297,7 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
reason++; reason++;
#endif #endif
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE == SE_CSS
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
if (!pWrapper) if (!pWrapper)
@ -316,7 +305,7 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
REGISTER_NATIVE_ADDR("TerminateRound", REGISTER_NATIVE_ADDR("TerminateRound",
PassInfo pass[2]; \ PassInfo pass[2]; \
pass[0].flags = PASSFLAG_BYVAL; \ pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \ pass[0].type = PassType_Float; \
pass[0].size = sizeof(float); \ pass[0].size = sizeof(float); \
pass[1].flags = PASSFLAG_BYVAL; \ pass[1].flags = PASSFLAG_BYVAL; \
pass[1].type = PassType_Basic; \ pass[1].type = PassType_Basic; \
@ -327,17 +316,10 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
if (params[3] == 1 && g_pTerminateRoundDetoured) if (params[3] == 1 && g_pTerminateRoundDetoured)
g_pIgnoreTerminateDetour = true; g_pIgnoreTerminateDetour = true;
unsigned char vstk[sizeof(void *) + sizeof(float)+ sizeof(int)]; ArgBuffer<void*, float, int> vstk(gamerules, sp_ctof(params[1]), reason);
unsigned char *vptr = vstk;
*(void **)vptr = gamerules;
vptr += sizeof(void *);
*(float *)vptr = sp_ctof(params[1]);
vptr += sizeof(float);
*(int*)vptr = reason;
pWrapper->Execute(vstk, NULL); pWrapper->Execute(vstk, NULL);
#elif !defined(WIN32) #elif SOURCE_ENGINE == SE_CSGO && !defined(WIN32)
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
if (!pWrapper) if (!pWrapper)
@ -345,7 +327,7 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
REGISTER_NATIVE_ADDR("TerminateRound", REGISTER_NATIVE_ADDR("TerminateRound",
PassInfo pass[4]; \ PassInfo pass[4]; \
pass[0].flags = PASSFLAG_BYVAL; \ pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \ pass[0].type = PassType_Float; \
pass[0].size = sizeof(float); \ pass[0].size = sizeof(float); \
pass[1].flags = PASSFLAG_BYVAL; \ pass[1].flags = PASSFLAG_BYVAL; \
pass[1].type = PassType_Basic; \ pass[1].type = PassType_Basic; \
@ -362,21 +344,10 @@ static cell_t CS_TerminateRound(IPluginContext *pContext, const cell_t *params)
if (params[3] == 1 && g_pTerminateRoundDetoured) if (params[3] == 1 && g_pTerminateRoundDetoured)
g_pIgnoreTerminateDetour = true; g_pIgnoreTerminateDetour = true;
unsigned char vstk[sizeof(void *) + sizeof(float) + (sizeof(int)*3)]; ArgBuffer<void*, float, int, int, int> vstk(gamerules, sp_ctof(params[1]), reason, 0, 0);
unsigned char *vptr = vstk;
*(void **)vptr = gamerules;
vptr += sizeof(void *);
*(float *)vptr = sp_ctof(params[1]);
vptr += sizeof(float);
*(int*)vptr = reason;
vptr += sizeof(int);
*(int*)vptr = 0;
vptr += sizeof(int);
*(int*)vptr = 0;
pWrapper->Execute(vstk, NULL); pWrapper->Execute(vstk, NULL);
#else #else // CSGO Win32
static void *addr = NULL; static void *addr = NULL;
if(!addr) if(!addr)
@ -515,80 +486,6 @@ static cell_t CS_GetWeaponPrice(IPluginContext *pContext, const cell_t *params)
} }
#endif #endif
static cell_t CS_GetClientClanTag(IPluginContext *pContext, const cell_t *params)
{
static void *addr;
if (!addr)
{
if (!g_pGameConf->GetMemSig("SetClanTag", &addr) || !addr)
{
return pContext->ThrowNativeError("Failed to locate function");
}
}
CBaseEntity *pEntity;
if (!(pEntity = GetCBaseEntity(params[1], true)))
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
static int tagOffsetOffset = -1;
static int tagOffset;
if (tagOffsetOffset == -1)
{
if (!g_pGameConf->GetOffset("ClanTagOffset", &tagOffsetOffset))
{
tagOffsetOffset = -1;
return pContext->ThrowNativeError("Unable to find ClanTagOffset gamedata");
}
tagOffset = *(int *)((intptr_t)addr + tagOffsetOffset);
}
size_t len;
const char *src = (char *)((intptr_t)pEntity + tagOffset);
pContext->StringToLocalUTF8(params[2], params[3], src, &len);
return len;
}
static cell_t CS_SetClientClanTag(IPluginContext *pContext, const cell_t *params)
{
static ICallWrapper *pWrapper = NULL;
if (!pWrapper)
{
REGISTER_NATIVE_ADDR("SetClanTag",
PassInfo pass[1]; \
pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \
pass[0].size = sizeof(char *); \
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 1))
}
CBaseEntity *pEntity;
if (!(pEntity = GetCBaseEntity(params[1], true)))
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
char *szNewTag;
pContext->LocalToString(params[2], &szNewTag);
unsigned char vstk[sizeof(CBaseEntity *) + sizeof(char *)];
unsigned char *vptr = vstk;
*(CBaseEntity **)vptr = pEntity;
vptr += sizeof(CBaseEntity *);
*(char **)vptr = szNewTag;
pWrapper->Execute(vstk, NULL);
return 1;
}
static cell_t CS_AliasToWeaponID(IPluginContext *pContext, const cell_t *params) static cell_t CS_AliasToWeaponID(IPluginContext *pContext, const cell_t *params)
{ {
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_CSGO
@ -832,6 +729,130 @@ static inline cell_t SetPlayerVar(IPluginContext *pContext, const cell_t *params
return 0; return 0;
} }
static inline cell_t GetPlayerStringVar(IPluginContext *pContext, const cell_t *params, const char *varName)
{
CBaseEntity *pPlayer = GetCBaseEntity(params[1], true);
if (!pPlayer)
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
char *pVar = GetPlayerVarAddressOrError<char>(varName, pContext, pPlayer);
if (pVar)
{
size_t len;
pContext->StringToLocalUTF8(params[2], params[3], pVar, &len);
return len;
}
return 0;
}
static inline cell_t SetPlayerStringVar(IPluginContext *pContext, const cell_t *params, const char *varName)
{
CBaseEntity *pPlayer = GetCBaseEntity(params[1], true);
if (!pPlayer)
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
char szSizeName[128];
g_pSM->Format(szSizeName, sizeof(szSizeName), "%sSize", varName);
int maxlen = 0;
if(!g_pGameConf->GetOffset(szSizeName, &maxlen))
{
return pContext->ThrowNativeError("Failed to locate %s offset in gamedata", szSizeName);
}
char *pVar = GetPlayerVarAddressOrError<char>(varName, pContext, pPlayer);
if (pVar)
{
char *newValue;
pContext->LocalToString(params[2], &newValue);
Q_strncpy(pVar, newValue, maxlen);
}
return 1;
}
static cell_t CS_GetClientClanTag(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
return GetPlayerStringVar(pContext, params, "ClanTag");
#else
static void *addr;
if (!addr)
{
if (!g_pGameConf->GetMemSig("SetClanTag", &addr) || !addr)
{
return pContext->ThrowNativeError("Failed to locate function");
}
}
CBaseEntity *pEntity;
if (!(pEntity = GetCBaseEntity(params[1], true)))
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
static int tagOffsetOffset = -1;
static int tagOffset;
if (tagOffsetOffset == -1)
{
if (!g_pGameConf->GetOffset("ClanTagOffset", &tagOffsetOffset))
{
tagOffsetOffset = -1;
return pContext->ThrowNativeError("Unable to find ClanTagOffset gamedata");
}
tagOffset = *(int *)((intptr_t)addr + tagOffsetOffset);
}
size_t len;
const char *src = (char *)((intptr_t)pEntity + tagOffset);
pContext->StringToLocalUTF8(params[2], params[3], src, &len);
return len;
#endif
}
static cell_t CS_SetClientClanTag(IPluginContext *pContext, const cell_t *params)
{
#if SOURCE_ENGINE == SE_CSGO
return SetPlayerStringVar(pContext, params, "ClanTag");
#else
static ICallWrapper *pWrapper = NULL;
if (!pWrapper)
{
REGISTER_NATIVE_ADDR("SetClanTag",
PassInfo pass[1]; \
pass[0].flags = PASSFLAG_BYVAL; \
pass[0].type = PassType_Basic; \
pass[0].size = sizeof(char *); \
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 1))
}
CBaseEntity *pEntity;
if (!(pEntity = GetCBaseEntity(params[1], true)))
{
return pContext->ThrowNativeError("Client index %d is not valid", params[1]);
}
char *szNewTag;
pContext->LocalToString(params[2], &szNewTag);
ArgBuffer<CBaseEntity*, char*> vstk(pEntity, szNewTag);
pWrapper->Execute(vstk, NULL);
return 1;
#endif
}
static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params) static cell_t CS_SetMVPCount(IPluginContext *pContext, const cell_t *params)
{ {
return SetPlayerVar<int>(pContext, params, "MVPs"); return SetPlayerVar<int>(pContext, params, "MVPs");

View File

@ -33,6 +33,8 @@
#include "util_cstrike.h" #include "util_cstrike.h"
#include "RegNatives.h" #include "RegNatives.h"
#include <iplayerinfo.h> #include <iplayerinfo.h>
#include <sm_argbuffer.h>
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_CSGO
#include "itemdef-hash.h" #include "itemdef-hash.h"
@ -134,16 +136,9 @@ CEconItemView *GetEconItemView(CBaseEntity *pEntity, int iSlot)
if (team != 2 && team != 3) if (team != 2 && team != 3)
return NULL; return NULL;
CEconItemView *ret; ArgBuffer<void*, int, int> vstk(reinterpret_cast<void*>(((intptr_t)pEntity + thisPtrOffset)), team, iSlot);
unsigned char vstk[sizeof(void *) + sizeof(int) * 2];
unsigned char *vptr = vstk;
*(void **)vptr = (void *)((intptr_t)pEntity + thisPtrOffset);
vptr += sizeof(void *);
*(int *)vptr = team;
vptr += sizeof(int);
*(int *)vptr = iSlot;
CEconItemView *ret = nullptr;
pWrapper->Execute(vstk, &ret); pWrapper->Execute(vstk, &ret);
return ret; return ret;
@ -163,13 +158,9 @@ CCSWeaponData *GetCCSWeaponData(CEconItemView *view)
pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &retpass, NULL, 0)) pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, &retpass, NULL, 0))
} }
unsigned char vstk[sizeof(CEconItemView *)]; ArgBuffer<CEconItemView*> vstk(view);
unsigned char *vptr = vstk;
*(CEconItemView **)vptr = view;
CCSWeaponData *pWpnData = NULL;
CCSWeaponData *pWpnData = nullptr;
pWrapper->Execute(vstk, &pWpnData); pWrapper->Execute(vstk, &pWpnData);
return pWpnData; return pWpnData;
@ -192,9 +183,9 @@ CEconItemSchema *GetItemSchema()
void *pSchema = NULL; void *pSchema = NULL;
pWrapper->Execute(NULL, &pSchema); pWrapper->Execute(NULL, &pSchema);
//In windows this is actually ItemSystem() + 4 is ItemSchema //On windows/mac this is actually ItemSystem() + sizeof(void *) is ItemSchema
#ifdef WIN32 #if defined(PLATFORM_WINDOWS) || defined(PLATFORM_APPLE)
return (CEconItemSchema *)((intptr_t)pSchema + 4); return (CEconItemSchema *)((intptr_t)pSchema + sizeof(void *));
#else #else
return (CEconItemSchema *)pSchema; return (CEconItemSchema *)pSchema;
#endif #endif
@ -234,14 +225,9 @@ CEconItemDefinition *GetItemDefintionByName(const char *classname)
g_RegNatives.Register(pWrapper); g_RegNatives.Register(pWrapper);
} }
unsigned char vstk[sizeof(void *) + sizeof(const char *)]; ArgBuffer<void*, const char *> vstk(pSchema, classname);
unsigned char *vptr = vstk;
*(void **)vptr = pSchema; CEconItemDefinition *pItemDef = nullptr;
vptr += sizeof(void *);
*(const char **)vptr = classname;
CEconItemDefinition *pItemDef = NULL;
pWrapper->Execute(vstk, &pItemDef); pWrapper->Execute(vstk, &pItemDef);
return pItemDef; return pItemDef;
@ -340,7 +326,7 @@ SMCSWeapon GetWeaponIdFromDefIdx(uint16_t iDefIdx)
SMCSWeapon_UMP45, SMCSWeapon_XM1014, SMCSWeapon_BIZON, SMCSWeapon_MAG7, SMCSWeapon_UMP45, SMCSWeapon_XM1014, SMCSWeapon_BIZON, SMCSWeapon_MAG7,
SMCSWeapon_NEGEV, SMCSWeapon_SAWEDOFF, SMCSWeapon_TEC9, SMCSWeapon_TASER, SMCSWeapon_NEGEV, SMCSWeapon_SAWEDOFF, SMCSWeapon_TEC9, SMCSWeapon_TASER,
SMCSWeapon_HKP2000, SMCSWeapon_MP7, SMCSWeapon_MP9, SMCSWeapon_NOVA, SMCSWeapon_HKP2000, SMCSWeapon_MP7, SMCSWeapon_MP9, SMCSWeapon_NOVA,
SMCSWeapon_P250, SMCSWeapon_NONE, SMCSWeapon_SCAR20, SMCSWeapon_SG556, SMCSWeapon_P250, SMCSWeapon_SHIELD, SMCSWeapon_SCAR20, SMCSWeapon_SG556,
SMCSWeapon_SSG08, SMCSWeapon_KNIFE_GG, SMCSWeapon_KNIFE, SMCSWeapon_FLASHBANG, SMCSWeapon_SSG08, SMCSWeapon_KNIFE_GG, SMCSWeapon_KNIFE, SMCSWeapon_FLASHBANG,
SMCSWeapon_HEGRENADE, SMCSWeapon_SMOKEGRENADE, SMCSWeapon_MOLOTOV, SMCSWeapon_DECOY, SMCSWeapon_HEGRENADE, SMCSWeapon_SMOKEGRENADE, SMCSWeapon_MOLOTOV, SMCSWeapon_DECOY,
SMCSWeapon_INCGRENADE, SMCSWeapon_C4, SMCSWeapon_KEVLAR, SMCSWeapon_ASSAULTSUIT, SMCSWeapon_INCGRENADE, SMCSWeapon_C4, SMCSWeapon_KEVLAR, SMCSWeapon_ASSAULTSUIT,
@ -357,7 +343,7 @@ ItemDefHashValue *GetHashValueFromWeapon(const char *szWeapon)
{ {
char tempWeapon[MAX_WEAPON_NAME_LENGTH]; char tempWeapon[MAX_WEAPON_NAME_LENGTH];
Q_strncpy(tempWeapon, szWeapon, sizeof(tempWeapon)); ke::SafeStrcpy(tempWeapon, sizeof(tempWeapon), szWeapon);
Q_strlower(tempWeapon); Q_strlower(tempWeapon);
if (strstr(tempWeapon, "weapon_") == NULL && strstr(tempWeapon, "item_") == NULL) if (strstr(tempWeapon, "weapon_") == NULL && strstr(tempWeapon, "item_") == NULL)
@ -367,7 +353,7 @@ ItemDefHashValue *GetHashValueFromWeapon(const char *szWeapon)
for (unsigned int i = 0; i < SM_ARRAYSIZE(szClassPrefixs); i++) for (unsigned int i = 0; i < SM_ARRAYSIZE(szClassPrefixs); i++)
{ {
char classname[MAX_WEAPON_NAME_LENGTH]; char classname[MAX_WEAPON_NAME_LENGTH];
Q_snprintf(classname, sizeof(classname), "%s%s", szClassPrefixs[i], tempWeapon); ke::SafeSprintf(classname, sizeof(classname), "%s%s", szClassPrefixs[i], tempWeapon);
ClassnameMap::Result res = g_mapClassToDefIdx.find(classname); ClassnameMap::Result res = g_mapClassToDefIdx.find(classname);
@ -390,8 +376,6 @@ ItemDefHashValue *GetHashValueFromWeapon(const char *szWeapon)
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE != SE_CSGO
void *GetWeaponInfo(int weaponID) void *GetWeaponInfo(int weaponID)
{ {
void *info;
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
if (!pWrapper) if (!pWrapper)
{ {
@ -407,11 +391,9 @@ void *GetWeaponInfo(int weaponID)
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1))
} }
unsigned char vstk[sizeof(int)]; ArgBuffer<int> vstk(weaponID);
unsigned char *vptr = vstk;
*(int *)vptr = weaponID;
void *info = nullptr;
pWrapper->Execute(vstk, &info); pWrapper->Execute(vstk, &info);
return info; return info;
@ -435,7 +417,6 @@ const char *GetWeaponNameFromClassname(const char *weapon)
const char *GetTranslatedWeaponAlias(const char *weapon) const char *GetTranslatedWeaponAlias(const char *weapon)
{ {
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE != SE_CSGO
const char *alias = NULL;
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
@ -453,12 +434,11 @@ const char *GetTranslatedWeaponAlias(const char *weapon)
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1))
} }
unsigned char vstk[sizeof(const char *)]; ArgBuffer<const char *> vstk(GetWeaponNameFromClassname(weapon));
unsigned char *vptr = vstk;
*(const char **)vptr = GetWeaponNameFromClassname(weapon);
const char *alias = nullptr;
pWrapper->Execute(vstk, &alias); pWrapper->Execute(vstk, &alias);
return alias; return alias;
#else //this should work for both games maybe replace both? #else //this should work for both games maybe replace both?
static const char *szAliases[] = static const char *szAliases[] =
@ -492,8 +472,6 @@ const char *GetTranslatedWeaponAlias(const char *weapon)
int AliasToWeaponID(const char *weapon) int AliasToWeaponID(const char *weapon)
{ {
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE != SE_CSGO
int weaponID = 0;
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
if (!pWrapper) if (!pWrapper)
@ -510,11 +488,9 @@ int AliasToWeaponID(const char *weapon)
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1))
} }
unsigned char vstk[sizeof(const char *)]; ArgBuffer<const char *> vstk(GetWeaponNameFromClassname(weapon));
unsigned char *vptr = vstk;
*(const char **)vptr = GetWeaponNameFromClassname(weapon);
int weaponID = 0;
pWrapper->Execute(vstk, &weaponID); pWrapper->Execute(vstk, &weaponID);
return weaponID; return weaponID;
@ -531,10 +507,8 @@ int AliasToWeaponID(const char *weapon)
const char *WeaponIDToAlias(int weaponID) const char *WeaponIDToAlias(int weaponID)
{ {
#if SOURCE_ENGINE != SE_CSGO #if SOURCE_ENGINE != SE_CSGO
const char *alias = NULL;
static ICallWrapper *pWrapper = NULL; static ICallWrapper *pWrapper = NULL;
if (!pWrapper) if (!pWrapper)
{ {
REGISTER_ADDR("WeaponIDToAlias", 0, REGISTER_ADDR("WeaponIDToAlias", 0,
@ -549,11 +523,9 @@ const char *WeaponIDToAlias(int weaponID)
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1)) pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retpass, pass, 1))
} }
unsigned char vstk[sizeof(int)]; ArgBuffer<int> vstk(weaponID);
unsigned char *vptr = vstk;
*(int *)vptr = weaponID;
const char *alias = nullptr;
pWrapper->Execute(vstk, &alias); pWrapper->Execute(vstk, &alias);
return alias; return alias;

View File

@ -2,27 +2,27 @@
import os import os
libcurl = builder.Build('curl-src/lib/AMBuilder') libcurl = builder.Build('curl-src/lib/AMBuilder')
for arch in SM.archs:
binary = SM.ExtLibrary(builder, 'webternet.ext', arch)
binary.compiler.includes += [
os.path.join(builder.sourcePath, 'extensions', 'curl', 'curl-src', 'include')
]
binary.compiler.defines += ['CURL_STATICLIB']
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
binary.compiler.postlink += [libcurl[arch].binary]
if builder.target.platform == 'linux':
binary.compiler.postlink += ['-lrt']
elif builder.target.platform == 'windows':
binary.compiler.postlink += ['ws2_32.lib']
binary = SM.ExtLibrary(builder, 'webternet.ext') binary.sources += [
binary.compiler.includes += [ 'extension.cpp',
os.path.join(builder.sourcePath, 'extensions', 'curl', 'curl-src', 'include') 'curlapi.cpp',
] '../../public/smsdk_ext.cpp'
binary.compiler.defines += ['CURL_STATICLIB'] ]
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
binary.compiler.postlink += [libcurl.binary]
if builder.target.platform == 'linux':
binary.compiler.postlink += ['-lrt']
elif builder.target.platform == 'windows':
binary.compiler.postlink += ['ws2_32.lib']
binary.sources += [ SM.extensions += [builder.Add(binary)]
'extension.cpp',
'curlapi.cpp',
'../../public/smsdk_ext.cpp'
]
SM.extensions += [builder.Add(binary)]

View File

@ -3,96 +3,98 @@ import os, platform
builder.SetBuildFolder('libcurl') builder.SetBuildFolder('libcurl')
binary = SM.StaticLibrary(builder, 'curl') rvalue = {}
binary.compiler.includes += [ for arch in SM.archs:
os.path.join(builder.sourcePath, 'extensions', 'curl', 'curl-src', 'lib'), binary = SM.StaticLibrary(builder, 'curl', arch)
os.path.join(builder.sourcePath, 'extensions', 'curl', 'curl-src', 'include') binary.compiler.includes += [
] os.path.join(builder.sourcePath, 'extensions', 'curl', 'curl-src', 'lib'),
os.path.join(builder.sourcePath, 'extensions', 'curl', 'curl-src', 'include')
if builder.target.platform == 'mac':
mac_version, ignore, ignore = platform.mac_ver()
mac_tuple = mac_version.split('.')
if int(mac_tuple[0]) >= 10 and int(mac_tuple[1]) >= 9:
binary.compiler.defines += ['BUILTIN_STRLCAT']
elif builder.target.platform == 'windows':
binary.compiler.defines += [
'BUILDING_LIBCURL',
'CURL_STATICLIB',
'CURL_DISABLE_LDAP',
] ]
elif builder.target.platform == 'linux':
binary.compiler.defines += ['_GNU_SOURCE']
if binary.compiler.family == 'clang': if builder.target.platform == 'mac':
# https://llvm.org/bugs/show_bug.cgi?id=16428 mac_version, ignore, ignore = platform.mac_ver()
binary.compiler.cflags += ['-Wno-attributes'] mac_tuple = mac_version.split('.')
if int(mac_tuple[0]) >= 10 and int(mac_tuple[1]) >= 9:
binary.compiler.defines += ['BUILTIN_STRLCAT']
elif builder.target.platform == 'windows':
binary.compiler.defines += [
'BUILDING_LIBCURL',
'CURL_STATICLIB',
'CURL_DISABLE_LDAP',
]
elif builder.target.platform == 'linux':
binary.compiler.defines += ['_GNU_SOURCE']
binary.sources += [ if binary.compiler.family == 'clang':
'base64.c', # https://llvm.org/bugs/show_bug.cgi?id=16428
'connect.c', binary.compiler.cflags += ['-Wno-attributes']
'content_encoding.c',
'cookie.c', binary.sources += [
'curl_addrinfo.c', 'base64.c',
'dict.c', 'connect.c',
'easy.c', 'content_encoding.c',
'escape.c', 'cookie.c',
'file.c', 'curl_addrinfo.c',
'formdata.c', 'dict.c',
'ftp.c', 'easy.c',
'getenv.c', 'escape.c',
'getinfo.c', 'file.c',
'gtls.c', 'formdata.c',
'hash.c', 'ftp.c',
'hostares.c', 'getenv.c',
'hostasyn.c', 'getinfo.c',
'hostip.c', 'gtls.c',
'hostip4.c', 'hash.c',
'hostip6.c', 'hostares.c',
'hostsyn.c', 'hostasyn.c',
'hostthre.c', 'hostip.c',
'http.c', 'hostip4.c',
'http_chunks.c', 'hostip6.c',
'http_digest.c', 'hostsyn.c',
'http_negotiate.c', 'hostthre.c',
'http_ntlm.c', 'http.c',
'if2ip.c', 'http_chunks.c',
'inet_ntop.c', 'http_digest.c',
'inet_pton.c', 'http_negotiate.c',
'krb4.c', 'http_ntlm.c',
'krb5.c', 'if2ip.c',
'ldap.c', 'inet_ntop.c',
'llist.c', 'inet_pton.c',
'md5.c', 'krb4.c',
'memdebug.c', 'krb5.c',
'mprintf.c', 'ldap.c',
'multi.c', 'llist.c',
'netrc.c', 'md5.c',
'nss.c', 'memdebug.c',
'parsedate.c', 'mprintf.c',
'progress.c', 'multi.c',
'qssl.c', 'netrc.c',
'rawstr.c', 'nss.c',
'security.c', 'parsedate.c',
'select.c', 'progress.c',
'sendf.c', 'qssl.c',
'share.c', 'rawstr.c',
'socks.c', 'security.c',
'speedcheck.c', 'select.c',
'splay.c', 'sendf.c',
'ssh.c', 'share.c',
'sslgen.c', 'socks.c',
'ssluse.c', 'speedcheck.c',
'strdup.c', 'splay.c',
'strequal.c', 'ssh.c',
'strerror.c', 'sslgen.c',
'strtok.c', 'ssluse.c',
'strtoofft.c', 'strdup.c',
'telnet.c', 'strequal.c',
'tftp.c', 'strerror.c',
'timeval.c', 'strtok.c',
'transfer.c', 'strtoofft.c',
'url.c', 'telnet.c',
'version.c' 'tftp.c',
] 'timeval.c',
rvalue = builder.Add(binary) 'transfer.c',
'url.c',
'version.c'
]
rvalue[arch] = builder.Add(binary)

View File

@ -1,19 +1,20 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os import os
binary = SM.ExtLibrary(builder, 'geoip.ext') for arch in SM.archs:
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang': binary = SM.ExtLibrary(builder, 'geoip.ext', arch)
binary.compiler.cxxflags += ['-fno-rtti'] if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
elif binary.compiler.family == 'msvc': binary.compiler.cxxflags += ['-fno-rtti']
binary.compiler.cxxflags += ['/GR-'] elif binary.compiler.family == 'msvc':
if builder.target.platform == 'windows': binary.compiler.cxxflags += ['/GR-']
binary.compiler.postlink += ['wsock32.lib'] if builder.target.platform == 'windows':
binary.compiler.postlink += ['wsock32.lib']
binary.sources += [ binary.sources += [
'extension.cpp', 'extension.cpp',
'GeoIP.c', 'GeoIP.c',
'../../public/smsdk_ext.cpp' '../../public/smsdk_ext.cpp'
] ]
SM.extensions += [builder.Add(binary)] SM.extensions += [builder.Add(binary)]

View File

@ -32,6 +32,7 @@
#include <sourcemod_version.h> #include <sourcemod_version.h>
#include "extension.h" #include "extension.h"
#include "GeoIP.h" #include "GeoIP.h"
#include "am-string.h"
/** /**
* @file extension.cpp * @file extension.cpp
@ -51,7 +52,7 @@ bool GeoIP_Extension::SDK_OnLoad(char *error, size_t maxlength, bool late)
if (!gi) if (!gi)
{ {
snprintf(error, maxlength, "Could not load configs/geoip/GeoIP.dat"); ke::SafeStrcpy(error, maxlength, "Could not load configs/geoip/GeoIP.dat");
return false; return false;
} }

View File

@ -2,45 +2,47 @@
import os import os
if SM.mysql_root: if SM.mysql_root:
binary = SM.ExtLibrary(builder, 'dbi.mysql.ext') for arch in SM.archs:
binary.compiler.cxxincludes += [ binary = SM.ExtLibrary(builder, 'dbi.mysql.ext', arch)
os.path.join(SM.mysql_root, 'include'), binary.compiler.cxxincludes += [
os.path.join(SM.mms_root, 'core', 'sourcehook') os.path.join(SM.mysql_root[arch], 'include'),
] os.path.join(SM.mms_root, 'core', 'sourcehook')
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
if builder.target.platform == 'linux' or builder.target.platform == 'mac':
binary.compiler.postlink += [
os.path.join(SM.mysql_root, 'lib', 'libmysqlclient_r.a'),
'-lz',
'-lpthread',
'-lm',
]
if builder.target.platform == 'linux':
binary.compiler.postlink += ['-lrt']
elif builder.target.platform == 'windows':
binary.compiler.postlink += [
os.path.join(SM.mysql_root, 'lib', 'opt', 'mysqlclient.lib'),
os.path.join(SM.mysql_root, 'lib', 'opt', 'zlib.lib'),
'wsock32.lib'
] ]
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
binary.sources += [ if builder.target.platform == 'linux' or builder.target.platform == 'mac':
'../../public/smsdk_ext.cpp', binary.compiler.postlink += [
'mysql/MyBasicResults.cpp', os.path.join(SM.mysql_root[arch], 'lib', 'libmysqlclient_r.a'),
'mysql/MyBoundResults.cpp', '-lz',
'mysql/MyDatabase.cpp', '-lpthread',
'mysql/MyDriver.cpp', '-lm',
'mysql/MyStatement.cpp', ]
'extension.cpp' if builder.target.platform == 'linux':
] binary.compiler.postlink += ['-lrt']
elif builder.target.platform == 'windows':
binary.compiler.defines += ['WIN32_LEAN_AND_MEAN']
binary.compiler.postlink += [
os.path.join(SM.mysql_root[arch], 'lib', 'mysqlclient.lib'),
'wsock32.lib'
]
binary.sources += [
'../../public/smsdk_ext.cpp',
'mysql/MyBasicResults.cpp',
'mysql/MyBoundResults.cpp',
'mysql/MyDatabase.cpp',
'mysql/MyDriver.cpp',
'mysql/MyStatement.cpp',
'extension.cpp'
]
if binary.compiler.family == 'msvc' and binary.compiler.version >= 1900: if binary.compiler.family == 'msvc' and binary.compiler.version >= 1900:
binary.sources += [ 'msvc15hack.c' ] binary.sources += [ 'msvc15hack.c' ]
binary.compiler.linkflags += ['legacy_stdio_definitions.lib', 'legacy_stdio_wide_specifiers.lib'] binary.compiler.linkflags += ['legacy_stdio_definitions.lib', 'legacy_stdio_wide_specifiers.lib']
binary.compiler.defines += ['HAVE_STRUCT_TIMESPEC']
SM.extensions += [builder.Add(binary)] SM.extensions += [builder.Add(binary)]

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