Compare commits

...

1367 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
Nicholas Hastings
1de6dbacad
Update TF2 CalcIsAttackCritical gamedata. 2017-12-14 08:27:37 -05:00
Michael Flaherty
64ab3a08b5 Add missing const to usermessage function parameters (#735) 2017-12-14 11:27:07 +00:00
Nicholas Hastings
4007ec8cf8 Temp fix for load issues on Linux. 2017-12-05 20:44:53 -05:00
Asher Baker
c33bf330a0
Add doi, remove dota 2017-12-04 21:47:00 +00:00
Michael Flaherty
830c3f36d3 Block reserved device names on windows (#733) 2017-12-03 11:38:56 +00:00
Michael Flaherty
a5583882f4 fix bad english 🍋 (#724) 2017-12-03 11:37:50 +00:00
Ruben Gonzalez
6896ef739d
Merge pull request #728 from alliedmodders/show-required-exts
Split optional extensions into their own block if not found.
2017-11-30 16:02:33 -05:00
Ruben Gonzalez
c87afde1bd Add optional extensions not found to sm exts list in a seperate list. 2017-11-30 14:21:19 -05:00
Ruben Gonzalez
51cea0e04e Only show extensions that failed to load if the extension is required. 2017-11-30 12:57:12 -05:00
Nicholas Hastings
89732f7935 Revert "Update pushbuild.txt"
This reverts commit 8589a091dd.
2017-11-27 20:57:18 -05:00
Kyle Sanderson
8589a091dd
Update pushbuild.txt
Force build.
2017-11-27 17:49:01 -08:00
Nicholas Hastings
d9bf0a816e Fix CreateInterface missing in loader. 2017-11-27 19:21:25 -05:00
Ruben Gonzalez
38ba9b4561
Merge pull request #727 from alliedmodders/reverse-csgo-native-changes
Revert "Make CS:GO specific natives exist only on CS:GO"
2017-11-27 13:39:09 -05:00
Ruben Gonzalez
8e6ca1ce09 Revert "Make CS:GO specific natives exist only on CS:GO"
This reverts commit 687db96b38.
2017-11-27 12:58:24 -05:00
Michael Flaherty
d685f30847 Add Translation Natives (#669)
* Add Translation Natives

See #626

* Fix vocab errors
* Better description
* Bump ITranslator Version
* Implement KyleS' Review Requests
* Improve documentation
2017-11-20 21:24:01 -08:00
Michael Flaherty
43cdf20fd3 Add FrameIterator to SourceMod (#716).
* Create FrameIterator type
This commit adds the FrameIterator type to core sm along with a few
methods around getting the information for each frame.

* Fix incorrect documentation
[skip ci]
* Implement KyleS's Changes
* A nit
2017-11-16 18:55:37 -08:00
Ruben Gonzalez
7507672895
Merge pull request #701 from alliedmodders/csgo-hashmap
CStrike extension changes for CS:GO
2017-11-03 19:48:55 -04:00
Nicholas Hastings
95afe72307
Separate out DOI build. (#718) 2017-11-03 15:45:16 -04:00
BenediktKa
539adcb8a2 Fix typo in reservedslots.phrases.txt (#717) 2017-11-03 12:19:08 -04:00
Nicholas Hastings
3a1bb177fc Fix TF2IgnitePlayer not working after game update (fixes #713). 2017-10-28 16:17:21 -04:00
Asher Baker
f156d48f45
Include missing ctype header for macOS build 2017-10-28 12:51:55 +01:00
Michael Flaherty
404e96ad45 Add KeyValues.ExportToString (#706) 2017-10-28 12:47:00 +01:00
Michael Flaherty
90ddc16a4b Lowercase windows/mac paths to avoid plugin duplicate loadings (Bug 6491) (#709) 2017-10-28 12:44:25 +01:00
FlaminSarge
c3b25e54f8 Add convenience logic for "offset" to Address definitions in GameConf (#580)
Allows for the last "read" offset for an Address to instead be "offset", which doesn't deref the addr pointer after applying the offset
Shortens the necessary coding to get a particular Address inside a function (old: store offset in a separate GameConf Offsets entry, apply the offset to the Address in SP)
2017-10-28 12:11:32 +01:00
Ruben Gonzalez
b6a2f72e95
Merge branch 'master' into csgo-hashmap 2017-10-27 18:57:28 -04:00
Ruben Gonzalez
6085afbaae Fix comment info 2017-10-27 18:55:02 -04:00
Kyle Sanderson
2658636377 Fix unsigned compiler warning. 2017-10-27 18:53:49 -04:00
Asher Baker
4bab834716
Merge pull request #672 from peace-maker/null_natives_fixed
Add natives to check for NULL_VECTOR and NULL_STRING
2017-10-27 20:03:09 +01:00
Nicholas Hastings
8f6f881937 Update tf2 stun and death flags. 2017-10-27 08:03:39 -04:00
JRiipinen
8807939a14 Update TF2_IsPlayerInCondition (#712)
* Update TF2_IsPlayerInCondition

* Update conditions too
2017-10-27 07:02:38 -04:00
Scott Ehlert
27b69559a3 Really fix macOS build. 2017-10-26 20:38:25 -05:00
Scott Ehlert
373fb4f776 Update amtl to fix macOS build. 2017-10-26 19:36:30 -05:00
David Anderson
8c88614c2e Merge pull request #714 from Headline22/dvander-rednavd
Pin sourcepawn submodule to 1.9-dev
2017-10-24 20:09:00 -07:00
Michael Flaherty
858a0ba17d Pin sourcepawn submodule to 1.9-dev 2017-10-24 19:16:14 -07:00
Nicholas Hastings
5cf6a0c875 Fix MakeBleed native call (add damage custom param).. 2017-10-22 10:48:27 -04:00
Benoist3012
a5c213ae7d make bleed linux sig fix 2017-10-22 10:48:27 -04:00
Nicholas Hastings
23a1c5f952 Tyop fix. 2017-10-22 09:32:02 -04:00
Nicholas Hastings
5aaea4c2c5 Update TF2 enums. 2017-10-22 08:52:02 -04:00
Nicholas Hastings
ab303e7394 Gamedata for 2017-10-20 TF2 update. 2017-10-19 23:59:14 -04:00
Michael Flaherty
4f54df65e9 Switch C header & Fix warnings (#702) 2017-10-15 10:32:01 +01:00
Kyle Sanderson
36f9a8ed7a NPOTB: Remove unsupported packages line from Travis-CI. 2017-10-10 12:00:11 -07:00
Kyle Sanderson
2ccaa376ba NPOTB: Enable better coverage testing with toolchains (Travis-CI). (#703)
NPOTB: Enable better coverage testing with toolchains (Travis-CI).
2017-10-09 18:34:01 -07:00
Kyle Sanderson
65bf85fcbe (Re-)Add support for gcc and clang3.9, 4.0, and 5.0. 2017-10-09 16:53:19 -07:00
Kyle Sanderson
30f061e818 Fix unsigned comparison warnings (-Werror + GCC5) from CS:GO fixes. 2017-10-09 13:00:52 -07:00
Kyle Sanderson
22e3d2d198 Fix GCC build with SourcePawn. 2017-10-09 11:51:49 -07:00
Ruben Gonzalez
687db96b38 Make CS:GO specific natives exist only on CS:GO 2017-10-04 18:20:06 -04:00
Ruben Gonzalez
588e88c7ee Fix build error. 2017-10-04 14:42:07 -04:00
Scott Ehlert
65a8f3cbf8 Trigger build. 2017-10-03 03:24:44 -05:00
Scott Ehlert
82e6d00cea Fix build. 2017-10-02 07:40:58 -05:00
Scott Ehlert
bbdecceb4b Switch to AMBuild 2.1 API. (#694) 2017-10-02 07:18:57 -05:00
Andrew
f67e4ce610 Making rename's LogAction message consistent... (#696)
with the other plugin's messages.
2017-09-26 20:22:38 -04:00
Andrew
f289799c57 Making gravity's LogAction message consistent... (#695)
with the other plugin's messages.
2017-09-26 20:22:30 -04:00
Andrew
aac279322b Making blind's LogAction message consistent... (#697)
with the other plugin's messages.
2017-09-26 20:22:02 -04:00
Kyle Sanderson
5d234bb9d6 Fix OnPlayerRunCmd crashing with invalid CUserCmd ptr. (#693) 2017-09-23 23:27:32 -07:00
peace-maker
7e898ee530 Fix core config values not being cached (#673)
Valid core config options aren't cached to be retrieved using `GetCoreConfigValue` after they've been loaded from core.cfg or set through the `sm config` root console menu.

E.g. `sm config ServerLang` would return `[SM] No such config option "ServerLang" exists.` all the time.

Stop notifying other listeners if the config key was consumed, but don't skip adding it to the cache.

Also fix `FollowCSGOServerGuidelines` always showing as unhandled command when being changed through `sm config FollowCSGOServerGuidelines yes`.
2017-09-23 17:24:39 -07:00
Andrew
54565c92f7 Add target arg to LogAction in basechat sm_psay. (#690) 2017-09-23 10:45:41 -07:00
Asher Baker
4e996a116d Allow seeking to end of datapack (#687) 2017-09-19 23:27:35 +01:00
Ruben Gonzalez
8c8af88cee Add additional native, fix include file. 2017-09-19 12:37:11 -04:00
Ruben Gonzalez
8a36d0486b Add enum value for max regular items. 2017-09-10 10:16:23 -04:00
Ruben Gonzalez
1f3b14367d Add new native to get enum value based on item definition index. 2017-09-09 23:27:32 -04:00
thewavelength
79ba2835f6 Fix build when product.version is mangled (#679)
Strip line breaks when reading product.version, as Git can mangle the line breaks if autocrlf is configured, resulting in `SM_BUILD_TAG` getting defined with a linebreak.
2017-09-10 01:17:35 +01:00
Ruben Gonzalez
3d461ecea1 Add support for CreateIitemEntityByName for CS:GO 2017-09-08 08:37:28 -04:00
Ruben Gonzalez
b4d34ef062 Merge pull request #671 from alliedmodders/csgo-weaponpricefix
Fix CS_GetWeaponPrice returning incorrect weapon prices.
2017-09-04 08:49:33 -04:00
Ruben Gonzalez
a341a0e85c Use implemented function to get weapon name. 2017-09-03 19:31:23 -04:00
Ruben Gonzalez
d8f0484327 Make IsValidWeaponID check weapon info on CS:S 2017-09-03 19:30:35 -04:00
Ruben Gonzalez
b68405b651 Fix cstrike include file. 2017-09-03 19:30:06 -04:00
Ruben Gonzalez
453e9da7c5 Intial CS:Go changes and slight changes for CS:S WeaponID related function. 2017-09-03 09:19:12 -04:00
Ruben Gonzalez
0e7a3b0173 Use keyvalue to get weapon price, change void * to appropriate class names. 2017-08-28 10:17:12 -04:00
Peace-Maker
7eef3948b1 Don't break backwards compatibility with unmanaged forwards
Instead of adding new functions to `IForward`, we just allow NULL to be passed to `PushArray` and `PushString`.
2017-08-25 23:23:50 +02:00
Peace-Maker
e609a33e6d Cleanup CForward::Execute using a helper function
Flatten out the nesting a bit.
2017-08-25 23:23:37 +02:00
Peace-Maker
41a9889cdd Add Call_PushNullVector and Call_PushNullString
Be able to push NULL_[VECTOR|STRING] to a forward or direct function call.
The callee can check the parameter using the IsNullVector/IsNullString natives.
2017-08-25 23:23:24 +02:00
Peace-Maker
3de269946c Add IsNativeParamNullVector and IsNativeParamNullString natives
Lets plugins check if some other plugin passed NULL_VECTOR or
NULL_STRING to a native in the native callback.
2017-08-25 23:23:07 +02:00
Peace-Maker
9fa4ed8bac Add IsNullVector and IsNullString natives
Let plugins check if a string or vector passed to a function is their
NULL_VECTOR or NULL_STRING.
2017-08-25 23:22:39 +02:00
Ruben Gonzalez
22033c21f2 Fix CS_GetWeaponPrice returning incorrect weapon prices. 2017-08-25 10:26:28 -04:00
Nicholas Hastings
d705f6a2e1 Update links in README. 2017-08-23 09:52:31 -04:00
Fyren
3d19bfd57e damn it, duck 2017-08-22 14:02:04 -06:00
Timocop
ea6cf26929 Ignore vote actions if target is no longer available (#649) 2017-08-22 20:56:12 +01:00
Maxim Telezhenko
68c00b8ae7 Remove superfluous assignment after delete (#654) 2017-08-22 20:55:04 +01:00
Michael
9af507a322 Remove replicated flag from sourcemod_version (#667) 2017-08-22 20:53:25 +01:00
Ruben Gonzalez
5f9d571e12 Fix trying to use signature function for WeaponIDToAlias on linux. 2017-08-21 15:00:22 -04:00
Ruben Gonzalez
f7d3e44b19 Fix CS:S build 2017-08-21 10:48:54 -04:00
Ruben Gonzalez
a01e9e510c Fix using Q_strcpy instead of Q_strncpy 2017-08-21 10:35:58 -04:00
Ruben Gonzalez
3eb297bee1 Fix cstrike extension natives/forwards due to update 2017-08-21 10:28:59 -04:00
Steve Zaretti
8627c0cbfc Fix CS:GO Reload offset (#660)
* Fix some CS:GO gamedata

I've just tested some of them.

 - Weapon_Drop
 - Reload

 I'm testing Weapon_CanUse in few minutes

* Weapon_CanUse did not change.

* prethink did'nt change either.

* I went too fast. Only weapon vtable changed.
2017-08-19 10:00:04 -04:00
Ruben Gonzalez
cbb5c6d740 Fix Handle buy call 2017-08-18 15:24:17 -04:00
Ruben Gonzalez
955a29a4aa Fix HandleCommand_Buy_Internal param order. 2017-08-18 15:06:20 -04:00
Ruben Gonzalez
1d9ea142c4 Update more CS:GO gamedata 2017-08-18 10:33:41 -04:00
awillinger
cb83a307ec Fix (parts of) CS:GO gamedata (#656)
* Fix SDKTools gamedata (thanks to Rodya)

* Fix CStrike Linux gamedata

* Fix keys

* Fix keys #2

* Adjust Windows offsets as well

* Update CommitSuicide (from Bara)
2017-08-18 14:06:31 +01:00
Asher Baker
902cae595b Include function name in cstrike ext error messages 2017-08-18 13:00:50 +01:00
shavit
b7b422f046 Removed gender from nomination changed translation phrase. (#653) 2017-08-15 06:53:48 +01:00
Asher Baker
01c6bb8c6f Add an explanatory note to GetSteamAccountID 2017-08-12 13:04:26 +01:00
Nicholas Hastings
aeb52d4f45 Trigger build for hl2sdk-csgo update. (fixes #648). 2017-08-06 10:37:31 -04:00
David Anderson
41bf281f1d Merge pull request #647 from alliedmodders/revert-606-null_natives
Revert "Add natives to check for NULL_VECTOR and NULL_STRING"
2017-08-03 17:13:51 -07:00
Asher Baker
11aab699a5 Revert "Add natives to check for NULL_VECTOR and NULL_STRING" 2017-08-04 00:44:47 +01:00
Nicholas Hastings
1924da3527 Update Contagion tempents gamedata. (Fixes #642) 2017-07-28 14:12:28 -04:00
Asher Baker
2e6d02ad52 Fixup types can include additional flags in the high bytes 2017-07-27 19:31:20 +01:00
Asher Baker
e4047c3f87 Merge pull request #606 from peace-maker/null_natives
Add natives to check for NULL_VECTOR and NULL_STRING
2017-07-25 19:19:26 +01:00
Nicholas Hastings
fa1d4ec5d6 Merge branch 'master' of https://github.com/alliedmodders/sourcemod 2017-07-23 09:03:12 -04:00
Nicholas Hastings
bcfdef0171 Trigger build for hl2sdk-insurgency update. 2017-07-23 09:02:48 -04:00
Peace-Maker
60320cd845 Cleanup CForward::Execute using a helper function
Flatten out the nesting a bit.
2017-07-22 23:08:31 +02:00
peace-maker
8840ce905d Update to latest SourcePawn (#639) 2017-07-18 12:48:39 +01:00
Nicholas Hastings
fd87cb6b23 Clear cached IClient ptr on disconnect (Fixes #637). 2017-07-08 08:25:23 -04:00
Nicholas Hastings
29d1187434 Cache created entities by reference instead of index in SDKHooks (#634)
Fixes #663.
2017-07-06 13:33:34 -04:00
Nicholas Hastings
fdac8a1677 Fix KeyValues.SetUInt64 truncating value (#635). 2017-07-06 13:11:01 -04:00
Arthurdead
44c744b8fd Add native to get gpGlobals->frametime (#629) 2017-06-26 11:18:12 +01:00
Nicholas Hastings
7f71f43c2e Another oops-fix for SDK 2013 mods.
Thanks @Ne3tCode
2017-06-24 08:49:36 -04:00
Nicholas Hastings
16d7e39b57 Oops. Fix non-bot IClient lookups for older SDK 2013 mods. 2017-06-23 14:43:39 -04:00
Nicholas Hastings
9a6900a0ba Don't let bots bypass the kick queue. It's not always safe. 2017-06-23 14:43:39 -04:00
Nicholas Hastings
e762c2ee56 Add support for IClient lookups on SDK 2013 mods with new enough engine. 2017-06-23 14:43:39 -04:00
Nicholas Hastings
c31eaa01a3 Cache player IClient pointer on connect. 2017-06-23 14:43:39 -04:00
Nicholas Hastings
338fdb37f6 Switch to C++11 class initializers for CPlayer. 2017-06-23 14:43:39 -04:00
Nicholas Hastings
79970ca5fa Update CS:GO InfoChanged offset. 2017-06-21 14:40:42 -04:00
Nicholas Hastings
bcae547365 Trigger build. 2017-06-21 13:14:57 -04:00
Nicholas Hastings
f7434cdae1 Trigger build for hl2sdk-sdk2013 change. 2017-06-21 08:42:12 -04:00
Ruben Gonzalez
b9fd586f2f Update CS:GO CBaseClient related gamedata. 2017-06-21 07:37:04 -04:00
Nicholas Hastings
e6e54813bb Trigger build against latest hl2sdk-tf2 update. Fixes #624) 2017-06-16 08:10:16 -04:00
Nicholas Hastings
328fa3b430 Merge branch 'master' of https://github.com/alliedmodders/sourcemod 2017-06-15 18:28:10 -04:00
Nicholas Hastings
78a2dec19e Updated more KreedzClimbing gamedata. 2017-06-15 18:26:06 -04:00
Ruben Gonzalez
f413ea7f4b Merge pull request #623 from alliedmodders/CSWeaponDrop-change
Use the same weapon drop function in CS:GO as in CS:S
2017-06-12 15:49:58 -04:00
Ruben Gonzalez
2f0272f864 Use the same weapon drop function in CS:GO as in CS:S 2017-06-12 08:39:27 -04:00
Nicholas Hastings
a984e23bf6 Update KreedzClimbing gamedir. 2017-06-08 12:44:59 -04:00
Nicholas Hastings
2acf5f85cd Fix ICommandLine lookup on Linux for Insurgency and Day of Infamy. 2017-05-28 08:29:38 -04:00
Ruben Gonzalez
fc1da58040 Merge branch 'master' of github.com:alliedmodders/sourcemod 2017-05-28 07:16:45 -04:00
Ruben Gonzalez
b3a89b70b5 Update CS:GO gamedata fixes #616 2017-05-28 07:16:01 -04:00
Duko
8753e58d7f Gamedata cleanup. 2017-05-26 10:21:24 -04:00
Ruben Gonzalez
ae0ece411e Fix CS:GO gamedata. 2017-05-24 10:42:22 -04:00
Ruben Gonzalez
b7be7eb44e Update CS:GO gamedata 2017-05-24 09:10:12 -04:00
Ruben Gonzalez
946150c8a2 Merge branch 'master' of github.com:alliedmodders/sourcemod 2017-05-24 08:41:53 -04:00
Ruben Gonzalez
9ebea1cdac Update CS:GO gamedata. 2017-05-24 08:41:30 -04:00
Duko
27b4f9538a Disable nextmap on Alien Swarm: Reactive Drop.
Bug: Disconnects players on changelevel
https://steamcommunity.com/app/563560/discussions/2/135509124600714346/
2017-05-20 07:23:27 -04:00
Duko
4ce13e9cbd Add gamedata for Alien Swarm: Reactive Drop. 2017-05-20 07:23:27 -04:00
Nicholas Hastings
7006533409 Update Kreedz Climbing gamedata. 2017-05-14 16:41:00 -04:00
Ruben Gonzalez
001503c85f Update CS:GO windows gamedata 2017-05-13 12:13:30 -04:00
Ruben Gonzalez
1831449e81 Update CS:GO gamedata for windows. 2017-05-13 08:44:25 -04:00
Ruben Gonzalez
cd530679bd Update CS:GO windows gamedata. 2017-05-12 21:24:11 -04:00
peace-maker
1351df4260 Add OnPlayerRunCmdPost forward (#591)
* Add OnPlayerRunCmdPost forward

Allow plugins to catch the values that are actually used by the game
after some eventual changes by other plugins.

* Add |const| qualifier to arrays in OnPlayerRunCmdPost forward
2017-05-09 15:16:05 +01:00
Peace-Maker
de42dfc783 Add Call_PushNullVector and Call_PushNullString
Be able to push NULL_[VECTOR|STRING] to a forward or direct function call.
The callee can check the parameter using the IsNullVector/IsNullString natives.
2017-05-04 22:56:31 -06:00
peace-maker
ed42d2feea Add missing parameter to DataPack.IsReadable (#603) 2017-04-30 13:49:18 -04:00
Nicholas Hastings
0a81a28b07 Add contributing guidelines. 2017-04-29 12:54:00 -04:00
Mohammad Ghasembeigi
c0ec537f29 Fix typo in file.inc include (#602) 2017-04-28 06:47:09 -04:00
Nicholas Hastings
ba81b5b2a5 Force build for hl2sdk-csgo update. 2017-04-26 06:30:56 -04:00
Nicholas Hastings
3671a69b9d Force build for hl2sdk-csgo update. 2017-04-25 21:57:16 -04:00
Nicholas Hastings
6a77e04a8e Fix default value always being when calling ParmValue(string,string). 2017-04-22 21:28:44 -04:00
Nicholas Hastings
8401ca3269 Add gamedata for Alien Swarm: Reactive Drop. 2017-04-22 10:31:41 -04:00
Michael Flaherty
a36dafb906 Add PrintToConsoleAll (#601) 2017-04-18 07:29:47 -04:00
Asher Baker
e880471296 Update blacklist.plugins.txt 2017-04-11 13:00:21 +01:00
Kyle Sanderson
e987cf6bfc Change CHalfLife2::GetMapDisplayName to always check for string substitutions. (#596) 2017-04-03 20:28:10 -04:00
Nicholas Hastings
7bb78e53c6 Update Day of Infamy gamedata. 2017-03-27 15:42:56 -04:00
Nicholas Hastings
99f7ee0588 Update Empires gamedata (supercedes #599). 2017-03-26 11:04:52 -04:00
Steve Zaretti
705ad3bcfc Fixed typo on previous PR (#600)
#598
2017-03-25 14:48:38 -04:00
Ruben Gonzalez
2febfae906 Update GDC symbols.txt (NPOTB). 2017-03-25 13:27:26 -04:00
Ruben Gonzalez
2db2af9343 Fix GDC's Linux SIg offset checking (NPOTB). 2017-03-25 09:29:45 -04:00
Ruben Gonzalez
8e813109a2 Updated CS:GO gamedata. 2017-03-25 09:03:08 -04:00
Ruben Gonzalez
8a6889663d Fix CS:GO gamedata. 2017-03-24 20:15:41 -04:00
Steve Zaretti
aee82c9be4 HUD is now supported on CSGO (#598)
* HUD now supported on CSGO

https://forums.alliedmods.net/showthread.php?t=295215

* Update common.games.txt

went a bit too fast
2017-03-20 07:23:53 -04:00
Nicholas Hastings
a5d364be49 Merge branch 'tf2-toolchainbeta' 2017-03-14 20:04:43 -04:00
FlaminSarge
3f21fa4b39 Update sm_map behavior to better reflect FindMap/GetMapDisplayName results (#588)
* Update sm_map to use GetMapDisplayName
Increase map name buffer sizes to PLATFORM_MAX_PATH

* Update sm_setnextmap to use ShowActivity2
2017-03-13 15:52:37 -07:00
peace-maker
0961e5dde3 Fix crash when accessing gamerules during mapchange (#593)
If the gamerules proxy entity doesn't exist, don't try to generate the
reference for it.
2017-03-11 08:54:38 -08:00
Ruben Gonzalez
89c4be525b Ignore replay and sourcetv in @spec targeting. (#595) 2017-03-11 16:12:43 +00:00
Nicholas Hastings
1135f9024a Fix error when configuring for csgo SDK build on VS 2017. 2017-03-11 09:28:24 -05:00
Nicholas Hastings
9924a28acf Fix AllowClLanguageVar setting being ignored in CS:GO. 2017-03-05 17:08:25 -05:00
Ross Bemrose
8ad5862461 Make CS:GO recognize both / and \ for GetMapDisplayName (#592) 2017-03-04 08:59:25 -05:00
Peace-Maker
b67da15b5b Add IsNativeParamNullVector and IsNativeParamNullString natives
Lets plugins check if some other plugin passed NULL_VECTOR or
NULL_STRING to a native in the native callback.
2017-03-03 11:47:03 -07:00
Peace-Maker
c1888c2d05 Add IsNullVector and IsNullString natives
Let plugins check if a string or vector passed to a function is their
NULL_VECTOR or NULL_STRING.
2017-03-03 11:45:39 -07:00
theSaint92
9d932b47fd rockthevote.sp - RoundToFloor() -> RoundToCeil() (#590)
The reason of update is described here https://forums.alliedmods.net/showthread.php?p=2499471
2017-02-28 23:05:00 +00:00
Nicholas Hastings
25af750af0 Update TF2 gamedata. 2017-02-20 19:30:07 -05:00
Benoist3012
08238a8036 Add FireEntityOutput native. (#587)
* AcceptEntityOutput native

* define fix

* MSVC fix and renamed native

* Added requested changes.

* tab/space fix
2017-02-15 19:29:43 -05:00
Nicholas Hastings
61f46845bd Update Insurgency gamedata. 2017-02-09 18:02:22 -05:00
Nicholas Hastings
9aec0b23dd Update FoF gamedata. 2017-02-09 18:02:05 -05:00
peace-maker
86363dd3ec Add ADT array blocksize getter (#578)
Add GetArrayBlockSize and GetStackBlockSize and equivalent properties to
the methodmaps to get the blocksize the array or stack was created with.

Useful when getting array handles from other plugins you didn't create
yourself.
2017-02-09 19:26:14 +00:00
Michael Flaherty
23feb54f6a Update Plugin Blacklist (#574)
* Update Blacklisted Plugins

Sourceless edit of a public plugin being distributed

https://board-tr.nitrado.net/index.php?page=Thread&threadID=22197

* Close comment (oops)
2017-02-09 19:21:00 +00:00
Asher Baker
55e463426d Update blacklist.plugins.txt 2017-02-09 19:07:25 +00:00
peace-maker
0743b757f6 Fix regression with GetEntPropEnt always returning -1 (#584)
Regression in #583

The `CBaseHandle *` was compared to a `IHandleEntity **` always failing
instead of comparing the actual base handles.

Fixes a small typo in MatchTypeDescAsInteger too, where a FIELD_CUSTOM
could fall through badly.
2017-02-09 07:43:15 -05:00
Nicholas Hastings
af9852a68f Add support for getting and setting output variables with Get/SetEntProp*. 2017-02-07 07:52:00 -05:00
Nicholas Hastings
113a4a55c6 Fix incorrect bit size given for vectors with FindDataMapInfo. 2017-02-07 07:52:00 -05:00
Nicholas Hastings
5e4a69def6 Update GDC's symbols.txt. 2017-02-06 08:11:01 -08:00
Nicholas Hastings
6e79114dee Update GDC's symbols.txt. 2017-02-06 07:58:57 -08:00
Nicholas Hastings
04055c411e Fix startup crash on CS:GO caused by PR #514 2017-02-06 08:25:51 -05:00
WildCard65
90b3df1181 Add 2 CSGO gamerules netprops to CSGO blocklist if FollowCSGOServerGuidelines is enabled. (#514)
* Add m_bIsValveDS and m_bIsQuestEligible

* Fix compile
2017-02-04 08:18:58 -05:00
peace-maker
9e27a867dd Fix typo in menu manager drawing no spacer (#581)
The "Back" slot was hidden even if the page had a "Next" button. Draw
the spacer correctly!
2017-02-04 08:16:27 -05:00
David Anderson
7239f1d00a Merge pull request #582 from alliedmodders/update-sp
Update to the latest SourcePawn.
2017-02-03 23:12:58 -08:00
David Anderson
613838626e Update to the latest SourcePawn. 2017-02-03 22:45:47 -08:00
Nicholas Hastings
5118ea621d Update Linux CS:GO TerminateRound gamedata. 2017-02-03 23:37:02 -05:00
peace-maker
ea8fdd8fbb Fix crash when a database transaction fails (bug 6531) (#577)
If one of the queries fails in a transaction, the DBI system would only allocate an array of the size of the amount of all the successful queries before the failed one. It writes data for all the queries though effectively writing past the array bounds leading to heap corruption.

Create the right sized array!
2017-01-22 22:27:31 -08:00
Kyle Sanderson
f9ec1484f8 Update SourcePawn Module to c687974f5451b9d312141bfa020f465bd8bf96aa . 2017-01-21 18:05:54 -08:00
Nicholas Hastings
c7f413f1b0 Sanitize servercfgfile and lservercfgfile values with sm_cvar (bug 6579). 2017-01-20 15:29:25 -05:00
GoD-Tony
3fd7b29d64 Fix GDC's Linux sigscanning (#576)
The pointer returned by dlopen is not inside the loaded librarys memory region.
2017-01-20 10:13:31 -05:00
GoD-Tony
a0f060f000 Update CS:GO TerminateRound gamedata (#575) 2017-01-20 07:33:42 -05:00
WildCard65
fd399b9b4b Fix memory leak in Regex extension. (#572)
* Fix memory leak in Regex extension.

"x" is never deleted when compile fails.

* Handle handle allocation failures.

Handle allocation failures also result in memory leaks.

* Fix typo.
2017-01-11 21:25:46 -05:00
Nicholas Hastings
ad3588d0aa Use newer MM:S api for Ep1/Original engine. (#548)
* Use newer MM:S api for Ep1/Original engine.

* Remove doubled FILENAME_1_6_EP1 define.
2017-01-11 21:25:00 -05:00
Nicholas Hastings
d9312799c3 Allow direct event FireToClient if broadcast disabled.
Event.FireToClient should not care whether or not broadcasting
is enabled for the event since we're already intentionally not
broadcasting.
2017-01-03 20:31:40 -05:00
Nicholas Hastings
cb39030cce Don't check handle ownership on Event.FireToClient
The handle does not get mutated here, so it is safe. Since we
don't currently support cloning event handles or copying events,
this also facilitates the only easy way of firing an existing game-
created event to a client.
2017-01-03 20:31:40 -05:00
Nicholas Hastings
0aa11374d8 Fix some gamedata issues.
"engine" and "game" were in the same #supported key in places, where
we wanted either to match, rather than both match.
2016-12-26 16:13:38 -05:00
Max Maton
0b7d99f03d Send the complete TextMsg usermsg (#571)
The source 2013 handler for TextMsg expects five strings in the message here: https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/client/hud_chat.cpp#L124

Because sourcemod doesn't send the last four strings along each message sent from sourcemod triggers an assert if the game is not built with RELEASE.
2016-12-25 17:33:18 -08:00
Nicholas Hastings
47d22a3051 Allow CStrike ext to load on CS:GO "mods".
They theoretically cannot have any binary changes since there is no
real SDK, so it should be compatible.
2016-12-25 08:31:39 -05:00
Nicholas Hastings
600f7e2342 Fix gamedata for CS:GO "mods". 2016-12-24 23:28:08 -05:00
Nicholas Hastings
fbe377a53d Limit Black Mesa to 6 max radio menu items. (7+ not bound) 2016-12-13 13:30:18 -05:00
Nicholas Hastings
8a7262afd5 Enable Radio menus for Black Mesa. 2016-12-13 13:23:24 -05:00
iNilo
02fcf37088 Use method-map .Style instead of GetMaxPageItems. (sm_msay patch) (#569) 2016-12-12 10:18:59 -05:00
iNilo
ec455394b4 Change sm_msay behavior to use GetMaxPageItems instead of hardcoded values (#568)
* Fix for CS:GO not showing the sm_msay exit button

Fix for CS:GO not showing the sm_msay exit button

![mSayPanel.CurrentKey = 9](http://i.imgur.com/t8079No.png)

![mSayPanel.CurrentKey = 10](http://i.imgur.com/qxgVoUM.png)

* Someone ate the semicolon

Made a new one

* Uses gamedata to determine the exit button

Uses gamedata to determine the exit button

* GetMenuStyle -> GetPanelStyle
2016-12-12 08:57:29 -05:00
Nicholas Hastings
ee501058fb Fix Panel.Style getter not being bound. 2016-12-12 08:52:26 -05:00
peace-maker
b74573fa12 Fix crash in CloneArray for too large arrays (#566)
If there is not enough memory to clone an array, throw an error instead
of crashing the server.
2016-12-11 20:55:11 -08:00
peace-maker
d3d16a93cf Fix threaded query's result handle access rights (#567)
Plugins were able to close the results handle in the threaded query
callback causing a double free crash. The access rights are setup right
before the handle is created, but weren't used.
2016-12-11 16:35:53 -08:00
Asher Baker
71788e2325 Update blacklist.plugins.txt 2016-12-09 18:36:35 +00:00
Nicholas Hastings
70d81430f8 Add support for more SQLite database open options. (#565)
* Add support for in-memory SQLite databases.

* Add support for opening SQLite databases via file URI.
2016-12-04 11:23:08 -05:00
ErikMinekus
19db7aef46 Fixed description for CharToLower and CharToUpper (#564) 2016-12-04 09:08:13 -05:00
peace-maker
151834a948 Fix case of not calling OnMapTimeLeftChanged in CS:GO (#563)
Round end reasons in CS:GO are +1 from the ones in CS:S. The
CSRoundEnd_GameStart reason for when the OnMapTimeLeftChanged forward
should be called should be one higher than in CS:S.
2016-12-01 17:09:48 -08:00
GoD-Tony
ec9af8feb6 Fix null check when generating signature. (#562) 2016-12-01 08:44:23 +00:00
peace-maker
3e201dd521 Add DETOUR_DECL_* marcos for more parameter counts (#561)
Add more macros for up to 8 parameters, because DETOUR_DECL_MEMBER8 is
the highest one yet.
2016-11-29 14:55:39 -08:00
Nicholas Hastings
152a86f6f4 Fix CS:GO OnGetWeaponPrice forward on Linux. 2016-11-29 11:05:39 -05:00
Nicholas Hastings
93da058dbd Fix innocuous copy/paste error. 2016-11-29 11:05:18 -05:00
Nicholas Hastings
7885d62f03 Add gamedata missing from last commit. 2016-11-29 10:53:04 -05:00
Nicholas Hastings
c4487b74ee Semi-tested fix for CS:GO GetWeaponPrice on Linux. 2016-11-29 10:42:05 -05:00
Nicholas Hastings
90cefa9daf Revert "Update CS:GO GetWeaponPrice gamedata."
This reverts commit f3994ce6dc.
2016-11-29 09:01:33 -05:00
Nicholas Hastings
f3994ce6dc Update CS:GO GetWeaponPrice gamedata. 2016-11-29 08:52:38 -05:00
Nicholas Hastings
2f82ef5ec6 Add CS:GO FindEntityByClassname signature for Linux. 2016-11-29 07:56:48 -05:00
Nicholas Hastings
e2ac0a085e Update Linux IServer gamedata. 2016-11-28 22:20:23 -05:00
Ruben Gonzalez
6290834e2b Update cstrike extension gamedata. 2016-11-28 21:54:24 -05:00
Nicholas Hastings
efa98f6b7f Untested Core, SDKTools, SDKHooks fixes. (CStrike ext fixes pending) 2016-11-28 21:27:53 -05:00
Asher Baker
87b0a8533f Update blacklist.plugins.txt 2016-11-17 23:21:50 +00:00
Nicholas Hastings
7a4a0271ef Trigger build for hl2sdk-bms changes. 2016-11-07 21:03:22 -05:00
Nicholas Hastings
990b45a273 Update TF2 gamedata. 2016-11-02 20:08:26 -04:00
David Anderson
1ff7b72bb0 Merge pull request #558 from peace-maker/suppress_not_runnable
Suppress logging of "Plugin not runnable" errors
2016-10-27 02:57:47 -04:00
Peace-Maker
7907a07686 Update to latest SourcePawn 2016-10-27 00:42:20 -06:00
Peace-Maker
4a8068d1c4 Suppress logging of "Plugin not runnable" errors
SourceMod itself and thirdparty extensions call functions in plugins
without making sure it is runnable. The plugin pausing feature isn't
supported anymore and is set to get nuked #438 which will reduce the
amount of not-runnable error reports.

We can't fix every third party extension, so suppressing the error from
the logs will stop the spam until pausing is removed.

#489 can be reverted after this.
2016-10-26 23:48:56 -06:00
Wliu
6a4500733d Add spacing to compile.sh (#53) 2016-10-24 14:50:24 +01:00
Luki
482a2f2eb5 Add AutoExecConfig native call to basevotes.sp (#535) 2016-10-14 13:17:23 -07:00
Luki
e74b5807a9 Add AutoExecConfig native call to basevotes.sp (#534)
Basevotes convars are missing from sourcemod.cfg and there is no config file for this, so I added AutoExecConfig.
2016-10-14 13:16:45 -07:00
Kyle Sanderson
371e9f2f93 Check multiple engine sources for updated AuthIDs. (#552)
* Check multiple engine sources for updated AuthIDs.
* References are not defined.
2016-10-14 12:44:00 -07:00
Kyle Sanderson
20b7592fcd GetPlayerNetworkIDString isn't alone anymore, we have friends. (#551)
* GetPlayerNetworkIDString isn't alone anymore, we have friends.

Completely speculative CS:GO fix, 50/50, 60/40.

* Preserve existing cycle-saving techniques.
* Style.
2016-10-13 22:14:51 -07:00
Nicholas Hastings
9158d3734e Trigger build against hl2sdk-csgo change. 2016-10-13 21:34:34 -04:00
Nicholas Hastings
6f9776e3f4 Trigger build against hl2sdk-csgo change. 2016-10-13 21:29:15 -04:00
Nicholas Hastings
d5ff829952 Speculative fix for CS:GO GetClientAuthId issue... 2016-10-13 21:21:58 -04:00
Nicholas Hastings
7fda6e412a Don't build for CS:GO on Mac anymore. (Game is 64-bit-only there now). 2016-10-13 20:54:54 -04:00
Nicholas Hastings
273cab1bbf Trigger build for hl2sdk-csgo update. (Fixes crash on player join.) 2016-10-13 20:40:17 -04:00
Ruben Gonzalez
c097bdc9ce Update more tf2 gamedata. 2016-10-12 21:36:29 -04:00
Ruben Gonzalez
da69ae0371 Update tf2 gamedata. 2016-10-12 21:22:48 -04:00
Nicholas Hastings
72ddd865d1 Add note about uninitialized data in ArrayList.Resize / ResizeArray. 2016-10-11 13:45:36 -04:00
Nicholas Hastings
1dd84e3ed3 Update CS:GO InfoChanged gamedata. (Fixes SetClientInfo). 2016-10-07 14:41:53 -04:00
Jonhasacat
fdb80bd9cf Fixed offsets for SetClientName (#547) 2016-10-07 09:41:05 +01:00
Ruben Gonzalez
549fea4b0a Trigger Build 2016-10-06 23:19:09 -04:00
Ruben Gonzalez
0c08b72b5e Update pushbuild.txt 2016-10-06 22:36:29 -04:00
»SoD« XeroX
227e324aa9 Fixed wrong return type in UserMessageToBfRead (#546)
Fixed wrong return type in UserMessageToBfRead
2016-10-06 13:55:27 +01:00
Nicholas Hastings
aae39da235 Update Insurgency gamedata. 2016-10-05 21:07:35 -04:00
Nicholas Hastings
cff585f2a1 Fixed doc on RadToDeg. 2016-10-04 12:42:22 -04:00
Asher Baker
ec7f1727e5 Allow setting multiple chat trigger characters (PR #449, bug 4341, bug 5668)
Special characters only, minus a couple of potentially-problematic characters.

Technically this is a breaking change - but anyone using multi-char triggers is probably crazy anyway and has been driven off by now.
2016-10-04 16:34:42 +01:00
Nicholas Hastings
098a693c1a Fixed return doc on CharToLower, CharToUpper. 2016-10-03 19:35:49 -04:00
Asher Baker
215599b90f Merge PR #489: Do not call functions in paused plugins
This should be reverted when pausing is removed, see PR discussion.
2016-10-03 16:51:45 +01:00
peace-maker
47eb7d60e5 Fix use-after-free crash in SQLite extension (#481)
When the server crashed and the process got terminated, the SqDriver
instance was killed first (e.g. by atexit). SqDatabase tries to access
SqDriver in its destructor.
This patch tells SqDatabase to not use anything from SqDriver anymore
after SqDriver got destroyed.

Next to that, the clientprefs extension relied on the IDatabase pointer
being valid to get the driver pointer. Cache the pointer, so the dbi
system still knows the IDBThreadOperation belonged to the now gone
driver, even after the database object is gone.
2016-10-03 16:31:17 +01:00
Kyle Sanderson
2deaa666f3 Fix erroneous () in DebugReport:: printouts. (#517) 2016-10-03 16:29:51 +01:00
Asher Baker
47dd2870d9 Merge pull request #476 from alliedmodders/query-format
Implement an auto-escaping Format native for SQL query construction
2016-10-03 16:20:01 +01:00
Nicholas Hastings
999f37800c Strip invalid UTF-8 char from end of player names. (#545) 2016-10-02 18:34:27 -04:00
Asher Baker
a54ee12ade Update MakeBleed gamedata 2016-10-01 18:15:41 +01:00
David Anderson
07ba8df977 Merge pull request #544 from alliedmodders/update-amtl
Update to the latest SourcePawn and AMTL.
2016-09-24 17:45:34 -07:00
David Anderson
27e812461f Update to the latest SourcePawn and AMTL. 2016-09-24 16:45:04 -07:00
Nicholas Hastings
29d4ea3245 Trigger build for hl2sdk-tf2 update. 2016-09-21 13:16:43 -04:00
iNilo
f70a3ea297 Typo in OnRemoveBan documentation (#542)
Fix typo in OnRemoveBan documentation
2016-09-17 17:23:59 +01:00
Nicholas Hastings
237db0504c Update GoldenEye:Source gamedata (bug 6529). 2016-09-11 14:51:04 -04:00
Kyle Sanderson
015b9e92b6 Sync AMTL with upstream fixes. (#538) 2016-08-28 14:01:53 -07:00
David Anderson
ab53e580db Merge pull request #537 from peace-maker/cellarray_bridge
Add ICellArray creation/deletion to logic bridge
2016-08-27 18:17:37 -07:00
Peace-Maker
ecbedb7b11 Don't expose CellArrays in ISourceMod to extensions
Don't let extensions have access to the internal implementation of cell
arrays.
2016-08-26 15:09:18 -07:00
Peace-Maker
5b9ae5917b Add ICellArray and create/free in ISourceMod
Add an ICellArray interface to expose the adt_array CellArray class from
logic to core.
Add methods to ISourceMod to create and delete ICellArray instances in
logic.
2016-08-21 21:32:23 +02:00
Nicholas Hastings
f3c454084a Update to latest Sourcepawn for fixens. 2016-08-19 10:22:23 -04:00
Nicholas Hastings
94383d995d Fix building of MySQL DBI extension on VS 2015+. 2016-08-18 14:20:37 -04:00
Ruben Gonzalez
51a6b9ce30 Update CS:GO gamedata for latest update. 2016-08-06 17:30:18 -04:00
Nicholas Hastings
a25e3755db Fix typo in updated Dino D-Day gamedata. 2016-08-06 13:34:41 -04:00
Nicholas Hastings
0707f14c7a Update Dino D-Day gamedata.
(Piggy-backing off of Blade Symphony now instead of Alien Swarm.
They switched to Portal 2 engine so detects as Blade Symphony, and
both are pretty vanilla at the engine level.)
2016-08-06 10:51:50 -04:00
Ruben Gonzalez
4b52a7e531 Update Insurgency gamedata. 2016-08-02 16:13:30 -04:00
Ruben Gonzalez
f2751815be Fix CS:GO signature for conflicts with detours. 2016-08-02 12:11:38 -04:00
Ross Bemrose
988d023e89 Fix /nominations returning Plugin_Continue (#532) 2016-07-31 13:16:38 -04:00
Luki
f06bdc9121 Add expanded documentation for sm_reserve_type (#531)
There is no information about sm_reserve_type 2 in the cfg file, even though reserve type 2 exists in the plugin and on the wikia.
2016-07-27 12:56:15 -07:00
David Anderson
a7f5fb7a08 Fix Linux build. 2016-07-26 14:46:58 -07:00
David Anderson
61e958e679 Merge pull request #529 from peace-maker/optional_natives
Keep optional natives optional after reloading
2016-07-26 12:59:32 -07:00
Nicholas Hastings
919a1e7bb9 Fix typo in DoI SlapSound13. 2016-07-26 11:15:28 -04:00
Nicholas Hastings
56585fc32a Add preliminary gamedata for Day of Infamy. 2016-07-26 08:26:26 -04:00
David Anderson
57229aac91 Merge pull request #530 from alliedmodders/new-amtl
Update to SourcePawn 1.9 and the latest AMTL.
2016-07-26 01:43:52 -07:00
David Anderson
3cccfc15da Update to SourcePawn 1.9 and the latest AMTL. 2016-07-26 01:36:35 -07:00
Nicholas Hastings
7008a566a8 Redownload GeoIP data if file size is 0, regardless of file modified time.. 2016-07-24 08:26:00 -04:00
Nicholas Hastings
100ddd6724 Trigger build. 2016-07-22 10:26:58 -04:00
Peace-Maker
2c8614c639 Keep optional natives optional after reloading
Bug 6518

Starting from no plugins loaded, after the final step of the following,
basetriggers will be marked as errored because mapchooser is missing:

Load basetriggers
Load mapchooser
Unload mapchooser
Load mapchooser
Unload mapchooser

We lose the SP_NTVFLAG_OPTIONAL when removing a WeakNative. The
__pl_mapchooser_SetNTVOptional() is only called in basetriggers when it
is loaded. It adds the OPTIONAL flag to the mapchooser natives the
basetrigger plugin uses.
When mapchooser is loaded, the native is overwritten and the OPTIONAL
flag consumed (WeakNative registered), but not preserved. Later when
mapchooser is unloaded the WeakNative is removed in
CNativeOwner::UnbindWeakRef, but the OPTIONAL flag isn't added again.
The next time mapchooser is loaded, the natives aren't optional anymore
and will cause a real dependency.

The change in ShareSys isn't needed to fix the error, but is included to
keep the SP_NTVFLAG_OPTIONAL flag consistent.
2016-07-21 01:52:47 +02:00
David Anderson
a34555c45d Merge pull request #527 from alliedmodders/fix-new-sp
Fix syntax for SourcePawn update.
2016-07-09 12:28:43 -07:00
David Anderson
adba0560d7 Fix syntax for SourcePawn update. 2016-07-09 12:24:18 -07:00
David Anderson
1b30e78db3 Update to the latest AMTL. 2016-07-09 12:16:17 -07:00
Nicholas Hastings
cb7eeef014 Remove TFHoliday_SpyVsEngyWar - no longer exists. 2016-07-08 15:44:49 -04:00
Nicholas Hastings
fc9aa50f3c Update TF2 "holiday" gamedata. 2016-07-08 15:44:16 -04:00
Nicholas Hastings
f268fddc3c Update TF2 gamedata. 2016-07-07 19:58:15 -04:00
Asher Baker
3152e7f43f Force build for CS:GO CUserCmd mouse vector fix 2016-07-03 01:04:02 +01:00
Nicholas Hastings
a2ceb8f7d5 Trigger build for hl2sdk-csgo update. 2016-06-25 07:36:34 -04:00
David Anderson
9db8c4af3e Merge pull request #524 from alliedmodders/rm-halfup
Remove half-up rounding.
2016-06-22 16:11:18 -04:00
David Anderson
34dedcaab1 Remove half-up rounding. 2016-06-22 12:54:36 -07:00
Asher Baker
58c00f4487 Download Clang from SourceMod site (#523)
Also switch to Clang 3.8
2016-06-20 17:12:58 +01:00
peace-maker
f425236bac Increase topmenu display buffer size (#520)
The buffer for menu options was 64 chars. That limit can easily be
reached by some utf8 string which would get truncated. Double the buffer
size to 128 chars.
2016-06-20 16:03:54 +01:00
Luki
023a3ca056 Change behaviour for mass renaming (#521)
Append number instead of randomizing when renaming multiple players.

Before the change:
sm_rename @all "Random Name" - this would rename everyone but the names would be randomized (random characters and numbers)

After the change:
sm_rename @all "Random Name" - this would rename everyone to: Random Name 1, Random Name 2, Random Name 3 ...  etc.

Description:
sm_rename can only rename 1 player at a time, when you specify a name. If you use this command on multiple players (like sm_rename @bots "A random bot"), their names get randomized(just like when you dont specify a name). So I propose this change, so you can rename multiple people.

PS:The funny thing is that there was a comment in the code about not wanting everyone to have a same name, but sm_rename doesnt a have check for this so you could use sm_rename to rename everyone, one by one, using the same name.
2016-06-20 13:24:36 +01:00
Nicholas Hastings
34a0cb170e Update FoF gamedata. 2016-06-16 16:15:48 -04:00
Nicholas Hastings
5e4ee1b849 Update CS:GO gamedata. 2016-06-16 16:14:36 -04:00
Nicholas Hastings
f668b3fe6c 🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍 2016-06-11 12:43:04 -04:00
Nicholas Hastings
f12924458f Merge branch 'vs2015' 2016-06-11 12:14:12 -04:00
Nicholas Hastings
857f5fcced Add PowerShell version of checkout-deps script for Windows (NPOTB). 2016-06-11 11:17:29 -04:00
Nicholas Hastings
4eb1e8a4b0 Fix float unary minus operator not functioning properly after PR #510. 2016-06-09 21:36:46 -04:00
Nicholas Hastings
0f96a28cca Use VSERVERTOOLS003 in Nuclear Dawn if server has it available. 2016-06-08 12:32:20 -04:00
Fyren
4d8e76202d Merge pull request #518 from alliedmodders/UTIL_ReplaceAll-fix
Fix UTIL_ReplaceAll not properly tracking length (bug 6472)
2016-06-06 16:40:17 -06:00
Fyren
e356758743 Merge pull request #516 from alliedmodders/scheduledpluginreloads
Better plugin reloads.
2016-06-06 16:29:07 -06:00
Fyren
4e654704dc Slightly better handling of plugin reloading. 2016-06-06 22:26:34 +00:00
Fyren
1790033458 Fix UTIL_ReplaceAll not properly tracking length. 2016-06-06 06:29:53 +00:00
Nicholas Hastings
e3d7a047bd Fixed varint sendprops being treated improperly in CS:GO. 2016-06-05 11:03:18 -04:00
Nicholas Hastings
a67c54a67c Bump version number. 2016-06-05 10:10:07 -04:00
ErikMinekus
b9f7f20046 Fixed return doc spacing for GetGameFolderName (#515) 2016-05-31 07:34:54 -04:00
Nicholas Hastings
c42f73b66c Update more Insurgency gamedata. 2016-05-27 09:33:20 -04:00
Nicholas Hastings
5a2bc4479d Update Insurgency gamedata. 2016-05-26 13:43:07 -04:00
Nicholas Hastings
31928e6282 Fix late/incorrect calls to TR_GetEntityIndex potentially causing crash. (#513) 2016-05-21 14:44:00 -04:00
Nicholas Hastings
9b3b2eb23e Fix comment and reduce branching in TF2_IsPlayerInCondition. 2016-05-21 12:55:47 -04:00
Nicholas Hastings
e127a55b0a Clarified func doc for some edict/entity funcs. 2016-05-21 12:53:55 -04:00
Nicholas Hastings
b7223932d2 Fix some funcommands gamedata for CS:GO.
The base SoundFinal and SoundBoom files don't exist there.
2016-05-21 12:53:27 -04:00
ErikMinekus
542bb59978 Update large includes for transitional syntax #2 (#511) 2016-05-21 09:16:49 -04:00
ErikMinekus
f91d659c6f Update large includes for transitional syntax #1 (#510) 2016-05-21 08:52:43 -04:00
ErikMinekus
7451257578 Update small includes for transitional syntax (#509) 2016-05-20 15:56:21 -04:00
Nicholas Hastings
d8835a426f Update FoF gamedata. 2016-05-20 09:53:43 -04:00
Nicholas Hastings
5edc46c994 Don't enable FileExists hook (SendFile forward) on TF2 servers with Replay. (#512)
It will crash. See PR #493 for details.
2016-05-19 19:11:28 -04:00
Kyle Sanderson
57c6e09fcf Merge pull request #493 from alliedmodders/tfreplaycrash
Only hook IBaseFileSystem::FileExists if we're also hooking INetChannel
2016-05-19 15:23:05 -07:00
Nicholas Hastings
626ee9ac65 Update more BM:S gamedata and trigger build against SDK change. 2016-05-16 17:52:38 -04:00
Nicholas Hastings
59191486b6 Update BM:S gamedata. 2016-05-15 09:16:09 -04:00
Nicholas Hastings
f645ca0daf Update FoF gamedata. 2016-05-14 08:01:10 -04:00
Nicholas Hastings
20c9815619 Add support for sending gameevent to specific client. (#505) 2016-05-12 22:15:23 -04:00
Nicholas Hastings
98e8f70424 Remove some unused gamedata. 2016-05-11 15:16:48 -04:00
ErikMinekus
6d9f46e983 Update fun plugins for transitional syntax (#508) 2016-05-11 10:56:12 -04:00
ErikMinekus
d9fb0ba64e Update base plugins for transitional syntax (#507) 2016-05-11 10:44:58 -04:00
ErikMinekus
e8734ccf28 Update small plugins for transitional syntax (#506) 2016-05-11 09:32:34 -04:00
Nicholas Hastings
11b4320204 Fix potential crash on plugin load when a required library is not found. 2016-04-27 10:49:39 -04:00
ErikMinekus
fb2117137e Update basebans and SQL admins plugins for transitional syntax (#484) 2016-04-27 09:34:22 -04:00
Maxim Telezhenko
730a9a4a40 Transitional Syntax for reservedslots.sp (#501) 2016-04-26 23:19:53 -04:00
Nicholas Hastings
40f2512317 Remove support for Source 1 Dota 2. (#496) 2016-04-26 23:18:47 -04:00
FlaminSarge
6dc602ad7c Update TFCond and tf2_stocks enums (#499)
* Update tf2_stocks DmgCustom and TFWeapon defines

* Update tf2 TFCond defines
2016-04-26 23:18:34 -04:00
Nicholas Hastings
b5876bdd33 Allow Plugin_Changed return on event PreHooks to not block. (#503)
This avoids issues from confusion that users have, returning Plugin_Changed
after altering event data, when Plugin_Changed isn't required and wasn't supported
in that scenario, and instead acted like Plugin_Handled.
2016-04-26 23:18:00 -04:00
Nicholas Hastings
29a5daab98 Allow support for running on filesystems that use 64-bit inodes on Linux. (#502)
Most supported games don't even support this case, but at least CS:GO does. WIthout
this fix, some filesystem calls can fail, or in the case of readdir, fail to return all/any files.
This was first observed when using an XFS-formatted volume on CentOS 7 x64.
2016-04-26 23:17:36 -04:00
Nicholas Hastings
ed46ca3328 Add support for retrieving game server Steam Id (bug 6404). (#495) 2016-04-26 23:17:08 -04:00
Kyle Sanderson
e6ec89d145 Change checkout-deps to use tls for mysql.
http://cdn.mysql.com -> https://cdn.mysql.com
2016-04-15 19:10:23 -07:00
Alexander Georgievskiy
b196d3e3c0 http://cdn.mysql.com -> https://cdn.mysql.com 2016-04-16 00:15:40 +03:00
Nicholas Hastings
ebb5607bd4 Really fix FollowCSGOServerGuidelines setting being ignored in SDKTools (always on) (bug 6480). 2016-03-30 15:59:51 -04:00
Nicholas Hastings
416abd81a1 Add support for compiling with VS2015. 2016-03-30 08:56:27 -04:00
Nicholas Hastings
c536a43914 Merge pull request #494 from akowald/gamerules-edictstate
Always send changes when using the GameRules_SetProp* natives.
2016-03-25 07:46:27 -04:00
akowald
283bdad552 Makes sending the change the default behavior with the GameRules_Set* natives. 2016-03-25 00:43:39 -04:00
Nicholas Hastings
0c8e6e2918 Fix FollowCSGOServerGuidelines setting being ignored in SDKTools (always on). 2016-03-21 15:29:48 -04:00
Kyle Sanderson
8924a9744e Only hook IBaseFileSystem::FileExists if we're also hooking INetChannel::SendFile or INetChannel::ProcessPacket.
This works around a TF Replay SourceHook crash that Johns was seeing when using 1.8.
SourceHook is not thread-safe at the time of this writing.
2016-03-20 14:07:08 -07:00
Nicholas Hastings
5815e49d93 Merge pull request #491 from alliedmodders/travis-clang-3.7
Update TravisCI build to use Clang 3.7.
2016-03-18 11:19:56 -04:00
Nicholas Hastings
70bc24218f Update TravisCI build to use Clang 3.7. 2016-03-18 08:31:01 -04:00
Peace-Maker
4f4903a05e Don't try to call functions in paused plugins
This avoids spam of "Plugin not runnable" exceptions on shutdown or
plugin unload.

When re/unloading a plugin which has other ones depending on it, like
the adminmenu, It pauses the depending plugins putting them in an
"Depends on plugin: %s" error state. ForwardSys doesn't remove them from
the forward lists on pause, specially the global forwards, and still
tries to call all the global forwards like OnPlayerRunCmd and
OnLibraryAdded etc. on the paused plugins. Executing functions in paused
runtimes has been ignored in the VM before introducing the "Exception"
mechanism, but now they're all logged.

This adds checks to make sure the plugin is runnable before calling a
function. (Stolen from #438)
2016-03-14 13:24:23 +01:00
David Anderson
f7bb423f06 Update to the latest SourcePawn and AMTL. 2016-03-13 16:29:11 -07:00
Nicholas Hastings
19bcc8417d Merge pull request #486 from alliedmodders/csgo-safety
Add initial version of safety checks for CS:GO to attempt to avoid user GSLT bans.
2016-03-02 15:26:34 -05:00
Nicholas Hastings
b65de29c92 Add initial version of safety checks for CS:GO to attempt to avoid user GSLT bans. 2016-03-02 15:25:01 -05:00
David Anderson
7bd1ed2339 Merge pull request #477 from 2m/wip-fix-sample-extension-2m
Fix compilation of sample extension
2016-02-29 18:12:15 -05:00
David Anderson
a7c7e72004 Merge pull request #485 from peace-maker/plugin_unloading
Fix scheduled plugin unloading
2016-02-29 10:53:26 -05:00
Peace-Maker
df59fd5b0e Fix scheduled plugin unloading
When unloading a plugin no plugin is allowed to execute code. There's
been some flawed logic in the scheduling, leading it to bail out if the
plugin was marked for scheduled unloading..

Also change the "error" message of `sm plugins unload` to something
nice.
2016-02-29 16:40:24 +01:00
Kyle Sanderson
0d80d3c57c Merge pull request #482 from peace-maker/ext_deps_name
Fix printing dependent extension name on unload
2016-02-27 15:00:35 -08:00
Peace-Maker
060f63e9db Fix printing dependent extension name
Typo which will print the name of the extension being unloaded instead
of the one which would be unloaded as well because of it.
2016-02-27 21:22:09 +01:00
Asher Baker
e243de0538 Merge pull request #480 from iNilo/patch-1
Add missing @error annotation to GetClientSerial
2016-02-25 14:17:57 +00:00
iNilo
11253eae1c GetClientSerial does not have @error documentation
Native "GetClientSerial" reported: Client index 0 is invalid
2016-02-25 15:06:23 +01:00
Nicholas Hastings
c81e1865e0 Merge pull request #479 from TheCreeper/master
Add support for EmpiresMod to mapchooser plugin.
2016-02-22 17:12:07 -05:00
TheCreeper
39d9f4da3f Be consistent. 2016-02-22 21:15:38 +00:00
TheCreeper
6d5dd40875 Add support for Empires to mapchooser. 2016-02-22 21:10:34 +00:00
Nicholas Hastings
051e7cf320 Update Empires gamedata. 2016-02-20 23:32:35 -05:00
Martynas Mickevičius
37210c9ef1 Fix compilation of sample extension. 2016-02-20 03:27:49 +02:00
Nicholas Hastings
3215e25318 Update TF2 gamedata. 2016-02-19 10:10:59 -08:00
Ruben Gonzalez
9d72f0b335 Update CS:GO gamedata for cstrike extension. 2016-02-18 11:16:05 -05:00
Ruben Gonzalez
803c6b0a82 Update TerminateRound detour comment's 2016-02-18 11:15:39 -05:00
Nicholas Hastings
4b04b8d51e Enable ShowMenu and HudMsg for KreedzClimbing. 2016-02-15 14:58:48 -05:00
Asher Baker
b239430247 Merge pull request #458 from stickz/patch-5
Move repeated code in reserved slots plugin to a helper function
2016-02-15 17:11:39 +00:00
Asher Baker
700ec92a9a Implement an auto-escaping Format native for SQL query construction 2016-02-15 15:05:16 +00:00
Asher Baker
272655f340 Changed AddString to be failable 2016-02-15 14:57:56 +00:00
Asher Baker
7c3bcc9c25 Add missing buffer size check to SQLite QuoteString impl 2016-02-15 14:19:11 +00:00
Asher Baker
1ff13c59cf Move the guts of Format to a helper function 2016-02-15 12:49:22 +00:00
Asher Baker
936bdc47f0 Add argument index to format error messages 2016-02-15 10:20:08 +00:00
Asher Baker
9008705b9d Pass format flags down to AddString 2016-02-15 10:16:14 +00:00
Asher Baker
886c358e91 Renumber format flags for sanity 2016-02-15 10:09:48 +00:00
Kyle Sanderson
76f33d2742 Merge pull request #474 from Benoist3012/Benoist3012-tf2-tfcond-enums-update
Update tf2.inc TFCond enums
2016-02-06 14:56:35 -08:00
Benoist3012
5703c323d6 Update tf2.inc 2016-02-06 15:27:09 +01:00
Benoist3012
40434f54aa Update tf2.inc 2016-02-06 13:35:37 +01:00
Nicholas Hastings
b9e9e15647 Merge pull request #473 from akowald/gamerules-crash
Fix for crashes related to the GameRules_Set* natives.
2016-02-03 18:30:53 -05:00
akowald
7fbc9869bd Fix for crashes related to the GameRules_Set* natives. 2016-02-03 16:20:31 -05:00
Nicholas Hastings
148943dad6 Merge pull request #472 from alliedmodders/more-stv-detect-fix
Fix SourceTV bot detection on Source SDK 2013 mods and BM:S.
2016-01-25 19:41:50 -05:00
Nicholas Hastings
90ca9d7a47 Fix SourceTV bot detection on Source SDK 2013 mods and BM:S.
See bug 5529.
2016-01-25 18:52:58 -05:00
Nicholas Hastings
a0e6f33828 Fix some typos in BM:S SDKHooks gamedata. 2016-01-25 06:59:42 -08:00
Kyle Sanderson
52e3b580f3 Merge pull request #471 from peace-maker/drawitem_returntag
Change Panel.DrawItem return tag to |int| (bug 6463)
2016-01-22 09:45:29 -08:00
Peace-Maker
1c0a5b0420 Change Panel.DrawItem return tag to |int| (bug 6463) 2016-01-22 18:30:32 +01:00
Asher Baker
f9448e30c9 Merge pull request #470 from powerlord/sampleext-updateambuild
Update sample_ext's AMBuildScript
2016-01-19 19:49:36 +00:00
Ross Bemrose
2f5257fcb5 Update sample_ext's AMBuildScript with the changes used in SourceMod's AMBuildScript 2016-01-19 12:29:15 -05:00
Nicholas Hastings
5a50c28afd Merge branch 'static-lib-sym-vis' 2016-01-09 11:50:42 -05:00
Nicholas Hastings
3c24ce4d7b Change --exclude-libs to be for Linux only. Apple's linker does not support it. 2016-01-09 11:50:13 -05:00
Nicholas Hastings
441bb0483a Merge pull request #469 from alliedmodders/static-lib-sym-vis
Don't export (all) symbols from included static lib on Linux/Mac.
2016-01-09 11:34:09 -05:00
Nicholas Hastings
05c7bd4be9 Don't export (all) symbols from included static lib on Linux/Mac. 2016-01-09 10:26:12 -05:00
Nicholas Hastings
3dc9c23b65 Updated NMRiH gamedata. 2016-01-07 20:03:08 -05:00
David Anderson
e0e9e87326 Merge pull request #468 from splewis/new-syntax-testing
Update sourcepawn testing include to new syntax.
2016-01-07 12:35:12 +07:00
Sean Lewis
52c7ef0f6f Update sourcepawn testing include to new syntax. 2016-01-06 18:35:16 -06:00
Nicholas Hastings
7ada5f957e Merge pull request #467 from peace-maker/removefromtrie_tag
Add missing |bool| return tag to RemoveFromTrie native
2016-01-05 10:55:18 -05:00
Peace-Maker
d3cc797f0f Add missing |bool| return tag to RemoveFromTrie native 2016-01-05 16:52:30 +01:00
Nicholas Hastings
8f4f0f61ea Merge pull request #466 from peace-maker/inform_customgd
Add info message when loading custom gamedata
2016-01-04 17:54:19 -05:00
Peace-Maker
edb820eae8 Add info message when loading custom gamedata
Print a message to console when there is a gamedata file loaded from the
|custom| folder.
2016-01-03 22:28:24 +01:00
Nicholas Hastings
497b51814d Merge pull request #465 from klausenbusk/bug-5515
Allow plugins to suppress entity outputs (bug 5515).

Contributed by:
Ryan Stecker <voidedweasel@gmail.com>
Peace-Maker <peace-maker@wcfan.de>
2015-12-30 20:33:25 -05:00
Nicholas Hastings
311203b5cf Fix Neotokyo SDKHooks gamedata (bug 6453). 2015-12-30 18:34:02 -05:00
Nicholas Hastings
7dc4d49b86 Fix Neotokyo SDKTools gamedata (bug 6453). 2015-12-30 16:11:22 -05:00
Kristian Klausen
4cba1925fd Allow plugins to suppress entity outputs (fix 5515). 2015-12-30 17:51:57 +01:00
Nicholas Hastings
23fafbd47d Update PVKII gamedata. 2015-12-30 08:34:54 -05:00
Nicholas Hastings
7fbcb81916 Merge pull request #456 from alliedmodders/canbeautobalanced
Add support for hooking CanBeAutobalanced to SDKHooks.
2015-12-29 15:56:24 -05:00
Kyle Sanderson
2812f227b7 Change SDKHooks CanBeAutoBalanced to only MRES_SUPERCEDE if the return changes. 2015-12-29 12:44:03 -08:00
Nicholas Hastings
ce07a44fb0 Merge pull request #455 from alliedmodders/normalshook-typeset
Converted NormalSHook to typeset and added old prototype.
2015-12-29 14:56:58 -05:00
Nicholas Hastings
23f9a1a524 Typo fix fix. 2015-12-22 16:18:53 -05:00
Ruben Gonzalez
c81466bb33 Trigger Build 2015-12-22 12:19:57 -05:00
Nicholas Hastings
26b056d2c4 Typo fix. 2015-12-22 09:58:57 -05:00
Nicholas Hastings
bd9fd43b76 Fix for Black Mesa's different GiveNamedItem prototype. 2015-12-22 09:55:15 -05:00
Nicholas Hastings
184ad9083c Fix for varint gamerules sendprops being treated improperly in Black Mesa. 2015-12-22 09:54:55 -05:00
Nicholas Hastings
8e7093ba2b Fix Black Mesa gamerules gamedata having always been incorrect. 2015-12-22 09:54:28 -05:00
Nicholas Hastings
eb3e7fcc32 Update Black Mesa gamedata for game update. 2015-12-22 09:54:05 -05:00
Nicholas Hastings
c5a81d7c6f Adjust for hl2sdk-bms updates. 2015-12-22 09:53:05 -05:00
Nicholas Hastings
f42e9ff812 Merge branch 'master' of https://github.com/alliedmodders/sourcemod 2015-12-17 15:01:14 -05:00
Nicholas Hastings
dc791f1fbe Update NMRiH gamedata. 2015-12-17 04:40:19 -08:00
Nicholas Hastings
bbd3d3f4b6 Update TF2 gamedata.. 2015-12-16 14:53:13 -05:00
Asher Baker
8370112aa4 Merge pull request #462 from GoD-Tony/vtable-dump-fix
Update IDA vtable dump script
2015-12-12 21:44:56 +00:00
GoD-Tony
5e51ca0f80 Update IDA vtable dump script
A small fix to work with multiple versions of IDA x86 & x64
2015-12-12 22:01:21 +01:00
Asher Baker
7821c34a7b Force a build to make sure I didn't break CS:GO 2015-12-11 20:54:05 +00:00
Nicholas Hastings
272d3c4b9e Trigger build for hl2sdk-csgo updates. 2015-12-09 13:37:38 -05:00
Nicholas Hastings
dd9d60e1d7 Revert part of Windows CS:GO gamedata change to fix IServer lookup. 2015-12-09 10:54:15 -05:00
Nicholas Hastings
3219abcd1f Update CS:GO engine gamedata. 2015-12-09 08:29:56 -05:00
Asher Baker
5733bb5b08 Force build for CS:GO SDK changes 2015-12-09 10:45:20 +00:00
stickz
75484c02a0 Add CheckHiddenSlots() Function 2015-11-27 12:51:38 -05:00
Nicholas Hastings
3e1ba143bf Merge pull request #457 from GoD-Tony/vtable-dump-x64
Add x64 support to IDA vtable dump script (npotb).
2015-11-26 16:46:59 -05:00
GoD-Tony
d3ea10a600 Add x64 support to IDA vtable dump script 2015-11-26 17:36:14 +01:00
Nicholas Hastings
818e1e4e18 Add support for hooking CanBeAutobalanced to SDKHooks. 2015-11-26 10:35:00 -05:00
Nicholas Hastings
126ce99cd9 Resize clients array in newest NormalSHook prototype to MAXPLAYERS.
The old version of the newer one is left as a third typeset member to not break
compilation for users opting into it on dev branch. Both typeset members with
old array size are however marked as deprecated, since they can be missing
a client.
2015-11-26 09:43:08 -05:00
Nicholas Hastings
0d787e24ce Converted NormalSHook to typeset and added old prototype.
New prototype was added in PR #247
2015-11-25 17:25:35 -05:00
Fyren
c11ac4c25e Update SP to version that uses its own new. 2015-11-21 07:51:12 +00:00
Asher Baker
ef147860c2 Fix GetEntSendPropOffs returning 0 for missing props when actual=false
Issue introduced in #439.
2015-11-21 01:46:35 +00:00
Fyren
0e80ffef55 Merge pull request #448 from alliedmodders/use-blamepluginerror
Update SP and use BlamePluginError in sdkhooks and sdktools.
2015-11-18 18:33:10 -07:00
Asher Baker
eb8996699e Merge pull request #443 from alliedmodders/fix-ext-dep-load
Fix crash on failing to load dependent extension.
2015-11-18 14:12:27 +00:00
Fyren
cf4f500eda And use it in sdktools, too. 2015-11-18 01:37:15 +00:00
Fyren
fec2fa3bf0 Update SP and use BlamePluginError in sdkhooks. 2015-11-18 01:24:31 +00:00
Nicholas Hastings
a4d06e1077 Update CTakeDamageInfoHack in SDK Hooks for semi-recent game/SDK updates. 2015-11-11 13:12:04 -05:00
Nicholas Hastings
5f9aaadacb Update Windows TerminateRound signature for CS:GO (bug 6432). 2015-11-10 21:27:24 -05:00
Asher Baker
a802fe3a8b Merge pull request #444 from alliedmodders/decl-bad
Pre-fill buffer for GetClientAuth*
2015-11-10 17:01:58 +00:00
Asher Baker
6ab0c35837 Pre-fill buffer for GetClientAuth* 2015-11-10 14:31:02 +00:00
Asher Baker
b81b6cd1c6 Fix crash on failing to load dependent extension. 2015-11-09 14:56:42 +00:00
David Anderson
c3e5d62bf6 Update to the latest AMTL: remove PassRef. 2015-11-08 13:51:22 -08:00
David Anderson
e2b399b8d3 Update to the latest AMTL - Rename Ref to RefPtr. 2015-11-08 13:14:57 -08:00
Kyle Sanderson
ce25a44e00 Merge pull request #442 from alliedmodders/netchanR
Use present netchannel instead of cached netchannel in CHookManager::SendFile.
2015-11-07 13:04:02 -08:00
Kyle Sanderson
72edc74e8b Use present netchannel instead of cached netchannel in CHookManager::SendFile. 2015-11-07 12:51:13 -08:00
Asher Baker
cf07ecef46 Merge pull request #441 from powerlord/mapdisplayname-backslash
Update GetMapDisplayName to use platform separator on CSGO
2015-11-06 08:31:12 +00:00
Ross Bemrose
c8caf7c860 Update FindMap testsuite plugin.
Update GetMapDisplayNAme to use platform separator on CSGO
2015-11-06 02:38:59 -05:00
Asher Baker
3b3b1d6342 And the last piece of the puzzle... normalise the slashes. 2015-11-05 17:45:26 +00:00
Asher Baker
04161da5a0 Alright, this should work. 2015-11-05 17:35:37 +00:00
Asher Baker
cce6fde4ea Whoops. 2015-11-05 17:03:51 +00:00
Asher Baker
b8e9aabd67 Windows sucks. This may or may not break the Windows build in retaliation. 2015-11-05 16:58:50 +00:00
Asher Baker
625f225448 Suppress error messages from missing repositories. 2015-11-05 11:06:43 +00:00
Asher Baker
e8eb9970a6 Last try before I revert all this. 2015-11-05 10:54:35 +00:00
Asher Baker
ed5771a861 Fix symbol dumping to work on ancient python versions. 2015-11-05 10:46:32 +00:00
Asher Baker
2c03498986 Really fix Mac symbol dumping. 2015-11-05 09:59:53 +00:00
Asher Baker
de675be862 Fix Mac symbol dumping. 2015-11-05 09:31:09 +00:00
Asher Baker
c109ea2cb6 Updated SourcePawn submodule. 2015-11-05 09:20:07 +00:00
Asher Baker
c1f8ebf65c Merge pull request #439 from alliedmodders/propinfo
Deprecate FindSendPropOffs and FindDataMapOffs
2015-11-04 20:55:37 +00:00
Asher Baker
c6323512ef Deprecate FindSendPropOffs and FindDataMapOffs, add HasEntProp. 2015-11-04 20:26:55 +00:00
Asher Baker
0387c45995 Fix Mac build. 2015-11-04 16:28:45 +00:00
Asher Baker
2ea3d9023b Fix libcurl build on Clang 3.5. 2015-11-04 15:21:13 +00:00
Nicholas Hastings
248d776a23 Update TF2 StunPlayer gamedata. 2015-11-03 20:38:12 -05:00
David Anderson
637941a978 Merge pull request #437 from alliedmodders/rm-pausing-12
Fix race between plugin unload and asynchronous query completion.
2015-11-01 14:52:58 -08:00
David Anderson
1f4be9798e Flush asynchronous queries before OnPluginEnd(). 2015-11-01 00:36:20 -07:00
David Anderson
c849616003 Add an OnPluginWillUnload callback that precedes OnPluginEnd(). 2015-11-01 00:30:37 -07:00
David Anderson
d674414cf0 Add a versioned IPluginsListener and deprecate the non-versioned class. 2015-11-01 00:23:33 -07:00
David Anderson
cb3f6df111 Require that no plugin code be live when any plugin unloads. 2015-10-31 19:38:30 -07:00
David Anderson
59623695af Improve plugin console diagnostics. 2015-10-31 17:30:33 -07:00
David Anderson
87e9dee78b Evict plugins that fail to load. 2015-10-31 17:30:33 -07:00
David Anderson
62edc5f4c0 Clean up "sm plugins list" after status meaning clarifications. 2015-10-31 17:25:59 -07:00
David Anderson
903315747d Clarify plugin states. 2015-10-31 17:25:59 -07:00
David Anderson
485ade2610 Fix a number of inconsistencies in plugin state.
1. Fixed OnPluginUnloaded not pairing if the plugin failed.
2. Unify error message handling in the second pass.
3. Do not add libraries if a plugin failed during OnPluginStart.
2015-10-31 17:25:59 -07:00
David Anderson
9e4fff3362 Add a state variable to CPlugin to indicate queue/list membership. 2015-10-31 17:25:59 -07:00
David Anderson
7cc911ae58 Separate plugin unloading into an eviction step, which disconnects the plugin from Core.
Note: this also ensures that library action callbacks are balanced (i.e., we do not notify
libraries are being dropped if they were never notified as being added).
2015-10-31 17:25:59 -07:00
David Anderson
82ff7d5af7 Rename CPlugin::SetErrorState to EvictWithError. 2015-10-31 17:25:59 -07:00
David Anderson
c4c6efb140 Remove a crazy unused function from CPluginManager. 2015-10-31 17:25:59 -07:00
David Anderson
f078ea1f8a Remove the Illiad-length mostly-wrong comment at the top of PluginSys.h 2015-10-31 17:25:59 -07:00
David Anderson
ab1b915a3c Fix re-entrancy issues in CPluginManager by using ReentrantList. 2015-10-31 17:24:22 -07:00
David Anderson
709149fbed Remove the CPluginIterator cache. 2015-10-31 17:23:24 -07:00
David Anderson
e57a076dc8 Remove CPluginManager's friend access to CPlugin. 2015-10-31 17:19:10 -07:00
David Anderson
c21b3a36fc Remove CPluginManager direct use of CPlugin::NativeOwner::m_fakes. 2015-10-31 17:19:10 -07:00
David Anderson
f765c8d436 Remove CPluginManager direct use of CPlugin::m_LibraryMissing. 2015-10-31 17:19:10 -07:00
David Anderson
ae44a6540a Remove CPluginManager direct use of CPlugin::m_FakeNativesMissing. 2015-10-31 17:19:10 -07:00
David Anderson
f27dbaf716 Remove CPluginManager direct use of CPlugin::m_RequiredLibs. 2015-10-31 17:19:10 -07:00
David Anderson
717ad38d06 Remove CPluginManager direct use of CPlugin::m_errormsg. 2015-10-31 17:19:10 -07:00
David Anderson
60f06d1414 Remove CPluginManager direct use of CPlugin::m_FileVersion. 2015-10-31 17:19:10 -07:00
David Anderson
a579136a3d Remove CPluginManager direct use of CPlugin::m_DateTime. 2015-10-31 17:19:10 -07:00
David Anderson
2f3d523ac0 Remove CPluginManager use of CPlugin::m_pRuntime. 2015-10-31 17:19:10 -07:00
David Anderson
df5c53fa4a Remove CPluginManager direct use of CPlugin::m_filename. 2015-10-31 17:19:10 -07:00
David Anderson
46c069dbbe Remove CPluginManager direct use of CPlugin::m_Libraries. 2015-10-31 17:19:09 -07:00
David Anderson
bda9defc0f Remove CPlugin's friend access to CPluginManager. 2015-10-31 17:19:09 -07:00
Asher Baker
8817b4277d Merge pull request #435 from alliedmodders/spelling
Spelling.
2015-10-30 19:20:39 +00:00
Asher Baker
4346e963e5 Correct spelling in API documentation. 2015-10-30 12:26:34 +00:00
Asher Baker
9bbcae1648 Correct spelling in configuration files. 2015-10-30 12:26:11 +00:00
Asher Baker
fc504737c5 Fix a misleading error message from "sm config".
The Ignore state could be hit if the value was read directly rather than using OnSourceModConfigChanged.
2015-10-30 11:06:54 +00:00
Kyle Sanderson
1a09f2b6df Merge pull request #433 from alliedmodders/dinner
NPOTB: Remove 0x prefix from two-byte instructions.
2015-10-29 02:25:15 -07:00
Kyle Sanderson
44d34d0e5d NPOTB: Remove 0x prefix from two-byte instructions. 2015-10-28 19:43:17 -07:00
Nicholas Hastings
56339ed43a makesig.idc fucked me without taking me to dinner and a movie first 2015-10-28 22:37:10 -04:00
Nicholas Hastings
393ab89c34 Update TF2 gamedata. 2015-10-28 19:58:36 -04:00
Asher Baker
38fd55a05d Normalize repository root path. 2015-10-28 13:31:02 +00:00
Asher Baker
e0e946afac Merge pull request #431 from alliedmodders/symbol-repos
Include repo information in symbol files
2015-10-28 13:12:10 +00:00
Asher Baker
4d3c89c065 Flip INFO REPO records around for parsing sanity. 2015-10-28 09:47:40 +00:00
Nicholas Hastings
a7b1a9a5fa Update Insurgency gamedata. 2015-10-27 18:38:59 -07:00
Nicholas Hastings
529d7e2659 Fix Insurgency build on Linux for SDK changes. 2015-10-27 18:17:26 -07:00
Asher Baker
4be998c4dc Include repo information in symbol files. 2015-10-27 17:24:03 +00:00
Nicholas Hastings
261a4bb81b Merge pull request #430 from alliedmodders/packaging-latest
Upload sourcemod-latest-<os> text file when packaging.
2015-10-26 14:55:54 -04:00
Nicholas Hastings
beba03292a Upload sourcemod-latest-<os> text file when packaging. 2015-10-26 11:13:57 -07:00
Ruben Gonzalez
6042518691 Update CS:GO CSore offset. 2015-10-24 19:16:35 -04:00
Ruben Gonzalez
02a9db8e50 Update CS:GO gamedata for CScore. 2015-10-24 01:53:49 -04:00
David Anderson
d0dda098a2 Merge pull request #429 from powerlord/sqltxn-dbresultset
Allow SQLTxnSuccess to use DBResultSet[] in addition to Handle[]
2015-10-22 23:40:28 -07:00
David Anderson
195a836999 Merge pull request #427 from alliedmodders/refactor-amb
Refactor and cleanup the AMBuildScript a bit.
2015-10-17 18:58:05 -07:00
Nicholas Hastings
366c3c0e16 Merge pull request #425 from WildCard65/WildCard65-FixedDBI.inc
Fixed DBResultSet.IsFieldNull
2015-10-13 15:12:18 -04:00
Ross Bemrose
a4b45aea9b Allow SQLTxnSuccess to use DBResultSet[] in addition to Handle[] 2015-10-13 14:50:59 -04:00
Nicholas Hastings
fa65b62a04 Merge pull request #428 from FlaminSarge/tf_mannpower_conds
Update TFCond enum
2015-10-10 14:15:48 -04:00
Nicholas Hastings
71439b30ab Fix NeoTokyo SDKTools gamedata signatures. 2015-10-10 14:08:43 -04:00
FlaminSarge
e585e34670 Update TFCond enum 2015-10-10 02:27:08 -07:00
Nicholas Hastings
2f2f057b47 Update Fistful of Frags gamedata. 2015-10-09 13:31:21 -04:00
Ruben Gonzalez
7e4bfce892 Update CS:GO gamedata. 2015-10-08 19:08:17 -04:00
David Anderson
6c5ab80418 Refactor and cleanup the AMBuildScript a bit. 2015-10-08 14:55:53 -07:00
Nicholas Hastings
121124e362 Merge pull request #426 from powerlord/holiday-communityupdate
Add Community Update holiday
2015-10-07 09:58:36 -04:00
Ross Bemrose
f4adf33b4e Renumber holidays
Add CommunityUpdate holiday
2015-10-07 09:40:06 -04:00
Nicholas Hastings
6fe4175fd2 Update TF2 CanPlayerTeleport signature on Windows. 2015-10-02 07:43:43 -04:00
WildCard65
8627fe1fa8 Fixed DBResultSet.IsFieldNull 2015-09-30 08:38:14 -04:00
Asher Baker
9310cfd164 Merge pull request #424 from alliedmodders/update-versioning
Promote git revision number to 4th version string component
2015-09-29 19:40:51 +01:00
Asher Baker
722c0eb32b Promote git revision number to 4th version string component 2015-09-29 11:07:16 +01:00
Nicholas Hastings
66a3811049 Add FireOutput gamedata for KreedzClimbing. 2015-09-28 16:16:23 -04:00
Ruben Gonzalez
c3fcc44718 Update CS:GO gamedata. 2015-09-25 23:09:39 -04:00
Nicholas Hastings
8b6e040581 Add gamedata for Kreedz Climbing. 2015-09-23 10:11:30 -04:00
David Anderson
88a47ff681 Switch to re-entrant lists in ForwardSys and CForward. 2015-09-21 01:07:34 -07:00
David Anderson
d0843ab997 Add a ReentrantList class to abstract list mutation during iteration. 2015-09-21 01:07:30 -07:00
David Anderson
c1396de2fc Replace SourceHook::List with ke::LinkedList in ForwardSys. 2015-09-21 01:07:25 -07:00
David Anderson
0810c4b217 Fix style issues in ForwardSys, removing extra blocks and tightening variable scope.
This also fixes a bug where IsFunctionRegistered() did not check the paused plugins list.
2015-09-21 01:07:18 -07:00
David Anderson
632c7d05dd Remove the forward cache and simplify CForward construction. 2015-09-21 01:07:01 -07:00
David Anderson
dcc192ee0d Use new header style. 2015-09-21 01:06:43 -07:00
David Anderson
9b1678bd18 Remove error outparams from first-pass internal plugin loading commands. 2015-09-21 00:51:20 -07:00
David Anderson
5f19fc036d Refactor AskPluginLoad() to contain its own error state. 2015-09-21 00:51:16 -07:00
David Anderson
5eec2e7d6d Remove error message outparam to LoadExtensions. 2015-09-21 00:51:11 -07:00
David Anderson
3195dec436 Split LoadOrRequireExtensions into two distinct functions. 2015-09-20 23:44:45 -07:00
David Anderson
15f4a05122 Factor the iterator out of LoadOrRequireExtensions. 2015-09-20 23:44:41 -07:00
David Anderson
e559e6ffa8 Simplify pass 2 of LoadOrRequireExtensions. 2015-09-20 23:44:37 -07:00
David Anderson
23290b35a7 Clean up LoadOrRequireExtensions and properly scope variables. 2015-09-20 23:44:34 -07:00
David Anderson
2b3da56fb5 Dedent a huge block of code. 2015-09-20 23:44:30 -07:00
David Anderson
370710c0ff Fix build. 2015-09-20 21:39:12 -07:00
David Anderson
4fc7eb8a6b Remove trailing whitespace. 2015-09-20 20:58:03 -07:00
David Anderson
38c01714d7 Clean up AskPluginLoad logic. 2015-09-20 20:57:59 -07:00
David Anderson
0e1a34a4d7 Hide CPlugin timestamp management details. 2015-09-20 20:57:55 -07:00
David Anderson
d5d7e8c9cf Factor guts of _LoadPlugin into a separate function. 2015-09-20 20:57:51 -07:00
David Anderson
76d681761d Factor malware checks into its own pass. 2015-09-20 20:57:47 -07:00
David Anderson
3807edbeb8 Move CPlugin compilation into its own function. 2015-09-20 20:57:43 -07:00
David Anderson
d9216cc599 Remove references to non-mapupdated plugins. 2015-09-20 20:31:30 -07:00
David Anderson
d551338510 Merge pull request #400 from alliedmodders/mv-srvcmds-x
Remove sm_srvcmds.cpp.
2015-09-20 15:15:43 -07:00
David Anderson
8a7dfdbc11 Move the "sm" command to core/logic. 2015-09-20 14:33:17 -07:00
David Anderson
1a7b708df8 Split command buffer peeking hacks out of the "sm" command. 2015-09-20 14:33:14 -07:00
David Anderson
168b779786 Move sm_dump_handles to core/logic. 2015-09-20 14:33:10 -07:00
David Anderson
c853050265 Move sm_reload_translations to Translator. 2015-09-20 14:33:06 -07:00
David Anderson
c614d19af0 Move sm_dump_admcache to AdminCache. 2015-09-20 14:33:02 -07:00
David Anderson
8b4f27a038 Add infrastructure to let logic define ConCommands. 2015-09-20 14:32:58 -07:00
Ruben Gonzalez
48eee4db9b Sync GDC symbols.txt to match one currently used (NPOTB). 2015-09-20 15:28:33 -04:00
David Anderson
c66d14605a Merge pull request #397 from alliedmodders/rm-old-mms
Remove code that handles long-dead Metamod:Source versions.
2015-09-18 14:38:52 -07:00
Nicholas Hastings
ac8a7ecad7 Merge pull request #416 from alliedmodders/rip-s1dota
Stop building Source 1 Dota 2 build.
2015-09-18 15:48:59 -04:00
Nicholas Hastings
292df5010f Stop building Source 1 Dota 2 build. 2015-09-18 15:36:46 -04:00
Nicholas Hastings
5f3f9e869e Trigger build for hl2sdk TF2/CS:S/DoD:S/HL2:DM CUserCmd changes.
Fixes mouse values in OnPlayerRunCommand.
2015-09-18 15:32:52 -04:00
Nicholas Hastings
e748d49343 In package script, set binmode for geoip out file (bug 6415).
This fixes newline conversion happening on Windows.
2015-09-18 10:08:39 -04:00
Nicholas Hastings
c085444a03 In packaging, use API for gunzip instead of executable (bug 6415). 2015-09-18 08:27:28 -04:00
Nicholas Hastings
c982cc9991 Merge pull request #354 from powerlord/findmap-plugins
GetMapDisplayName and associated core plugin changes.
2015-09-17 11:17:40 -04:00
Ruben Gonzalez
249be7ad56 Merge pull request #411 from alliedmodders/terminate-fix
Add shim for TerminateRound for  CS:GO
2015-09-16 19:31:52 -04:00
Ruben Gonzalez
6268abe2c3 Untab #ifdef's 2015-09-16 19:21:58 -04:00
Ruben Gonzalez
6aa776eab7 Add comments to VIP RoundEnd reasons. Fix typo. 2015-09-16 19:21:21 -04:00
Ruben Gonzalez
c86a6abdc5 Add shim for TerminateRound for CS:GO 2015-09-16 19:03:40 -04:00
Nicholas Hastings
0e4edd4419 Merge pull request #401 from alliedmodders/css-sync
Updated gamedata for CS:S, DoD:S, and HL2:DM.
2015-09-16 18:14:58 -04:00
David Anderson
2a6b37dc81 Merge pull request #410 from alliedmodders/fix-static
Fix temporary parameter list being static.
2015-09-16 10:01:39 -07:00
David Anderson
485975fd99 Fix temporary parameter list being static. 2015-09-16 00:27:36 -07:00
David Anderson
c36f80b93d Don't use server commands to flush plugin unloads. 2015-09-15 19:43:41 -07:00
David Anderson
08cadcdda6 Merge pull request #372 from alliedmodders/rm-pausing
Cleanup some PluginSys idiosyncracies.
2015-09-15 19:15:26 -07:00
David Anderson
d473b0441d Allow plugin info fields to outlive their runtime. 2015-09-15 19:07:22 -07:00
Ruben Gonzalez
189369fcf3 Fix GDC byte offset check printing for linux (NPOTB) 2015-09-15 21:59:24 -04:00
Ruben Gonzalez
a01a63cb71 Update CS:GO gamedata. 2015-09-15 19:23:28 -04:00
Ross Bemrose
10a95cfdce Add new function: GetMapDisplayName.
This function will resolve the name of a map using FindMap, then (if applicable), will turn a workshop map name into a nicely formatted name.

Currently only TF2 and CS:GO Map Workshops are supported.  More can be added at a later date.

This function returns false if a map was not found, but true in any other instance even if FindMap could not resolve the map name.

This patch also updates the following core plugins to use this GetMapDisplayName:

BaseTriggers
BaseVotes
MapChooser
NextMap
Nominations
RandomCycle
RockTheVote
2015-09-15 16:16:58 -04:00
David Anderson
653dd36020 Merge pull request #378 from powerlord/fix-convar
Fix ConVar .IntValue, .BoolValue, and .FloatValue assignments (Bug 6405)
2015-09-15 12:33:51 -07:00
Nicholas Hastings
28bf744a18 Merge pull request #399 from alliedmodders/tf2branch-nontf2-ismapvalid
Fix IsMapValid call on non-TF2 TF2-branch games to use old behavior requiring only map name
2015-09-14 20:44:24 -04:00
Nicholas Hastings
e7d9795fc1 Fix IsMapValid call on non-TF2 TF2-branch games to use old behavior requiring only map name. 2015-09-14 19:24:28 -04:00
David Anderson
2adae27557 Clean up CPlugin member variables. 2015-09-14 12:55:42 -07:00
David Anderson
3430962cbe Simplify required libs handling and make sure they create dependency links. 2015-09-14 12:53:23 -07:00
David Anderson
0aaa659e29 Fix how the mark-serial is used.
The mark-serial is a generation number to optimize dependency tracking. It did not actually get
applied correctly, meaning that in rare cases we could miss dependencies. This patch removes the
incorrect serial propagation and ensures that we don't double-count a dependent plugin.

Additionally, this patch ensures that all callers of BindNativeToPlugin() will update the mark
serial, as is required to correctly track dependencies.
2015-09-14 12:50:50 -07:00
David Anderson
9ef8cc7064 Separate the top of UnloadPlugin into a precursor function. 2015-09-14 12:50:39 -07:00
Nicholas Hastings
44bacdc067 Fix recent regression with finding engine ptr on CS:S, DoD:S, HL2:DM.
They are still only have engine v21, not yet v22 (let alone v23).
2015-09-14 09:56:06 -04:00
Nicholas Hastings
7d2c0bd962 Merge pull request #408 from alliedmodders/css-sync2
Update metamod-attached extensions to use same engine ptr lookup as core
2015-09-13 17:45:13 -04:00
Ruben Gonzalez
bb39c54f17 Merge pull request #403 from alliedmodders/gdc-fix
Fix Makefile for GDC and improve output (NPOTB)
2015-09-13 17:23:24 -04:00
Nicholas Hastings
8f8c00c66d Update metamod-attached extensions to use same engine ptr lookup as core.
(On TF2-branch games, always search for engine v23 first, falling back to v22.)
2015-09-13 17:18:33 -04:00
Kyle Sanderson
5b3b17799f Merge pull request #407 from Thordin/FindEntityByNetClass
Added IsFree() edict check to FindEntityByNetClass
2015-09-13 14:02:38 -07:00
thordin
3a59baab2c Added IsFree() edict check to FindEntityByNetClass. 2015-09-13 13:49:31 -07:00
David Anderson
fc947c68f7 Merge pull request #404 from alliedmodders/fix-crash
Fix a regression from the ConCmdManager refactoring that causes a crash using SourceMod commands in the server console.
2015-09-12 22:53:09 -07:00
Ruben Gonzalez
cfd116b93b Removed public/sourcepawn from include. Add -Wno-unused for unused variables. 2015-09-12 20:30:53 -04:00
Kyle Sanderson
afc88694fd Merge pull request #305 from KyleSanderson/filetranshooks
Add File Transfer hooks to SDKTools (Bug 4222).
2015-09-12 13:12:50 -07:00
Kyle Sanderson
274e7bd329 Add FileTransfer Hooks to SDKTools (r=Drifter). 2015-09-12 13:01:33 -07:00
Nicholas Hastings
8777d0d0da Use unlink() instead of rm in packaging script for Windows compat. 2015-09-12 15:12:45 -04:00
Nicholas Hastings
8ce41407dd When downloading translations for packaging, bypass certificate check.
It will fail on the slaves and we're resolving to internal addressing anyway.
2015-09-12 14:16:38 -04:00
David Anderson
bcd80d3e84 Fix a regression from the ConCmdManager refactoring that causes a crash using SourceMod commands in the server console. 2015-09-12 00:26:47 -07:00
Nicholas Hastings
cfa09f22c1 Merge pull request #390 from alliedmodders/pkg-more
Add translation files and updated GeoIP data to snapshots (bug 5728)
2015-09-11 15:53:38 -04:00
Ruben Gonzalez
cec5bfe7b2 Update Makefile to compile against central. Added some more info on byte checks. 2015-09-11 15:36:11 -04:00
Nicholas Hastings
f1a907c298 Merge pull request #402 from alliedmodders/shim-noshim
Shim for TF2-branch games to find latest, non-shimmed engine iface. 2
2015-09-11 09:24:24 -04:00
Nicholas Hastings
f6d7fd4949 Don't use VInterfaceMatch when wanting explicit iface version. 2015-09-11 05:40:03 -07:00
Nicholas Hastings
2bd91dd93b Fix always failing when falling back to engine v22. 2015-09-11 05:38:53 -07:00
Nicholas Hastings
2b13f28cfc Updated gamedata for CS:S, DoD:S, and HL2:DM. 2015-09-11 05:29:09 -07:00
Nicholas Hastings
3c264d78bb Merge pull request #398 from alliedmodders/shim-noshim
Shim for TF2-branch games to find latest, non-shimmed engine iface.
2015-09-10 22:47:13 -04:00
Nicholas Hastings
82b7485001 Shim for TF2-branch games to find latest, non-shimmed engine iface. 2015-09-10 20:43:48 -04:00
Nicholas Hastings
c6c034f90a Trigger build for hl2sdk-tf2 changes. 2015-09-10 19:54:32 -04:00
Nicholas Hastings
cb9f2b9144 Trigger build for hl2sdk-tf2 changes.. 2015-09-10 18:31:30 -04:00
Kyle Sanderson
6909f7f23c Merge pull request #396 from alliedmodders/findmapconst
Change FindMap to take a const char* for searching instead of char*.
2015-09-10 12:14:43 -07:00
Kyle Sanderson
f59df243ea Change FindMap to take a const char* for searching instead of char*. 2015-09-10 11:47:46 -07:00
Kyle Sanderson
d9839bab68 Fix sm-central crashing on start (bug 6413). 2015-09-10 11:32:10 -07:00
David Anderson
fe16e8e47c Move the SetCommandClient hook into GameHooks. 2015-09-09 20:03:23 -07:00
David Anderson
fd961f4712 Remove code to handle SourceHook versions 3 and lower. 2015-09-09 19:00:18 -07:00
David Anderson
b548ba7b58 Remove bad-console-read protection logic for Metamod:Source 1.7 and earlier. 2015-09-09 18:59:31 -07:00
David Anderson
df672dd8ce Remove the ability to compile against Metamod:Source versions lower than 1.8. 2015-09-09 18:54:43 -07:00
David Anderson
c54b54ded0 Use GameHooks for ChatTriggers. 2015-09-09 18:51:21 -07:00
David Anderson
5757b729ac Hide MRES_SUPERCEDE from command hook callbacks. 2015-09-09 18:45:20 -07:00
David Anderson
b048dc7b10 Move ConCommand hooks into GameHooks and switch callbacks to ICommandArgs. 2015-09-09 18:40:04 -07:00
David Anderson
b63bfdc72a Rename QueryHookMode to ClientCvarQueryMode. 2015-09-09 18:40:01 -07:00
David Anderson
fa93426f6a Remove blanket includes from sm_stringutil. 2015-09-09 15:18:24 -07:00
David Anderson
86f0a77e73 Reduce dependence on sm_strdup. 2015-09-09 15:18:24 -07:00
David Anderson
13a783d441 Remove UTIL_Format() and UTIL_FormatArgs(). 2015-09-09 15:18:17 -07:00
David Anderson
e08697ad54 Remove strncopy(). 2015-09-09 14:57:47 -07:00
David Anderson
67ba703b84 Merge pull request #392 from alliedmodders/mv-datapack
Move CDataPack from core to logic.
2015-09-09 14:41:49 -07:00
Kyle Sanderson
d85568b54b Merge pull request #321 from Bara20/getentityrendercolor
Add GetEntityRenderColor stock.
2015-09-08 16:22:16 -07:00
David Anderson
67c8ee4ce3 Move CDataPack from core to logic. 2015-09-06 11:02:52 -07:00
David Anderson
69984f472f Remove unused, NPOTB CrazyDebugger. 2015-09-05 20:44:00 -07:00
Nicholas Hastings
2ab7c08da9 Add translation files and updated GeoIP data to snapshots. 2015-09-01 11:30:45 -07:00
David Anderson
4e275eea97 Split intercom.h into separate headers and reduce shared header inclusion. 2015-08-31 10:00:49 -07:00
David Anderson
4f1705e001 Rename some bridge interfaces. 2015-08-31 09:57:32 -07:00
David Anderson
5d55ff23bd Move OnQueryCvarValueFinished into the global hook manager. 2015-08-31 09:22:08 -07:00
David Anderson
2ed044804d Move OnConVarChanged into a global hook. 2015-08-31 09:18:29 -07:00
David Anderson
32ba03538b Move CCommandArgs into its own header. 2015-08-31 00:07:37 -07:00
David Anderson
23feee0e00 Put the game provider in its own header. 2015-08-31 00:07:34 -07:00
David Anderson
401aa038f8 Start a new bridge mechanism for global callbacks. 2015-08-31 00:07:27 -07:00
David Anderson
38e1c2f1f3 Clean up the core side of the logic bridge. 2015-08-30 23:30:15 -07:00
David Anderson
9e4d396d5e Virtualize MMS functions in the core/logic bridge. 2015-08-30 23:29:46 -07:00
David Anderson
5c5d43137d Virtualize game state functions in the core/logic bridge. 2015-08-30 23:29:23 -07:00
David Anderson
bdfdab1d3a Virtualize game description functions in the core/logic bridge. 2015-08-30 23:28:59 -07:00
David Anderson
9366882ac4 Virtualize ConVar bridge functions. 2015-08-30 23:28:44 -07:00
David Anderson
0f9e5234fe Convert core_bridge to a proper class declaration. 2015-08-30 23:28:28 -07:00
David Anderson
3d5c9f0e21 Rename smcore to bridge, and use it as a pointer. 2015-08-30 23:27:53 -07:00
David Anderson
a2dac43833 Remove CCommand from the logic bridge. 2015-08-30 21:02:14 -07:00
David Anderson
28346c99f2 Move RootConsoleMenu into core/logic. 2015-08-30 21:01:46 -07:00
David Anderson
23d55dd9d5 Move RootConsoleMenu::ConsolePrint into the logic bridge. 2015-08-30 21:01:27 -07:00
David Anderson
2c886943a0 Move RootConsoleMenu into its own header and .cpp file. 2015-08-30 21:01:10 -07:00
David Anderson
9d805ea9fb Replace the AddRootConsoleCommand API to not expose internal structures. 2015-08-30 21:01:03 -07:00
David Anderson
e992c33f35 Factor irrelevant stuff out of RootConsoleMenu. 2015-08-30 21:00:42 -07:00
David Anderson
ecbcc7ba16 Move the sourcemod_version convar. 2015-08-30 21:00:39 -07:00
David Anderson
6503e92d66 Move LibrarySys from core to logic. 2015-08-30 20:11:22 -07:00
David Anderson
207f643d3a Replace g_LibSys usage with AMTL primitives. 2015-08-30 20:11:02 -07:00
David Anderson
ec01ca72a0 Replace internal ILibrary use with ke::SharedLib. 2015-08-30 20:10:59 -07:00
David Anderson
5ecd906905 Replace CLibrary with a wrapper around ke::SharedLib. 2015-08-30 20:10:57 -07:00
David Anderson
e78fe93e92 Move gnprintf/atcprintf from core to logic. 2015-08-30 19:32:46 -07:00
David Anderson
9d2bee261c Move TrimWhitespace from core to logic. 2015-08-30 18:42:25 -07:00
David Anderson
c261bb0b2e Merge branch 'rm-strncopy' 2015-08-30 18:38:31 -07:00
David Anderson
204ca3aca5 Update to the latest AMTL revision. 2015-08-30 18:38:05 -07:00
David Anderson
a158205f30 Remove strncopy from the core/logic bridge. 2015-08-30 18:21:07 -07:00
David Anderson
3786a2756b Merge pull request #379 from alliedmodders/rm-format
Remove Format/FormatArgs from the core/logic bridge.
2015-08-30 21:04:20 -04:00
David Anderson
457266d249 Make UTIL_Format wrap ke::SafeSprintf. 2015-08-30 18:03:36 -07:00
David Anderson
9ba1363d86 Remove Format/FormatArgs from the core/logic bridge. 2015-08-30 18:03:31 -07:00
David Anderson
2d40af31a2 Merge pull request #383 from alliedmodders/new-amtl
Update to the latest AMTL version.
2015-08-27 10:55:00 -04:00
David Anderson
c87b3c0859 Update to the latest AMTL version. 2015-08-27 01:01:18 -04:00
David Anderson
e30b57cb4a Update build scripts for new AMTL folder structure. 2015-08-26 15:54:55 -04:00
Ross Bemrose
569a53182c Allow sm_SetConVarString, sm_SetConVarFloat, and sm_SetConVarNum treat notify and replicate as non-existent.
Remove special functions for BoolValue, IntValue, and FloatValue.
2015-08-24 17:03:47 -04:00
Asher Baker
ee2a408d44 Merge pull request #376 from s3bul/convars/define
Add missing include guard for convars.inc
2015-08-19 19:33:04 +01:00
Sebastian K
e030bb4451 Add define included 2015-08-19 20:27:33 +02:00
Nicholas Hastings
9e3ed67185 Merge pull request #375 from alliedmodders/tf2-update-15-08-18-pre
Update TF2 gamedata.
2015-08-18 19:00:44 -04:00
Asher Baker
d1768b7089 Update TF2 gamedata 2015-08-18 21:09:33 +01:00
David Anderson
55647cc18e Update to the latest SourcePawn revision. 2015-08-18 09:51:24 -07:00
Kyle Sanderson
9ebd4ad627 Merge pull request #319 from KyleSanderson/20isntagoodnumber
Allow GetMapHistorySize to return numbers greater than 20 (r=Dr!fter).
2015-09-05 13:58:03 -07:00
Nicholas Hastings
d6476728f9 Merge pull request #391 from alliedmodders/dataprop-stringt-arrays
Fix quirks with Get/SetEntPropString on string_t arrays in datadesc
2015-09-02 21:55:14 -04:00
Nicholas Hastings
1e1b23dc31 Add missing sanity checks on element param on SetEntPropString for data props. 2015-09-02 18:35:37 -04:00
Nicholas Hastings
5cdf35d687 Fix array detection/handling for GetEntPropString with string_t arrays (bug 6409). 2015-09-02 18:33:58 -04:00
Ruben Gonzalez
229769ed22 Fix CS:GO Score gamedata. 2015-08-15 20:16:02 -04:00
Nicholas Hastings
4dd641287d Fix typo in last commit. 2015-08-15 11:56:36 -04:00
Nicholas Hastings
199d1b8eeb Fix Mac build. 2015-08-14 22:00:43 -04:00
Nicholas Hastings
31cd5c7863 Merge pull request #371 from alliedmodders/clang-3.6
Fix build on Clang 3.6.
2015-08-14 21:56:35 -04:00
Nicholas Hastings
a95527a72c Merge pull request #370 from alliedmodders/valvefs-default-pathid
Make path id default to "GAME" instead of NULL for FileExists and FileSize if param missing.
2015-08-14 08:44:34 -04:00
Nicholas Hastings
4f0c06d068 Merge pull request #369 from alliedmodders/bug-6391
Fix bIsStringIndex not being initialized in SetEntPropString for non-index SendProps (bug 6391).
2015-08-14 08:32:33 -04:00
Nicholas Hastings
af4573e7af Fix build on Clang. 2015-08-14 08:31:52 -04:00
Nicholas Hastings
620cb405b1 Fix build on Clang 3.6. 2015-08-14 08:25:40 -04:00
Nicholas Hastings
a08a693bf3 Make path id default to "GAME" instead of NULL for FileExists and FileSize if param missing.
This only affects plugins compiled before the param existed in the includes. NULL defaults to "GAME"
on some engine versions, but is invalid on others, causing any file to not be found.
2015-08-14 07:52:50 -04:00
Nicholas Hastings
8a726a8fbb Fix bIsStringIndex not being initialized in SetEntPropString for non-index SendProps. 2015-08-14 07:50:10 -04:00
David Anderson
ff692f6040 Merge pull request #366 from peace-maker/timer_paused
Fix calling timer callback in paused plugins
2015-08-13 22:14:02 -07:00
David Anderson
246c32a202 Update SourcePawn and AMTL. 2015-08-13 22:08:47 -07:00
David Anderson
f81786cea0 Merge pull request #368 from alliedmodders/rm-binding
Update includes to remove binding syntax.
2015-08-12 12:31:55 -07:00
David Anderson
bcfef75c5d Update regex and datapack includes to not use binding syntax. 2015-08-12 11:52:57 -07:00
Peace-Maker
0a14d3f50c Fix calling timer callback in paused plugins
Don't try to call the timer callback, if it's not runnable.
Error wasn't reported before the exception refactoring.
2015-08-09 01:50:36 +02:00
David Anderson
17c4649651 Update SourcePawn for bug 6396. 2015-08-02 12:54:34 -07:00
Nicholas Hastings
4c895a78c6 Update Insurgency gamedata. 2015-07-29 06:58:56 -04:00
David Anderson
152807b977 Update AMTL and SourcePawn submodules to master. 2015-07-25 17:25:59 -07:00
Nicholas Hastings
45f5ac64e1 Merge pull request #364 from alliedmodders/bug-6391
Fix maxlen in SetEntPropString not being initialized (bug 6391).
2015-07-25 14:54:06 -04:00
Nicholas Hastings
b438a5b39e Merge pull request #365 from powerlord/sampleext-fixcopyfiles
sampleext PackageScript: Add missing CopyFiles function.
2015-07-25 14:17:08 -04:00
Ross Bemrose
b705de0143 Add missing CopyFiles function. 2015-07-25 13:16:17 -04:00
Nicholas Hastings
f589298879 Fix maxlen in SetEntPropString not being initialized (bug 6391).
This var is only used when setting a direct string, rather than a string_t. Some flawed
logic was causing it to only be set if the sendprop didn't have a proxy function (although
all strings should; that's how we detect whether it's a string_t or not). The var only needs
to be set if it's not a string_t, but does not hurt anything if it is.
2015-07-25 10:46:41 -04:00
Nicholas Hastings
7d153cf9f9 Merge pull request #363 from VoiDeD/datapack-pos
Introduce a datapack position tag.
2015-07-20 18:34:54 -04:00
Ryan Stecker
86b04e36b5 Clarify the Get/SetPackPosition documentation. 2015-07-20 15:03:57 -05:00
Ryan Stecker
33d13ff81c Hide datapack positions behind an opaque handle. 2015-07-20 15:03:04 -05:00
Nicholas Hastings
dcbc85b2cf Update FoF sdktools gamedata. 2015-07-17 08:12:47 -04:00
Nicholas Hastings
5123527c66 Merge pull request #311 from alliedmodders/juju
Use the new Travis-CI Container environment.
2015-07-14 20:19:11 -04:00
Nicholas Hastings
c4e7b8a795 More tweaks. 2015-07-14 19:44:52 -04:00
Nicholas Hastings
41297b96d0 Add gcc-multilib to build reqs. 2015-07-13 21:43:27 -04:00
Nicholas Hastings
d30cab04c3 Merge pull request #360 from alliedmodders/cckv
Add support for listening to, blocking, changing, and faking ClientCommandKeyValues.
2015-07-13 21:35:25 -04:00
Ruben Gonzalez
3ab31eba7b Update FoF sdktools gamedata. 2015-07-13 08:53:30 -04:00
Nicholas Hastings
e7aa159896 Clarify doc regarding KV handle. 2015-07-12 19:21:28 -04:00
Nicholas Hastings
4db1280c59 Add comment to note that pStk actually gets deleted. 2015-07-12 19:18:27 -04:00
Nicholas Hastings
5893737321 Fix handle leak. 2015-07-12 17:38:50 -04:00
Nicholas Hastings
c85cc5cbf7 Add support for listening to, blocking, changing, and faking ClientCommandKeyValues. 2015-07-12 13:14:46 -04:00
Asher Baker
705b5d3f5f Merge pull request #340 from asherkin/datapack-alloc
Improve DataPack memory allocation & Report size for DataPack Handles
2015-07-08 20:07:40 +01:00
Nicholas Hastings
8a978dc71f Remove hack around FuzzyMatch never being returned in TF2 for FindMap.
It has been fixed now in the game.
2015-07-04 13:42:50 -04:00
Nicholas Hastings
c32683225f Merge pull request #357 from alliedmodders/dumps-datestamps
Dumps datestamps
2015-07-03 19:33:02 -04:00
Nicholas Hastings
01941d5504 Merge pull request #353 from alliedmodders/getentpropstringt
Better string_t support for Get/Set EntPropString
2015-07-03 19:32:54 -04:00
Nicholas Hastings
8fb97a6152 Add date to sm_dump_netprops_xml output. 2015-07-03 10:39:44 -04:00
Nicholas Hastings
801da2db37 Fix MSVC compile. 2015-07-03 10:38:15 -04:00
Nicholas Hastings
52147ca75f Use datadesc instead of serverclass for m_iName lookup.
m_iName is not networked on all games.
2015-07-03 08:57:15 -04:00
Nicholas Hastings
2f3a3942b5 Merge pull request #356 from alliedmodders/revert-355-master
Revert "Changing MAX_NAME_LENGTH from 32 to 128 due to CSGO having 128."
2015-07-02 17:36:36 -04:00
Kyle Sanderson
ed57a2f3d8 Merge pull request #355 from TheMadSword/master
Changing MAX_NAME_LENGTH from 32 to 128 due to CSGO having 128.
2015-07-02 14:27:33 -07:00
Nicholas Hastings
3ab4e4f24e Update sm_dump_netprops to include date of dump, similar to datamaps and classes dump commands. 2015-07-02 17:21:40 -04:00
Nicholas Hastings
1336d9cf5e Update date format on sm_dump_classes and sm_dump_datamaps to use the less ambiguous Y/m/d...
Instead of d/m/Y.
2015-07-02 17:21:03 -04:00
TheMadSword
1b706bcbcf Changing MAX_NAME_LENGTH from 32 to 128 due to CSGO having 128 bytes
buffer-size.
2015-07-02 16:14:54 -04:00
Nicholas Hastings
1a5714c3ca Fix build for ep1 and darkm. 2015-07-02 15:22:33 -04:00
Nicholas Hastings
e0a83ff7b2 Add support for setting string_t values with SetEntPropString.
Adds new AllowPooledString func to CHalfLife2 to allocate a string in the game's string pool.
Also fixes SetEntPropString using incorrect offset for nested sendprops.
2015-07-02 14:47:31 -04:00
Nicholas Hastings
93bec920cf Add support for GetEntPropString(Prop_Send) with netvars backed by string_t vars. 2015-07-02 14:00:47 -04:00
Nicholas Hastings
8d8c9aa55b Revert "Changing MAX_NAME_LENGTH from 32 to 128 due to CSGO having 128." 2015-07-02 13:34:40 -04:00
Asher Baker
668839d1cb Update TF2 Disguise signature. 2015-07-02 14:37:48 +01:00
Kyle Sanderson
a410aefd6d Merge pull request #352 from peace-maker/charset_thread
Lock database before setting character set
2015-06-29 12:14:09 -07:00
Peace-Maker
c6a7e86762 Lock database before setting character set
SQL_SetCharset wasn't thread safe and could race with other threaded
queries causing a crash.
2015-06-29 20:44:45 +02:00
Nicholas Hastings
f960c64dc6 Merge pull request #351 from alliedmodders/expose-findmap
Expose FindMap/ResolveFuzzyMapName to plugins.
2015-06-28 12:43:56 -04:00
Nicholas Hastings
80838af4a2 Work around eFindMap_FuzzyMatch never actually being returned in TF2. 2015-06-28 09:48:01 -04:00
Nicholas Hastings
7564c09aff Merge pull request #341 from powerlord/ambuild-sampleext
Add AMBuild2 script to Sample Extension.
2015-06-27 20:10:00 -04:00
Nicholas Hastings
60ac7e23d0 Updated FindMap function doc. 2015-06-27 20:04:20 -04:00
Nicholas Hastings
c383f1dc43 Fix compile errors on Clang by implementing own enum. 2015-06-27 19:58:14 -04:00
Nicholas Hastings
f107ff9cd2 Expose FindMap/ResolveFuzzyMapName to plugins. 2015-06-27 13:10:47 -04:00
Ruben Gonzalez
25a8209ffc Update CS:GO gamedata MVP base to be the same as Scores. 2015-06-26 11:00:10 -04:00
Ruben Gonzalez
3c0b89b80f Update CS:GO MVP and Contribution score offsets. 2015-06-26 10:44:20 -04:00
Nicholas Hastings
11c40e385e Merge pull request #347 from alliedmodders/double
Call OnClientDisconnect(_Post) if the client has already connected (bug 6361).
2015-06-18 17:43:34 -04:00
Nicholas Hastings
d0574dbe28 Merge pull request #226 from powerlord/mapchooser-updates
More New API changes for MapChooser, Nominations, RockTheVote, RandomCycle, and NextMap.
2015-06-12 14:58:12 -04:00
Nicholas Hastings
b4011f3e8b Update Insurgency gamedata. 2015-06-12 05:24:54 -07:00
Kyle Sanderson
0f9b9d0a24 Call OnClientDisconnect(_Post) if the client is already connected. 2015-06-11 20:14:25 -07:00
Nicholas Hastings
c0d4dfa6ed Update IsMapValid for today's TF2 update. 2015-06-11 17:48:58 -04:00
Nicholas Hastings
a4821f9389 Merge pull request #346 from alliedmodders/ctype-fixes
Fix some ctype misuses (bug 6377).
2015-06-10 19:29:35 -04:00
Nicholas Hastings
14e0a9a487 Fix some ctype misuses (bug 6377).
isalpha, isdigit, isupper, and islower do not return 0/1. They return 0 or anything-else. Since the bool tag in pawn only supports exactly 0 and 1, we need to return 1 for all truthy returns in the natives that wrap these.
2015-06-10 14:40:48 -04:00
Nicholas Hastings
b17c7adcd5 Add gamedata for Modular Combat. 2015-06-10 10:02:34 -04:00
Nicholas Hastings
a70722eb25 Update FoF gamedata. 2015-06-09 13:01:50 -04:00
Nicholas Hastings
13ecd11543 Merge pull request #344 from alliedmodders/update-convar-flags
Update ConVar flags in console.inc.
2015-06-07 11:18:27 -04:00
Ross Bemrose
ba0bf5668d One minor issue left from the merge 2015-06-04 21:42:25 -04:00
Ross Bemrose
338b4ed5d9 Merge remote-tracking branch 'remotes/origin/master' into mapchooser-updates
Conflicts:
	plugins/nominations.sp
	plugins/rockthevote.sp
2015-06-04 21:39:04 -04:00
Kyle Sanderson
a4f5c802a9 Merge pull request #345 from VoiDeD/fix-sizes-part-deux
Fix more buffer sizes for map names.
2015-06-04 16:34:55 -07:00
Ryan Stecker
8bc3d5d93c Fix more buffer sizes for map names. 2015-06-04 18:32:49 -05:00
Nicholas Hastings
850a73d718 Merge pull request #343 from alliedmodders/fix-sizes
Fix some buffer sizes in shipped plugins.
2015-06-04 18:27:52 -04:00
Nicholas Hastings
74802ce96e Minor indent fix. 2015-06-04 17:07:25 -04:00
Nicholas Hastings
952ee53383 Converted back to defines. Added deprecation notices on FCVAR_PLUGIN and FCVAR_LAUNCHERONLY. 2015-06-04 06:48:01 -04:00
Nicholas Hastings
1804dce9d9 More small convar flag inc changes:
* Re-added FCVAR_PLUGIN (shimmed to 0) and FCVAR_LAUNCHER with deprecation notes.
* Changed defines to const ints.
* Updated comments to use our newer, single-line comment style for cleanliness.
2015-06-03 23:38:31 -04:00
Nicholas Hastings
4231adaedf Update ConVar flags in console.inc.
The existing list was from the original engine, not even being accurate for EP1.
Flags that were never used and have since been removed from headers were removed.
Flags that were removed, but were used at one time co-exist with new flags that took over their value where applicable.
Flags that only exist on some engine versions are noted as such in the comment.
2015-06-03 23:06:26 -04:00
Nicholas Hastings
9e0dbfcf68 Fix inconsistencies with buffer sizes for player names.
Found any I could not using MAX_NAME_LENGTH and changed them to use it. I think that we should
increase MAX_NAME_LENGTH to 128 for CS:GO at some point as that's what it uses internally.
(Presumably to get the client's full multibyte name from Steam without truncation mid-codepoint which
can happen in other games. Steam's max is 32 characters if I remember correctly, but allows multibyte chars).
2015-06-03 22:40:43 -04:00
Nicholas Hastings
5139eef183 Fix buffer sizes used for map names (64 -> MAX_PATH).
As more games are now supporting maps nested in subfolders or in folders outside of the maps folder,
we need to account for the full path that the game uses to refer to the map for compatibility. Many other
places for fixed for this already after CS:GO added Steam Workshop support for maps.
2015-06-03 22:28:58 -04:00
Nicholas Hastings
974e18292a Update FoF gamedata. 2015-06-02 17:59:13 -04:00
Nicholas Hastings
3291e3a38f Fix crash on Black Mesa when an entity is deleted and SDK Hooks is loaded. 2015-05-31 23:21:43 -04:00
Nicholas Hastings
4db57b84b5 Fix sm_trigger_show default in shipped sourcemod.cfg match default in basetriggers. 2015-05-30 07:52:31 -04:00
Ruben Gonzalez
c2ba31e341 Update more CS:GO gamedata. 2015-05-28 13:29:05 -04:00
David Anderson
cb6024e334 Update AMTL and SourcePawn. 2015-05-27 10:22:40 -04:00
Ruben Gonzalez
12239fe852 Update CS:GO gamedata for latest update. 2015-05-26 22:04:08 -04:00
Nicholas Hastings
a88070d063 Add GetDataMap gamedata for Black Mesa. 2015-05-25 18:20:38 -04:00
Nicholas Hastings
9f8a40f482 Merge pull request #337 from alliedmodders/earlier-maxclients
Populate MaxClients before OnPluginStart is called.
2015-05-20 06:48:08 -04:00
Nicholas Hastings
d4babee202 Merge pull request #339 from alliedmodders/mapcycle-finding
Enable finding mapcycle in cfg dir on sdk2013 and bms.
2015-05-20 06:47:59 -04:00
Nicholas Hastings
7cfadb4584 Merge pull request #342 from alliedmodders/bug-6365
Fix regression in admin-sql-threaded when porting to transitional syntax (bug 6365).
2015-05-18 13:12:12 -04:00
Nicholas Hastings
fc2fe79fe7 Fix regression in admin-sql-threaded when porting to transitional syntax. 2015-05-18 10:15:17 -04:00
Nicholas Hastings
2abb8e6335 Remove engine check for whether or not to search alt mapcycle paths. 2015-05-18 09:16:36 -04:00
Nicholas Hastings
cb4b710885 Removed comment regarding MaxClients not being available in OnPluginStart. 2015-05-18 09:11:57 -04:00
Ruben Gonzalez
869777e9c4 Trigger build. 2015-05-15 20:53:17 -04:00
Ruben Gonzalez
eab5e78150 Trigger Build 2015-05-15 18:30:02 -04:00
Ruben Gonzalez
0344c3d56f Trigger Build 2015-05-15 15:51:37 -04:00
Ross Bemrose
43f4a2f7b7 Fix checking the wrong directory for smsdk_ext.cpp. Updated some comments. 2015-05-14 14:16:19 -04:00
Ross Bemrose
0022b750b5 Split AMBuildScript into AMBulde and AMBuildScript 2015-05-14 13:48:59 -04:00
Ross Bemrose
d49714bb10 Add AMBuildScript, configure.py, and PackageScript 2015-05-14 12:36:59 -04:00
Asher Baker
fd48f4adfd Report size for DataPack Handles. 2015-05-13 19:43:53 +01:00
Asher Baker
7f97e67931 Saner allocation policy for DataPacks. 2015-05-13 19:43:35 +01:00
Nicholas Hastings
11bf32f6f1 Enable finding mapcycle in cfg dir on sdk2013 and bms. 2015-05-13 06:49:37 -07:00
Nicholas Hastings
55dee2d847 Trigger build for hl2sdk-bms update. 2015-05-12 21:03:36 -04:00
Nicholas Hastings
ae78acf97a Remove harmless remnant of reverted change. 2015-05-12 13:39:06 -04:00
Nicholas Hastings
fda0978225 Merge pull request #338 from alliedmodders/nuke-address-minvalid
Remove Address_MinimumValid entry from sp incs
2015-05-12 13:05:31 -04:00
Nicholas Hastings
227323c96d Merge pull request #336 from alliedmodders/link-libm
Link libm in all bin, not just engine-specific ones.
2015-05-12 11:54:52 -04:00
Nicholas Hastings
51344262c6 Merge pull request #333 from TheMadSword/IncreasedPrintToBufferSize
Increased PrintToChat, PrintCenter & PrintHint w/ "all" version, buffer sizes from 192 to 254.
2015-05-12 09:23:25 -04:00
Nicholas Hastings
4152e05dcd Fix indentation. 2015-05-12 06:21:32 -07:00
Nicholas Hastings
5574acda3d Remove Address_MinimumValid entry from sp incs
We have this defined in core for error checking, but it's useless in sp since unsigned comparisons are not supported.
2015-05-12 06:35:48 -04:00
Nicholas Hastings
75a93314a2 Rename PlayerManager::m_FirstPass to m_bServerActivated for clarity. 2015-05-11 20:42:26 -04:00
Nicholas Hastings
91b2ab8be1 Fixed some badness with the player initialization moving. 2015-05-11 20:29:00 -04:00
Nicholas Hastings
8fc689c89a Populate MaxClients before OnPluginStart is called. 2015-05-11 19:31:22 -04:00
Nicholas Hastings
b3efc36487 Link libm in all bin, not just engine-specific ones.
This fixes the "undefined symbol: floorf" error that some people were getting in sourcemod.logic.so.
2015-05-11 18:59:12 -04:00
Nicholas Hastings
71cb002bc1 Merge branch 'master' of https://github.com/alliedmodders/sourcemod 2015-05-11 06:54:55 -04:00
Nicholas Hastings
78dcb8a0f3 Add gamedata file missing in PackageScript. 2015-05-11 06:52:56 -04:00
Nicholas Hastings
9d6cbfe0cc Remove unused gamedata. 2015-05-11 06:52:21 -04:00
Nicholas Hastings
7ab3d76c9f Merge pull request #331 from alliedmodders/support-bms
Add support for Black Mesa Multiplayer.
2015-05-10 18:44:20 -04:00
TheMadSword
6686badc93 Increased PrintHint and PrintCenter buffer 2015-05-09 09:22:07 -04:00
Asher Baker
1b47b68cc7 Correct NameHashSet::add() return type. 2015-05-09 11:57:49 +01:00
TheMadSword
b70873e046 Changed buffer size for games with ChatSayText='yes', tested in CSS&CSGO w/ adding the kv in engine.cs*.txt 2015-05-07 22:55:15 -04:00
Asher Baker
f7c6fc9d1f Restore check_thunks error message. 2015-05-07 21:53:38 +01:00
TheMadSword
f57dbeb60f Increased PrintToChat & PrintToChatAll buffer size from 192 to 254; works in CSS/CSGO; dunno for the rest 2015-05-07 09:38:25 -04:00
Nicholas Hastings
397c45457a Fix spacing in PackageScript. 2015-05-06 22:18:43 -04:00
Nicholas Hastings
909598920b Disable nextmap on Black Mesa for now. (Doesn't ship with mapcycle.txt). 2015-05-06 22:01:57 -04:00
Nicholas Hastings
dac3d1c988 Remove leftover debug code. 2015-05-06 22:01:39 -04:00
Nicholas Hastings
9164730b07 Add gamedata for Black Mesa. 2015-05-06 22:01:29 -04:00
Nicholas Hastings
64f9aedebc Add basic support for Black Mesa.
(Basically a copy of SDK 2013's support, but against BMS SDK).
2015-05-06 21:12:13 -04:00
Yed
5694a759ce Add IsFree check to FindEntityByNetClass in SDKTools (PR #330). 2015-05-04 18:13:11 -07:00
Nicholas Hastings
ffedae66f4 Trigger build for hl2sdk-dota changes. 2015-05-03 15:07:07 -04:00
Nicholas Hastings
a480bf0014 Trigger build for hl2sdk-dota changes. 2015-05-03 10:01:00 -04:00
Nicholas Hastings
2432540d6e Merge branch 'set-client-name' 2015-04-17 04:50:13 -07:00
Nicholas Hastings
16eeaf625f Enable the "name %s" command blocking on CS:GO as well. 2015-04-17 06:51:48 -04:00
Kyle Sanderson
f421278166 Merge pull request #325 from VoiDeD/setfailstate-crash
Notify plugin listeners of SetFailState'd plugins on unload. (bug 6347)
2015-04-15 15:34:12 -07:00
Ryan Stecker
03e0c7317d Notify plugin listeners of SetFailState'd plugins on unload. (bug 6347) 2015-04-12 19:25:07 -05:00
Nicholas Hastings
fee99f3629 Sourcepawn fix. 2015-04-12 18:35:57 -04:00
Nicholas Hastings
35c81365be Update Sourcepawn submodule to get fix for bug 6329.
- Fix bug where complex |this| values could be corrupted while evaluating function arguments. (bug 6329)
2015-04-12 16:52:28 -04:00
Nicholas Hastings
8ff1a9daf3 Merge pull request #322 from alliedmodders/fix-coreconf-order
Fix CoreConfig init to happen after SMGlobalClasses from logic bin are added (r=asherkin).
2015-04-05 10:43:17 -04:00
Nicholas Hastings
6c6ed241d3 Fix CoreConfig init to happen after SMGlobalClasses from logic bin are added.
This fixes OnSourceModConfigChanged not being called for logic classes when
config is first read, matching behavior for core classes. The function is still called
before each class's OnSourceModStartup func.
2015-04-05 10:06:30 -04:00
Nicholas Hastings
b84114bc8e Update sourcepawn submodule to version with --gen=vs fix. 2015-04-05 09:32:59 -04:00
Bara
1748a411e1 Added GetEntityRenderColor 2015-04-04 01:38:30 +02:00
Kyle Sanderson
aa99eb803b Allow GetMapHistorySize to return numbers greater than 20. 2015-04-02 13:50:47 -07:00
Kyle Sanderson
47eabfb7fb Spaces 2015-04-02 10:46:49 -07:00
Kyle Sanderson
a6ab14f28e Add errno. 2015-04-02 10:46:11 -07:00
Kyle Sanderson
a42cfed39c Enable travis-ci container environment. 2015-04-02 10:38:34 -07:00
Kyle Sanderson
88c4618230 Merge pull request #320 from KyleSanderson/dust
Remove Project Files from older outdated build systems.
2015-04-02 10:34:57 -07:00
Kyle Sanderson
de58944140 Change checkout-deps.sh to do a user install instead of sudo. 2015-04-01 23:51:18 -07:00
Kyle Sanderson
7341bd184e Remove Project Files from older outdated build systems. 2015-04-01 19:54:34 -07:00
Kyle Sanderson
7a8bf78f39 Merge pull request #229 from powerlord/menuactions_all_warning_fix
Stop MENU_ACTIONS_ALL from tossing warnings with #pragma newdecls required
2015-04-01 19:39:52 -07:00
Nicholas Hastings
7268987461 Merge pull request #301 from alliedmodders/get-team-entity
Add GetTeamEntity native to SDKTools.
2015-04-01 22:30:18 -04:00
Nicholas Hastings
ce56680fff Merge pull request #315 from alliedmodders/direxists-empty
Make DirExists("") throw an error.
2015-04-01 22:30:03 -04:00
Nicholas Hastings
ea7d5ad8f1 Merge pull request #314 from alliedmodders/tfconds-reducks
Pass a handle instead of entptr to ProcessCondChange for stability.
2015-04-01 22:29:55 -04:00
Nicholas Hastings
91302da050 Merge pull request #313 from alliedmodders/set-client-name
Add SetClientName native.
2015-04-01 22:29:44 -04:00
Nicholas Hastings
d49c72cf8b Fix typo in core AMBuilder file triggering exception when triggering exception. 2015-03-31 17:39:04 -04:00
Nicholas Hastings
c11036a7b9 Update TF2 gamedata. 2015-03-31 17:37:44 -04:00
David Anderson
5dd4037c02 Update the sourcepawn repo. 2015-03-30 16:24:23 -07:00
Ruben Gonzalez
176a8182e8 Merge pull request #316 from alliedmodders/ondropweapon-fix
Fix not being able to block CS_OnCSWeaponDrop and clarify include file. (bug 6334)
2015-03-29 18:32:00 -04:00
Ruben Gonzalez
debbaea384 Merge pull request #317 from alliedmodders/ffgamedata-update
Fix Fortress Forever gamedata.
2015-03-27 21:45:55 -04:00
Ruben Gonzalez
756255999f Fix Fortress Forever gamedata. 2015-03-27 21:29:06 -04:00
Ruben Gonzalez
35e4374e2e Fix not being able to block CS_OnCSWeaponDrop and clarify include file. 2015-03-27 19:54:42 -04:00
Nicholas Hastings
7b56dd5c8a Fix build. 2015-03-22 19:23:58 -04:00
Nicholas Hastings
53f9bb0402 Add missing SetClientName description in function doc. 2015-03-22 18:56:02 -04:00
Nicholas Hastings
885117fb66 Add hack-fix for CS:S reverting name changes done with SetClientName. 2015-03-22 18:29:11 -04:00
Nicholas Hastings
d12d7625aa Remove unused phrase. 2015-03-22 15:36:07 -04:00
Nicholas Hastings
7399991181 Add SetClientName gamedata. 2015-03-22 15:17:31 -04:00
Nicholas Hastings
e62654acba Change sm_rename to use new SetClientName native. 2015-03-22 12:15:30 -07:00
Nicholas Hastings
7d795b523e Add SetClientName native. 2015-03-22 12:15:08 -07:00
Nicholas Hastings
38817bdd2c Pass a handle instead of entptr to ProcessCondChange for stability. 2015-03-22 06:53:51 -07:00
Peace-Maker
4b8a581c9a Fix crash in games that don't support radio style menus
Fix regression in ad7d920
GetMenuStyleHandle(MenuStyle_Radio) crashes games, which don't support
the radio menu style. The style is never added to the menu manager, if
it's not supported, so GetMenuStyleHandle tries to call IsSupported on a
nullptr
2015-03-21 18:53:41 -04:00
David Anderson
8b0a10ad1d Checkout submodules recursively. 2015-03-15 19:31:34 -07:00
David Anderson
7fc993e079 Fix build. 2015-03-15 19:27:44 -07:00
David Anderson
d846d91b0b Merge pull request #300 from alliedmodders/sp-upstream
Use upstream SourcePawn as a submodule.
2015-03-15 19:19:55 -07:00
Nicholas Hastings
660d6201ab Merge pull request #310 from InstantMuffin/patch-2
Fixed missing include in gdc-psyfork/memoryutils.cpp (r=psychonic).
2015-03-15 20:22:47 -04:00
David Anderson
2ab3498ab0 Use upstream SourcePawn as a submodule. 2015-03-15 16:38:38 -07:00
InstantMuffin
f7f4ea4243 Fixed missing include in psyfork/memoryutils.cpp
Error:
MemoryUtils.cpp: In member function ‘void* MemoryUtils::ResolveSymbol(void*, const char*)’:
MemoryUtils.cpp:249:43: error: ‘fstat’ was not declared in this scope
  if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)

Fixed by adding missing include: #include <sys/stat.h>
2015-03-15 21:42:06 +01:00
Ruben Gonzalez
637471ef29 Merge pull request #303 from alliedmodders/tf2_vstk_fix
Fix some TF2 natives not having the correct vstk size.
2015-03-14 09:26:16 -04:00
Ruben Gonzalez
f06a3605d2 Fix typo 2015-03-13 16:52:20 -04:00
Ruben Gonzalez
f523d6a74d Update function signature comments. 2015-03-13 16:19:57 -04:00
Ruben Gonzalez
ff8cbf97c4 FIx some TF2 natives not having the correct vstk size. 2015-03-12 18:28:17 -04:00
Ruben Gonzalez
a947dfa9d5 Update TF2's MakeBleed native for the latest update. 2015-03-12 17:54:47 -04:00
Nicholas Hastings
28870d2ae5 Make OpenDirectory error for empty path match error in DirExists. 2015-03-10 18:58:00 -07:00
Nicholas Hastings
cc3b86ea80 Throw an error if DirExists called with empty path. 2015-03-10 18:57:28 -07:00
Nicholas Hastings
ae8efdddcb Add GetTeamEntity native to SDKTools. 2015-03-10 07:27:43 -07:00
David Anderson
7f24f137d6 Merge pull request #299 from alliedmodders/amtl-upstream
Use upstream AMTL as a submodule.
2015-03-08 12:13:11 -07:00
David Anderson
eaea3c927d Update upstream AMTL as a submodule. 2015-03-08 00:24:03 -08:00
David Anderson
72475d6770 Merge pull request #295 from DoctorMcKay/fix-doc
Moved note about releasing resources from OnPluginStart to OnPluginEnd
2015-03-08 00:10:13 -08:00
David Anderson
8bb6f0e5c6 Merge pull request #297 from alliedmodders/rm-packing
Remove scpack.
2015-03-07 12:42:00 -08:00
David Anderson
0b990e46ab Remove scpack. 2015-03-07 11:39:11 -08:00
David Anderson
1d313e3120 Move macro assembler out of public/assembler into sourcepawn/vm/x86. 2015-03-07 11:16:37 -08:00
David Anderson
561004c4bf Move SourcePawn headers out of public/ into sourcepawn/include. 2015-03-07 11:13:32 -08:00
David Anderson
6f1eefbdbe Strip internal SourcePawn dependencies on SM relative paths. 2015-03-07 11:07:20 -08:00
David Anderson
23ac0b4637 Keep one copy of zlib in the SourcePawn tree. 2015-03-07 11:02:44 -08:00
David Anderson
a008a3f804 Remove msvc project files for SourcePawn. 2015-03-07 10:53:12 -08:00
David Anderson
c81e7e3410 Move batchtool out of sourcepawn. 2015-03-07 10:52:13 -08:00
David Anderson
d459ebee41 Rename jit/ to vm/. 2015-03-07 10:50:35 -08:00
Nicholas Hastings
ea684d5933 Merge pull request #296 from WildCard65/WildCard65-patch-1
Port remainder of regex.inc to transitional syntax (r=psychonic).
2015-03-07 08:09:12 -05:00
WildCard65
a730cfe9b5 Fixed regex.inc 2015-03-07 08:07:11 -05:00
Alexander Corn
c9b6b7b212 Moved note about releasing resources from OnPluginStart to OnPluginEnd 2015-03-06 15:25:39 -05:00
Nicholas Hastings
d72a9150a1 Merge pull request #294 from alliedmodders/explicit-ret-types
Add explicit return types to forwards missing them (r=dvander).
2015-03-06 15:19:37 -05:00
Nicholas Hastings
bfaedba9ed Merge pull request #287 from peace-maker/tempent_range
Add TE_SendToAllInRange (r=psychonic).
2015-03-06 15:19:24 -05:00
David Anderson
0c5cbe536f Revert unintentional change. 2015-03-06 11:00:15 -08:00
David Anderson
175f9afa68 Merge pull request #240 from alliedmodders/stock-values
Allow capturing non-public functions as values.
2015-03-06 10:53:21 -08:00
David Anderson
8216097b2c Allow capturing non-public functions as values. 2015-03-06 10:51:46 -08:00
Nicholas Hastings
adbdcd6b1d Add explicit return types to forwards missing them. 2015-03-06 10:18:09 -08:00
Nicholas Hastings
ac4f594063 Trigger build for hl2sdk-dota changes. 2015-03-06 11:25:37 -05:00
Nicholas Hastings
2d53547e03 Merge pull request #289 from alliedmodders/more-ninvoke-killing
Remove references to INativeInvoker.h from extension boilerplate.
2015-03-06 07:37:46 -05:00
David Anderson
7c775aee2e Merge pull request #288 from klausenbusk/patch-1
Updated KillTimer documentation to reflect "Invalid handles" = runtime error.
2015-03-06 01:52:32 -08:00
Fyren
b1ae2a178f Merge pull request #293 from alliedmodders/spcomp-option-spaces
Reapply ancient patch to allow spaces in spcomp options.
2015-03-06 02:50:50 -07:00
David Anderson
fa2dc5b20a Merge pull request #290 from InstantMuffin/patch-1
Documentation oddities for Call_PushStringEx
2015-03-06 01:43:54 -08:00
Fyren
dd8fa985c1 Reapply ancient patch to allow space in spcomp options. 2015-03-06 09:08:24 +00:00
Fyren
81926ceae2 Merge pull request #292 from alliedmodders/sourcepawn-fix-signed-compare
Signed comparison warning fixes.
2015-03-06 01:48:54 -07:00
Fyren
d3da389f9f Signed comparison warning fixes. 2015-03-06 08:08:41 +00:00
David Anderson
782eee3c58 Merge pull request #291 from VoiDeD/spcomp-error25-improvements
Improve the diagnostic given when a function prototype doesn't match an existing definition
2015-03-05 23:04:19 -08:00
Kyle Sanderson
d0d0ea5051 Merge pull request #269 from KyleSanderson/wnoerrorsign
Add Wno-error=sign-compare for gcc to Compiler. r=dvander
2015-03-05 20:05:06 -08:00
Ryan Stecker
3509f963ee Improve the diagnostic given when a function prototype doesn't match an existing definition. 2015-03-05 18:45:15 -06:00
InstantMuffin
98cbef547a Update functions.inc 2015-03-05 21:03:46 +01:00
David Anderson
90d3841ab2 Fix mac build. 2015-03-05 11:51:08 -08:00
InstantMuffin
3f2ad5ccb0 Documentation oddities for Call_PushStringEx
See changes for details, should be obvious. What also strikes me as odd is that there is only one cpflag atm. Has this always been the case? Will there be more in the future? Or why is this designed to be a flagstring?
2015-03-05 20:47:05 +01:00
Nicholas Hastings
6f8ffd55a7 Merge pull request #263 from alliedmodders/admins-trans
Update admins.inc with methodmaps, newdecls (r=dvander, asherkin).
2015-03-05 14:32:15 -05:00
Nicholas Hastings
96703c247c Remove references to INativeInvoker.h from extension boilerplate. 2015-03-05 10:59:19 -08:00
Nicholas Hastings
c39565ddb1 Fix spacing. 2015-03-05 10:56:54 -08:00
Nicholas Hastings
70390ff1f7 Purge Purge. 2015-03-05 10:56:36 -08:00
Kristian Klausen
924b7621ac Updated KillTimer documentation.. 2015-03-05 17:15:54 +01:00
David Anderson
715a51d01f Merge pull request #285 from alliedmodders/frames
Implement a new stack and error handling model for the SourcePawn VM.
2015-03-04 23:45:59 -08:00
David Anderson
a1afa23bc4 Implement a new stack and error handling model for the SourcePawn VM.
This has three major changes to SourcePawn. First, the API now supports the concept of "exceptions". The exception state is a global property of an instance of the SourcePawn VM. Exceptions can be caught or suppressed. Many places in SourceMod have been updated to check exceptions instead of errors.

The new API obsoletes major parts of the embedder API - all but one method of invoking functions is obsoleted, and the debug interface has been scrapped. Extensions using the native API will not be affected, however, ThrowNativeError has been deprecated in favor of ReportError.

Second, the SourcePawn concept of a "stack" has been unified at the API level. A stack frame iterator now iterates over all SourcePawn invocations, rather than the topmost plugin. This makes error handling more consistent and removes another dependency on context-per-plugin.

Finally, the implementation of stack frames has been changed dramatically. Rather than maintain a complicated and expensive return pointer stack, we now rely on the implicit one provided by the CPU. The stack frame iterator now walks the JIT stack directly. This removes many unnecessary bookkeeping instructions from the generated code, in particular making the CALL instruction 40% faster.

These changes required some fair surgery to the JIT. Its error paths are now slightly more complicated, as they have to throw an exception rather than return an error code. In addition, any path that can throw an exception is now responsible for creating an "exit frame", which exists to tell the stack frame iterator about transitions from the JIT to the VM.
2015-03-04 23:45:30 -08:00
Peace-Maker
b53947ccc3 Add TE_SendToAllInRange
Add helper stock to mimic PVS and PAS recipient filters for tempents in
the SDK.
2015-03-03 17:22:01 +01:00
Nicholas Hastings
b43da7b7f0 Fix Mac build. 2015-02-27 04:53:31 -08:00
Nicholas Hastings
fdc3c0791e Merge pull request #266 from alliedmodders/tfconds-reducks
Replace frameloop for player condition checks in TF2 ext with sendproxies (r=All of the KyleS).
2015-02-27 04:43:15 -08:00
David Anderson
04827466b0 Rewrite the .smx parser.
This removes one the last remnants of the SourceMod 1.0 VM implementation.

The new parser introduces a number of design changes in the VM. First, the VM now takes greater responsibility for validating and sanity checking the structure of the SMX container format. Previously, malformed SMX files could easily crash SourcePawn. The loader now rejects files that have out-of-bounds offsets or incomplete sections. Complex sections, like debug info or the code stream, are verified lazily.

Internally, the sp_plugin_t structure has been removed. It has been replaced by a new LegacyImage class, designed to be independent from the SPVM API. This potentially lets us load code streams from non-.smx containers. More importantly, it removes a lot of bookkeeping and pre-computed state from PluginRuntime. The LegacyImage class is now responsible for handling debug info as well.

PluginRuntime is now intended to hold only cached or immutable data, and PluginContext holds all VM state. As such PluginContext is now responsible for allocating a plugin's runtime memory, not PluginRuntime.

Finally, some aspects of the loading process have been cleaned up. The
decompression and image handoff logic should now be easier to
understand.
2015-02-25 22:28:10 -08:00
David Anderson
afbcdc8a20 Merge branch 'rm-interpreter' 2015-02-25 22:22:07 -08:00
David Anderson
b5ae5defcf Merge branch 'simpl-fns' 2015-02-25 22:21:43 -08:00
David Anderson
1f351c50d5 Merge branch 'fix-native-updating' 2015-02-25 22:20:41 -08:00
David Anderson
9a37b94f4d Merge pull request #280 from alliedmodders/rm-ctx
Remove sp_context_t.
2015-02-26 15:46:32 -08:00
David Anderson
acf6dcac86 Remove the interpreter. 2015-02-24 23:57:08 -08:00
David Anderson
fcec0ee7c7 Use AutoPtr in more places in the JIT. 2015-02-24 23:50:42 -08:00
David Anderson
b9b0ec865c Simplify the JIT function cache. 2015-02-24 23:43:07 -08:00
David Anderson
fcaa5361c8 Don't expose mutable sp_native_t. 2015-02-24 23:10:18 -08:00
David Anderson
33588b65ce Remove sp_context_t. 2015-02-24 21:54:34 -08:00
David Anderson
c09c65e4c7 Remove sp_context_t::plugin. 2015-02-24 21:54:34 -08:00
David Anderson
11ea385169 Remove sp_context_t::rval. 2015-02-24 21:54:34 -08:00
David Anderson
3a0310e832 Remove sp_context_t::basecx. 2015-02-24 21:54:34 -08:00
David Anderson
31ab1ced06 Move hp from sp_context_t to PluginContext. 2015-02-24 21:54:34 -08:00
David Anderson
b2c61a341a Move sp from sp_context_t to PluginContext. 2015-02-24 21:54:30 -08:00
David Anderson
4c9321f02a Move frm from sp_context_t to PluginContext. 2015-02-24 21:01:05 -08:00
David Anderson
d2005bd42a Move cip from sp_context_t to PluginContext. 2015-02-24 20:53:44 -08:00
David Anderson
8817de8a55 Remove err from sp_context_t. 2015-02-24 20:41:51 -08:00
David Anderson
97dbc7ff07 Move n_err from sp_context_t to PluginContext. 2015-02-24 20:16:13 -08:00
dvander@alliedmods.net
9c104ef310 Move nidx from sp_context_t to PluginContext. 2015-02-24 19:59:45 -08:00
Asher Baker
7f0ff04ccf Updated plugin blacklist. 2015-02-25 01:10:28 +00:00
dvander@alliedmods.net
5502fbbdc1 Move the tracker from sp_context_t to PluginContext. 2015-02-24 15:43:41 -08:00
dvander@alliedmods.net
deedc1aaa6 Remove unused fields from sp_context_t. 2015-02-24 15:21:52 -08:00
dvander@alliedmods.net
37af05c456 Move the debug return stack into PluginContext. 2015-02-24 15:20:00 -08:00
David Anderson
8c35d79576 Merge pull request #279 from alliedmodders/mv-basecontext
Rename BaseContext to PluginContext.
2015-02-24 14:56:32 -08:00
Asher Baker
6572989993 Merge pull request #213 from splewis/find-array-nonzero-blocks
Add block parameter to FindValueInArray native.
2015-02-24 22:37:49 +00:00
dvander@alliedmods.net
8eed58a467 Rename sp_vm_basecontext to plugin-context. 2015-02-24 12:55:00 -08:00
dvander@alliedmods.net
2e77155b4e Rename BaseContext to PluginContext. 2015-02-24 12:50:09 -08:00
dvander@alliedmods.net
8b8edf6e70 Remove dead file and fix gcc build. 2015-02-24 11:39:28 -08:00
dvander@alliedmods.net
f0aa177bf8 Merge branch 'cc3' 2015-02-24 11:06:11 -08:00
dvander@alliedmods.net
e163204643 Merge branch 'cc2'. 2015-02-24 11:05:25 -08:00
dvander@alliedmods.net
50d7d7eedb Merge branch 'rm-watchdog-singleton' 2015-02-24 11:04:06 -08:00
David Anderson
ec05036a2d Merge pull request #274 from alliedmodders/refactor-api
Refactor the public API entrypoint for SourcePawn.
2015-02-24 11:03:32 -08:00
Nicholas Hastings
b8223d1b98 Merge pull request #267 from 50Wliu/tf2_setclientteam
Add TF2_SetClientTeam to provide symmetry to TF2_GetClientTeam (r=psychonic).
2015-02-24 10:23:23 -05:00
David Anderson
781c5129a9 Remove the JITX86 class. 2015-02-24 02:03:58 -08:00
David Anderson
111dd7eb68 Factor code stubs out of JITX86. 2015-02-24 02:03:58 -08:00
David Anderson
21f5400d9c Remove ICompilationData. 2015-02-24 02:03:57 -08:00
David Anderson
8cf3e227ea Move context var initialization into BaseContext. 2015-02-24 02:03:56 -08:00
David Anderson
8c95919b32 Move watchdog/runtime interaction into Environment. 2015-02-24 02:03:55 -08:00
David Anderson
b406c3d03d Merge sp_vm_engine and engine2. 2015-02-24 02:03:55 -08:00
David Anderson
c70e87d582 Move the code cache into Environment, and out of knight/shared. 2015-02-24 01:57:50 -08:00
David Anderson
57ba8fd09b De-singleton-ify the watchdog timer. 2015-02-24 01:53:37 -08:00
David Anderson
3cf3f6c3f8 Merge sp_vm_engine and engine2. 2015-02-24 01:52:14 -08:00
David Anderson
499f7b3929 Refactor the public API entrypoint for SourcePawn. 2015-02-24 01:52:13 -08:00
David Anderson
e58415f94a Fix shell build on Windows. 2015-02-24 01:49:03 -08:00
David Anderson
38d2c3690a Merge pull request #273 from alliedmodders/add-shell
Build the debug spshell as part of AMBuild.
2015-02-23 20:28:30 -08:00
David Anderson
4212fb88c8 Build the debug spshell as part of AMBuild. 2015-02-23 20:21:17 -08:00
David Anderson
f769e1a00c Merge pull request #272 from alliedmodders/rn-runtime
Rename BaseRuntime to PluginRuntime.
2015-02-23 16:56:18 -08:00
dvander@alliedmods.net
1f9b898702 Rename BaseRuntime files to plugin-runtime. 2015-02-23 16:44:15 -08:00
dvander@alliedmods.net
2f71cb4cd7 Rename BaseRuntime to PluginRuntime. 2015-02-23 16:40:36 -08:00
David Anderson
b8d2be9a0d Merge pull request #271 from alliedmodders/rm-jit-function
Rename some horrible classes.
2015-02-23 16:28:28 -08:00
dvander@alliedmods.net
b2d8dde3a5 Rename Function to CompiledFunction. 2015-02-23 16:27:57 -08:00
dvander@alliedmods.net
0ee4885056 Rename sp_vm_function to scripted-invoker. 2015-02-23 16:14:59 -08:00
dvander@alliedmods.net
45bac7feb0 Rename jit_function to compiled-function. 2015-02-23 16:04:57 -08:00
dvander@alliedmods.net
892b8c05b1 Rename JitFunction to CompiledFunction and CFunction to ScriptedInvoker. 2015-02-23 16:03:08 -08:00
David Anderson
7d64ade621 Merge pull request #270 from alliedmodders/modernize-vm-style
Modernize sourcepawn/jit style.
2015-02-23 14:38:28 -08:00
dvander@alliedmods.net
45c43f4aee Modernize sp_vm_basecontext. 2015-02-23 13:40:01 -08:00
dvander@alliedmods.net
1b47aa10ca Modernize sp_vm_engine style. 2015-02-23 13:08:28 -08:00
dvander@alliedmods.net
bcd88b4437 Modernize sp_vm_function style. 2015-02-23 13:01:00 -08:00
dvander@alliedmods.net
10d778e344 Modernize engine2.* style. 2015-02-23 12:49:26 -08:00
dvander@alliedmods.net
0100ebadb9 Fix build on GCC. 2015-02-23 12:40:02 -08:00
Wliu
20b5f76572 🎨 Change to TF2_ChangeClientTeam 2015-02-22 20:20:45 -05:00
Nicholas Hastings
62ed3973b5 Fix Insurgency s_pTempEntities offset on Windows. 2015-02-22 20:08:42 -05:00
Nicholas Hastings
5f7e800444 Use new IVEngineServer::GetIServer to get IServer* on Insurgency. 2015-02-22 15:16:26 -05:00
Nicholas Hastings
b52b5f46f0 Update Insurgency Windows SDKTools gamedata. 2015-02-22 10:14:53 -05:00
Kyle Sanderson
3386a3af80 Add Wno-error=sign-compare for gcc to Compiler. 2015-02-21 20:25:39 -08:00
Kyle Sanderson
9099516906 Merge pull request #200 from alliedmodders/travis-clang-3.5
Make TravisCI builds use Clang 3.5 to match our Buildbot builds.
2015-02-21 19:28:38 -08:00
Kyle Sanderson
f235f97d95 Install g++-4.8 before installing llvm 3.5 2015-02-21 19:20:18 -08:00
Kyle Sanderson
4bd4d8d4a5 Merge pull request #268 from KyleSanderson/MenuCrash
Root Menu Handles during Display (Bug 5620,r=dvander).
2015-02-21 17:25:25 -08:00
Kyle Sanderson
284fab7254 Root Menu Handles during Display. 2015-02-21 17:10:26 -08:00
Wliu
f772c88eed Whoops. 2015-02-20 21:26:34 -05:00
Wliu
58d94c2827 Adds TF2_SetClientTeam to provide symmetry to TF2_GetClientTeam
Also remove some trailing whitespace
2015-02-20 21:23:27 -05:00
Nicholas Hastings
7e8d4b89ca Trigger build for hl2sdk-dota changes. 2015-02-20 09:16:40 -05:00
Nicholas Hastings
70be2941fe All of the KyleS. 2015-02-18 22:42:06 -05:00
Nicholas Hastings
9ffbac4f4e Simplified code. (We don't need m_Shared). 2015-02-18 18:44:31 -05:00
Nicholas Hastings
684b59a921 Don't fire forwards if client isn't ingame. 2015-02-18 12:33:37 -08:00
Nicholas Hastings
e8765c5d3d Move m_CondOffset initialization to ctor. 2015-02-18 12:32:45 -08:00
Nicholas Hastings
d179240c45 Merge pull request #265 from alliedmodders/missing-fs-native
Add missing impl for File.ReadUint16 (r=dvander).
2015-02-18 15:10:05 -05:00
Nicholas Hastings
ac530a4ce0 Fix passing incorrect cond# to forwards for CondEx/2/3 fields. 2015-02-18 12:09:17 -08:00
Nicholas Hastings
589482736f Merge pull request #247 from AnthonyIacono/normalshook-upgrade
Improvements for NormalSHook functionality (r=psychonic).
2015-02-18 14:43:33 -05:00
Nicholas Hastings
3d2bd070ad Merge pull request #264 from davidskuza/sample-ext-vs-update
Updated Visual Studio sample_ext files.
2015-02-18 14:38:22 -05:00
Nicholas Hastings
c4a58b1c95 Make sure processing and fwd calls happen on main thread. 2015-02-18 05:35:58 -08:00
Nicholas Hastings
b9579a53ce Add missing impl for File.ReadUint16. 2015-02-18 04:50:20 -08:00
Developer
94c439e533 Updated Visual Studio sample_ext files 2015-02-18 10:34:38 +01:00
Nicholas Hastings
a327a788c1 Trigger build for hl2sdk-csgo changes. 2015-02-17 15:52:31 -05:00
Nicholas Hastings
a541acb2bc Convert admin SQL plugins to use AdminId/GroupId methodmaps, newdecls. 2015-02-17 09:13:40 -08:00
Nicholas Hastings
63d1fa2d8e Convert admin-flatfile to use AdminId/GroupId methodmaps and newdecls. 2015-02-17 08:24:46 -08:00
Nicholas Hastings
e4ee52e1ac Convert adminhelp to newdecls. 2015-02-17 08:24:11 -08:00
Nicholas Hastings
c0729ff5e2 Add methodmap for GroupId. 2015-02-17 08:21:14 -08:00
Nicholas Hastings
c2d37cdff5 Add methmodmap for AdminId. 2015-02-17 07:19:56 -08:00
Nicholas Hastings
0f00a2db08 Remove unused result value in OnRebuildAdminCache forward call. 2015-02-17 06:43:49 -08:00
Nicholas Hastings
67e74581cc Make result ptr in IForward::Execute default to NULL (which is allowed). 2015-02-17 06:43:07 -08:00
David Anderson
eb9f496cd8 Merge pull request #262 from VoiDeD/bug-6310
Fix tag mismatch warning when using SQLite_UseDatabase. (bug 6310)
2015-02-15 21:45:46 -08:00
Ryan Stecker
0203d2c811 Fix tag mismatch warning when using SQLite_UseDatabase. (bug 6310) 2015-02-15 21:53:31 -06:00
Nicholas Hastings
6bc2d20177 Mess with some array sizes. 2015-02-08 20:30:15 -05:00
Nicholas Hastings
350eb462ca Rewrite TF2 extension's player conditions handling to remove dirty frame loop. 2015-02-08 20:03:07 -05:00
Nicholas Hastings
591aea54b6 Merge pull request #261 from alliedmodders/handle-dump-loc
Make handle dump location relative to gamedir to match other sm_dump commands (r=kyles).
2015-02-08 17:14:42 -05:00
Nicholas Hastings
00ad38f5b7 Actually use game path instead of SM path as base. 2015-02-07 09:25:25 -08:00
Nicholas Hastings
261e135845 Make handle dump location relative to gamedir to match other sm_dump commands. 2015-02-07 09:21:53 -08:00
Nicholas Hastings
f50d8317f6 Merge currently in-use gdc-psyfork symbols.txt. 2015-02-05 14:44:58 -05:00
Anthony
3558418ed7 Initializing soundEntry and using something safer than strcpy 2015-02-05 11:12:33 -08:00
Nicholas Hastings
fca927884b Merge pull request #260 from alliedmodders/bug-6303
Fix crash when creating and destroying a TopMenu before map start (bug 6303, r=asherkin).
2015-02-04 16:16:23 -05:00
Nicholas Hastings
10c62dc0c0 Fix crash when creating and destroying a TopMenu without map change (bug 6303). 2015-02-04 09:57:04 -08:00
David Anderson
7e9b22cb6e Merge pull request #259 from alliedmodders/rm-sizeof-defarg
Remove sizeof() as a special-case default argument value.
2015-02-03 12:44:00 -08:00
Nicholas Hastings
c427dfbea7 Merge pull request #203 from alliedmodders/bug-6248
Remove faulty g_FlagSet array in adminsys (bug 6248) (r=asherkin).
2015-02-03 12:39:43 -05:00
Nicholas Hastings
e88039d4e0 Fix FindFlagChar not finding char for AdminFlag_Custom6. 2015-02-03 10:32:34 -05:00
Nicholas Hastings
84a59c6fb7 Fix g_ReverseFlags array size. 2015-02-03 10:27:32 -05:00
Nicholas Hastings
19be28cc2e Rename g_FlagSet to g_FlagCharSet to avoid some confusion. 2015-02-03 10:26:28 -05:00
David Anderson
c116a731f1 Remove sizeof() as a special-case default argument value. 2015-02-02 21:10:20 -08:00
Ruben Gonzalez
cf9dd08c45 Merge pull request #258 from alliedmodders/weaponprice-fix-wip
Fix GetWeaponPrice for CS:GO
2015-02-01 12:06:07 -05:00
Nicholas Hastings
a88b447327 Merge pull request #257 from alliedmodders/sm-plugins-refresh
Fix "sm plugins refresh" not refreshing changed plugins (r=dvander).
2015-01-31 15:31:49 -05:00
Nicholas Hastings
52514a96bd Fix "sm plugins refresh" not refreshing changed plugins. 2015-01-31 15:28:21 -05:00
Ruben Gonzalez
5ffb4d9845 Merge branch 'master' into weaponprice-fix-wip 2015-01-31 15:15:44 -05:00
David Anderson
0bb2dc32af Merge pull request #256 from alliedmodders/bug6302
Don't special case hierarchy-free enumeration constants when used as array indices. (bug 6302)
2015-01-31 10:50:24 -08:00
Ruben Gonzalez
213e7ced8c Initial CSGO GetWeaponPrice fixes 2015-01-31 12:44:18 -05:00
David Anderson
380479cadd Don't special case hierarchy-free enumeration constants when used as array indices. (bug 6302) 2015-01-29 00:16:06 -08:00
David Anderson
04c23383b1 Merge pull request #255 from alliedmodders/bug6298
Fix chained field expressions losing lvalue-ness. (bug 6298)
2015-01-28 17:49:52 -08:00
David Anderson
90ff154598 Fix chained field expressions losing lvalue-ness. (bug 6298) 2015-01-28 17:31:16 -08:00
Nicholas Hastings
840b432ce0 Merge pull request #253 from alliedmodders/adminmenu-newdecl
Convert adminmenu to use newdecls and new classes/methodmaps (r=dvander).
2015-01-28 18:52:53 -05:00
Nicholas Hastings
e1b6e09cd3 Merge pull request #250 from alliedmodders/sdkhooks-newdecls
Convert remainder of sdkhooks.inc to newdecls (r=dvander).
2015-01-28 18:52:41 -05:00
Nicholas Hastings
ad8373925a Merge pull request #251 from alliedmodders/topmenus-stuff
Topmenus stuff (r=dvander).
2015-01-28 18:52:23 -05:00
Nicholas Hastings
2292515315 Merge pull request #254 from alliedmodders/bug-6226
Fix incorrect error line show for incorrect return value on forwards (bug 6226, r=asherkin).
2015-01-28 14:45:06 -05:00
Nicholas Hastings
d9ce8249cb Fix incorrect error line show for incorrect return value on forwards (bug 6226). 2015-01-28 09:51:02 -08:00
Nicholas Hastings
b3bb37323d Merge pull request #252 from alliedmodders/sdkhooks-lvlinit-block
Don't allow plugins to block LevelInit (wtf) (r=asherkin).
2015-01-27 21:31:03 -05:00
Nicholas Hastings
c6b5675262 Merge pull request #249 from alliedmodders/signunsigned-stack-warning
Fix signed/unsigned compare warning in smn_adt_stack (r=asherkin).
2015-01-27 21:29:23 -05:00
Nicholas Hastings
43bca4dcc2 Convert adminmenu to use newdecls and new classes/methodmaps. 2015-01-27 18:13:10 -08:00
Nicholas Hastings
dbbc30368d Convert remainder of sdkhooks.inc to newdecls. 2015-01-27 18:06:14 -08:00
Nicholas Hastings
5f651f7fde Convert remainder of topmenus.inc to newdecls. 2015-01-27 18:03:59 -08:00
Nicholas Hastings
eadfec75a4 Make TopMenuHandler pass topmeut as TopMenu instead of Handle. 2015-01-27 18:03:24 -08:00
Nicholas Hastings
e2aab2ab10 Don't allow plugins to block LevelInit (wtf). 2015-01-27 18:01:30 -08:00
Nicholas Hastings
8705aea634 Fix signed/unsigned compare warning in smn_adt_stack. 2015-01-27 17:59:55 -08:00
David Anderson
3040708d4e Merge pull request #215 from Thordin/more_handles
Increased handles to 32k
2015-01-26 11:24:46 -08:00
David Anderson
2382902fe4 Merge pull request #244 from alliedmodders/db-fix
Fix wrong value in transitional DBI callback. (bug 6292)
2015-01-23 14:07:22 -08:00
Anthony
ee0575bbb0 Adding EmitSoundEntry() for engines >= portal 2 2015-01-21 10:33:29 -08:00
Nicholas Hastings
aff2551942 Remove conditionals in ambuild scripts for using msvc <2013 (not supported). 2015-01-21 11:04:52 -05:00
Nicholas Hastings
18b54b9064 Update protobuf include path for Dota build. 2015-01-21 11:04:03 -05:00
Kyle Sanderson
d1af9b5fd1 Merge pull request #248 from KyleSanderson/mysqltimeout
Establish a default timeout for MySQL connectivity.
2015-01-21 06:46:18 -08:00
Kyle Sanderson
e3349116cb Establish a default timeout for MySQL connectivity. 2015-01-21 05:58:45 -08:00
Kyle Sanderson
c70f16c65a Force reconfigure. 2015-01-20 18:15:15 -08:00
Kyle Sanderson
37d9867c06 Merge pull request #129 from KyleSanderson/SDKDep
Enable SDK independence with MM:S enabled extensions.
2015-01-20 17:22:04 -08:00
Anthony
cddae6f456 Upgrading the normal sound hook for games like CS:GO 2015-01-20 15:08:57 -08:00
Ryan Stecker
ff27484527 Prevent null auth string comparisons. 2015-01-19 07:48:45 -05:00
Nicholas Hastings
324d52bf2b Merge pull request #246 from alliedmodders/bot-admins
Fix regression causing "BOT" to no longer be valid in adminsys for Steam identities (r=asherkin).
2015-01-17 16:15:14 -05:00
Nicholas Hastings
9f648879e5 Fix regression causing "BOT" to no longer be valid in adminsys for Steam identities. 2015-01-17 10:11:04 -05:00
Nicholas Hastings
a7c41f6ac2 Merge pull request #245 from chauffer/master
Add missing semicolon.
2015-01-17 08:20:17 -05:00
Simone
fbb6e88d0d Add missing semicolon. 2015-01-17 11:47:26 +01:00
David Anderson
49383e7391 Fix wrong value in transitional DBI callback. (bug 6292) 2015-01-16 00:33:29 -08:00
David Anderson
f715952128 Merge pull request #243 from VoiDeD/umsg-callback
Use BfRead or Protobuf tags in umsg hook callbacks, rather than a generic Handle.
2015-01-15 11:58:25 -08:00
Ryan Stecker
2516654d2e Use BfRead or Protobuf tags in umsg hook callbacks, rather than a generic Handle. 2015-01-15 13:40:21 -06:00
Ryan Stecker
8dbcfde314 Revert "Use BfRead tag in umsg hook typedef, rather than a generic Handle."
This reverts commit 89119880b5.
2015-01-15 13:32:54 -06:00
David Anderson
4218674e7c Merge pull request #242 from VoiDeD/umsg-callback
Use BfRead tag in umsg hook typedef, rather than a generic Handle.
2015-01-13 20:28:54 -08:00
Ryan Stecker
89119880b5 Use BfRead tag in umsg hook typedef, rather than a generic Handle. 2015-01-13 21:33:11 -06:00
Nicholas Hastings
42956c0a10 Add PlayerRunCommand gamedata for Dark Messiah. 2015-01-11 11:45:03 -05:00
Nicholas Hastings
e0e2c00d12 Fix ICommandLine not being found in Dark Messiah. 2015-01-11 11:44:45 -05:00
Ross Bemrose
691d891794 Merge branch 'master' of https://github.com/alliedmodders/sourcemod into mapchooser-updates 2015-01-09 09:42:07 -05:00
Nicholas Hastings
df6dfec728 Trigger build for hl2sdk-dota update. 2015-01-09 09:06:57 -05:00
Nicholas Hastings
dfa36b7735 Update TF2 gamedata. 2015-01-07 14:09:36 -05:00
Asher Baker
c28426a09f Fix threads leaking if they're not joined. (bug 3460, r=dvander) 2015-01-06 20:29:47 +00:00
Ross Bemrose
8567246772 ClearArray was changed to Clear in recent SourceMod builds. 2015-01-06 10:07:15 -05:00
Ross Bemrose
a9961d3bb4 Merge branch 'master' of https://github.com/alliedmodders/sourcemod into mapchooser-updates 2015-01-06 10:04:25 -05:00
David Anderson
bded4f9142 Fix uninitialized variable in decl_enum(). 2015-01-04 12:12:16 -08:00
David Anderson
491036a1e6 Allow "stock static" in addition to "static stock". 2015-01-04 12:04:51 -08:00
Nicholas Hastings
3e012e7f79 Fix ArrayList.Clear func name. 2015-01-04 12:28:38 -05:00
Nicholas Hastings
3929ff1f27 Fix typo on ArrayList.Erase native. 2015-01-04 11:58:44 -05:00
Nicholas Hastings
56d768f546 Merge pull request #239 from peace-maker/sdkhooks_otdsig
Fix missing params in OnTakeDamagePost typedef (r=psychonic).
2015-01-03 15:00:03 -05:00
David Anderson
4ec992474e Remove some heinous preprocessor directives.
Gone:
 - #emit (bah-roken!)
 - #pragma compress (useless)
 - #pragma library (useless)
2015-01-03 11:41:37 -08:00
David Anderson
822501b8a1 Fix typos in dbi.inc transitional syntax. 2015-01-03 11:38:51 -08:00
David Anderson
bf3ff460b3 Merge pull request #93 from peace-maker/failstate_dependencies
Pause dependent plugins on SetFailState. (bug 6120, r=dvander)
2015-01-03 10:55:52 -08:00
Peace-Maker
ff9ae0782e Fix missing params in OnTakeDamagePost typedef
Looks like the |weapon| parameter went missing during the switch to the
transitional syntax.

There was no -Post typedef including the |damagecustom| bit at all too.
2015-01-03 19:45:27 +01:00
Nicholas Hastings
66defdfc27 Merge pull request #237 from alliedmodders/ep1-servertools
Don't look for IServerTools on ep1 games (r=asherkin).
2015-01-01 16:29:11 -05:00
Nicholas Hastings
3e65d308a8 Don't looks for IServerTools on ep1 games.
(We don't use it and it doesn't exist on most.)
2015-01-01 14:56:37 -05:00
Nicholas Hastings
a88d0da1af Merge pull request #236 from alliedmodders/sdkhooks-noload-crash
Fix SDKHooks causing crash on plugin load/unload or player connect/disconnect if missing gamedata (r=asherkin).
2014-12-30 21:08:29 -05:00
Nicholas Hastings
aa38226337 Fix SDKHooks causing crash on plugin load/unload or player connect/disconnect if missing gamedata. 2014-12-30 20:56:28 -05:00
Nicholas Hastings
5961ed2e4a More gamedata cleanup. 2014-12-30 17:23:52 -05:00
Nicholas Hastings
4dd9131847 Merge pull request #234 from alliedmodders/expose-getmulticastrecips
Expose Message_DetermineMulticastRecipients as GetClientsInRange native (r=asherkin).
2014-12-30 15:42:25 -05:00
Nicholas Hastings
6d1a2b0d86 Expose Message_DetermineMulticastRecipients as GetClientsInRange native. 2014-12-30 15:37:57 -05:00
Nicholas Hastings
cdaf54dfe0 Merge pull request #235 from alliedmodders/dmapdump-offset
Add offset printing to datamap dumps (r=asherkin)..
2014-12-30 14:29:51 -05:00
Nicholas Hastings
7f0edd441e Add offset printing to datamap dumps. 2014-12-30 08:36:35 -05:00
Nicholas Hastings
4a9dffd3e1 Change sm_trigger_show default value to 0 / disabled. 2014-12-29 11:56:07 -05:00
Ross Bemrose
f69f4eb85f Fixes to make mapchooser.inc transitional compliant. Also updated comments in mapchooser.sp to match the new mapchooser.inc signature. 2014-12-26 12:36:12 -05:00
Ross Bemrose
84782a40df Merge branch 'master' of https://github.com/alliedmodders/sourcemod into mapchooser-updates 2014-12-26 12:30:21 -05:00
Nicholas Hastings
047c143879 Revert "Disable FireOutput detour on Windows for Dota for now."
This reverts commit a7c9aff568.
2014-12-24 11:01:32 -05:00
Nicholas Hastings
a7c9aff568 Disable FireOutput detour on Windows for Dota for now. 2014-12-24 10:37:51 -05:00
Nicholas Hastings
fe6d44bbd5 Fix build. 2014-12-23 08:27:41 -08:00
Nicholas Hastings
489b7f1d33 Gamedata cleanup. 2014-12-23 08:18:40 -08:00
Nicholas Hastings
ad9de71ac9 Add new and remove old gamerules gamedata for numerous games. 2014-12-23 11:04:05 -05:00
Nicholas Hastings
3edaac9bd7 Merge pull request #230 from peace-maker/mysql_unpack_spam
Don't unpack mysql verbosely in checkout-deps.sh.
2014-12-23 09:02:46 -05:00
Nicholas Hastings
9247a8ab00 Merge pull request #232 from FlaminSarge/tf_mannpower_conds
Update TFCond enum for Mannpower.
2014-12-23 08:22:30 -05:00
FlaminSarge
7b71ff2643 Denote TFCond multiples of 32 consistently 2014-12-23 02:21:02 -08:00
FlaminSarge
97e88640ca Update TFCond enum for Mannpower 2014-12-23 02:13:51 -08:00
Nicholas Hastings
e1b89a3008 Update TF2 gamedata. 2014-12-22 17:30:29 -05:00
Ross Bemrose
6dff44da54 Merge branch 'master' of https://github.com/alliedmodders/sourcemod into mapchooser-updates 2014-12-22 15:56:18 -05:00
Nicholas Hastings
7fddf5abf4 Disable nextmap on Insurgency. 2014-12-20 22:55:36 -05:00
Peace-Maker
6c17f247df Don't unpack mysql verbosely
I doubt we're interested in the filename of every single file
contained in the mysql archive when it's decompressed.

It bloats up the travis build log.
2014-12-20 11:32:15 +01:00
Peace-Maker
9b2e77711a Plugin_Failed == "An unrecoverable error"
Change the meaning of Plugin_Failed status to indicate, that the plugin
can't recover from the error.
Make sure those previously loaded plugins are shown correctly in sm
plugins info x.
2014-12-20 11:08:30 +01:00
Peace-Maker
0b131d6864 Pause dependent plugins on SetFailState (bug 6120)
When a plugin calls SetFailState it is paused and all natives it
registered are unavailable. Other plugins, which depend on those natives
keep running and error whenever they try to call those natives.

This correctly sets the dependent plugins to an error state as if the
plugin which called SetFailState was unloaded.
2014-12-20 11:07:57 +01:00
Nicholas Hastings
abb8d8447f Move bot auth to after connect to fix old too-early-authid bug now causing crash (r=VoiDeD). 2014-12-19 18:27:18 -05:00
Ross Bemrose
7edc1f8a6d Stop MENU_ACTIONS_ALL from tossing warnings when #pragma newdecls required is set. 2014-12-19 11:29:05 -05:00
Ross Bemrose
a0dd8cbc97 Merge branch 'master' of https://github.com/alliedmodders/sourcemod into mapchooser-updates 2014-12-19 11:15:04 -05:00
Nicholas Hastings
4f15715993 Merge pull request #228 from VoiDeD/fix-version
Update manual builds to use version 1.8.0
2014-12-18 19:42:59 -05:00
Ryan Stecker
679b2863fa Update manual builds to use version 1.8.0 2014-12-18 18:18:55 -06:00
Nicholas Hastings
13f6e2d4d0 Trigger build. 2014-12-18 05:09:25 -08:00
Nicholas Hastings
4311dc3270 Bump version to 1.8.0-dev. 2014-12-18 04:55:58 -08:00
Ross Bemrose
01f4b204c9 Added two items missed in the original conversion with the Runoff vote. 2014-12-17 16:05:14 -05:00
Ross Bemrose
f40bfbf762 Updated nextmap.inc. Also fixed copyright years and added missing copyright header to mapchooser.inc (all .inc files use the same copyright header, so...) 2014-12-17 11:53:02 -05:00
Ross Bemrose
ccf5aa6b54 Change all view_as<>(null) back to INVALID_HANDLE for now. 2014-12-17 11:07:51 -05:00
Ross Bemrose
032dde7be9 Missed a few GetArrayCell and GetArraySizes in MapChooser. 2014-12-16 17:00:00 -05:00
Ross Bemrose
2d5b71c832 Deleted comment... checked into it and its working as intended. 2014-12-16 16:57:49 -05:00
Ross Bemrose
8272151d78 Convert the MapChooser VoteHandlers over to the new style. 2014-12-16 16:20:03 -05:00
Ross Bemrose
1b79252947 Update NextMap, Nominations, RandomCycle, and RockTheVote with newer MethodMap stuff 2014-12-16 14:16:06 -05:00
Ross Bemrose
bc4d6b7104 Eliminate extraneous view_as calls and also update mapchooser.inc. 2014-12-16 13:53:54 -05:00
Ross Bemrose
46839b9752 Update MapChooser to use 1.7 syntax... except there's a bug you run into with Advanced Vote Callbacks. 2014-12-16 13:38:43 -05:00
Thordin
f27c33cd18 Increased handles to 32k 2014-12-07 21:50:40 -08:00
Sean Lewis
d2e01da287 Wrap 3rd parameter in FindValueInArray to check for existence. 2014-12-06 17:07:54 -06:00
Sean Lewis
3ef2bdcb8d Add block parameter to FindValueInArray native. 2014-12-06 03:21:53 -06:00
Nicholas Hastings
cd304dc800 Make TravisCI builds use Clang 3.5 to match our Buildbot builds. 2014-11-10 20:25:29 -05:00
Kyle Sanderson
901890e36d Eliminate SDK dependence for MM:S enabled extensions. 2014-08-09 14:42:38 -07:00
1018 changed files with 178496 additions and 170564 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

74
.github/CONTRIBUTING.md vendored Normal file
View File

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

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.

1
.gitignore vendored
View File

@ -35,3 +35,4 @@ obj-*/
*.orig
*.smx
*.swp
*.gdb_history

6
.gitmodules vendored Normal file
View File

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

View File

@ -1,11 +1,118 @@
git:
depth: 3
sudo: false
language: cpp
compiler:
- clang
os: linux
dist: trusty
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-3.9
- llvm-toolchain-trusty-4.0
- llvm-toolchain-trusty-5.0
packages:
- lib32stdc++6
- lib32z1-dev
- libc6-dev-i386
- linux-libc-dev
- g++-multilib
# - clang-3.6
# - clang-3.8
# - clang-4.0
# - clang-5.0
# - g++-6
# - g++-6-multilib
- clang-3.9
- g++-4.8-multilib
- g++-4.8
- g++-4.9-multilib
- g++-4.9
- g++-5-multilib
- g++-5
- g++-7-multilib
- g++-7
cache:
directories:
- ../mysql-5.0
env:
- MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
- MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
- MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
matrix:
fast_finish: true
include:
- os: linux
sudo: false
language: cpp
addons:
apt:
packages: ['clang-3.6', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
cache:
directories: ['../mysql-5.0']
env: ['MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6"']
- os: linux
sudo: false
language: cpp
addons:
apt:
packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
cache:
directories: ['../mysql-5.0']
env: ['MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"']
- os: linux
sudo: false
language: cpp
addons:
apt:
sources: ['llvm-toolchain-trusty-4.0']
packages: ['clang-4.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
cache:
directories: ['../mysql-5.0']
env: ['MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"']
- os: linux
sudo: false
language: cpp
addons:
apt:
sources: ['llvm-toolchain-trusty-5.0']
packages: ['clang-5.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
cache:
directories: ['../mysql-5.0']
env: ['MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"']
- os: linux
sudo: false
language: cpp
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'g++-6-multilib', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
cache:
directories: ['../mysql-5.0']
env: ['MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"']
allow_failures:
- env: MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7"
- env: MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
- env: MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
- env: MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
- env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
before_script:
- sudo apt-get update -qq
- sudo apt-get install -y g++-multilib libc6-dev-i386 lib32stdc++6 lib32z1-dev
- CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
script:
- mkdir build && cd build
- python ../configure.py --enable-optimize --sdks=episode1,tf2,l4d2,csgo,dota
- ambuild
- PATH="~/.local/bin:$PATH"
- eval "${MATRIX_EVAL}"
- python ../configure.py --enable-optimize --sdks=episode1,css,tf2,l4d2,csgo,dota
- ambuild

View File

@ -11,32 +11,52 @@ class SDK(object):
self.platform = platform
self.name = dir
self.path = None # Actual path
self.platformSpec = platform
# By default, nothing supports x64.
if type(platform) is list:
self.platformSpec = {p: ['x86'] for p in platform}
else:
self.platformSpec = platform
def shouldBuild(self, target, archs):
if target.platform not in self.platformSpec:
return False
if not len([i for i in self.platformSpec[target.platform] if i in archs]):
return False
return True
WinOnly = ['windows']
WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac']
CSGO = {
'windows': ['x86'],
'linux': ['x86', 'x64'],
'mac': ['x64']
}
PossibleSDKs = {
'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'),
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'),
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'),
'tf2': SDK('HL2SDKTF2', '2.tf2', '10', 'TF2', WinLinuxMac, 'tf2'),
'l4d': SDK('HL2SDKL4D', '2.l4d', '11', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
'nucleardawn': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '14', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
'tf2': SDK('HL2SDKTF2', '2.tf2', '11', 'TF2', WinLinuxMac, 'tf2'),
'l4d': SDK('HL2SDKL4D', '2.l4d', '12', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
'nucleardawn': SDK('HL2SDKND', '2.nd', '13', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '15', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '15', 'ALIENSWARM', WinOnly, 'swarm'),
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'),
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '19', 'CSGO', WinLinuxMac, 'csgo'),
'dota': SDK('HL2SDKDOTA', '2.dota', '20', 'DOTA', WinLinuxMac, 'dota'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '16', 'PORTAL2', [], 'portal2'),
'blade': SDK('HL2SDKBLADE', '2.blade', '17', 'BLADE', WinLinux, 'blade'),
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '18', 'INSURGENCY', WinLinuxMac, 'insurgency'),
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '13', 'CONTAGION', WinOnly, 'contagion'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, 'csgo'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'),
'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'),
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '14', 'CONTAGION', WinOnly, 'contagion'),
'bms': SDK('HL2SDKBMS', '2.bms', '10', 'BMS', WinLinux, 'bms'),
'doi': SDK('HL2SDKDOI', '2.doi', '20', 'DOI', WinLinuxMac, 'doi'),
}
def ResolveEnvPath(env, folder):
@ -59,6 +79,28 @@ def ResolveEnvPath(env, folder):
def Normalize(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):
def __init__(self):
@ -67,10 +109,12 @@ class SMConfig(object):
self.extensions = []
self.generated_headers = None
self.mms_root = None
self.mysql_root = None
self.mysql_root = {}
self.spcomp = None
self.spcomp_bins = None
self.smx_files = {}
self.versionlib = None
self.archs = builder.target.arch.replace('x86_64', 'x64').split(',')
def use_auto_versioning(self):
if builder.backend != 'amb2':
@ -104,7 +148,7 @@ class SMConfig(object):
for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name]
if builder.target_platform in sdk.platform:
if sdk.shouldBuild(builder.target, self.archs):
if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
else:
@ -117,10 +161,10 @@ class SMConfig(object):
sdk.path = Normalize(sdk_path)
self.sdks[sdk_name] = sdk
if len(self.sdks) < 1:
raise Exception('At least one SDK must be available.')
if len(self.sdks) < 1 and len(sdk_list):
raise Exception('No SDKs were found that build on {0}-{1}, nothing to do.'.format(
builder.target.platform, builder.target.arch))
if builder.options.mms_path:
self.mms_root = builder.options.mms_path
else:
@ -136,165 +180,207 @@ class SMConfig(object):
if builder.options.hasMySql:
if builder.options.mysql_path:
self.mysql_root = builder.options.mysql_path
self.mysql_root['x86'] = builder.options.mysql_path
else:
for i in range(7):
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
if self.mysql_root:
for i in range(10):
self.mysql_root['x86'] = ResolveEnvPath('MYSQL55', 'mysql-5.' + str(i))
if self.mysql_root['x86']:
break
if not self.mysql_root 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!')
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):
builder.AddConfigureFile('pushbuild.txt')
if not set(self.archs).issubset(['x86', 'x64']):
raise Exception('Unknown target architecture: {0}'.format(builder.target.arch))
cxx = builder.DetectCompilers()
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'):
cxx.defines += [
'stricmp=strcasecmp',
'_stricmp=strcasecmp',
'_snprintf=snprintf',
'_vsnprintf=vsnprintf',
'HAVE_STDINT_H',
'GNUC',
]
cxx.cflags += [
'-pipe',
'-fno-strict-aliasing',
'-Wall',
'-Werror',
'-Wno-unused',
'-Wno-switch',
'-Wno-array-bounds',
'-msse',
'-m32',
]
cxx.cxxflags += [
'-std=c++11',
]
self.configure_gcc(cxx)
elif cxx.family == 'msvc':
self.configure_msvc(cxx)
have_gcc = cxx.vendor == 'gcc'
have_clang = cxx.vendor == 'clang'
if have_clang or (have_gcc and cxx.version >= '4'):
cxx.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.version >= '4.6'):
cxx.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if have_gcc and cxx.version >= '4.8':
cxx.cflags += ['-Wno-unused-result']
if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
cxx.linkflags += ['-m32']
cxx.cxxflags += [
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
]
if have_gcc:
cxx.cflags += ['-mfpmath=sse']
elif cxx.vendor == 'msvc':
if builder.options.debug == '1':
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
else:
cxx.cflags += ['/MT']
cxx.defines += [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
'_ITERATOR_DEBUG_LEVEL=0',
]
if cxx.version < 1800:
cxx.defines += 'strtoull=_strtoui64'
cxx.cflags += [
'/W3',
]
cxx.cxxflags += [
'/EHsc',
'/GR-',
'/TP',
]
cxx.linkflags += [
'/MACHINE:X86',
'/SUBSYSTEM:WINDOWS',
'kernel32.lib',
'user32.lib',
'gdi32.lib',
'winspool.lib',
'comdlg32.lib',
'advapi32.lib',
'shell32.lib',
'ole32.lib',
'oleaut32.lib',
'uuid.lib',
'odbc32.lib',
'odbccp32.lib',
]
# Optimization
# Optimizaiton
if builder.options.opt == '1':
cxx.defines += ['NDEBUG']
if cxx.like('gcc'):
cxx.cflags += ['-O3']
elif cxx.like('msvc'):
cxx.cflags += ['/Ox', '/Zo']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
# Debugging
if builder.options.debug == '1':
cxx.defines += ['DEBUG', '_DEBUG']
if cxx.like('msvc'):
cxx.cflags += ['/Od', '/RTC1']
# This needs to be after our optimization flags which could otherwise disable it.
if cxx.vendor == 'msvc':
# Don't omit the frame pointer.
cxx.cflags += ['/Oy-']
# Platform-specifics
if builder.target_platform == 'linux':
cxx.defines += ['_LINUX', 'POSIX']
if cxx.vendor == 'gcc':
cxx.linkflags += ['-static-libgcc']
elif cxx.vendor == 'clang':
cxx.linkflags += ['-lgcc_eh']
elif builder.target_platform == 'mac':
cxx.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [
'-mmacosx-version-min=10.5',
'-arch', 'i386',
'-lstdc++',
'-stdlib=libstdc++',
]
cxx.cxxflags += ['-stdlib=libstdc++']
elif builder.target_platform == 'windows':
cxx.defines += ['WIN32', '_WINDOWS']
if builder.target.platform == 'linux':
self.configure_linux(cxx)
elif builder.target.platform == 'mac':
self.configure_mac(cxx)
elif builder.target.platform == 'windows':
self.configure_windows(cxx)
# Finish up.
cxx.defines += [
'SOURCEMOD_BUILD',
'SM_USE_VERSIONLIB',
]
cxx.includes += [
os.path.join(builder.sourcePath, 'public'),
]
if self.use_auto_versioning():
cxx.defines += ['SM_GENERATED_BUILD']
cxx.includes += [os.path.join(builder.buildPath, 'includes')]
cxx.includes += [os.path.join(builder.sourcePath, 'versionlib')]
cxx.includes += [
os.path.join(builder.buildPath, 'includes'),
os.path.join(builder.sourcePath, 'versionlib'),
]
def AddVersioning(self, binary):
if builder.target_platform == 'windows':
def configure_gcc(self, cxx):
cxx.defines += [
'stricmp=strcasecmp',
'_stricmp=strcasecmp',
'_snprintf=snprintf',
'_vsnprintf=vsnprintf',
'HAVE_STDINT_H',
'GNUC',
]
cxx.cflags += [
'-pipe',
'-fno-strict-aliasing',
'-Wall',
'-Werror',
'-Wno-unused',
'-Wno-switch',
'-Wno-array-bounds',
'-msse',
'-fvisibility=hidden',
]
cxx.cxxflags += [
'-std=c++11',
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
'-fvisibility-inlines-hidden',
]
have_gcc = cxx.family == 'gcc'
have_clang = cxx.family == 'clang'
if cxx.version >= 'clang-3.9':
cxx.cxxflags += ['-Wno-expansion-to-defined']
if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0':
cxx.cflags += ['-Wno-varargs']
if cxx.version >= 'clang-3.6' or cxx.version >= 'apple-clang-7.0':
cxx.cxxflags += ['-Wno-inconsistent-missing-override']
if cxx.version >= 'clang-2.9' or cxx.version >= 'apple-clang-3.0':
cxx.cxxflags += ['-Wno-null-dereference']
if have_clang or (cxx.version >= 'gcc-4.6'):
cxx.cflags += ['-Wno-narrowing']
if have_clang or (cxx.version >= 'gcc-4.7'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if cxx.version >= 'gcc-4.8':
cxx.cflags += ['-Wno-unused-result']
if cxx.version >= 'gcc-9.0':
cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned']
if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
if have_gcc:
cxx.cflags += ['-mfpmath=sse']
cxx.cflags += ['-Wno-maybe-uninitialized']
if builder.options.opt == '1':
cxx.cflags += ['-O3']
def configure_msvc(self, cxx):
if builder.options.debug == '1':
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
else:
cxx.cflags += ['/MT']
cxx.defines += [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
'_ITERATOR_DEBUG_LEVEL=0',
]
cxx.cflags += [
'/W3',
]
cxx.cxxflags += [
'/EHsc',
'/GR-',
'/TP',
]
cxx.linkflags += [
'kernel32.lib',
'user32.lib',
'gdi32.lib',
'winspool.lib',
'comdlg32.lib',
'advapi32.lib',
'shell32.lib',
'ole32.lib',
'oleaut32.lib',
'uuid.lib',
'odbc32.lib',
'odbccp32.lib',
]
if builder.options.opt == '1':
cxx.cflags += ['/Ox', '/Zo']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
if builder.options.debug == '1':
cxx.cflags += ['/Od', '/RTC1']
# This needs to be after our optimization flags which could otherwise disable it.
# Don't omit the frame pointer.
cxx.cflags += ['/Oy-']
def configure_linux(self, cxx):
cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
cxx.linkflags += ['-lm']
if cxx.family == 'gcc':
cxx.linkflags += ['-static-libgcc']
elif cxx.family == 'clang':
cxx.linkflags += ['-lgcc_eh']
def configure_mac(self, cxx):
cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [
'-mmacosx-version-min=10.5',
'-lstdc++',
'-stdlib=libstdc++',
]
cxx.cxxflags += ['-stdlib=libstdc++']
def configure_windows(self, cxx):
cxx.defines += ['WIN32', '_WINDOWS']
def AddVersioning(self, binary, arch):
if builder.target.platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
@ -302,52 +388,83 @@ class SMConfig(object):
]
if self.use_auto_versioning():
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
elif builder.target_platform == 'mac':
elif builder.target.platform == 'mac':
if binary.type == 'library':
binary.compiler.postlink += [
'-compatibility_version', '1.0.0',
'-current_version', self.productVersion
]
if self.use_auto_versioning():
binary.compiler.linkflags += [self.versionlib]
binary.compiler.linkflags += [self.versionlib[arch]]
binary.compiler.sourcedeps += SM.generated_headers
return binary
def LibraryBuilder(self, compiler, name, arch):
binary = compiler.Library(name)
AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
return binary
def Library(self, context, name):
binary = context.compiler.Library(name)
return self.AddVersioning(binary)
def ProgramBuilder(self, compiler, name, arch):
binary = compiler.Program(name)
AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
if '-static-libgcc' in binary.compiler.linkflags:
binary.compiler.linkflags.remove('-static-libgcc')
if '-lgcc_eh' in binary.compiler.linkflags:
binary.compiler.linkflags.remove('-lgcc_eh')
if binary.compiler.like('gcc'):
binary.compiler.linkflags += ['-lstdc++', '-lpthread']
if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE']
return binary
def StaticLibraryBuilder(self, compiler, name, arch):
binary = compiler.StaticLibrary(name)
AppendArchSuffix(binary, name, arch)
return binary;
def Program(self, context, name):
binary = context.compiler.Program(name)
return self.AddVersioning(binary)
def Library(self, context, name, arch):
compiler = context.cxx.clone()
SetArchFlags(compiler, arch, builder.target.platform)
return self.LibraryBuilder(compiler, name, arch)
def Program(self, context, name, arch):
compiler = context.cxx.clone()
SetArchFlags(compiler, arch, builder.target.platform)
return self.ProgramBuilder(compiler, name, arch)
def StaticLibrary(self, context, name, arch):
compiler = context.cxx.clone()
SetArchFlags(compiler, arch, builder.target.platform)
return self.StaticLibraryBuilder(compiler, name, arch)
def ConfigureForExtension(self, context, compiler):
compiler.cxxincludes += [
os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sdk'),
os.path.join(builder.sourcePath, 'public'),
os.path.join(builder.sourcePath, 'public', 'extensions'),
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
os.path.join(builder.sourcePath, 'public', 'amtl'),
]
return compiler
def ExtLibrary(self, context, name):
binary = context.compiler.Library(name)
def ExtLibrary(self, context, name, arch):
binary = self.Library(context, name, arch)
self.ConfigureForExtension(context, binary.compiler)
return self.AddVersioning(binary)
return binary
def ConfigureForHL2(self, binary, sdk):
def ConfigureForHL2(self, binary, sdk, arch):
compiler = binary.compiler
if sdk.name == 'episode1':
mms_path = os.path.join(self.mms_root, 'core-legacy')
else:
mms_path = os.path.join(self.mms_root, 'core')
SetArchFlags(compiler, arch, builder.target.platform)
compiler.cxxincludes += [
os.path.join(mms_path),
os.path.join(mms_path, 'sourcehook'),
os.path.join(self.mms_root, 'core'),
os.path.join(self.mms_root, 'core', 'sourcehook'),
]
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
@ -372,7 +489,7 @@ class SMConfig(object):
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name == 'sdk2013' and compiler.like('gcc'):
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'):
# The 2013 SDK already has these in public/tier0/basetypes.h
compiler.defines.remove('stricmp=strcasecmp')
compiler.defines.remove('_stricmp=strcasecmp')
@ -381,39 +498,49 @@ class SMConfig(object):
if compiler.like('msvc'):
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
if compiler.version >= 1900:
compiler.linkflags += ['legacy_stdio_definitions.lib']
else:
compiler.defines += ['COMPILER_GCC']
if arch == 'x64':
compiler.defines += ['X64BITS', 'PLATFORM_64BITS']
# For everything after Swarm, this needs to be defined for entity networking
# to work properly with sendprop value changes.
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']:
compiler.defines += ['NETWORK_VARS_ENABLED']
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']:
if builder.target_platform in ['linux', 'mac']:
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2']:
if builder.target.platform in ['linux', 'mac']:
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
if sdk.name == 'csgo' and builder.target_platform == 'linux':
if sdk.name == 'csgo' and builder.target.platform == 'linux':
compiler.linkflags += ['-lstdc++']
compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
if builder.target_platform == 'linux':
if builder.target.platform == 'linux':
if sdk.name == 'episode1':
lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name == 'sdk2013':
elif sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
elif arch == 'x64':
lib_folder = os.path.join(sdk.path, 'lib', 'linux64')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target_platform == 'mac':
if sdk.name == 'sdk2013':
elif builder.target.platform == 'mac':
if sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
elif arch == 'x64':
lib_folder = os.path.join(sdk.path, 'lib', 'osx64')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target_platform in ['linux', 'mac']:
if sdk.name == 'sdk2013':
if builder.target.platform in ['linux', 'mac']:
if sdk.name in ['sdk2013', 'bms'] or arch == 'x64':
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
@ -424,26 +551,28 @@ class SMConfig(object):
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
]
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
self.AddVersioning(binary)
if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']:
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 = []
if builder.target_platform == 'linux':
compiler.linkflags[0:0] = ['-lm']
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'nucleardawn', 'l4d2']:
if builder.target.platform == 'linux':
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
elif arch == 'x64' and sdk.name == 'csgo':
dynamic_libs = ['libtier0_client.so', 'libvstdlib_client.so']
elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo']:
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac':
elif builder.target.platform == 'mac':
compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows':
elif builder.target.platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo']:
libs.append('interfaces')
for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
@ -464,19 +593,21 @@ class SMConfig(object):
return binary
def HL2Library(self, context, name, sdk):
binary = context.compiler.Library(name)
def HL2Library(self, context, name, sdk, arch):
binary = self.Library(context, name, arch)
self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(binary, sdk)
return self.ConfigureForHL2(binary, sdk, arch)
def HL2Project(self, context, name):
project = context.compiler.LibraryProject(name)
project = context.cxx.LibraryProject(name)
self.ConfigureForExtension(context, project.compiler)
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))
return self.ConfigureForHL2(binary, sdk)
AppendArchSuffix(binary, name, arch)
self.AddVersioning(binary, arch)
return self.ConfigureForHL2(binary, sdk, arch)
SM = SMConfig()
SM.detectProductVersion()
@ -484,15 +615,31 @@ SM.detectSDKs()
SM.configure()
if SM.use_auto_versioning():
SM.generated_headers = builder.RunScript(
SM.generated_headers = builder.Build(
'tools/buildbot/Versioning',
{ 'SM': SM }
)
SM.versionlib = builder.RunScript(
SM.versionlib = builder.Build(
'versionlib/AMBuilder',
{ 'SM': SM }
)
# Build SourcePawn externally.
SP = builder.Build('sourcepawn/AMBuildScript', {
'external_root': SM,
'external_amtl': os.path.join(builder.sourcePath, 'public', 'amtl'),
'external_build': ['core'],
})
if len(SP.spcomp) > 1:
SM.spcomp = SP.spcomp['x86']
else:
SM.spcomp = SP.spcomp[list(SP.spcomp.keys())[0]]
SM.spcomp_bins = list(SP.spcomp.values())
for arch in SM.archs:
SM.binaries += [
SP.libsourcepawn[arch]
]
BuildScripts = [
'loader/AMBuilder',
'core/AMBuilder',
@ -510,8 +657,6 @@ BuildScripts = [
'extensions/tf2/AMBuilder',
'extensions/topmenus/AMBuilder',
'extensions/updater/AMBuilder',
'sourcepawn/compiler/AMBuilder',
'sourcepawn/jit/AMBuilder',
]
if builder.backend == 'amb2':
@ -520,7 +665,7 @@ if builder.backend == 'amb2':
'tools/buildbot/PackageScript',
]
builder.RunBuildScripts(BuildScripts, { 'SM': SM })
builder.Build(BuildScripts, { 'SM': SM })
if builder.options.breakpad_dump:
builder.RunScript('tools/buildbot/BreakpadSymbols', { 'SM': SM })
builder.Build('tools/buildbot/BreakpadSymbols', { 'SM': SM })

View File

@ -6,12 +6,22 @@ General
- [SourceMod website](http://www.sourcemod.net): Source Engine scripting and server administration
- [Forum](https://forums.alliedmods.net/forumdisplay.php?f=52): Discussion forum including plugin/extension development
- [General documentation](https://wiki.alliedmods.net/Category:SourceMod_Documentation): Miscellaneous information about SourceMod
- [Latest release](http://www.sourcemod.net/downloads.php): The latest stable SourceMod release
- [Build snapshots](http://www.sourcemod.net/snapshots.php): Builds of recent development versions
- [Stable builds](http://www.sourcemod.net/downloads.php?branch=stable): The latest stable SourceMod releases
- [Dev builds](http://www.sourcemod.net/downloads.php?branch=dev): Builds of recent development versions
Development
-----------
- [Issue tracker](https://bugs.alliedmods.net): 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)
- [SourcePawn scripting](https://wiki.alliedmods.net/Category:SourceMod_Scripting): SourcePawn examples and introduction to the language
- [SourceMod plugin API](https://sm.alliedmods.net/new-api): Online SourceMod plugin API reference generated from the include files
- [SourceMod extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces
Contact
-------
- Connect with us on [GameSurge](https://gamesurge.net) IRC in #sourcemod
- Alternatively feel free to join our [Discord](https://discord.gg/HgZctSS) server
License
-------
SourceMod is licensed under the GNU General Public License version 3. Special exceptions are outlined in the LICENSE.txt file inside of the licenses folder.

View File

@ -0,0 +1,46 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_API_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_API_H_
#include <bridge/include/CoreProvider.h>
#include <bridge/include/LogicProvider.h>
#include <stdint.h>
namespace SourceMod {
// Add 1 to the RHS of this expression to bump the intercom file
// This is to prevent mismatching core/logic binaries
static const uint32_t SM_LOGIC_MAGIC = 0x0F47C0DE - 57;
} // namespace SourceMod
typedef void (*LogicInitFunction)(SourceMod::CoreProvider *core, SourceMod::sm_logic_t *logic);
typedef LogicInitFunction (*LogicLoadFunction)(uint32_t magic);
typedef SourceMod::ITextParsers *(*GetITextParsers)();
#endif // _INCLUDE_SOURCEMOD_BRIDGE_API_H_

View File

@ -0,0 +1,140 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_CORE_PROVIDER_API_H_
#define _INCLUDE_SOURCEMOD_CORE_PROVIDER_API_H_
#include <stddef.h>
#include <stdint.h>
#include <IAdminSystem.h>
#include <amtl/am-function.h>
namespace SourcePawn {
class ISourcePawnEngine;
class ISourcePawnEngine2;
} // namespace SourcePawn
// SDK types.
#if defined(SM_LOGIC)
class ConCommandBase {};
class ConVar : public ConCommandBase {};
#else
class ConCommandBase;
class ConVar;
#endif
class KeyValues;
struct ServerGlobals
{
const double *universalTime;
float *interval_per_tick;
float *frametime;
};
namespace SourceMod {
class ISourceMod;
class IVEngineServerBridge;
class IFileSystemBridge;
class ITimerSystem;
class IPlayerManager;
class IGameHelpers;
class IMenuManager;
struct DatabaseInfo;
class IPlayerInfoBridge;
class ICommandArgs;
typedef ke::Lambda<bool(int client, const ICommandArgs*)> CommandFunc;
class CoreProvider
{
public:
/* Objects */
ISourceMod *sm;
IVEngineServerBridge *engine;
IFileSystemBridge *filesystem;
IPlayerInfoBridge *playerInfo;
ITimerSystem *timersys;
IPlayerManager *playerhelpers;
IGameHelpers *gamehelpers;
IMenuManager *menus;
SourcePawn::ISourcePawnEngine **spe1;
SourcePawn::ISourcePawnEngine2 **spe2;
const char *gamesuffix;
/* Data */
ServerGlobals *serverGlobals;
void * serverFactory;
void * engineFactory;
void * matchmakingDSFactory;
SMGlobalClass * listeners;
// ConVar functions.
virtual ConVar *FindConVar(const char *name) = 0;
virtual const char *GetCvarString(ConVar *cvar) = 0;
virtual bool GetCvarBool(ConVar* cvar) = 0;
// Command functions.
virtual void DefineCommand(const char *cmd, const char *help, const CommandFunc &callback) = 0;
// Game description functions.
virtual bool GetGameName(char *buffer, size_t maxlength) = 0;
virtual const char *GetGameDescription() = 0;
virtual const char *GetSourceEngineName() = 0;
virtual bool SymbolsAreHidden() = 0;
// Game state and helper functions.
virtual bool IsMapLoading() = 0;
virtual bool IsMapRunning() = 0;
virtual int MaxClients() = 0;
virtual bool DescribePlayer(int index, const char **namep, const char **authp, int *useridp) = 0;
virtual void LogToGame(const char *message) = 0;
virtual void ConPrint(const char *message) = 0;
virtual void ConsolePrint(const char *fmt, ...) = 0;
virtual void ConsolePrintVa(const char *fmt, va_list ap) = 0;
// Game engine helper functions.
virtual bool IsClientConVarQueryingSupported() = 0;
virtual int QueryClientConVar(int client, const char *cvar) = 0;
// Metamod:Source functions.
virtual int LoadMMSPlugin(const char *file, bool *ok, char *error, size_t maxlength) = 0;
virtual void UnloadMMSPlugin(int id) = 0;
const char * (*GetCoreConfigValue)(const char*);
void (*DoGlobalPluginLoads)();
bool (*AreConfigsExecuted)();
void (*ExecuteConfigs)(IPluginContext *ctx);
void (*GetDBInfoFromKeyValues)(KeyValues *, DatabaseInfo *);
int (*GetActivityFlags)();
int (*GetImmunityMode)();
void (*UpdateAdminCmdFlags)(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool (*LookForCommandAdminFlags)(const char *cmd, FlagBits *pFlags);
int (*GetGlobalTarget)();
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_CORE_PROVIDER_API_H_

View File

@ -0,0 +1,81 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_INCLUDE_IEXTBRIDGE_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IEXTBRIDGE_H_
#include <sp_vm_api.h>
#include <IExtensionSys.h>
#include <sh_vector.h>
struct edict_t;
namespace SourceMod {
using namespace SourceHook;
using namespace SourcePawn;
class SMPlugin;
class IExtensionSys : public IExtensionManager
{
public:
virtual IExtension *LoadAutoExtension(const char *name, bool bErrorOnMissing=true) = 0;
virtual void TryAutoload() = 0;
virtual void Shutdown() = 0;
virtual IExtension *FindExtensionByFile(const char *name) = 0;
virtual bool LibraryExists(const char *name) = 0;
virtual void CallOnCoreMapStart(edict_t *edictList, int edictCount, int maxClients) = 0;
virtual IExtension *GetExtensionFromIdent(IdentityToken_t *token) = 0;
virtual void BindChildPlugin(IExtension *ext, SMPlugin *plugin) = 0;
virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0;
virtual const CVector<IExtension *> *ListExtensions() = 0;
virtual void FreeExtensionList(const CVector<IExtension *> *list) = 0;
virtual void CallOnCoreMapEnd() = 0;
};
class AutoExtensionList
{
public:
AutoExtensionList(IExtensionSys *extensions)
: extensions_(extensions), list_(extensions_->ListExtensions())
{
}
~AutoExtensionList()
{
extensions_->FreeExtensionList(list_);
}
const CVector<IExtension *> *operator ->()
{
return list_;
}
private:
IExtensionSys *extensions_;
const CVector<IExtension *> *list_;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IEXTBRIDGE_H_

View File

@ -0,0 +1,63 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_IFILESYSTEM_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_IFILESYSTEM_H_
typedef void * FileHandle_t;
typedef int FileFindHandle_t;
namespace SourceMod {
class IFileSystemBridge
{
public:
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
virtual const char *FindNext(FileFindHandle_t handle) = 0;
virtual bool FindIsDirectory(FileFindHandle_t handle) = 0;
virtual void FindClose(FileFindHandle_t handle) = 0;
virtual FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0) = 0;
virtual void Close(FileHandle_t file) = 0;
virtual char *ReadLine(char *pOutput, int maxChars, FileHandle_t file) = 0;
virtual bool EndOfFile(FileHandle_t file) = 0;
virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 0;
virtual unsigned int Size(const char *pFileName, const char *pPathID = 0) = 0;
virtual int Read(void* pOutput, int size, FileHandle_t file) = 0;
virtual int Write(void const* pInput, int size, FileHandle_t file) = 0;
virtual void Seek(FileHandle_t file, int post, int seekType) = 0;
virtual unsigned int Tell(FileHandle_t file) = 0;
virtual int FPrint(FileHandle_t file, const char *pData) = 0;
virtual void Flush(FileHandle_t file) = 0;
virtual bool IsOk(FileHandle_t file) = 0;
virtual void RemoveFile(const char *pRelativePath, const char *pathID = 0) = 0;
virtual void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID = 0) = 0;
virtual bool IsDirectory(const char *pFileName, const char *pathID = 0) = 0;
virtual void CreateDirHierarchy(const char *path, const char *pathID = 0) = 0;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_BRIDGE_IFILESYSTEM_H_

43
bridge/include/ILogger.h Normal file
View File

@ -0,0 +1,43 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_LOGGER_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_LOGGER_H_
namespace SourceMod {
class ILogger
{
public:
virtual void LogMessage(const char *msg, ...) = 0;
virtual void LogError(const char *msg, ...) = 0;
virtual void LogFatal(const char *msg, ...) = 0;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_BRIDGE_LOGGER_H_

View File

@ -0,0 +1,55 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_INCLUDE_IPLAYERINFO_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPLAYERINFO_H_
class IPlayerInfo;
namespace SourceMod {
class IPlayerInfoBridge
{
public:
virtual bool IsObserver(IPlayerInfo *pInfo) = 0;
virtual int GetTeamIndex(IPlayerInfo *pInfo) = 0;
virtual int GetFragCount(IPlayerInfo *pInfo) = 0;
virtual int GetDeathCount(IPlayerInfo *pInfo) = 0;
virtual int GetArmorValue(IPlayerInfo *pInfo) = 0;
virtual void GetAbsOrigin(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual void GetAbsAngles(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual void GetPlayerMins(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual void GetPlayerMaxs(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual const char *GetWeaponName(IPlayerInfo *pInfo) = 0;
virtual const char *GetModelName(IPlayerInfo *pInfo) = 0;
virtual int GetHealth(IPlayerInfo *pInfo) = 0;
virtual void ChangeTeam(IPlayerInfo *pInfo, int iTeamNum) = 0;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPLAYERINFO_H_

View File

@ -0,0 +1,45 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_INCLUDE_IPROVIDERCALLBACK_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPROVIDERCALLBACK_H_
namespace SourceMod {
// Global callbacks provided to Core.
class IProviderCallbacks
{
public:
// Called when a log message is printed. Return true to supercede.
virtual bool OnLogPrint(const char *msg) = 0;
// Called each frame tick.
virtual void OnThink(bool simulating) = 0;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_IPROVIDERCALLBACK_H_

View File

@ -0,0 +1,112 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_INCLUDE_ISCRIPTMANAGER_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_ISCRIPTMANAGER_H_
#include <sp_vm_api.h>
#include <IPluginSys.h>
#include <sh_vector.h>
#include <sh_string.h>
namespace SourceMod {
using namespace SourceHook;
using namespace SourcePawn;
class IChangeableForward;
enum LibraryAction
{
LibraryAction_Removed,
LibraryAction_Added
};
struct AutoConfig
{
SourceHook::String autocfg;
SourceHook::String folder;
bool create;
};
class SMPlugin : public IPlugin
{
public:
virtual size_t GetConfigCount() = 0;
virtual AutoConfig *GetConfig(size_t i) = 0;
virtual void AddLibrary(const char *name) = 0;
virtual void AddConfig(bool create, const char *cfg, const char *folder) = 0;
virtual void EvictWithError(PluginStatus status, const char *fmt, ...) = 0;
};
class IScriptManager
{
public:
virtual void LoadAll(const char *config_path, const char *plugins_path) = 0;
virtual void RefreshAll() = 0;
virtual void Shutdown() = 0;
virtual IdentityToken_t *GetIdentity() = 0;
virtual void SyncMaxClients(int maxClients) = 0;
virtual void AddPluginsListener(IPluginsListener *listener) = 0;
virtual void RemovePluginsListener(IPluginsListener *listener) = 0;
virtual IPluginIterator *GetPluginIterator() = 0;
virtual void OnLibraryAction(const char *name, LibraryAction action) = 0;
virtual bool LibraryExists(const char *name) = 0;
virtual SMPlugin *FindPluginByOrder(unsigned num) = 0;
virtual SMPlugin *FindPluginByIdentity(IdentityToken_t *ident) = 0;
virtual SMPlugin *FindPluginByContext(IPluginContext *ctx) = 0;
virtual SMPlugin *FindPluginByContext(sp_context_t *ctx) = 0;
virtual SMPlugin *FindPluginByConsoleArg(const char *text) = 0;
virtual SMPlugin *FindPluginByHandle(Handle_t hndl, HandleError *errp) = 0;
virtual bool UnloadPlugin(IPlugin *plugin) = 0;
virtual const CVector<SMPlugin *> *ListPlugins() = 0;
virtual void FreePluginList(const CVector<SMPlugin *> *list) = 0;
virtual void AddFunctionsToForward(const char *name, IChangeableForward *fwd) = 0;
};
class AutoPluginList
{
public:
AutoPluginList(IScriptManager *scripts)
: scripts_(scripts), list_(scripts->ListPlugins())
{
}
~AutoPluginList()
{
scripts_->FreePluginList(list_);
}
const CVector<SMPlugin *> *operator ->()
{
return list_;
}
private:
IScriptManager *scripts_;
const CVector<SMPlugin *> *list_;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_BRIDGE_INCLUDE_ISCRIPTMANAGER_H_

View File

@ -0,0 +1,48 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_BRIDGE_IVENGINESERVER_H_
#define _INCLUDE_SOURCEMOD_BRIDGE_IVENGINESERVER_H_
struct edict_t;
namespace SourceMod {
class IVEngineServerBridge
{
public:
virtual bool IsDedicatedServer() = 0;
virtual void InsertServerCommand(const char *cmd) = 0;
virtual void ServerCommand(const char *cmd) = 0;
virtual void ServerExecute() = 0;
virtual const char *GetClientConVarValue(int clientIndex, const char *name) = 0;
virtual void ClientCommand(edict_t *pEdict, const char *szCommand) = 0;
virtual void FakeClientCommand(edict_t *pEdict, const char *szCommand) = 0;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_BRIDGE_IVENGINESERVER_H_

View File

@ -0,0 +1,92 @@
// vim: set ts=4 sw=4 tw=99 noet:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_LOGIC_PROVIDER_API_H_
#define _INCLUDE_SOURCEMOD_LOGIC_PROVIDER_API_H_
#include <sp_vm_api.h>
class SMGlobalClass;
namespace SourceMod {
using namespace SourcePawn;
class CoreProvider;
class IThreader;
class ITranslator;
class IGameConfig;
class IScriptManager;
class IShareSys;
class IHandleSys;
class ICommandArgs;
class IForwardManager;
class IAdminSystem;
class IRootConsole;
class IProviderCallbacks;
class IExtensionSys;
class ITextParsers;
class ILogger;
class ICellArray;
struct sm_logic_t
{
SMGlobalClass *head;
IThreader *threader;
ITranslator *translator;
const char *(*stristr)(const char *, const char *);
size_t (*atcprintf)(char *, size_t, const char *, IPluginContext *, const cell_t *, int *);
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...);
void (*AddCorePhraseFile)(const char *filename);
unsigned int (*ReplaceAll)(char*, size_t, const char *, const char *, bool);
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
IGameConfig * (*GetCoreGameConfig)();
IDebugListener *debugger;
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
void (*AddNatives)(sp_nativeinfo_t *natives);
void (*RegisterProfiler)(IProfilingTool *tool);
ICellArray * (*CreateCellArray)(size_t blocksize);
void (*FreeCellArray)(ICellArray *arr);
void * (*FromPseudoAddress)(uint32_t pseudoAddr);
uint32_t (*ToPseudoAddress)(void *addr);
IScriptManager *scripts;
IShareSys *sharesys;
IExtensionSys *extsys;
IHandleSys *handlesys;
IForwardManager *forwardsys;
IAdminSystem *adminsys;
IdentityToken_t *core_ident;
ILogger *logger;
IRootConsole *rootmenu;
IProviderCallbacks *callbacks;
float sentinel;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_LOGIC_PROVIDER_API_H_

View File

@ -65,6 +65,10 @@ sm_flood_time 0.75
// no reserved slot access (spectator players are selected first) is kicked to make room. Thus, the reserved
// slots always remains free. The only situation where the reserved slot(s) can become properly occupied is
// if the server is full with reserve slot access clients.
// 2 : The same as sm_reserve_type 1 except once a certain number of admins have been reached, the reserve slot
// stops kicking people and anyone can join to fill the server. You can use this to simulate having a large
// number of reserved slots with sm_reserve_type 0 but with only need to have 1 slot unavailable when there are
// less admins connected.
// --
// Requires: reservedslots.smx
// Default: 0
@ -93,7 +97,7 @@ sm_hide_slots 0
// Default: 1
sm_chat_mode 1
// Specifies whether or not "timeleft" will automaticly be triggered every
// Specifies whether or not "timeleft" will automatically be triggered every
// x seconds. Valid values are 0 (Disabled) to 1800 seconds.
// --
// Requires: basetriggers.smx
@ -105,8 +109,8 @@ sm_timeleft_interval 0
// 1 (Enabled)
// --
// Requires: basetriggers.smx
// Default: 1
sm_trigger_show 1
// Default: 0
sm_trigger_show 0
// Specifies whether or not to display vote progress to clients in the
// "hint" box (near the bottom of the screen in most games).

View File

@ -30,12 +30,12 @@
"ServerLang" "en"
/**
* String to use as the public chat trigger. Set an empty string to disable.
* List of characters to use for public chat triggers. Set an empty list to disable.
*/
"PublicChatTrigger" "!"
/**
* String to use as the silent chat trigger. Set an empty string to disable.
* List of characters to use for silent chat triggers. Set an empty list to disable.
*/
"SilentChatTrigger" "/"
@ -44,7 +44,7 @@
* but it does not evaluate to an actual command, it will be displayed
* publicly. This setting allows you to suppress accidental typings.
*
* The default value is "no". A value of "yes" will supress.
* The default value is "no". A value of "yes" will suppress.
*/
"SilentFailSuppress" "no"
@ -132,5 +132,18 @@
* passed. You can disable this feature by setting the value to "0".
*/
"SlowScriptTimeout" "8"
/**
* Per "http://blog.counter-strike.net/index.php/server_guidelines/", certain plugin
* functionality will trigger all of the game server owner's Game Server Login Tokens
* (GSLTs) to get banned when executed on a Counter-Strike: Global Offensive game server.
*
* Enabling this option will block plugins from using functionality that is known to cause this.
* This option only has any effect on CS:GO. Note that this does NOT guarantee that you cannot
* receive a ban.
*
* Disable this option at your own risk.
*/
"FollowCSGOServerGuidelines" "yes"
}

View File

@ -1,7 +1,7 @@
# vim: set ts=2 sw=2 tw=99 noet:
import sys
try:
from ambuild2 import run
from ambuild2 import run, util
except:
try:
import ambuild
@ -12,25 +12,31 @@ except:
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
sys.exit(1)
run = run.PrepareBuild(sourcePath=sys.path[0])
run.default_build_folder = 'obj-' + run.target_platform
run.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
def make_objdir_name(p):
return 'obj-' + util.Platform() + '-' + p.target_arch
parser = run.BuildParser(sourcePath=sys.path[0], api='2.1')
parser.default_arch = 'x86'
parser.default_build_folder = make_objdir_name
parser.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs')
run.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')
run.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
parser.options.add_option('--mysql64-path', type=str, dest='mysql64_path', default=None,
help='Path to 64-bit MySQL 5')
parser.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source')
run.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',
help='Enable debugging symbols')
run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
parser.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization')
run.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
parser.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
help='Disable building MySQL extension')
run.options.add_option('-s', '--sdks', default='all', dest='sdks',
parser.options.add_option('-s', '--sdks', default='all', dest='sdks',
help='Build against specified SDKs; valid args are "all", "present", or '
'comma-delimited list of engine names (default: %default)')
run.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
parser.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
default=False, help='Dump and upload breakpad symbols')
run.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
parser.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
default=False, help='Disable the auto versioning script')
run.Configure()
parser.Configure()

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
project = SM.HL2Project(builder, 'sourcemod')
@ -9,7 +9,6 @@ project.sources += [
'sm_stringutil.cpp',
'MenuVoting.cpp',
'smn_events.cpp',
'CDataPack.cpp',
'frame_hooks.cpp',
'smn_nextmap.cpp',
'sourcemm_api.cpp',
@ -21,7 +20,6 @@ project.sources += [
'NextMap.cpp',
'ConCmdManager.cpp',
'ConVarManager.cpp',
'LibrarySys.cpp',
'PlayerManager.cpp',
'TimerSys.cpp',
'CoreConfig.cpp',
@ -38,81 +36,78 @@ project.sources += [
'EventManager.cpp',
'MenuStyle_Radio.cpp',
'sm_autonatives.cpp',
'sm_srvcmds.cpp',
'ConsoleDetours.cpp',
'vprof_tool.cpp',
'smn_commandline.cpp',
'GameHooks.cpp',
]
for sdk_name in SM.sdks:
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)
compiler = binary.compiler
binary_name = 'sourcemod.' + sdk.ext
binary = SM.HL2Config(project, binary_name, sdk, arch)
compiler = binary.compiler
if sdk.name == 'csgo':
compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
]
elif sdk.name == 'dota':
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', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
builder.sourcePath
]
if builder.target_platform == 'linux':
compiler.postlink += ['-lpthread', '-lrt']
if sdk.name == 'csgo':
compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
]
if sdk.name == 'csgo' or sdk.name == 'dota':
if builder.target_platform == 'linux':
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', '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 msvc_ver == 1700:
vs_year = '2012'
elif msvc_ver == 1600:
vs_year = '2010'
else:
raise Exception('Cannot find libprotobuf for MSVC version "' + compiler.version + '"')
if compiler.like('msvc'):
compiler.defines += ['_ALLOW_KEYWORD_MACROS']
if builder.target.platform == 'linux':
compiler.postlink += ['-lpthread', '-lrt']
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 builder.target.platform == 'linux':
if arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
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 in ['csgo', 'dota']:
binary.sources += ['smn_protobuf.cpp']
else:
binary.sources += ['smn_bitbuffer.cpp']
if sdk.name == 'csgo':
binary.sources += ['smn_protobuf.cpp']
else:
binary.sources += ['smn_bitbuffer.cpp']
if sdk.name == 'csgo':
binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
]
elif sdk.name == 'dota':
binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'network_connection.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'ai_activity.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_commonmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessage_helpers.cpp'),
]
if sdk.name == 'csgo':
binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
]
SM.binaries += builder.Add(project)

View File

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

View File

@ -44,11 +44,7 @@ public: //IRecipientFilter
bool IsReliable() const;
bool IsInitMessage() const;
int GetRecipientCount() const;
#if SOURCE_ENGINE == SE_DOTA
CEntityIndex GetRecipientIndex(int slot) const;
#else
int GetRecipientIndex(int slot) const;
#endif
public:
void Initialize(const cell_t *ptr, size_t count);
void SetToReliable(bool isreliable);
@ -83,11 +79,7 @@ inline int CellRecipientFilter::GetRecipientCount() const
return m_Size;
}
#if SOURCE_ENGINE == SE_DOTA
inline CEntityIndex CellRecipientFilter::GetRecipientIndex(int slot) const
#else
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
#endif
{
int ret;
if ((slot < 0) || (slot >= GetRecipientCount()))
@ -99,11 +91,7 @@ inline int CellRecipientFilter::GetRecipientIndex(int slot) const
ret = static_cast<int>(m_Players[slot]);
}
#if SOURCE_ENGINE == SE_DOTA
return CEntityIndex(ret);
#else
return ret;
#endif
}
inline void CellRecipientFilter::SetToInit(bool isinitmsg)

View File

@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@ -8,7 +8,7 @@
* 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
@ -37,32 +37,18 @@
#include "HalfLife2.h"
#include "logic_bridge.h"
#include "sourcemod.h"
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#else
# if SH_IMPL_VERSION >= 4
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
#endif
#include "provider.h"
#include <bridge/include/ILogger.h>
#include <amtl/am-string.h>
ChatTriggers g_ChatTriggers;
bool g_bSupressSilentFails = false;
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
ChatTriggers::ChatTriggers() : m_bWillProcessInPost(false),
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL)
{
m_PubTrigger = sm_strdup("!");
m_PrivTrigger = sm_strdup("/");
m_PubTriggerSize = 1;
m_PrivTriggerSize = 1;
m_PubTrigger = "!";
m_PrivTrigger = "/";
m_bIsChatTrigger = false;
m_bPluginIgnored = true;
#if SOURCE_ENGINE == SE_EPISODEONE
@ -72,32 +58,47 @@ ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
ChatTriggers::~ChatTriggers()
{
delete [] m_PubTrigger;
m_PubTrigger = NULL;
delete [] m_PrivTrigger;
m_PrivTrigger = NULL;
delete [] m_ArgSBackup;
m_ArgSBackup = NULL;
}
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
const char *value,
void ChatTriggers::SetChatTrigger(ChatTriggerType type, const char *value)
{
ke::AutoPtr<char[]> filtered(new char[strlen(value) + 1]);
const char *src = value;
char *dest = filtered.get();
char c;
while ((c = *src++) != '\0') {
if (c <= ' ' || c == '"' || c == '\'' || (c >= '0' && c <= '9') || c == ';' || (c >= 'A' && c <= 'Z') || c == '\\' || (c >= 'a' && c <= 'z') || c >= 0x7F) {
logger->LogError("Ignoring %s chat trigger character '%c', not in valid set: %s", (type == ChatTrigger_Private ? "silent" : "public"), c, "!#$%&()*+,-./:<=>?@[]^_`{|}~");
continue;
}
*dest++ = c;
}
*dest = '\0';
if (type == ChatTrigger_Private) {
m_PrivTrigger = filtered.get();
} else {
m_PubTrigger = filtered.get();
}
}
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
char *error,
size_t maxlength)
{
if (strcmp(key, "PublicChatTrigger") == 0)
{
delete [] m_PubTrigger;
m_PubTrigger = sm_strdup(value);
m_PubTriggerSize = strlen(m_PubTrigger);
SetChatTrigger(ChatTrigger_Public, value);
return ConfigResult_Accept;
}
else if (strcmp(key, "SilentChatTrigger") == 0)
{
delete [] m_PrivTrigger;
m_PrivTrigger = sm_strdup(value);
m_PrivTriggerSize = strlen(m_PrivTrigger);
SetChatTrigger(ChatTrigger_Private, value);
return ConfigResult_Accept;
}
else if (strcmp(key, "SilentFailSuppress") == 0)
@ -124,70 +125,43 @@ void ChatTriggers::OnSourceModAllInitialized_Post()
void ChatTriggers::OnSourceModGameInitialized()
{
m_pSayCmd = FindCommand("say");
m_pSayTeamCmd = FindCommand("say_team");
ConCommand *say_team = FindCommand("say_team");
if (m_pSayCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
CommandHook::Callback pre_hook = [this] (int client, const ICommandArgs *args) -> bool {
return this->OnSayCommand_Pre(client, args);
};
CommandHook::Callback post_hook = [this] (int client, const ICommandArgs *args) -> bool {
return this->OnSayCommand_Post(client, args);
};
if (ConCommand *say = FindCommand("say")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say, post_hook));
}
if (m_pSayTeamCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
if (ConCommand *say_team = FindCommand("say_team")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say_team, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_team, post_hook));
}
#if SOURCE_ENGINE == SE_EPISODEONE
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
if (m_bIsINS)
{
m_pSay2Cmd = FindCommand("say2");
if (m_pSay2Cmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
if (m_bIsINS) {
if (ConCommand *say2 = FindCommand("say2")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say2, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say2, post_hook));
}
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
m_pSaySquadCmd = FindCommand("say_squad");
if (m_pSaySquadCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
if (ConCommand *say_squad = FindCommand("say_squad")) {
hooks_.append(sCoreProviderImpl.AddCommandHook(say_squad, pre_hook));
hooks_.append(sCoreProviderImpl.AddPostCommandHook(say_squad, post_hook));
}
#endif
}
void ChatTriggers::OnSourceModShutdown()
{
if (m_pSayCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
}
if (m_pSayTeamCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
}
#if SOURCE_ENGINE == SE_EPISODEONE
if (m_bIsINS && m_pSay2Cmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
if (m_pSaySquadCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
#endif
hooks_.clear();
forwardsys->ReleaseForward(m_pShouldFloodBlock);
forwardsys->ReleaseForward(m_pDidFloodBlock);
@ -195,32 +169,20 @@ void ChatTriggers::OnSourceModShutdown()
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
}
#if SOURCE_ENGINE == SE_DOTA
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
bool ChatTriggers::OnSayCommand_Pre(int client, const ICommandArgs *command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{
#else
void ChatTriggers::OnSayCommand_Pre()
{
CCommand command;
#endif
int client = g_ConCmds.GetCommandClient();
m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
m_bPluginIgnored = true;
const char *args = command.ArgS();
const char *args = command->ArgS();
if (!args)
{
RETURN_META(MRES_IGNORED);
}
return false;
/* Save these off for post hook as the command data returned from the engine in older engine versions
/* Save these off for post hook as the command data returned from the engine in older engine versions
* can be NULL, despite the data still being there and valid. */
m_Arg0Backup = command.Arg(0);
m_Arg0Backup = command->Arg(0);
size_t len = strlen(args);
#if SOURCE_ENGINE == SE_EPISODEONE
@ -233,9 +195,7 @@ void ChatTriggers::OnSayCommand_Pre()
}
if (len == 0)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
}
#endif
@ -246,16 +206,14 @@ void ChatTriggers::OnSayCommand_Pre()
if (
#if SOURCE_ENGINE == SE_EPISODEONE
!m_bIsINS &&
!m_bIsINS &&
#endif
client != 0 && args[0] == '"' && args[len-1] == '"')
{
/* The server normally won't display empty say commands, but in this case it does.
* I don't think it's desired so let's block it. */
if (len <= 2)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
args++;
len--;
@ -284,20 +242,16 @@ void ChatTriggers::OnSayCommand_Pre()
if (client == 0)
{
if (CallOnClientSayCommand(client) >= Pl_Handled)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
RETURN_META(MRES_IGNORED);
return false;
}
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
/* We guarantee the client is connected */
if (!pPlayer || !pPlayer->IsConnected())
{
RETURN_META(MRES_IGNORED);
}
return false;
/* Check if we need to block this message from being sent */
if (ClientIsFlooding(client))
@ -305,33 +259,32 @@ void ChatTriggers::OnSayCommand_Pre()
char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client))
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
ke::SafeSprintf(buffer, sizeof(buffer), "You are flooding the server!");
/* :TODO: we should probably kick people who spam too much. */
char fullbuffer[192];
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
ke::SafeSprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s", buffer);
g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
m_bWasFloodedMessage = true;
RETURN_META(MRES_SUPERCEDE);
return true;
}
bool is_trigger = false;
bool is_silent = false;
/* Check for either trigger */
if (m_PubTriggerSize && strncmp(m_ArgSBackup, m_PubTrigger, m_PubTriggerSize) == 0)
{
is_trigger = true;
args = &m_ArgSBackup[m_PubTriggerSize];
}
else if (m_PrivTriggerSize && strncmp(m_ArgSBackup, m_PrivTrigger, m_PrivTriggerSize) == 0)
{
// Prefer the silent trigger in case of clashes.
if (strchr(m_PrivTrigger.chars(), m_ArgSBackup[0])) {
is_trigger = true;
is_silent = true;
args = &m_ArgSBackup[m_PrivTriggerSize];
} else if (strchr(m_PubTrigger.chars(), m_ArgSBackup[0])) {
is_trigger = true;
}
if (is_trigger) {
// Bump the args past the chat trigger - we only support single-character triggers now.
args = &m_ArgSBackup[1];
}
/**
@ -348,29 +301,17 @@ void ChatTriggers::OnSayCommand_Pre()
}
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
if (CallOnClientSayCommand(client) >= Pl_Handled)
{
RETURN_META(MRES_SUPERCEDE);
}
return true;
/* Otherwise, let the command continue */
RETURN_META(MRES_IGNORED);
return false;
}
#if SOURCE_ENGINE == SE_DOTA
void ChatTriggers::OnSayCommand_Post(const CCommandContext &context, const CCommand &command)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
#else
void ChatTriggers::OnSayCommand_Post()
#endif
bool ChatTriggers::OnSayCommand_Post(int client, const ICommandArgs *command)
{
int client = g_ConCmds.GetCommandClient();
if (m_bWillProcessInPost)
{
/* Reset this for re-entrancy */
@ -378,11 +319,7 @@ void ChatTriggers::OnSayCommand_Post()
/* Execute the cached command */
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
#if SOURCE_ENGINE == SE_DOTA
engine->ClientCommand(client, "%s", m_ToExecute);
#else
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
#endif
SetReplyTo(old);
}
@ -396,16 +333,17 @@ void ChatTriggers::OnSayCommand_Post()
m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
return false;
}
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
{
/* Extract a command. This is kind of sloppy. */
/* Extract a command. This is kind of sloppy. */
char cmd_buf[64];
size_t cmd_len = 0;
const char *inptr = args;
while (*inptr != '\0'
&& !textparsers->IsWhitespace(inptr)
while (*inptr != '\0'
&& !textparsers->IsWhitespace(inptr)
&& *inptr != '"'
&& cmd_len < sizeof(cmd_buf) - 1)
{
@ -428,12 +366,12 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
return false;
}
/* Now, prepend. Don't worry about the buffers. This will
/* Now, prepend. Don't worry about the buffers. This will
* work because the sizes are limited from earlier.
*/
char new_buf[80];
strcpy(new_buf, "sm_");
strncopy(&new_buf[3], cmd_buf, sizeof(new_buf)-3);
ke::SafeStrcpy(&new_buf[3], sizeof(new_buf)-3, cmd_buf);
/* Recheck */
if (!g_ConCmds.LookForSourceModCommand(new_buf))
@ -452,12 +390,12 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
/* Check if we need to prepend sm_ */
if (prepended)
{
len = UTIL_Format(m_ToExecute, sizeof(m_ToExecute), "sm_%s", args);
len = ke::SafeSprintf(m_ToExecute, sizeof(m_ToExecute), "sm_%s", args);
} else {
len = strncopy(m_ToExecute, args, sizeof(m_ToExecute));
len = ke::SafeStrcpy(m_ToExecute, sizeof(m_ToExecute), args);
}
} else {
strncopy(m_ToExecute, args, sizeof(m_ToExecute));
ke::SafeStrcpy(m_ToExecute, sizeof(m_ToExecute), args);
}
return true;

View File

@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@ -8,7 +8,7 @@
* 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
@ -34,9 +34,11 @@
#include "sm_globals.h"
#include "sourcemm_api.h"
#include "GameHooks.h"
#include <IGameHelpers.h>
#include <compat_wrappers.h>
#include <IForwardSys.h>
#include <amtl/am-string.h>
class ChatTriggers : public SMGlobalClass
{
@ -48,43 +50,32 @@ public: //SMGlobalClass
void OnSourceModAllInitialized_Post();
void OnSourceModGameInitialized();
void OnSourceModShutdown();
ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
char *error,
size_t maxlength);
private: //ConCommand
#if SOURCE_ENGINE == SE_DOTA
void OnSayCommand_Pre(const CCommandContext &, const CCommand &command);
void OnSayCommand_Post(const CCommandContext &, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void OnSayCommand_Pre(const CCommand &command);
void OnSayCommand_Post(const CCommand &command);
#else
void OnSayCommand_Pre();
void OnSayCommand_Post();
#endif
bool OnSayCommand_Pre(int client, const ICommandArgs *args);
bool OnSayCommand_Post(int client, const ICommandArgs *args);
public:
unsigned int GetReplyTo();
unsigned int SetReplyTo(unsigned int reply);
bool IsChatTrigger();
bool WasFloodedMessage();
private:
enum ChatTriggerType {
ChatTrigger_Public,
ChatTrigger_Private,
};
void SetChatTrigger(ChatTriggerType type, const char *value);
bool PreProcessTrigger(edict_t *pEdict, const char *args);
bool ClientIsFlooding(int client);
cell_t CallOnClientSayCommand(int client);
private:
ConCommand *m_pSayCmd;
ConCommand *m_pSayTeamCmd;
#if SOURCE_ENGINE == SE_EPISODEONE
ConCommand *m_pSay2Cmd;
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
ConCommand *m_pSaySquadCmd;
#endif
char *m_PubTrigger;
size_t m_PubTriggerSize;
char *m_PrivTrigger;
size_t m_PrivTriggerSize;
ke::Vector<ke::RefPtr<CommandHook>> hooks_;
ke::AString m_PubTrigger;
ke::AString m_PrivTrigger;
bool m_bWillProcessInPost;
bool m_bIsChatTrigger;
bool m_bWasFloodedMessage;

View File

@ -30,33 +30,25 @@
*/
#include "ConCmdManager.h"
#include "sm_srvcmds.h"
#include "sm_stringutil.h"
#include "PlayerManager.h"
#include "HalfLife2.h"
#include "ChatTriggers.h"
#include "logic_bridge.h"
#include "sourcemod.h"
#include "provider.h"
#include "command_args.h"
#include <bridge/include/IScriptManager.h>
using namespace ke;
ConCmdManager g_ConCmds;
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#else
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#endif
SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
typedef ke::LinkedList<CmdHook *> PluginHookList;
void RegisterInPlugin(CmdHook *hook);
ConCmdManager::ConCmdManager()
{
m_CmdClient = 0;
}
ConCmdManager::~ConCmdManager()
@ -66,19 +58,16 @@ ConCmdManager::~ConCmdManager()
void ConCmdManager::OnSourceModAllInitialized()
{
scripts->AddPluginsListener(this);
g_RootMenu.AddRootConsoleCommand("cmds", "List console commands", this);
SH_ADD_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &ConCmdManager::SetCommandClient), false);
rootmenu->AddRootConsoleCommand3("cmds", "List console commands", this);
}
void ConCmdManager::OnSourceModShutdown()
{
scripts->RemovePluginsListener(this);
/* All commands should already be removed by the time we're done */
SH_REMOVE_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &ConCmdManager::SetCommandClient), false);
g_RootMenu.RemoveRootConsoleCommand("cmds", this);
rootmenu->RemoveRootConsoleCommand("cmds", this);
}
void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name)
{
/* Whoa, first get its information struct */
ConCmdInfo *pInfo;
@ -113,7 +102,7 @@ void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
delete hook;
}
RemoveConCmd(pInfo, name, is_read_safe, false);
RemoveConCmd(pInfo, name, false);
}
void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
@ -132,7 +121,7 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
hook->admin->group->hooks.remove(hook);
if (hook->info->hooks.empty())
RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true, true);
RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true);
iter = pList->erase(iter);
delete hook;
@ -141,28 +130,13 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
delete pList;
}
#if SOURCE_ENGINE == SE_DOTA
void CommandCallback(const CCommandContext &context, const CCommand &command)
void CommandCallback(DISPATCH_ARGS)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void CommandCallback(const CCommand &command)
{
#else
void CommandCallback()
{
CCommand command;
#endif
DISPATCH_PROLOGUE;
EngineArgs args(command);
g_HL2.PushCommandStack(&command);
g_ConCmds.InternalDispatch(command);
g_HL2.PopCommandStack();
}
void ConCmdManager::SetCommandClient(int client)
{
m_CmdClient = client + 1;
AutoEnterCommand autoEnterCommand(&args);
g_ConCmds.InternalDispatch(sCoreProviderImpl.CommandClient(), &args);
}
ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
@ -218,6 +192,7 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
hook->pf->PushCell(args);
cell_t tempres = result;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
{
if (tempres > result)
@ -230,15 +205,13 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
return (ResultType)result;
}
void ConCmdManager::InternalDispatch(const CCommand &command)
bool ConCmdManager::InternalDispatch(int client, const ICommandArgs *args)
{
int client = m_CmdClient;
if (client)
{
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer || !pPlayer->IsConnected())
return;
return false;
}
/**
@ -256,11 +229,11 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
* case-insensitive. We can't even use our sortedness.
*/
if (client == 0 && !engine->IsDedicatedServer())
return;
return false;
ConCmdList::iterator item = FindInList(cmd);
if (item == m_CmdList.end())
return;
return false;
pInfo = *item;
}
@ -270,10 +243,10 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
* "nicer" when we expose explicit say hooks.
*/
if (g_ChatTriggers.WasFloodedMessage())
return;
return false;
cell_t result = Pl_Continue;
int args = command.ArgC() - 1;
int argc = args->ArgC() - 1;
// On a listen server, sometimes the server host's client index can be set
// as 0. So index 1 is passed to the command callback to correct this
@ -309,7 +282,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
hook->pf->PushCell(realClient);
}
hook->pf->PushCell(args);
hook->pf->PushCell(argc);
cell_t tempres = result;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
@ -322,11 +295,9 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
}
if (result >= Pl_Handled)
{
if (!pInfo->sourceMod)
RETURN_META(MRES_SUPERCEDE);
return;
}
return !pInfo->sourceMod;
return false;
}
bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
@ -346,20 +317,20 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
{
UTIL_Format(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();
if (replyto == SM_REPLY_CONSOLE)
{
char fullbuffer[192];
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer);
ke::SafeSprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer);
pPlayer->PrintToConsole(fullbuffer);
}
else if (replyto == SM_REPLY_CHAT)
{
char fullbuffer[192];
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.", buffer);
ke::SafeSprintf(fullbuffer, sizeof(fullbuffer), "[SM] %s.", buffer);
g_HL2.TextMsg(client, HUD_PRINTTALK, fullbuffer);
}
@ -371,9 +342,10 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
const char *group,
int adminflags,
const char *description,
int flags)
int flags,
IPlugin *pPlugin)
{
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
if (!pInfo)
return false;
@ -385,7 +357,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
return false;
i->value = new CommandGroup();
}
Ref<CommandGroup> cmdgroup = i->value;
RefPtr<CommandGroup> cmdgroup = i->value;
CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description);
pHook->admin = new AdminCmdInfo(cmdgroup, adminflags);
@ -417,10 +389,11 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
const char *name,
const char *description,
int flags)
int flags,
IPlugin *pPlugin)
{
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags, pPlugin);
if (!pInfo)
return false;
@ -517,7 +490,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
if (!r.found())
return;
Ref<CommandGroup> group(r->value);
RefPtr<CommandGroup> group(r->value);
for (PluginHookList::iterator iter = group->hooks.begin(); iter != group->hooks.end(); iter++)
{
@ -531,7 +504,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
}
}
void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_read_safe, bool untrack)
void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool untrack)
{
/* Remove from the trie */
m_Cmds.remove(name);
@ -554,15 +527,8 @@ void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_rea
}
else
{
if (is_read_safe)
{
/* Remove the external hook */
SH_REMOVE_HOOK(ConCommand, Dispatch, info->pCmd, SH_STATIC(CommandCallback), false);
}
if (untrack)
{
UntrackConCommandBase(info->pCmd, this);
}
}
}
@ -591,7 +557,7 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
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;
if (!m_Cmds.retrieve(name, &pInfo))
@ -616,12 +582,17 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
char *new_name = sm_strdup(name);
char *new_help = sm_strdup(description);
pCmd = new ConCommand(new_name, CommandCallback, new_help, flags);
pInfo->pPlugin = pPlugin;
pInfo->sourceMod = true;
}
else
{
TrackConCommandBase(pCmd, this);
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CommandCallback), false);
CommandHook::Callback callback = [this] (int client, const ICommandArgs *args) -> bool {
AutoEnterCommand autoEnterCommand(args);
return this->InternalDispatch(client, args);
};
pInfo->sh_hook = sCoreProviderImpl.AddCommandHook(pCmd, callback);
}
pInfo->pCmd = pCmd;
@ -633,17 +604,17 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
return pInfo;
}
void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
{
if (command.ArgC() >= 3)
if (command->ArgC() >= 3)
{
const char *text = command.Arg(2);
const char *text = command->Arg(2);
IPlugin *pPlugin = scripts->FindPluginByConsoleArg(text);
if (!pPlugin)
{
g_RootMenu.ConsolePrint("[SM] Plugin \"%s\" was not found.", text);
UTIL_ConsolePrint("[SM] Plugin \"%s\" was not found.", text);
return;
}
@ -653,20 +624,20 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
PluginHookList *pList;
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
UTIL_ConsolePrint("[SM] No commands found for: %s", plname);
return;
}
if (pList->empty())
{
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
UTIL_ConsolePrint("[SM] No commands found for: %s", plname);
return;
}
const char *type = NULL;
const char *name;
const char *help;
g_RootMenu.ConsolePrint("[SM] Listing commands for: %s", plname);
g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
UTIL_ConsolePrint("[SM] Listing commands for: %s", plname);
UTIL_ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
for (PluginHookList::iterator iter = pList->begin(); iter != pList->end(); iter++)
{
CmdHook *hook = *iter;
@ -680,11 +651,11 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
help = hook->helptext.chars();
else
help = hook->info->pCmd->GetHelpText();
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
UTIL_ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
}
return;
}
g_RootMenu.ConsolePrint("[SM] Usage: sm cmds <plugin #>");
UTIL_ConsolePrint("[SM] Usage: sm cmds <plugin #>");
}

View File

@ -40,6 +40,8 @@
#include <IRootConsoleMenu.h>
#include <IAdminSystem.h>
#include "concmd_cleaner.h"
#include "GameHooks.h"
#include <am-autoptr.h>
#include <sm_stringhashmap.h>
#include <am-utility.h>
#include <am-inlinelist.h>
@ -58,13 +60,13 @@ struct CommandGroup : public ke::Refcounted<CommandGroup>
struct AdminCmdInfo
{
AdminCmdInfo(const ke::Ref<CommandGroup> &group, FlagBits flags)
AdminCmdInfo(const ke::RefPtr<CommandGroup> &group, FlagBits flags)
: group(group),
flags(flags),
eflags(0)
{
}
ke::Ref<CommandGroup> group;
ke::RefPtr<CommandGroup> group;
FlagBits flags; /* default flags */
FlagBits eflags; /* effective flags */
};
@ -97,14 +99,17 @@ struct ConCmdInfo
{
ConCmdInfo()
{
pPlugin = nullptr;
sourceMod = false;
pCmd = NULL;
pCmd = nullptr;
eflags = 0;
}
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
ConCommand *pCmd; /**< Pointer to the command itself */
CmdHookList hooks; /**< Hook list */
FlagBits eflags; /**< Effective admin flags */
ke::RefPtr<CommandHook> sh_hook; /**< SourceHook hook, if any. */
IPlugin *pPlugin; /**< Owning plugin handle. */
};
typedef List<ConCmdInfo *> ConCmdList;
@ -115,13 +120,7 @@ class ConCmdManager :
public IPluginsListener,
public IConCommandTracker
{
#if SOURCE_ENGINE == SE_DOTA
friend void CommandCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
friend void CommandCallback(const CCommand &command);
#else
friend void CommandCallback();
#endif
friend void CommandCallback(DISPATCH_ARGS);
public:
ConCmdManager();
~ConCmdManager();
@ -131,28 +130,28 @@ public: //SMGlobalClass
public: //IPluginsListener
void OnPluginDestroyed(IPlugin *plugin);
public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
public: //IConCommandTracker
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override;
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,
const char *name,
const char *group,
int adminflags,
const char *description,
int flags);
int flags,
IPlugin *pPlugin);
ResultType DispatchClientCommand(int client, const char *cmd, int args, ResultType type);
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool LookForSourceModCommand(const char *cmd);
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
private:
void InternalDispatch(const CCommand &command);
bool InternalDispatch(int client, const ICommandArgs *args);
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
void SetCommandClient(int client);
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags, IPlugin *pPlugin);
void AddToCmdList(ConCmdInfo *info);
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack);
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool untrack);
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
// Case insensitive
@ -161,21 +160,16 @@ private:
// Case sensitive
ConCmdInfo *FindInTrie(const char *name);
public:
inline int GetCommandClient()
{
return m_CmdClient;
}
inline const List<ConCmdInfo *> & GetCommandList()
{
return m_CmdList;
}
private:
typedef StringHashMap<ke::Ref<CommandGroup> > GroupMap;
typedef StringHashMap<ke::RefPtr<CommandGroup> > GroupMap;
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
GroupMap m_CmdGrps; /* command group map */
ConCmdList m_CmdList; /* command list */
int m_CmdClient; /* current client */
};
extern ConCmdManager g_ConCmds;

View File

@ -29,28 +29,16 @@
#include "ConVarManager.h"
#include "HalfLife2.h"
#include "sm_srvcmds.h"
#include "sm_stringutil.h"
#include <sh_vector.h>
#include <sm_namehashset.h>
#include "logic_bridge.h"
#include "sourcemod.h"
#include "provider.h"
#include <bridge/include/IScriptManager.h>
ConVarManager g_ConVarManager;
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
#else
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *);
#endif
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
#elif SOURCE_ENGINE != SE_DARKMESSIAH
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
#endif
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
typedef List<const ConVar *> ConVarList;
NameHashSet<ConVarInfo *> convar_cache;
@ -89,7 +77,7 @@ public:
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
ConVarManager::ConVarManager() : m_ConVarType(0)
{
}
@ -112,29 +100,12 @@ void ConVarManager::OnSourceModStartup(bool late)
void ConVarManager::OnSourceModAllInitialized()
{
/**
* Episode 2 has this function by default, but the older versions do not.
*/
#if SOURCE_ENGINE == SE_EPISODEONE
if (g_SMAPI->GetGameDLLVersion() >= 6)
{
SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
m_bIsDLLQueryHooked = true;
}
#endif
g_Players.AddClientListener(this);
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
#else
SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
#endif
scripts->AddPluginsListener(this);
/* Add the 'convars' option to the 'sm' console command */
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
rootmenu->AddRootConsoleCommand3("cvars", "View convars created by a plugin", this);
}
void ConVarManager::OnSourceModShutdown()
@ -180,32 +151,10 @@ void ConVarManager::OnSourceModShutdown()
}
convar_cache.clear();
#if SOURCE_ENGINE != SE_DARKMESSIAH
/* Unhook things */
if (m_bIsDLLQueryHooked)
{
SH_REMOVE_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
m_bIsDLLQueryHooked = false;
}
else if (m_bIsVSPQueryHooked)
{
#if SOURCE_ENGINE != SE_DOTA
SH_REMOVE_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
#endif
m_bIsVSPQueryHooked = false;
}
#endif
g_Players.RemoveClientListener(this);
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
#else
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
#endif
/* Remove the 'convars' option from the 'sm' console command */
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
rootmenu->RemoveRootConsoleCommand("cvars", this);
scripts->RemovePluginsListener(this);
@ -213,45 +162,12 @@ void ConVarManager::OnSourceModShutdown()
handlesys->RemoveType(m_ConVarType, g_pCoreIdent);
}
/**
* Orange Box will never use this.
*/
void ConVarManager::OnSourceModVSPReceived()
{
/**
* Don't bother if the DLL is already hooked.
*/
if (m_bIsDLLQueryHooked)
{
return;
}
/* For later MM:S versions, use the updated API, since it's cleaner. */
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
int engine = g_SMAPI->GetSourceEngineBuild();
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
{
return;
}
#else
if (g_HL2.IsOriginalEngine() || vsp_version < 2)
{
return;
}
#endif
#if SOURCE_ENGINE != SE_DARKMESSIAH && SOURCE_ENGINE != SE_DOTA
SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
m_bIsVSPQueryHooked = true;
#endif
}
bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
{
return convar_cache.retrieve(name, pVar);
}
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name)
{
/* Only check convars that have not been created by SourceMod's core */
ConVarInfo *pInfo;
@ -340,19 +256,19 @@ bool ConVarManager::GetHandleApproxSize(HandleType_t type, void *object, unsigne
return true;
}
void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
void ConVarManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
{
int argcount = command.ArgC();
int argcount = command->ArgC();
if (argcount >= 3)
{
bool wantReset = false;
/* Get plugin index that was passed */
const char *arg = command.Arg(2);
const char *arg = command->Arg(2);
if (argcount >= 4 && strcmp(arg, "reset") == 0)
{
wantReset = true;
arg = command.Arg(3);
arg = command->Arg(3);
}
/* Get plugin object */
@ -360,7 +276,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
if (!plugin)
{
g_RootMenu.ConsolePrint("[SM] Plugin \"%s\" was not found.", arg);
UTIL_ConsolePrint("[SM] Plugin \"%s\" was not found.", arg);
return;
}
@ -374,14 +290,14 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
/* If no convar list... */
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
{
g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname);
UTIL_ConsolePrint("[SM] No convars found for: %s", plname);
return;
}
if (!wantReset)
{
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
UTIL_ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
UTIL_ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
}
/* Iterate convar list and display/reset each one */
@ -390,7 +306,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter);
if (!wantReset)
{
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
UTIL_ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
} else {
pConVar->Revert();
}
@ -398,14 +314,14 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
if (wantReset)
{
g_RootMenu.ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname);
UTIL_ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname);
}
return;
}
/* Display usage of subcommand */
g_RootMenu.ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>");
UTIL_ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>");
}
Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *description, int flags, bool hasMin, float min, bool hasMax, float max)
@ -625,35 +541,13 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
{
QueryCvarCookie_t cookie = 0;
#if SOURCE_ENGINE != SE_DARKMESSIAH
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
if (m_bIsDLLQueryHooked)
{
#if SOURCE_ENGINE == SE_DOTA
cookie = engine->StartQueryCvarValue(CEntityIndex(IndexOfEdict(pPlayer)), name);
#else
cookie = engine->StartQueryCvarValue(pPlayer, name);
#endif
}
#if SOURCE_ENGINE != SE_DOTA
else if (m_bIsVSPQueryHooked)
{
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
}
#endif
else
{
return InvalidQueryCvarCookie;
}
QueryCvarCookie_t cookie = sCoreProviderImpl.QueryClientConVar(IndexOfEdict(pPlayer), name);
if (pCallback != NULL)
{
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
m_ConVarQueries.push_back(query);
}
#endif
return cookie;
}
@ -696,11 +590,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
}
}
#if SOURCE_ENGINE >= SE_ORANGEBOX
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
#else
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
#endif
{
/* If the values are the same, exit early in order to not trigger callbacks */
if (strcmp(pConVar->GetString(), oldValue) == 0)
@ -720,16 +610,8 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
if (pInfo->changeListeners.size() != 0)
{
for (List<IConVarChangeListener *>::iterator i = pInfo->changeListeners.begin();
i != pInfo->changeListeners.end();
i++)
{
#if SOURCE_ENGINE >= SE_ORANGEBOX
for (auto i = pInfo->changeListeners.begin(); i != pInfo->changeListeners.end(); i++)
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
#else
(*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
#endif
}
}
if (pForward != NULL)
@ -746,23 +628,16 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
bool ConVarManager::IsQueryingSupported()
{
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
return sCoreProviderImpl.IsClientConVarQueryingSupported();
}
#if SOURCE_ENGINE != SE_DARKMESSIAH
#if SOURCE_ENGINE == SE_DOTA
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
#else
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
#endif // SE_DOTA
void ConVarManager::OnClientQueryFinished(QueryCvarCookie_t cookie,
int client,
EQueryCvarValueStatus result,
const char *cvarName,
const char *cvarValue)
{
#if SOURCE_ENGINE == SE_CSGO
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
{
return;
}
#endif
IPluginFunction *pCallback = NULL;
cell_t value = 0;
List<ConVarQuery>::iterator iter;
@ -783,11 +658,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
cell_t ret;
pCallback->PushCell(cookie);
#if SOURCE_ENGINE == SE_DOTA
pCallback->PushCell(player.Get());
#else
pCallback->PushCell(IndexOfEdict(pPlayer));
#endif
pCallback->PushCell(client);
pCallback->PushCell(result);
pCallback->PushString(cvarName);

View File

@ -43,11 +43,7 @@
#include <compat_wrappers.h>
#include "concmd_cleaner.h"
#include "PlayerManager.h"
#if SOURCE_ENGINE == SE_DARKMESSIAH
class EQueryCvarValueStatus;
typedef int QueryCvarCookie_t;
#endif
#include <sm_stringhashmap.h>
using namespace SourceHook;
@ -72,6 +68,10 @@ struct ConVarInfo
{
return strcmp(name, info->pVar->GetName()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
/**
@ -100,16 +100,15 @@ public: // SMGlobalClass
void OnSourceModStartup(bool late);
void OnSourceModAllInitialized();
void OnSourceModShutdown();
void OnSourceModVSPReceived();
public: // IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
public: //IConCommandTracker
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override;
public: //IClientListener
void OnClientDisconnected(int client);
public:
@ -147,37 +146,26 @@ public:
HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar);
// Called via game hooks.
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
#if SOURCE_ENGINE != SE_DARKMESSIAH
void OnClientQueryFinished(
QueryCvarCookie_t cookie,
int client,
EQueryCvarValueStatus result,
const char *cvarName,
const char *cvarValue);
#endif
private:
/**
* Adds a convar to a plugin's list.
*/
static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar);
/**
* Static callback that Valve's ConVar object executes when the convar's value changes.
*/
#if SOURCE_ENGINE >= SE_ORANGEBOX
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
#else
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
#endif
/**
* Callback for when StartQueryCvarValue() has finished.
*/
#if SOURCE_ENGINE == SE_DOTA
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue);
#elif SOURCE_ENGINE != SE_DARKMESSIAH
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue);
#endif
private:
HandleType_t m_ConVarType;
List<ConVarInfo *> m_ConVars;
List<ConVarQuery> m_ConVarQueries;
bool m_bIsDLLQueryHooked;
bool m_bIsVSPQueryHooked;
};
extern ConVarManager g_ConVarManager;

View File

@ -50,7 +50,10 @@
#include "HalfLife2.h"
#include "ConCommandBaseIterator.h"
#include "logic_bridge.h"
#include "command_args.h"
#include "provider.h"
#include <am-utility.h>
#include <bridge/include/ILogger.h>
#if defined PLATFORM_POSIX
# include <dlfcn.h>
@ -59,26 +62,12 @@
# include <unistd.h>
#endif
#if SH_IMPL_VERSION >= 5
# if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
# elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
# else
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
# endif
#else
# if SH_IMPL_VERSION >= 4
extern int __SourceHook_FHVPAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>,bool);
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
# endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#endif
#if SH_IMPL_VERSION >= 4
class GenericCommandHooker : public IConCommandLinkListener
{
struct HackInfo
@ -134,18 +123,16 @@ class GenericCommandHooker : public IConCommandLinkListener
}
}
# if SOURCE_ENGINE == SE_DOTA
void Dispatch(const CCommandContext &context, const CCommand& args)
# elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void Dispatch(const CCommand& args)
# else
#else
void Dispatch()
# endif
#endif
{
cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand)
# if SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
, args
# endif
#endif
);
if (res >= Pl_Handled)
RETURN_META(MRES_SUPERCEDE);
@ -262,308 +249,6 @@ public:
}
};
/**
* END DVP HOOK VERSION
*/
#else /* SH_IMPL_VERSION >= 4 */
/**
* BEGIN ENGINE DETOUR VERSION
*/
# include <jit/jit_helpers.h>
# include <jit/x86/x86_macros.h>
class GenericCommandHooker
{
struct Patch
{
Patch() : applied(false)
{
}
bool applied;
void *base;
unsigned char search[16];
size_t search_len;
size_t offset;
size_t saveat;
int regparam;
void *detour;
};
Patch ces;
Patch cgc;
public:
static void DelayedActivation(void *inparam)
{
GenericCommandHooker *cdtrs = reinterpret_cast<GenericCommandHooker*>(inparam);
/* Safe to re-enter because the frame queue is lock+swapped. */
if ((!cdtrs->ces.applied || !cdtrs->cgc.applied) &&
g_HL2.PeekCommandStack() != NULL)
{
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, cdtrs);
return;
}
if (!cdtrs->ces.applied)
cdtrs->ApplyPatch(&cdtrs->ces);
if (!cdtrs->cgc.applied)
cdtrs->ApplyPatch(&cdtrs->cgc);
}
bool Enable()
{
const char *platform = NULL;
# if defined(PLATFORM_WINDOWS)
platform = "Windows";
# else
void *addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
Dl_info info;
if (!dladdr(addrInBase, &info))
{
g_Logger.LogError("Command filter could not find engine name");
return false;
}
if (strstr(info.dli_fname, "engine_i486"))
{
platform = "Linux_486";
}
else if (strstr(info.dli_fname, "engine_i686"))
{
platform = "Linux_686";
}
else if (strstr(info.dli_fname, "engine_amd"))
{
platform = "Linux_AMD";
}
else
{
g_Logger.LogError("Command filter could not determine engine (%s)", info.dli_fname);
return false;
}
# endif
if (!PrepPatch("Cmd_ExecuteString", "CES", platform, &ces))
return false;
if (!PrepPatch("CGameClient::ExecuteString", "CGC", platform, &cgc))
return false;
if (g_HL2.PeekCommandStack() != NULL)
{
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, this);
return true;
}
ApplyPatch(&ces);
ApplyPatch(&cgc);
return true;
}
void Disable()
{
UndoPatch(&ces);
UndoPatch(&cgc);
}
private:
# if !defined PLATFORM_WINDOWS
# define PAGE_READWRITE PROT_READ|PROT_WRITE
# define PAGE_EXECUTE_READ PROT_READ|PROT_EXEC
static inline uintptr_t AddrToPage(uintptr_t address)
{
return (address & ~(uintptr_t(sysconf(_SC_PAGE_SIZE) - 1)));
}
# endif
void Protect(void *addr, size_t length, int prot)
{
# if defined PLATFORM_WINDOWS
DWORD ignore;
VirtualProtect(addr, length, prot, &ignore);
# else
uintptr_t startPage = AddrToPage(uintptr_t(addr));
length += (uintptr_t(addr) - startPage);
mprotect((void*)startPage, length, prot);
# endif
}
void UndoPatch(Patch *patch)
{
if (!patch->applied || patch->detour == NULL)
return;
g_pSourcePawn->FreePageMemory(patch->detour);
unsigned char *source = (unsigned char *)patch->base + patch->offset;
Protect(source, patch->search_len, PAGE_READWRITE);
for (size_t i = 0; i < patch->search_len; i++)
source[i] = patch->search[i];
Protect(source, patch->search_len, PAGE_EXECUTE_READ);
}
void ApplyPatch(Patch *patch)
{
assert(!patch->applied);
size_t length = 0;
void *callback = (void*)&ConsoleDetours::Dispatch;
/* Bogus assignment to make compiler is doing the right thing. */
patch->detour = callback;
/* Assemgle the detour. */
JitWriter writer;
writer.outbase = NULL;
writer.outptr = NULL;
do
{
/* Need a specific register, or value on stack? */
if (patch->regparam != -1)
IA32_Push_Reg(&writer, patch->regparam);
/* Call real function. */
IA32_Write_Jump32_Abs(&writer, IA32_Call_Imm32(&writer, 0), callback);
/* Restore stack. */
if (patch->regparam != -1)
IA32_Pop_Reg(&writer, patch->regparam);
/* Copy any saved bytes */
if (patch->saveat)
{
for (size_t i = patch->saveat; i < patch->search_len; i++)
{
writer.write_ubyte(patch->search[i]);
}
}
/* Jump back to the caller. */
unsigned char *target = (unsigned char *)patch->base + patch->offset + patch->search_len;
IA32_Jump_Imm32_Abs(&writer, target);
/* Assemble, if we can. */
if (writer.outbase == NULL)
{
length = writer.outptr - writer.outbase;
patch->detour = g_pSourcePawn->AllocatePageMemory(length);
if (patch->detour == NULL)
{
g_Logger.LogError("Ran out of memory!");
return;
}
g_pSourcePawn->SetReadWrite(patch->detour);
writer.outbase = (jitcode_t)patch->detour;
writer.outptr = writer.outbase;
}
else
{
break;
}
} while (true);
g_pSourcePawn->SetReadExecute(patch->detour);
unsigned char *source = (unsigned char *)patch->base + patch->offset;
Protect(source, 6, PAGE_READWRITE);
source[0] = 0xFF;
source[1] = 0x25;
*(void **)&source[2] = &patch->detour;
Protect(source, 6, PAGE_EXECUTE_READ);
patch->applied = true;
}
bool PrepPatch(const char *signature, const char *name, const char *platform, Patch *patch)
{
/* Get the base address of the function. */
if (!g_pGameConf->GetMemSig(signature, &patch->base) || patch->base == NULL)
{
g_Logger.LogError("Command filter could not find signature: %s", signature);
return false;
}
const char *value;
char keyname[255];
/* Get the verification bytes that will be written over. */
UTIL_Format(keyname, sizeof(keyname), "%s_Patch_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
{
g_Logger.LogError("Command filter could not find key: %s", keyname);
return false;
}
patch->search_len = UTIL_DecodeHexString(patch->search, sizeof(patch->search), value);
if (patch->search_len < 6)
{
g_Logger.LogError("Error decoding %s value, or not long enough", keyname);
return false;
}
/* Get the offset into the function. */
UTIL_Format(keyname, sizeof(keyname), "%s_Offset_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
{
g_Logger.LogError("Command filter could not find key: %s", keyname);
return false;
}
patch->offset = atoi(value);
if (patch->offset > 20000)
{
g_Logger.LogError("Command filter %s value is bogus", keyname);
return false;
}
/* Get the number of bytes to save from what was written over. */
patch->saveat = 0;
UTIL_Format(keyname, sizeof(keyname), "%s_Save_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
{
patch->saveat = atoi(value);
if (patch->saveat >= patch->search_len)
{
g_Logger.LogError("Command filter %s value is too large", keyname);
return false;
}
}
/* Get register for parameter, if any. */
patch->regparam = -1;
UTIL_Format(keyname, sizeof(keyname), "%s_Reg_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
{
patch->regparam = atoi(value);
}
/* Everything loaded from gamedata, make sure the patch will succeed. */
unsigned char *address = (unsigned char *)patch->base + patch->offset;
for (size_t i = 0; i < patch->search_len; i++)
{
if (address[i] != patch->search[i])
{
g_Logger.LogError("Command filter %s has changed (byte %x is not %x sub-offset %d)",
name, address[i], patch->search[i], i);
return false;
}
}
return true;
}
};
static bool dummy_hook_set = false;
void DummyHook()
{
if (dummy_hook_set)
{
dummy_hook_set = false;
RETURN_META(MRES_SUPERCEDE);
}
}
#endif
/**
* BEGIN THE ACTUALLY GENERIC CODE.
*/
@ -622,13 +307,13 @@ bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
}
else
{
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
IChangeableForward *forward;
if (!m_Listeners.retrieve(str, &forward))
if (!m_Listeners.retrieve(str.get(), &forward))
{
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
m_Listeners.insert(str, forward);
m_Listeners.insert(str.get(), forward);
}
forward->AddFunction(fun);
}
@ -644,18 +329,18 @@ bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
}
else
{
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
ke::AutoPtr<char[]> str(UTIL_ToLowerCase(command));
IChangeableForward *forward;
if (!m_Listeners.retrieve(str, &forward))
if (!m_Listeners.retrieve(str.get(), &forward))
return false;
return forward->RemoveFunction(fun);
}
}
cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
cell_t ConsoleDetours::InternalDispatch(int client, const ICommandArgs *args)
{
char name[255];
const char *realname = args.Arg(0);
const char *realname = args->Arg(0);
size_t len = strlen(realname);
// Disallow command strings that are too long, for now.
@ -674,7 +359,7 @@ cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
cell_t result = Pl_Continue;
m_pForward->PushCell(client);
m_pForward->PushString(name);
m_pForward->PushCell(args.ArgC() - 1);
m_pForward->PushCell(args->ArgC() - 1);
m_pForward->Execute(&result, NULL);
/* Don't let plugins block this. */
@ -693,7 +378,7 @@ cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
cell_t result2 = Pl_Continue;
forward->PushCell(client);
forward->PushString(name);
forward->PushCell(args.ArgC() - 1);
forward->PushCell(args->ArgC() - 1);
forward->Execute(&result2, NULL);
if (result2 > result)
@ -713,27 +398,12 @@ cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
{
CCommand args;
#endif
g_HL2.PushCommandStack(&args);
cell_t res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), args);
g_HL2.PopCommandStack();
#if SH_IMPL_VERSION < 4
if (res >= Pl_Handled)
EngineArgs cargs(args);
cell_t res;
{
/* See bug 4020 - we can't optimize this because looking at the vtable
* is probably more expensive, since there's no SH_GET_ORIG_VFNPTR_ENTRY.
*/
SH_ADD_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false);
dummy_hook_set = true;
pBase->Dispatch();
SH_REMOVE_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false);
AutoEnterCommand autoEnterCommand(&cargs);
res = g_ConsoleDetours.InternalDispatch(sCoreProviderImpl.CommandClient(), &cargs);
}
else
{
/* Make sure the command gets invoked. See bug 4019 on making this better. */
pBase->Dispatch();
}
#endif
return res;
}

View File

@ -36,6 +36,10 @@
#include <IForwardSys.h>
#include <sm_stringhashmap.h>
namespace SourceMod {
class ICommandArgs;
} // namespace SourceMod
class ConsoleDetours :
public SMGlobalClass,
public IFeatureProvider
@ -54,7 +58,7 @@ public:
bool AddListener(IPluginFunction *fun, const char *command);
bool RemoveListener(IPluginFunction *fun, const char *command);
private:
cell_t InternalDispatch(int client, const CCommand& args);
cell_t InternalDispatch(int client, const SourceMod::ICommandArgs *args);
#if SOURCE_ENGINE >= SE_ORANGEBOX
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
#else

View File

@ -33,13 +33,20 @@
#include "CoreConfig.h"
#include "sourcemod.h"
#include "sourcemm_api.h"
#include "sm_srvcmds.h"
#include "sm_stringutil.h"
#include "LibrarySys.h"
#include "Logger.h"
#include "frame_hooks.h"
#include "logic_bridge.h"
#include "compat_wrappers.h"
#include <sourcemod_version.h>
#include <amtl/os/am-path.h>
#include <amtl/os/am-fsutil.h>
#include <sh_list.h>
#include <IForwardSys.h>
#include <bridge/include/IScriptManager.h>
#include <bridge/include/ILogger.h>
using namespace SourceHook;
#ifdef PLATFORM_WINDOWS
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
@ -60,22 +67,11 @@ ConVar *g_ServerCfgFile = NULL;
void CheckAndFinalizeConfigs();
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
void Hook_ExecDispatchPre(const CCommandContext &context, const CCommand &cmd)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
void Hook_ExecDispatchPre(const CCommand &cmd)
#elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
void Hook_ExecDispatchPre()
#else
# if SH_IMPL_VERSION >= 4
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
void Hook_ExecDispatchPre()
#endif
{
@ -91,9 +87,7 @@ void Hook_ExecDispatchPre()
}
}
#if SOURCE_ENGINE == SE_DOTA
void Hook_ExecDispatchPost(const CCommandContext &context, const CCommand &cmd)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void Hook_ExecDispatchPost(const CCommand &cmd)
#else
void Hook_ExecDispatchPost()
@ -117,7 +111,7 @@ void CheckAndFinalizeConfigs()
void CoreConfig::OnSourceModAllInitialized()
{
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
rootmenu->AddRootConsoleCommand3("config", "Set core configuration options", this);
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
@ -133,7 +127,7 @@ CoreConfig::~CoreConfig()
void CoreConfig::OnSourceModShutdown()
{
g_RootMenu.RemoveRootConsoleCommand("config", this);
rootmenu->RemoveRootConsoleCommand("config", this);
forwardsys->ReleaseForward(g_pOnServerCfg);
forwardsys->ReleaseForward(g_pOnConfigsExecuted);
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered);
@ -183,44 +177,45 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName)
g_bGotTrigger = false;
}
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
void CoreConfig::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
{
int argcount = command.ArgC();
int argcount = command->ArgC();
if (argcount >= 4)
{
const char *option = command.Arg(2);
const char *value = command.Arg(3);
const char *option = command->Arg(2);
const char *value = command->Arg(3);
char error[255];
ConfigResult res = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error));
if (res == ConfigResult_Reject)
{
g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\". (%s)", option, value, error);
} else if (res == ConfigResult_Ignore) {
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
UTIL_ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\". (%s)", option, value, error);
} else {
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" successfully set to \"%s\".", option, value);
if (res == ConfigResult_Ignore) {
UTIL_ConsolePrint("[SM] WARNING: Config option \"%s\" is not registered.", option);
}
UTIL_ConsolePrint("[SM] Config option \"%s\" set to \"%s\".", option, value);
}
return;
} else if (argcount >= 3) {
const char *option = command.Arg(2);
const char *option = command->Arg(2);
const char *value = GetCoreConfigValue(option);
if (value == NULL)
{
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
UTIL_ConsolePrint("[SM] No such config option \"%s\" exists.", option);
} else {
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" is set to \"%s\".", option, value);
UTIL_ConsolePrint("[SM] Config option \"%s\" is set to \"%s\".", option, value);
}
return;
}
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> [value]");
UTIL_ConsolePrint("[SM] Usage: sm config <option> [value]");
}
void CoreConfig::Initialize()
@ -237,7 +232,7 @@ void CoreConfig::Initialize()
*/
if (corecfg)
{
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
ke::path::Format(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
}
else
{
@ -246,11 +241,11 @@ void CoreConfig::Initialize()
/* Format path to config file */
if (basepath)
{
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s/%s", g_SourceMod.GetGamePath(), basepath, "configs/core.cfg");
ke::path::Format(filePath, sizeof(filePath), "%s/%s/%s", g_SourceMod.GetGamePath(), basepath, "configs/core.cfg");
}
else
{
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), sm_corecfgfile.GetDefault());
ke::path::Format(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), sm_corecfgfile.GetDefault());
}
}
@ -282,7 +277,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key,
ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value, ConfigSource source, char *error, size_t maxlength)
{
ConfigResult result;
ConfigResult result = ConfigResult_Ignore;
/* Notify! */
SMGlobalClass *pBase = SMGlobalClass::head;
@ -290,7 +285,7 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
{
if ((result = pBase->OnSourceModConfigChanged(option, value, source, error, maxlength)) != ConfigResult_Ignore)
{
return result;
break;
}
pBase = pBase->m_pGlobalClassNext;
}
@ -298,7 +293,7 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
ke::AString vstr(value);
m_KeyValues.replace(option, ke::Move(vstr));
return ConfigResult_Ignore;
return result;
}
const char *CoreConfig::GetCoreConfigValue(const char *key)
@ -341,12 +336,12 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "cfg/%s", folder);
if (!g_LibSys.IsPathDirectory(path))
if (!ke::file::IsDirectory(path))
{
char *cur_ptr = path;
size_t len;
g_LibSys.PathFormat(path, sizeof(path), "%s", folder);
ke::path::Format(path, sizeof(path), "%s", folder);
len = g_SourceMod.BuildPath(Path_Game, build, sizeof(build), "cfg");
do
@ -367,14 +362,12 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
{
next_ptr = NULL;
}
len += g_LibSys.PathFormat(&build[len],
len += ke::path::Format(&build[len],
sizeof(build)-len,
"/%s",
cur_ptr);
if (!g_LibSys.CreateFolder(build))
{
if (!ke::file::CreateDirectory(build))
break;
}
cur_ptr = next_ptr;
} while (cur_ptr);
}
@ -386,13 +379,13 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
if (cfg->folder.size())
{
g_LibSys.PathFormat(local,
sizeof(local),
ke::path::Format(local,
sizeof(local),
"%s/%s.cfg",
cfg->folder.c_str(),
cfg->autocfg.c_str());
} else {
g_LibSys.PathFormat(local,
ke::path::Format(local,
sizeof(local),
"%s.cfg",
cfg->autocfg.c_str());
@ -400,7 +393,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
g_SourceMod.BuildPath(Path_Game, file, sizeof(file), "cfg/%s", local);
bool file_exists = g_LibSys.IsPathFile(file);
bool file_exists = ke::file::IsFile(file);
if (!file_exists && will_create)
{
List<const ConVar *> *convars = NULL;
@ -419,8 +412,11 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
for (iter = convars->begin(); iter != convars->end(); iter++)
{
const ConVar *cvar = (*iter);
if ((cvar->GetFlags() & FCVAR_DONTRECORD) == FCVAR_DONTRECORD)
#if SOURCE_ENGINE >= SE_ORANGEBOX
if (cvar->IsFlagSet(FCVAR_DONTRECORD))
#else
if (cvar->IsBitSet(FCVAR_DONTRECORD))
#endif
{
continue;
}
@ -429,7 +425,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
char *dptr = descr;
/* Print comments until there is no more */
strncopy(descr, cvar->GetHelpText(), sizeof(descr));
ke::SafeStrcpy(descr, sizeof(descr), cvar->GetHelpText());
while (*dptr != '\0')
{
/* Find the next line */
@ -478,7 +474,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
if (file_exists)
{
char cmd[255];
UTIL_Format(cmd, sizeof(cmd), "exec %s\n", local);
ke::SafeSprintf(cmd, sizeof(cmd), "exec %s\n", local);
engine->ServerCommand(cmd);
}
@ -533,7 +529,7 @@ void SM_ExecuteForPlugin(IPluginContext *ctx)
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
}
char cmd[255];
UTIL_Format(cmd, sizeof(cmd), "sm internal 2 %d\n", plugin->GetSerial());
ke::SafeSprintf(cmd, sizeof(cmd), "sm_internal 2 %d\n", plugin->GetSerial());
engine->ServerCommand(cmd);
}
}
@ -580,7 +576,24 @@ void SM_InternalCmdTrigger()
{
/* Order is important here. We need to buffer things before we send the command out. */
g_pOnAutoConfigsBuffered->Execute(NULL);
engine->ServerCommand("sm internal 1\n");
engine->ServerCommand("sm_internal 1\n");
g_PendingInternalPush = false;
}
CON_COMMAND(sm_internal, "")
{
#if SOURCE_ENGINE <= SE_DARKMESSIAH
CCommand args;
#endif
if (args.ArgC() < 1)
return;
const char *arg = args.Arg(1);
if (strcmp(arg, "1") == 0) {
SM_ConfigsExecuted_Global();
} else if (strcmp(arg, "2") == 0) {
if (args.ArgC() >= 3)
SM_ConfigsExecuted_Plugin(atoi(args.Arg(2)));
}
}

View File

@ -55,7 +55,7 @@ public: // SMGlobalClass
public: // ITextListener_SMC
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
public: // IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
public:
/**
* Initializes CoreConfig by reading from core.cfg file

View File

@ -1,199 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "sm_globals.h"
#include "sourcemm_api.h"
#include "Tlhelp32.h"
#include "LibrarySys.h"
#include "minidump.h"
#include "sm_stringutil.h"
bool HookImportAddrTable(BYTE *base, const char *func, DWORD hookfunc, char *err, size_t maxlength)
{
IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)base;
if (dos->e_magic != IMAGE_DOS_SIGNATURE)
{
UTIL_Format(err, maxlength, "%s", "Could not detect valid DOS signature");
return false;
}
IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE)
{
UTIL_Format(err, maxlength, "%s", "Could not detect valid NT signature");
return false;
}
IMAGE_IMPORT_DESCRIPTOR *desc =
(IMAGE_IMPORT_DESCRIPTOR *)
(base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if (base == (BYTE *)desc)
{
UTIL_Format(err, maxlength, "%s", "Could not find IAT");
return false;
}
bool entryFound = false;
while (desc->Name)
{
if (desc->FirstThunk != 0)
{
IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk);
DWORD *iat = (DWORD *)(base + desc->FirstThunk);
while (data->u1.Function)
{
if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32)
{
IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData);
if (strcmp((char *)import->Name, func) == 0)
{
DWORD oldprot, oldprot2;
VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot);
*iat = hookfunc;
VirtualProtect(iat, 4, oldprot, &oldprot2);
entryFound = true;
}
}
data++;
iat++;
}
}
desc++;
}
if (!entryFound)
{
UTIL_Format(err, maxlength, "Could not find IAT entry for %s", func);
return false;
}
return true;
}
BOOL
WINAPI
MiniDumpWriteDump2(
IN HANDLE hProcess,
IN DWORD ProcessId,
IN HANDLE hFile,
IN MINIDUMP_TYPE DumpType,
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
)
{
DumpType = (MINIDUMP_TYPE)((int)DumpType|MiniDumpWithFullMemory|MiniDumpWithHandleData);
return MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType, ExceptionParam, UserStreamParam, CallbackParam);
}
FARPROC WINAPI GetProcAddress2(HMODULE hModule, LPCSTR lpProcName)
{
if (strcmp(lpProcName, "MiniDumpWriteDump") == 0)
{
return (FARPROC)MiniDumpWriteDump2;
}
return GetProcAddress(hModule, lpProcName);
}
HMODULE WINAPI LoadLibraryEx2(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{
HMODULE lib = LoadLibraryEx(lpFileName, hFile, dwFlags);
/* Steam.dll seems to get loaded using an abs path, thus the use of stristr() */
if (stristr(lpFileName, "steam.dll"))
{
char err[64];
if (!HookImportAddrTable((BYTE *)lib, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
{
Error("[SM] %s in steam.dll\n", err);
return NULL;
}
}
return lib;
}
class CrazyWindowsDebugger : public SMGlobalClass
{
public:
void OnSourceModAllInitialized()
{
HANDLE hModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
MODULEENTRY32 me32;
BYTE *engine = NULL;
BYTE *steam = NULL;
char err[64];
me32.dwSize = sizeof(MODULEENTRY32);
if (!Module32First(hModuleList, &me32))
{
Error("Could not initialize crazy debugger!");
}
do
{
if (strcasecmp(me32.szModule, "engine.dll") == 0)
{
engine = me32.modBaseAddr;
}
else if (strcasecmp(me32.szModule, "steam.dll") == 0)
{
steam = me32.modBaseAddr;
}
} while (Module32Next(hModuleList, &me32));
CloseHandle(hModuleList);
/* This really should not happen, but ... */
if (!engine)
{
Error("[SM] Could not find engine.dll\n");
}
/* Steam.dll isn't loaded yet */
if (!steam)
{
if (!HookImportAddrTable(engine, "LoadLibraryExA", (DWORD)LoadLibraryEx2, err, sizeof(err)))
{
Error("[SM] %s in engine.dll)\n", err);
}
}
else
{
if (!HookImportAddrTable(steam, "GetProcAddress", (DWORD)GetProcAddress2, err, sizeof(err)))
{
Error("[SM] %s in steam.dll)\n", err);
}
}
}
} s_CrazyDebugger;

View File

@ -31,7 +31,10 @@
#include "EventManager.h"
#include "sm_stringutil.h"
#include "PlayerManager.h"
#include "logic_bridge.h"
#include <bridge/include/IScriptManager.h>
EventManager g_EventManager;
@ -155,7 +158,7 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
}
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
#if SOURCE_ENGINE >= SE_LEFT4DEAD
int EventManager::GetEventDebugID()
{
return EVENT_DEBUG_ID_INIT;
@ -359,6 +362,13 @@ void EventManager::FireEvent(EventInfo *pInfo, bool bDontBroadcast)
m_FreeEvents.push(pInfo);
}
void EventManager::FireEventToClient(EventInfo *pInfo, IClient *pClient)
{
// The IClient vtable is +sizeof(void *) from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - sizeof(void *));
pGameClient->FireGameEvent(pInfo->pEvent);
}
void EventManager::CancelCreatedEvent(EventInfo *pInfo)
{
/* Free event from IGameEventManager2 */
@ -423,7 +433,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
m_EventCopies.push(gameevents->DuplicateEvent(pEvent));
}
if (res)
if (res >= Pl_Handled)
{
gameevents->FreeEvent(pEvent);
RETURN_META_VALUE(MRES_SUPERCEDE, false);

View File

@ -41,6 +41,8 @@
#include <IForwardSys.h>
#include <IPluginSys.h>
class IClient;
using namespace SourceHook;
struct EventInfo
@ -75,6 +77,10 @@ struct EventHook
{
return strcmp(name, hook->name.chars()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
enum EventHookMode
@ -110,7 +116,7 @@ public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent);
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
#if SOURCE_ENGINE >= SE_LEFT4DEAD
int GetEventDebugID();
#endif
public:
@ -126,6 +132,7 @@ public:
EventHookError UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
EventInfo *CreateEvent(IPluginContext *pContext, const char *name, bool force=false);
void FireEvent(EventInfo *pInfo, bool bDontBroadcast=false);
void FireEventToClient(EventInfo *pInfo, IClient *pClient);
void CancelCreatedEvent(EventInfo *pInfo);
private: // IGameEventManager2 hooks
bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast);

171
core/GameHooks.cpp Normal file
View File

@ -0,0 +1,171 @@
// vim: set ts=4 sw=4 tw=99 noet :
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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 "GameHooks.h"
#include "sourcemod.h"
#include "ConVarManager.h"
#include "command_args.h"
#include "provider.h"
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
#else
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *);
#endif
#if SOURCE_ENGINE != SE_DARKMESSIAH
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
#endif
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#else
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#endif
SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
GameHooks::GameHooks()
: client_cvar_query_mode_(ClientCvarQueryMode::Unavailable),
last_command_client_(-1)
{
}
void GameHooks::Start()
{
// Hook ICvar::CallGlobalChangeCallbacks.
#if SOURCE_ENGINE >= SE_ORANGEBOX
hooks_ += SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
#else
hooks_ += SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
#endif
// Episode 2 has this function by default, but the older versions do not.
#if SOURCE_ENGINE == SE_EPISODEONE
if (g_SMAPI->GetGameDLLVersion() >= 6) {
hooks_ += SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &GameHooks::OnQueryCvarValueFinished), false);
client_cvar_query_mode_ = ClientCvarQueryMode::DLL;
}
#endif
hooks_ += SH_ADD_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &GameHooks::SetCommandClient), false);
}
void GameHooks::OnVSPReceived()
{
if (client_cvar_query_mode_ != ClientCvarQueryMode::Unavailable)
return;
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
return;
#if SOURCE_ENGINE != SE_DARKMESSIAH
hooks_ += SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &GameHooks::OnQueryCvarValueFinished), false);
client_cvar_query_mode_ = ClientCvarQueryMode::VSP;
#endif
}
void GameHooks::Shutdown()
{
for (size_t i = 0; i < hooks_.length(); i++)
SH_REMOVE_HOOK_ID(hooks_[i]);
hooks_.clear();
client_cvar_query_mode_ = ClientCvarQueryMode::Unavailable;
}
#if SOURCE_ENGINE >= SE_ORANGEBOX
void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
#else
void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue)
#endif
{
#if SOURCE_ENGINE < SE_ORANGEBOX
float flOldValue = atof(oldValue);
#endif
g_ConVarManager.OnConVarChanged(pConVar, oldValue, flOldValue);
}
#if SOURCE_ENGINE != SE_DARKMESSIAH
void GameHooks::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue){
int client = IndexOfEdict(pPlayer);
# if SOURCE_ENGINE == SE_CSGO
if (g_Players.HandleConVarQuery(cookie, client, result, cvarName, cvarValue))
return;
# endif
g_ConVarManager.OnClientQueryFinished(cookie, client, result, cvarName, cvarValue);
}
#endif
ke::RefPtr<CommandHook>
GameHooks::AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
{
return new CommandHook(cmd, callback, false);
}
ke::RefPtr<CommandHook>
GameHooks::AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback)
{
return new CommandHook(cmd, callback, true);
}
void GameHooks::SetCommandClient(int client)
{
last_command_client_ = client + 1;
}
CommandHook::CommandHook(ConCommand *cmd, const Callback &callback, bool post)
: hook_id_(0),
callback_(callback)
{
hook_id_ = SH_ADD_HOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &CommandHook::Dispatch), post);
}
CommandHook::~CommandHook()
{
if (hook_id_)
SH_REMOVE_HOOK_ID(hook_id_);
}
void CommandHook::Dispatch(DISPATCH_ARGS)
{
DISPATCH_PROLOGUE;
EngineArgs args(command);
AddRef();
bool rval = callback_(sCoreProviderImpl.CommandClient(), &args);
Release();
if (rval)
RETURN_META(MRES_SUPERCEDE);
}
void CommandHook::Zap()
{
hook_id_ = 0;
}

133
core/GameHooks.h Normal file
View File

@ -0,0 +1,133 @@
// vim: set ts=4 sw=4 tw=99 noet :
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_PROVIDER_GAME_HOOKS_H_
#define _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_
// Needed for CEntityIndex, edict_t, etc.
#include <stdint.h>
#include <stddef.h>
#include <eiface.h>
#include <iserverplugin.h>
#include <amtl/am-refcounting.h>
#include <amtl/am-vector.h>
#include <amtl/am-function.h>
class ConVar;
class CCommand;
struct CCommandContext;
#if SOURCE_ENGINE >= SE_ORANGEBOX
# define DISPATCH_ARGS const CCommand &command
# define DISPATCH_PROLOGUE
#else
# define DISPATCH_ARGS
# define DISPATCH_PROLOGUE CCommand command
#endif
namespace SourceMod {
// Describes the mechanism in which client cvar queries are implemented.
enum class ClientCvarQueryMode {
Unavailable,
DLL,
VSP
};
class ICommandArgs;
class CommandHook : public ke::Refcounted<CommandHook>
{
public:
// return false to RETURN_META(MRES_IGNORED), or true to SUPERCEDE.
typedef ke::Lambda<bool(int, const ICommandArgs *)> Callback;
public:
CommandHook(ConCommand *cmd, const Callback &callback, bool post);
~CommandHook();
void Dispatch(DISPATCH_ARGS);
void Zap();
private:
int hook_id_;
Callback callback_;
};
class GameHooks
{
public:
GameHooks();
void Start();
void Shutdown();
void OnVSPReceived();
ClientCvarQueryMode GetClientCvarQueryMode() const {
return client_cvar_query_mode_;
}
public:
ke::RefPtr<CommandHook> AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
ke::RefPtr<CommandHook> AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &callback);
int CommandClient() const {
return last_command_client_;
}
private:
// Static callback that Valve's ConVar object executes when the convar's value changes.
#if SOURCE_ENGINE >= SE_ORANGEBOX
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
#else
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
#endif
// Callback for when StartQueryCvarValue() has finished.
#if SOURCE_ENGINE != SE_DARKMESSIAH
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue);
#endif
void SetCommandClient(int client);
private:
class HookList : public ke::Vector<int>
{
public:
HookList &operator += (int hook_id) {
this->append(hook_id);
return *this;
}
};
HookList hooks_;
ClientCvarQueryMode client_cvar_query_mode_;
int last_command_client_;
};
} // namespace SourceMod
#endif // _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_

View File

@ -2,7 +2,7 @@
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* Copyright (C) 2004-2016 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
@ -38,38 +38,20 @@
#include <IGameConfigs.h>
#include <compat_wrappers.h>
#include <Logger.h>
#include "LibrarySys.h"
#include <amtl/os/am-shared-library.h>
#include "logic_bridge.h"
#include <tier0/mem.h>
#include <bridge/include/ILogger.h>
#if SOURCE_ENGINE == SE_DOTA
#include <game/shared/protobuf/usermessages.pb.h>
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessages.pb.h>
#endif
typedef ICommandLine *(*FakeGetCommandLine)();
#if defined _WIN32
#define TIER0_NAME "tier0.dll"
#define VSTDLIB_NAME "vstdlib.dll"
#elif defined __APPLE__
#define TIER0_NAME "libtier0.dylib"
#define VSTDLIB_NAME "libvstdlib.dylib"
#elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN
#define TIER0_NAME "libtier0_srv.so"
#define VSTDLIB_NAME "libvstdlib_srv.so"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#define TIER0_NAME "libtier0.so"
#define VSTDLIB_NAME "libvstdlib.so"
#else
#define TIER0_NAME "tier0_i486.so"
#define VSTDLIB_NAME "vstdlib_i486.so"
#endif
#endif
#define TIER0_NAME FORMAT_SOURCE_BIN_NAME("tier0")
#define VSTDLIB_NAME FORMAT_SOURCE_BIN_NAME("vstdlib")
CHalfLife2 g_HL2;
ConVar *sv_lan = NULL;
@ -112,24 +94,10 @@ CHalfLife2::~CHalfLife2()
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
#endif
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
bool is_original_engine = false;
#endif
void CHalfLife2::OnSourceModStartup(bool late)
{
#if SOURCE_ENGINE != SE_DARKMESSIAH
/* The Ship currently is the only known game to use an older version of the engine */
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
#else
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
#endif
{
is_original_engine = true;
}
else if (g_pSharedChangeInfo == NULL)
if (g_SMAPI->GetSourceEngineBuild() != SOURCE_ENGINE_ORIGINAL && !g_pSharedChangeInfo)
{
g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
}
@ -149,15 +117,70 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
{
InitLogicalEntData();
InitCommandLine();
#if SOURCE_ENGINE == SE_CSGO
m_CSGOBadList.init();
m_CSGOBadList.add("m_iItemDefinitionIndex");
m_CSGOBadList.add("m_iEntityLevel");
m_CSGOBadList.add("m_iItemIDHigh");
m_CSGOBadList.add("m_iItemIDLow");
m_CSGOBadList.add("m_iAccountID");
m_CSGOBadList.add("m_iEntityQuality");
m_CSGOBadList.add("m_bInitialized");
m_CSGOBadList.add("m_szCustomName");
m_CSGOBadList.add("m_iAttributeDefinitionIndex");
m_CSGOBadList.add("m_iRawValue32");
m_CSGOBadList.add("m_iRawInitialValue32");
m_CSGOBadList.add("m_nRefundableCurrency");
m_CSGOBadList.add("m_bSetBonus");
m_CSGOBadList.add("m_OriginalOwnerXuidLow");
m_CSGOBadList.add("m_OriginalOwnerXuidHigh");
m_CSGOBadList.add("m_nFallbackPaintKit");
m_CSGOBadList.add("m_nFallbackSeed");
m_CSGOBadList.add("m_flFallbackWear");
m_CSGOBadList.add("m_nFallbackStatTrak");
m_CSGOBadList.add("m_iCompetitiveRanking");
m_CSGOBadList.add("m_iCompetitiveRankType");
m_CSGOBadList.add("m_nActiveCoinRank");
m_CSGOBadList.add("m_nMusicID");
#endif
}
ConfigResult CHalfLife2::OnSourceModConfigChanged(const char *key, const char *value,
ConfigSource source, char *error, size_t maxlength)
{
if (strcasecmp(key, "FollowCSGOServerGuidelines") == 0)
{
#if SOURCE_ENGINE == SE_CSGO
if (strcasecmp(value, "no") == 0)
{
m_bFollowCSGOServerGuidelines = false;
return ConfigResult_Accept;
}
else if (strcasecmp(value, "yes") == 0)
{
m_bFollowCSGOServerGuidelines = true;
return ConfigResult_Accept;
}
else
{
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
return ConfigResult_Reject;
}
#endif
}
return ConfigResult_Ignore;
}
void CHalfLife2::InitLogicalEntData()
{
#if SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_DODS \
|| SOURCE_ENGINE == SE_HL2DM \
|| SOURCE_ENGINE == SE_CSS \
|| SOURCE_ENGINE == SE_SDK2013
#if SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_DODS \
|| SOURCE_ENGINE == SE_HL2DM \
|| SOURCE_ENGINE == SE_CSS \
|| SOURCE_ENGINE == SE_SDK2013 \
|| SOURCE_ENGINE == SE_BMS \
|| SOURCE_ENGINE == SE_NUCLEARDAWN
if (g_SMAPI->GetServerFactory(false)("VSERVERTOOLS003", nullptr))
{
@ -205,7 +228,12 @@ void CHalfLife2::InitLogicalEntData()
return;
}
#ifdef PLATFORM_X86
g_EntList = *reinterpret_cast<void **>(addr + offset);
#elif defined PLATFORM_X64
int32_t varOffset = *reinterpret_cast<int32_t *>(addr + offset);
g_EntList = reinterpret_cast<void *>(addr + offset + sizeof(int32_t) + varOffset);
#endif
}
}
@ -234,34 +262,33 @@ void CHalfLife2::InitLogicalEntData()
void CHalfLife2::InitCommandLine()
{
char error[256];
if (!is_original_engine)
#if SOURCE_ENGINE != SE_DARKMESSIAH
if (g_SMAPI->GetSourceEngineBuild() != SOURCE_ENGINE_ORIGINAL)
{
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error)));
if (lib == NULL)
{
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(TIER0_NAME, error, sizeof(error));
if (!lib) {
logger->LogError("Could not load %s: %s", TIER0_NAME, error);
return;
}
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine_Tier0");
m_pGetCommandLine = lib->get<decltype(m_pGetCommandLine)>("CommandLine_Tier0");
/* '_Tier0' dropped on Alien Swarm version */
if (m_pGetCommandLine == NULL)
{
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
m_pGetCommandLine = lib->get<decltype(m_pGetCommandLine)>("CommandLine");
}
}
else
#endif
{
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error)));
if (lib == NULL)
{
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(VSTDLIB_NAME, error, sizeof(error));
if (!lib) {
logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error);
return;
}
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
m_pGetCommandLine = lib->get<decltype(m_pGetCommandLine)>("CommandLine");
}
if (m_pGetCommandLine == NULL)
@ -278,21 +305,10 @@ ICommandLine *CHalfLife2::GetValveCommandLine()
return ((FakeGetCommandLine)((FakeGetCommandLine *)m_pGetCommandLine))();
}
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
bool CHalfLife2::IsOriginalEngine()
{
return is_original_engine;
}
#endif
#if SOURCE_ENGINE != SE_DARKMESSIAH
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
{
#if SOURCE_ENGINE == SE_DOTA
return engine->GetChangeAccessor( IndexOfEdict((const edict_t *)this) );
#else
return engine->GetChangeAccessor( (const edict_t *)this );
#endif
}
#endif
@ -497,20 +513,10 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
/* Use SayText user message instead */
if (chat_saytext != NULL && strcmp(chat_saytext, "yes") == 0)
{
char buffer[192];
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
char buffer[253];
ke::SafeSprintf(buffer, sizeof(buffer), "%s\1\n", msg);
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_SayText *pMsg;
if ((pMsg = (CUserMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_client(0);
pMsg->set_text(buffer);
pMsg->set_chat(false);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_SayText *pMsg;
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
@ -537,16 +543,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
}
}
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_TextMsg *pMsg;
if ((pMsg = (CUserMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_dest(dest);
pMsg->add_param(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_TextMsg *pMsg;
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
@ -568,6 +565,10 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
pBitBuf->WriteByte(dest);
pBitBuf->WriteString(msg);
pBitBuf->WriteString("");
pBitBuf->WriteString("");
pBitBuf->WriteString("");
pBitBuf->WriteString("");
#endif
g_UserMsgs.EndMessage();
@ -579,15 +580,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
{
cell_t players[] = {client};
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_HintText *pMsg;
if ((pMsg = (CUserMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_message(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
@ -617,15 +610,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
{
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_HintText *pMsg;
if ((pMsg = (CUserMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_message(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
{
@ -660,13 +645,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
int count = 0;
cell_t players[] = {client};
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_VGUIMenu *pMsg;
if ((pMsg = (CUserMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_VGUIMenu *pMsg;
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
{
@ -691,18 +670,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
SubKey = data->GetFirstSubKey();
}
#if SOURCE_ENGINE == SE_DOTA
pMsg->set_name(name);
pMsg->set_show(show);
while (SubKey)
{
CUserMsg_VGUIMenu_Keys *key = pMsg->add_keys();
key->set_name(SubKey->GetName());
key->set_value(SubKey->GetString());
SubKey = SubKey->GetNextKey();
}
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
pMsg->set_name(name);
pMsg->set_show(show);
@ -758,11 +726,7 @@ void CHalfLife2::ProcessFakeCliCmdQueue()
if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
{
CPlayer *pPlayer = g_Players.GetPlayerByIndex(pFake->client);
#if SOURCE_ENGINE == SE_DOTA
engine->ClientCommand(pPlayer->GetIndex(), "%s", pFake->cmd.c_str());
#else
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
#endif
}
m_CmdQueue.pop();
@ -784,11 +748,7 @@ bool CHalfLife2::IsLANServer()
bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
{
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
#else
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
#endif
{
Assert(filesystem);
#ifdef _MSC_VER
@ -823,19 +783,19 @@ bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, cons
}
}
void CHalfLife2::PushCommandStack(const CCommand *cmd)
void CHalfLife2::PushCommandStack(const ICommandArgs *cmd)
{
CachedCommandInfo info;
info.args = cmd;
#if SOURCE_ENGINE <= SE_DARKMESSIAH
strncopy(info.cmd, cmd->Arg(0), sizeof(info.cmd));
ke::SafeStrcpy(info.cmd, sizeof(info.cmd), cmd->Arg(0));
#endif
m_CommandStack.push(info);
}
const CCommand *CHalfLife2::PeekCommandStack()
const ICommandArgs *CHalfLife2::PeekCommandStack()
{
if (m_CommandStack.empty())
{
@ -873,7 +833,7 @@ void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
kick.client = client;
kick.userid = userid;
UTIL_Format(kick.buffer, sizeof(kick.buffer), "%s", msg);
ke::SafeStrcpy(kick.buffer, sizeof(kick.buffer), msg);
m_DelayedKicks.push(kick);
}
@ -1205,46 +1165,260 @@ const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity)
return *(const char **)(((unsigned char *)pEntity) + offset);
}
#if SOURCE_ENGINE >= SE_LEFT4DEAD
static bool ResolveFuzzyMapName(const char *fuzzyName, char *outFullname, int size)
SMFindMapResult CHalfLife2::FindMap(char *pMapName, size_t nMapNameMax)
{
return this->FindMap(pMapName, pMapName, nMapNameMax);
}
#ifdef PLATFORM_WINDOWS
bool CheckReservedFilename(const char *in, const char *reservedName)
{
size_t nameLen = strlen(reservedName);
for (size_t i = 0; i < nameLen; ++i)
{
if (reservedName[i] != tolower(in[i]))
{
return false;
}
}
if (in[nameLen] == '\0' || in[nameLen] == '.')
{
return true;
}
return false;
}
bool IsWindowsReservedDeviceName(const char *pMapname)
{
static const char * const reservedDeviceNames[] = {
"con", "prn", "aux", "clock$", "nul", "com1",
"com2", "com3", "com4", "com5", "com6", "com7",
"com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4",
"lpt5", "lpt6", "lpt7", "lpt8", "lpt9"
};
size_t reservedCount = sizeof(reservedDeviceNames) / sizeof(reservedDeviceNames[0]);
for (size_t i = 0; i < reservedCount; ++i)
{
if (CheckReservedFilename(pMapname, reservedDeviceNames[i]))
{
return true;
}
}
return false;
}
#endif
SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_t nMapNameMax)
{
/* We need to ensure user input does not contain reserved device names on windows */
#ifdef PLATFORM_WINDOWS
if (IsWindowsReservedDeviceName(pMapName))
{
return SMFindMapResult::NotFound;
}
#endif
ke::SafeStrcpy(pFoundMap, nMapNameMax, pMapName);
#if SOURCE_ENGINE >= SE_LEFT4DEAD
static char mapNameTmp[PLATFORM_MAX_PATH];
g_SourceMod.Format(mapNameTmp, sizeof(mapNameTmp), "maps%c%s.bsp", PLATFORM_SEP_CHAR, pMapName);
if (filesystem->FileExists(mapNameTmp, "GAME"))
{
// If this is already an exact match, don't attempt to autocomplete it further (de_dust -> de_dust2).
// ... but still check that map file is actually valid.
// We check FileExists first to avoid console message about IsMapValid with invalid map.
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
}
static ConCommand *pHelperCmd = g_pCVar->FindCommand("changelevel");
// This shouldn't happen.
if (!pHelperCmd || !pHelperCmd->CanAutoComplete())
return false;
{
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
}
static size_t helperCmdLen = strlen(pHelperCmd->GetName());
CUtlVector<CUtlString> results;
pHelperCmd->AutoCompleteSuggest(fuzzyName, results);
pHelperCmd->AutoCompleteSuggest(pMapName, results);
if (results.Count() == 0)
return false;
return SMFindMapResult::NotFound;
// Results come back as you'd see in autocomplete. (ie. "changelevel fullmapnamehere"),
// so skip ahead to start of map path/name
// Like the engine, we're only going to deal with the first match.
strncopy(outFullname, &results[0][helperCmdLen + 1], size);
bool bExactMatch = Q_strcmp(pMapName, &results[0][helperCmdLen + 1]) == 0;
if (bExactMatch)
{
return SMFindMapResult::Found;
}
else
{
ke::SafeStrcpy(pFoundMap, nMapNameMax, &results[0][helperCmdLen + 1]);
return SMFindMapResult::FuzzyMatch;
}
#elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS
static IVEngineServer *engine23 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer023", nullptr));
if (engine23)
{
static char szTemp[PLATFORM_MAX_PATH];
if (pFoundMap == NULL)
{
ke::SafeStrcpy(szTemp, SM_ARRAYSIZE(szTemp), pMapName);
pFoundMap = szTemp;
nMapNameMax = 0;
}
return static_cast<SMFindMapResult>(engine->FindMap(pFoundMap, static_cast<int>(nMapNameMax)));
}
else
{
static IVEngineServer *engine21 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer021", nullptr));
return engine21->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
}
#else
return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found;
#endif
}
bool CHalfLife2::GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax)
{
SMFindMapResult result = FindMap(pMapName, pDisplayname, nMapNameMax);
if (result == SMFindMapResult::NotFound)
return false;
char *pPos;
if ((pPos = strrchr(pDisplayname, '/')) != NULL || (pPos = strrchr(pDisplayname, '\\')) != NULL)
ke::SafeStrcpy(pDisplayname, nMapNameMax, &pPos[1]);
if ((pPos = strstr(pDisplayname, ".ugc")) != NULL)
pPos[0] = '\0';
return true;
}
#endif
bool CHalfLife2::IsMapValid(const char *map)
{
if (!map || !map[0])
return false;
return FindMap(map) == SMFindMapResult::Found;
}
bool ret = engine->IsMapValid(map);
#if SOURCE_ENGINE >= SE_LEFT4DEAD
if (!ret)
// TODO: Add ep1 support for this. (No IServerTools available there)
#if SOURCE_ENGINE >= SE_ORANGEBOX
string_t CHalfLife2::AllocPooledString(const char *pszValue)
{
// This is admittedly a giant hack, but it's a relatively safe method for
// inserting a string into the game's string pool that isn't likely to break.
//
// We find the first valid ent (should always be worldspawn), save off it's
// current targetname string_t, set it to our string to insert via SetKeyValue,
// read back the new targetname value, restore the old value, and return the new one.
CBaseEntity *pEntity = ((IServerUnknown *) servertools->FirstEntity())->GetBaseEntity();
auto *pDataMap = GetDataMap(pEntity);
assert(pDataMap);
static int offset = -1;
if (offset == -1)
{
static char szFuzzyName[PLATFORM_MAX_PATH];
if (ResolveFuzzyMapName(map, szFuzzyName, sizeof(szFuzzyName)))
sm_datatable_info_t info;
bool found = FindDataMapInfo(pDataMap, "m_iName", &info);
assert(found);
offset = info.actual_offset;
}
string_t *pProp = (string_t *) ((intp) pEntity + offset);
string_t backup = *pProp;
servertools->SetKeyValue(pEntity, "targetname", pszValue);
string_t newString = *pProp;
*pProp = backup;
return newString;
}
#endif
bool CHalfLife2::GetServerSteam3Id(char *pszOut, size_t len) const
{
CSteamID sid((uint64)GetServerSteamId64());
switch (sid.GetEAccountType())
{
case k_EAccountTypeAnonGameServer:
ke::SafeSprintf(pszOut, len, "[A:%u:%u:%u]", sid.GetEUniverse(), sid.GetAccountID(), sid.GetUnAccountInstance());
break;
case k_EAccountTypeGameServer:
ke::SafeSprintf(pszOut, len, "[G:%u:%u]", sid.GetEUniverse(), sid.GetAccountID());
break;
case k_EAccountTypeInvalid:
ke::SafeSprintf(pszOut, len, "[I:%u:%u]", sid.GetEUniverse(), sid.GetAccountID());
break;
default:
return false;
}
return true;
}
#if defined( PLATFORM_WINDOWS )
#define STEAM_LIB_PREFIX
#define STEAM_LIB_SUFFIX
#elif defined( PLATFORM_LINUX )
#define STEAM_LIB_PREFIX "lib"
#define STEAM_LIB_SUFFIX ".so"
#elif defined( PLATFORM_APPLE )
#define STEAM_LIB_PREFIX "lib"
#define STEAM_LIB_SUFFIX ".dylib"
#endif
uint64_t CHalfLife2::GetServerSteamId64() const
{
#if SOURCE_ENGINE == SE_BLADE \
|| SOURCE_ENGINE == SE_BMS \
|| SOURCE_ENGINE == SE_CSGO \
|| SOURCE_ENGINE == SE_CSS \
|| SOURCE_ENGINE == SE_DODS \
|| SOURCE_ENGINE == SE_EYE \
|| SOURCE_ENGINE == SE_HL2DM \
|| SOURCE_ENGINE == SE_INSURGENCY \
|| SOURCE_ENGINE == SE_DOI \
|| SOURCE_ENGINE == SE_SDK2013 \
|| SOURCE_ENGINE == SE_ALIENSWARM \
|| SOURCE_ENGINE == SE_TF2
const CSteamID *sid = engine->GetGameServerSteamID();
if (sid)
{
return sid->ConvertToUint64();
}
#else
typedef uint64_t(* GetServerSteamIdFn)(void);
static GetServerSteamIdFn fn = nullptr;
if (!fn)
{
ke::SharedLib steam_api(STEAM_LIB_PREFIX "steam_api" STEAM_LIB_SUFFIX);
if (steam_api.valid())
{
ret = engine->IsMapValid(szFuzzyName);
fn = (GetServerSteamIdFn)steam_api.lookup("SteamGameServer_GetSteamID");
}
}
if (fn)
{
return fn();
}
#endif
return ret;
return 1ULL;
}

View File

@ -2,7 +2,7 @@
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* Copyright (C) 2004-2016 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
@ -36,6 +36,7 @@
#include <sh_string.h>
#include <sh_tinyhash.h>
#include <am-utility.h>
#include <am-hashset.h>
#include <am-hashmap.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
@ -47,11 +48,11 @@
#include <datamap.h>
#include <ihandleentity.h>
#include <tier0/icommandline.h>
#if SOURCE_ENGINE >= SE_PORTAL2
#include <string_t.h>
#endif
class CCommand;
namespace SourceMod {
class ICommandArgs;
} // namespace SourceMod
using namespace SourceHook;
using namespace SourceMod;
@ -59,6 +60,33 @@ using namespace SourceMod;
#define HUD_PRINTTALK 3
#define HUD_PRINTCENTER 4
#if defined _WIN32
#define SOURCE_BIN_PREFIX ""
#define SOURCE_BIN_SUFFIX ""
#define SOURCE_BIN_EXT ".dll"
#elif defined __APPLE__
#define SOURCE_BIN_PREFIX ""
#define SOURCE_BIN_SUFFIX ""
#define SOURCE_BIN_EXT ".dylib"
#elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN \
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_INSURGENCY || SOURCE_ENGINE == SE_DOI
#define SOURCE_BIN_PREFIX "lib"
#define SOURCE_BIN_SUFFIX "_srv"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#define SOURCE_BIN_PREFIX "lib"
#define SOURCE_BIN_SUFFIX ""
#else
#define SOURCE_BIN_PREFIX ""
#define SOURCE_BIN_SUFFIX "_i486"
#endif
#define SOURCE_BIN_EXT ".so"
#endif
#define FORMAT_SOURCE_BIN_NAME(basename) \
(SOURCE_BIN_PREFIX basename SOURCE_BIN_SUFFIX SOURCE_BIN_EXT)
struct DataTableInfo
{
struct SendPropPolicy
@ -67,13 +95,21 @@ struct DataTableInfo
{
return strcmp(name, info.prop->GetName()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
static inline bool matches(const char *name, const DataTableInfo *info)
{
return strcmp(name, info->sc->GetName()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
DataTableInfo(ServerClass *sc)
: sc(sc)
{
@ -89,6 +125,10 @@ struct DataMapCachePolicy
{
return strcmp(name, info.prop->fieldName) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
@ -102,7 +142,7 @@ struct DelayedFakeCliCmd
struct CachedCommandInfo
{
const CCommand *args;
const ICommandArgs *args;
#if SOURCE_ENGINE <= SE_DARKMESSIAH
char cmd[300];
#endif
@ -123,16 +163,27 @@ public:
int m_SerialNumber;
CEntInfo *m_pPrev;
CEntInfo *m_pNext;
#if (SOURCE_ENGINE >= SE_PORTAL2) && (SOURCE_ENGINE != SE_DOTA)
#if SOURCE_ENGINE >= SE_PORTAL2
string_t m_iName;
string_t m_iClassName;
#endif
};
// Corresponds to TF2's eFindMapResult in eiface.h
// Not yet in other games, but eventually in others on same branch.
enum class SMFindMapResult : cell_t {
Found,
NotFound,
FuzzyMatch,
NonCanonical,
PossiblyAvailable
};
class CHalfLife2 :
public SMGlobalClass,
public IGameHelpers
{
friend class AutoEnterCommand;
public:
CHalfLife2();
~CHalfLife2();
@ -141,6 +192,8 @@ public:
void OnSourceModAllInitialized();
void OnSourceModAllInitialized_Post();
/*void OnSourceModAllShutdown();*/
ConfigResult OnSourceModConfigChanged(const char *key, const char *value,
ConfigSource source, char *error, size_t maxlength) override;
public: //IGameHelpers
SendProp *FindInSendTable(const char *classname, const char *offset);
bool FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info);
@ -174,20 +227,25 @@ public: //IGameHelpers
const char *GetEntityClassname(edict_t *pEdict);
const char *GetEntityClassname(CBaseEntity *pEntity);
bool IsMapValid(const char *map);
SMFindMapResult FindMap(char *pMapName, size_t nMapNameMax);
SMFindMapResult FindMap(const char *pMapName, char *pFoundMap = NULL, size_t nMapNameMax = 0);
bool GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax);
#if SOURCE_ENGINE >= SE_ORANGEBOX
string_t AllocPooledString(const char *pszValue);
#endif
bool GetServerSteam3Id(char *pszOut, size_t len) const override;
uint64_t GetServerSteamId64() const override;
public:
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
void ProcessFakeCliCmdQueue();
public:
void PushCommandStack(const CCommand *cmd);
void PopCommandStack();
const CCommand *PeekCommandStack();
const ICommandArgs *PeekCommandStack();
const char *CurrentCommandName();
void AddDelayedKick(int client, int userid, const char *msg);
void ProcessDelayedKicks();
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
bool IsOriginalEngine();
#endif
private:
void PushCommandStack(const ICommandArgs *cmd);
void PopCommandStack();
DataTableInfo *_FindServerClass(const char *classname);
private:
void InitLogicalEntData();
@ -206,10 +264,31 @@ private:
CStack<CachedCommandInfo> m_CommandStack;
Queue<DelayedKickInfo> m_DelayedKicks;
void *m_pGetCommandLine;
#if SOURCE_ENGINE == SE_CSGO
public:
bool CanSetCSGOEntProp(const char *pszPropName)
{
return !m_bFollowCSGOServerGuidelines || !m_CSGOBadList.has(pszPropName);
}
private:
ke::HashSet<ke::AString, detail::StringHashMapPolicy> m_CSGOBadList;
bool m_bFollowCSGOServerGuidelines = true;
#endif
};
extern CHalfLife2 g_HL2;
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
class AutoEnterCommand
{
public:
AutoEnterCommand(const ICommandArgs *args) {
g_HL2.PushCommandStack(args);
}
~AutoEnterCommand() {
g_HL2.PopCommandStack();
}
};
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_

View File

@ -34,10 +34,10 @@
#include "sourcemm_api.h"
#include "sm_stringutil.h"
#include "Logger.h"
#include "LibrarySys.h"
#include "TimerSys.h"
#include "logic_bridge.h"
#include <sourcemod_version.h>
#include <bridge/include/IProviderCallbacks.h>
bool g_in_game_log_hook = false;
@ -48,7 +48,7 @@ SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
static void HookLogPrint(const char *message)
{
g_in_game_log_hook = true;
bool stopped = logicore.OnLogPrint(message);
bool stopped = logicore.callbacks->OnLogPrint(message);
g_in_game_log_hook = false;
if (stopped)

View File

@ -1,216 +0,0 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ..
HL2SDK_ORIG = ../../hl2sdk
HL2SDK_OB = ../../hl2sdk-ob
HL2SDK_CSS = ../../hl2sdk-css
HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve
HL2SDK_L4D = ../../hl2sdk-l4d
HL2SDK_L4D2 = ../../hl2sdk-l4d2
HL2SDK_CSGO = ../../hl2sdk-csgo
MMSOURCE = ../../mmsource-central
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
Database.cpp DebugReporter.cpp EventManager.cpp HalfLife2.cpp Logger.cpp \
PlayerManager.cpp TimerSys.cpp UserMessages.cpp \
sm_autonatives.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp \
frame_hooks.cpp concmd_cleaner.cpp NextMap.cpp \
NativeOwner.cpp logic_bridge.cpp ConsoleDetours.cpp
OBJECTS += smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
smn_database.cpp smn_entities.cpp smn_events.cpp \
smn_fakenatives.cpp smn_filesystem.cpp smn_halflife.cpp \
smn_keyvalues.cpp smn_player.cpp \
smn_usermsgs.cpp smn_menus.cpp smn_vector.cpp \
smn_hudtext.cpp smn_nextmap.cpp
OBJECTS += ExtensionSys.cpp \
ForwardSys.cpp \
HandleSys.cpp \
LibrarySys.cpp \
PluginInfoDatabase.cpp \
PluginSys.cpp \
ShareSys.cpp \
NativeInvoker.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc
override ENGSET = false
ifneq (,$(filter original orangebox css orangeboxvalve left4dead left4dead2 csgo,$(ENGINE)))
override ENGSET = true
endif
ifeq "$(ENGINE)" "original"
HL2SDK = $(HL2SDK_ORIG)
HL2LIB = $(HL2SDK)/linux_sdk
CFLAGS += -DSOURCE_ENGINE=1
METAMOD = $(MMSOURCE)/core-legacy
INCLUDE += -I$(HL2SDK)/public/dlls
BINARY = sourcemod.1.ep1.so
endif
ifeq "$(ENGINE)" "orangebox"
HL2SDK = $(HL2SDK_OB)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=3
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.ep2.so
endif
ifeq "$(ENGINE)" "css"
HL2SDK = $(HL2SDK_CSS)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=6
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.css.so
endif
ifeq "$(ENGINE)" "orangeboxvalve"
HL2SDK = $(HL2SDK_OB_VALVE)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=7
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.ep2v.so
endif
ifeq "$(ENGINE)" "left4dead"
HL2SDK = $(HL2SDK_L4D)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=8
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.l4d.so
endif
ifeq "$(ENGINE)" "left4dead2"
HL2SDK = $(HL2SDK_L4D2)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=9
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.l4d2.so
endif
ifeq "$(ENGINE)" "csgo"
HL2SDK = $(HL2SDK_CSGO)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=12
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.csgo.so
endif
HL2PUB = $(HL2SDK)/public
OS := $(shell uname -s)
ifeq "$(OS)" "Darwin"
LIB_EXT = dylib
HL2LIB = $(HL2SDK)/lib/mac
else
LIB_EXT = so
ifeq "$(ENGINE)" "original"
HL2LIB = $(HL2SDK)/linux_sdk
else
HL2LIB = $(HL2SDK)/lib/linux
endif
endif
ifneq (,$(filter original orangebox left4dead,$(ENGINE)))
LIB_SUFFIX = _i486.$(LIB_EXT)
else
LIB_PREFIX = lib
ifneq (,$(filter orangeboxvalve css,$(ENGINE)))
ifneq "$(OS)" "Darwin"
LIB_SUFFIX = _srv.$(LIB_EXT)
else
LIB_SUFFIX = .$(LIB_EXT)
endif
else
LIB_SUFFIX = .$(LIB_EXT)
endif
endif
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \
-DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \
-DSE_PORTAL2=11 -DSE_CSGO=12
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) \
$(LIB_PREFIX)tier0$(LIB_SUFFIX) -static-libgcc
ifeq "$(ENGINE)" "csgo"
LINK += $(HL2LIB)/interfaces_i486.a
endif
INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \
-I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook \
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
CFLAGS += -D_LINUX -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
-Wno-uninitialized -Wno-unused -Wno-switch -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H \
-DSM_DEFAULT_THREADER -m32 -DCOMPILER_GCC
CPPFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -fno-threadsafe-statics -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug.$(ENGINE)
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release.$(ENGINE)
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all: check
mkdir -p $(BIN_DIR)
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX)
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX)
$(MAKE) -f Makefile sourcemod
check:
if [ "$(ENGSET)" = "false" ]; then \
echo "You must supply one of the following values for ENGINE:"; \
echo "csgo, left4dead2, left4dead, orangeboxvalve, css, orangebox, or original"; \
exit 1; \
fi
sourcemod: check $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
default: all
clean: check
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/$(BINARY)

View File

@ -308,7 +308,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
{
ItemDrawInfo &dr = drawItems[foundItems].draw;
/* Is the item valid? */
if (menu->GetItemInfo(i, &dr) != NULL)
if (menu->GetItemInfo(i, &dr, client) != NULL)
{
/* Ask the user to change the style, if necessary */
mh->OnMenuDrawItem(menu, client, i, dr.style);
@ -398,7 +398,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
}
while (++lastItem < totalItems)
{
if (menu->GetItemInfo(lastItem, &dr) != NULL)
if (menu->GetItemInfo(lastItem, &dr, client) != NULL)
{
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
if (IsSlotItem(panel, dr.style))
@ -420,7 +420,7 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
lastItem--;
while (lastItem != 0)
{
if (menu->GetItemInfo(lastItem, &dr) != NULL)
if (menu->GetItemInfo(lastItem, &dr, client) != NULL)
{
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
if (IsSlotItem(panel, dr.style))
@ -446,7 +446,7 @@ skip_search:
char text[50];
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "No Vote", &client))
{
UTIL_Format(text, sizeof(text), "No Vote");
ke::SafeStrcpy(text, sizeof(text), "No Vote");
}
ItemDrawInfo dr(text, 0);
position = panel->DrawItem(dr);
@ -570,7 +570,7 @@ skip_search:
/* If there are no control options,
* Instead just pad with invisible slots.
*/
if (!displayPrev && !displayPrev)
if (!displayNext && !displayPrev)
{
padItem.style = ITEMDRAW_NOTEXT;
}
@ -606,7 +606,7 @@ skip_search:
{
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
{
UTIL_Format(text, sizeof(text), "Back");
ke::SafeStrcpy(text, sizeof(text), "Back");
}
dr.style = ITEMDRAW_CONTROL;
position = panel->DrawItem(dr);
@ -616,7 +616,7 @@ skip_search:
{
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
{
UTIL_Format(text, sizeof(text), "Previous");
ke::SafeStrcpy(text, sizeof(text), "Previous");
}
dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
position = panel->DrawItem(dr);
@ -637,7 +637,7 @@ skip_search:
{
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
{
UTIL_Format(text, sizeof(text), "Next");
ke::SafeStrcpy(text, sizeof(text), "Next");
}
dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
position = panel->DrawItem(dr);
@ -668,7 +668,7 @@ skip_search:
{
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
{
UTIL_Format(text, sizeof(text), "Exit");
ke::SafeStrcpy(text, sizeof(text), "Exit");
}
dr.style = ITEMDRAW_CONTROL;
position = panel->DrawItem(dr);

View File

@ -338,7 +338,8 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
#endif
0,
PITCH_NORM,
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2
0,
#endif
&pos);
@ -632,7 +633,7 @@ bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
return false;
}
CItem item;
CItem item(m_items.length());
item.info = info;
if (draw.display)
@ -654,7 +655,7 @@ bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDr
if (position >= m_items.length())
return false;
CItem item;
CItem item(position);
item.info = info;
if (draw.display)
item.display = new ke::AString(draw.display);
@ -678,11 +679,16 @@ void CBaseMenu::RemoveAllItems()
m_items.clear();
}
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */, int client/* =0 */)
{
if (position >= m_items.length())
return NULL;
if (client > 0 && position < m_RandomMaps[client].length())
{
position = m_RandomMaps[client][position];
}
if (draw)
{
draw->display = m_items[position].display->chars();
@ -692,6 +698,62 @@ const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =
return m_items[position].info.chars();
}
void CBaseMenu::ShufflePerClient(int start, int stop)
{
// limit map len to 255 items since it's using uint8
int length = MIN(GetItemCount(), 255);
if (stop >= 0)
length = MIN(length, stop);
for (int i = 1; i < SM_MAXPLAYERS + 1; i++)
{
// populate per-client map ...
m_RandomMaps[i].resize(length);
for (int j = 0; j < length; j++)
m_RandomMaps[i][j] = j;
// ... and random shuffle it
for (int j = length - 1; j > start; j--)
{
int x = rand() % (j - start + 1) + start;
uint8_t tmp = m_RandomMaps[i][x];
m_RandomMaps[i][x] = m_RandomMaps[i][j];
m_RandomMaps[i][j] = tmp;
}
}
}
void CBaseMenu::SetClientMapping(int client, int *array, int length)
{
length = MIN(length, 255);
m_RandomMaps[client].resize(length);
for (int i = 0; i < length; i++)
{
m_RandomMaps[client][i] = array[i];
}
}
bool CBaseMenu::IsPerClientShuffled()
{
for (int i = 1; i < SM_MAXPLAYERS + 1; i++)
{
if(m_RandomMaps[i].length() > 0)
return true;
}
return false;
}
unsigned int CBaseMenu::GetRealItemIndex(int client, unsigned int position)
{
if (client > 0 && position < m_RandomMaps[client].length())
{
position = m_RandomMaps[client][position];
return m_items[position].index;
}
return position;
}
unsigned int CBaseMenu::GetItemCount()
{
return m_items.length();

View File

@ -34,6 +34,7 @@
#include <IMenuManager.h>
#include <IPlayerHelpers.h>
#include <am-autoptr.h>
#include <am-string.h>
#include <am-vector.h>
#include "sm_fastlink.h"
@ -43,36 +44,40 @@ using namespace SourceMod;
class CItem
{
public:
CItem()
CItem(unsigned int index)
{
this->index = index;
style = 0;
access = 0;
}
CItem(ke::Moveable<CItem> other)
: info(ke::Move(other->info)),
display(ke::Move(other->display))
CItem(CItem &&other)
: info(ke::Move(other.info)),
display(ke::Move(other.display))
{
style = other->style;
access = other->access;
index = other.index;
style = other.style;
access = other.access;
}
CItem & operator =(ke::Moveable<CItem> other)
CItem & operator =(CItem &&other)
{
info = ke::Move(other->info);
display = ke::Move(other->display);
style = other->style;
access = other->access;
index = other.index;
info = ke::Move(other.info);
display = ke::Move(other.display);
style = other.style;
access = other.access;
return *this;
}
public:
unsigned int index;
ke::AString info;
ke::AutoPtr<ke::AString> display;
unsigned int style;
unsigned int access;
private:
CItem(const CItem &other) KE_DELETE;
CItem &operator =(const CItem &other) KE_DELETE;
CItem(const CItem &other) = delete;
CItem &operator =(const CItem &other) = delete;
};
class CBaseMenuPlayer
@ -137,7 +142,7 @@ public:
virtual bool InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw);
virtual bool RemoveItem(unsigned int position);
virtual void RemoveAllItems();
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL);
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL, int client=0);
virtual unsigned int GetItemCount();
virtual bool SetPagination(unsigned int itemsPerPage);
virtual unsigned int GetPagination();
@ -151,6 +156,10 @@ public:
virtual unsigned int GetMenuOptionFlags();
virtual void SetMenuOptionFlags(unsigned int flags);
virtual IMenuHandler *GetHandler();
virtual void ShufflePerClient(int start, int stop);
virtual void SetClientMapping(int client, int *array, int length);
virtual bool IsPerClientShuffled();
virtual unsigned int GetRealItemIndex(int client, unsigned int position);
unsigned int GetBaseMemUsage();
private:
void InternalDelete();
@ -167,6 +176,7 @@ protected:
Handle_t m_hHandle;
IMenuHandler *m_pHandler;
unsigned int m_nFlags;
ke::Vector<uint8_t> m_RandomMaps[SM_MAXPLAYERS+1];
};
#endif //_INCLUDE_MENUSTYLE_BASE_H

View File

@ -83,6 +83,10 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
}
g_bRadioInit = true;
// Always register the style. Use IsSupported() to check for validity before use.
g_Menus.AddStyle(this);
const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
if (!msg || msg[0] == '\0')
{
@ -118,7 +122,6 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
}
}
g_Menus.AddStyle(this);
g_Menus.SetDefaultStyle(this);
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
@ -138,11 +141,7 @@ void CRadioStyle::OnSourceModShutdown()
bool CRadioStyle::IsSupported()
{
#if SOURCE_ENGINE == SE_DOTA
return false;
#else
return (g_ShowMenuId != -1);
#endif
}
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
@ -173,10 +172,9 @@ void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFi
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
#endif
{
#if SOURCE_ENGINE != SE_DOTA
int count = pFilter->GetRecipientCount();
#ifdef USE_PROTOBUF_USERMESSAGES
#if SOURCE_ENGINE == SE_CSGO
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
#else
bf_read br(bf->GetBasePointer(), 3);
@ -191,7 +189,6 @@ void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFil
{
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
}
#endif
}
void CRadioStyle::OnUserMessageSent(int msg_id)
@ -453,7 +450,7 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
{
if (title[0] != '\0')
{
display_len = UTIL_Format(display_pkt,
display_len = ke::SafeSprintf(display_pkt,
sizeof(display_pkt),
"%s\n%s",
title,
@ -461,9 +458,8 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
}
else
{
display_len = UTIL_Format(display_pkt,
display_len = ke::SafeStrcpy(display_pkt,
sizeof(display_pkt),
"%s",
text);
}
display_keys = keys;
@ -471,7 +467,6 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
void CRadioMenuPlayer::Radio_Refresh()
{
#if SOURCE_ENGINE != SE_DOTA
cell_t players[1] = { (cell_t)m_index };
char *ptr = display_pkt;
char save = 0;
@ -488,8 +483,7 @@ void CRadioMenuPlayer::Radio_Refresh()
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
}
#ifdef USE_PROTOBUF_USERMESSAGES
// If or when we need to support multiple games per engine with this, we can switch to reflection
#if SOURCE_ENGINE == SE_CSGO
// TODO: find what happens past 240 on CS:GO
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
msg->set_bits_valid_slots(display_keys);
@ -525,7 +519,6 @@ void CRadioMenuPlayer::Radio_Refresh()
#endif
display_last_refresh = gpGlobals->curtime;
#endif // !DOTA
}
int CRadioDisplay::GetAmountRemaining()
@ -593,6 +586,7 @@ bool CRadioMenu::DisplayAtItem(int client,
return false;
}
AutoHandleRooter ahr(this->GetHandle());
return g_RadioMenuStyle.DoClientMenu(client,
this,
start_item,

View File

@ -41,6 +41,8 @@
#include "sm_fastlink.h"
#include <sh_stack.h>
#include <compat_wrappers.h>
#include "logic/common_logic.h"
#include "AutoHandleRooter.h"
using namespace SourceMod;

View File

@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@ -65,20 +65,16 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom
void ValveMenuStyle::OnSourceModAllInitialized()
{
#if SOURCE_ENGINE != SE_DOTA
g_Players.AddClientListener(this);
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
#endif
}
void ValveMenuStyle::OnSourceModShutdown()
{
#if SOURCE_ENGINE != SE_DOTA
SH_RELEASE_CALLCLASS(g_pSPHCC);
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
g_Players.RemoveClientListener(this);
#endif
}
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
@ -297,7 +293,7 @@ unsigned int CValveMenuDisplay::DrawItem(const ItemDrawInfo &item)
}
char buffer[255];
UTIL_Format(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
ke::SafeSprintf(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
KeyValues *ki = m_pKv->FindKey(g_OptionNumTable[m_NextPos], true);
ki->SetString("command", g_OptionCmdTable[m_NextPos]);
@ -382,7 +378,7 @@ bool CValveMenu::SetExtOption(MenuOption option, const void *valuePtr)
{
if (option == MenuOption_IntroMessage)
{
strncopy(m_IntroMsg, (const char *)valuePtr, sizeof(m_IntroMsg));
ke::SafeStrcpy(m_IntroMsg, sizeof(m_IntroMsg), (const char *)valuePtr);
return true;
} else if (option == MenuOption_IntroColor) {
unsigned int *array = (unsigned int *)valuePtr;
@ -408,6 +404,7 @@ bool CValveMenu::DisplayAtItem(int client,
return false;
}
AutoHandleRooter ahr(this->GetHandle());
return g_ValveMenuStyle.DoClientMenu(client, this, start_item, alt_handler ? alt_handler : m_pHandler, time);
}

View File

@ -39,6 +39,8 @@
#include "KeyValues.h"
#include "sm_fastlink.h"
#include <compat_wrappers.h>
#include "logic/common_logic.h"
#include "AutoHandleRooter.h"
using namespace SourceMod;

View File

@ -514,15 +514,16 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
/* Check by our item count, NOT the vote array size */
if (item < m_Items)
{
m_ClientVotes[client] = item;
m_Votes[item]++;
unsigned int index = menu->GetRealItemIndex(client, item);
m_ClientVotes[client] = index;
m_Votes[index]++;
m_NumVotes++;
if (sm_vote_chat.GetBool() || sm_vote_console.GetBool() || sm_vote_client_console.GetBool())
{
static char buffer[1024];
ItemDrawInfo dr;
menu->GetItemInfo(item, &dr);
menu->GetItemInfo(item, &dr, client);
if (sm_vote_console.GetBool())
{

View File

@ -35,8 +35,10 @@
#include "sourcemm_api.h"
#include "sm_stringutil.h"
#include "sourcehook.h"
#include "sm_srvcmds.h"
#include "logic_bridge.h"
#include "compat_wrappers.h"
#include <time.h>
#include <bridge/include/ILogger.h>
NextMapManager g_NextMap;
@ -46,24 +48,16 @@ SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, co
SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool);
#endif
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#else
# if SH_IMPL_VERSION >= 4
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
#endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#endif
ConCommand *changeLevelCmd = NULL;
ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY);
ConVar sm_maphistory_size("sm_maphistory_size", "20");
bool g_forcedChange = false;
@ -144,8 +138,8 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
logger->LogMessage("[SM] Changed map to \"%s\"", newmap);
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change");
#if SOURCE_ENGINE != SE_DARKMESSIAH
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
@ -168,33 +162,36 @@ void NextMapManager::OnSourceModLevelChange( const char *mapName )
{
/* Something intercepted the mapchange */
char newReason[255];
UTIL_Format(newReason, sizeof(newReason), "%s (Map overridden)", m_tempChangeInfo.m_changeReason);
ke::SafeSprintf(newReason, sizeof(newReason), "%s (Map overridden)", m_tempChangeInfo.m_changeReason);
m_mapHistory.push_back(new MapChangeData(lastMap, newReason, m_tempChangeInfo.startTime));
}
/* TODO: Should this be customizable? */
if (m_mapHistory.size() > 20)
int historydiff = sm_maphistory_size.GetInt();
if (historydiff > 0)
{
SourceHook::List<MapChangeData *>::iterator iter;
iter = m_mapHistory.begin();
historydiff -= m_mapHistory.size();
} else if (historydiff < 0)
{
historydiff = (m_mapHistory.size() * -1);
}
for (SourceHook::List<MapChangeData *>::iterator iter = m_mapHistory.begin(); historydiff++ < 0; iter = m_mapHistory.erase(iter))
{
delete (MapChangeData *)*iter;
m_mapHistory.erase(iter);
}
}
m_tempChangeInfo.m_mapName[0] ='\0';
m_tempChangeInfo.m_changeReason[0] = '\0';
m_tempChangeInfo.startTime = time(NULL);
UTIL_Format(lastMap, sizeof(lastMap), "%s", mapName);
ke::SafeStrcpy(lastMap, sizeof(lastMap), mapName);
}
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
{
/* Store the mapname and reason */
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), "%s", mapName);
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "%s", changeReason);
ke::SafeStrcpy(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName);
ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), changeReason);
/* Change level and skip our hook */
g_forcedChange = true;
@ -208,10 +205,7 @@ NextMapManager::NextMapManager()
m_mapHistory = SourceHook::List<MapChangeData *>();
}
#if SOURCE_ENGINE == SE_DOTA
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command)
{
#else
@ -227,7 +221,7 @@ void CmdChangeLevelCallback()
if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0')
{
UTIL_Format(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
UTIL_Format(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1));
ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command");
}
}

View File

@ -33,16 +33,17 @@
#define _INCLUDE_SOURCEMOD_NEXTMAP_H_
#include "sm_globals.h"
#include "eiface.h"
#include <eiface.h>
#include "sh_list.h"
#include "sm_stringutil.h"
#include <amtl/am-string.h>
struct MapChangeData
{
MapChangeData(const char *mapName, const char *changeReason, time_t time)
{
UTIL_Format(m_mapName, sizeof(m_mapName), mapName);
UTIL_Format(m_changeReason, sizeof(m_changeReason), changeReason);
ke::SafeStrcpy(m_mapName, sizeof(m_mapName), mapName);
ke::SafeStrcpy(m_changeReason, sizeof(m_changeReason), changeReason);
startTime = time;
}
@ -58,9 +59,7 @@ struct MapChangeData
time_t startTime;
};
#if SOURCE_ENGINE == SE_DOTA
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command);
#else
void CmdChangeLevelCallback();
@ -71,9 +70,7 @@ class NextMapManager : public SMGlobalClass
public:
NextMapManager();
#if SOURCE_ENGINE == SE_DOTA
friend void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
friend void CmdChangeLevelCallback(const CCommand &command);
#else
friend void CmdChangeLevelCallback();

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* Copyright (C) 2004-2015 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
@ -38,16 +38,20 @@
#include <IForwardSys.h>
#include <IPlayerHelpers.h>
#include <IAdminSystem.h>
#include <ITranslator.h>
#include <sh_string.h>
#include <sh_list.h>
#include <sh_vector.h>
#include <am-string.h>
#include <am-deque.h>
#include "ConVarManager.h"
#include <steam/steamclientpublic.h>
using namespace SourceHook;
class IClient;
#define PLAYER_LIFE_UNKNOWN 0
#define PLAYER_LIFE_ALIVE 1
#define PLAYER_LIFE_DEAD 2
@ -104,6 +108,9 @@ public:
void DoBasicAdminChecks();
void MarkAsBeingKicked();
int GetLifeState();
// This can be NULL for fakeclients due to limitations in our impl
IClient *GetIClient() const;
private:
void Initialize(const char *name, const char *ip, edict_t *pEntity);
void Connect();
@ -115,45 +122,52 @@ private:
void Authorize_Post();
void DoPostConnectAuthorization();
bool IsAuthStringValidated();
bool SetEngineString();
bool SetCSteamID();
void ClearNetchannelQueue(void);
private:
bool m_IsConnected;
bool m_IsInGame;
bool m_IsAuthorized;
bool m_bIsInKickQueue;
bool m_IsConnected = false;
bool m_IsInGame = false;
bool m_IsAuthorized = false;
bool m_bIsInKickQueue = false;
String m_Name;
String m_Ip;
String m_IpNoPort;
ke::AString m_AuthID;
ke::AString m_Steam2Id;
ke::AString m_Steam3Id;
AdminId m_Admin;
bool m_TempAdmin;
edict_t *m_pEdict;
IPlayerInfo *m_Info;
AdminId m_Admin = INVALID_ADMIN_ID;
bool m_TempAdmin = false;
edict_t *m_pEdict = nullptr;
IPlayerInfo *m_Info = nullptr;
IClient *m_pIClient = nullptr;
String m_LastPassword;
bool m_bAdminCheckSignalled;
bool m_bAdminCheckSignalled = false;
int m_iIndex;
unsigned int m_LangId;
int m_UserId;
bool m_bFakeClient;
bool m_bIsSourceTV;
bool m_bIsReplay;
unsigned int m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
int m_UserId = -1;
bool m_bFakeClient = false;
bool m_bIsSourceTV = false;
bool m_bIsReplay = false;
serial_t m_Serial;
CSteamID m_SteamId;
#if SOURCE_ENGINE == SE_CSGO
QueryCvarCookie_t m_LanguageCookie;
QueryCvarCookie_t m_LanguageCookie = InvalidQueryCvarCookie;
#endif
ke::Deque<ke::AString> m_PrintfBuffer;
};
class PlayerManager :
public SMGlobalClass,
public IPlayerManager
public IPlayerManager,
public IGameEventListener2
{
friend class CPlayer;
public:
PlayerManager();
~PlayerManager();
public: //SMGlobalClass
void OnSourceModStartup(bool late) override;
void OnSourceModAllInitialized();
void OnSourceModShutdown();
void OnSourceModLevelEnd();
@ -163,16 +177,6 @@ public:
CPlayer *GetPlayerByIndex(int client) const;
void RunAuthChecks();
public:
#if SOURCE_ENGINE == SE_DOTA
bool OnClientConnect(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
bool OnClientConnect_Post(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
void OnClientPutInServer(CEntityIndex index, char const *playername);
void OnClientDisconnect(CEntityIndex index, int reason);
void OnClientDisconnect_Post(CEntityIndex index, int reason);
void OnClientCommand(CEntityIndex index, const CCommand &args);
void OnClientSettingsChanged(CEntityIndex index);
//void OnClientSettingsChanged_Pre(CEntityIndex client);
#else
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
void OnClientPutInServer(edict_t *pEntity, char const *playername);
@ -180,13 +184,18 @@ public:
void OnClientDisconnect_Post(edict_t *pEntity);
#if SOURCE_ENGINE >= SE_ORANGEBOX
void OnClientCommand(edict_t *pEntity, const CCommand &args);
#if SOURCE_ENGINE >= SE_EYE
void OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pCommand);
void OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *pCommand);
#endif
#else
void OnClientCommand(edict_t *pEntity);
#endif
void OnClientSettingsChanged(edict_t *pEntity);
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
#endif
void OnServerHibernationUpdate(bool bHibernating);
void OnClientPrintf(edict_t *pEdict, const char *szMsg);
void OnPrintfFrameAction(unsigned int serial);
public: //IPlayerManager
void AddClientListener(IClientListener *listener);
void RemoveClientListener(IClientListener *listener);
@ -194,6 +203,7 @@ public: //IPlayerManager
IGamePlayer *GetGamePlayer(edict_t *pEdict);
int GetMaxClients();
int GetNumPlayers();
int GetNumClients();
int GetClientOfUserId(int userid);
bool IsServerActivated();
int FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags);
@ -204,6 +214,8 @@ public: //IPlayerManager
int GetClientFromSerial(unsigned int serial);
void ClearAdminId(AdminId id);
void RecheckAnyAdmins();
public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent);
public:
inline int MaxClients()
{
@ -223,15 +235,15 @@ public:
unsigned int GetReplyTo();
unsigned int SetReplyTo(unsigned int reply);
void MaxPlayersChanged(int newvalue = -1);
inline bool InClientCommandKeyValuesHook()
{
return m_bInCCKVHook;
}
#if SOURCE_ENGINE == SE_CSGO
bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
bool HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
#endif
private:
#if SOURCE_ENGINE == SE_DOTA
void OnServerActivate();
#else
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
#endif
void InvalidatePlayer(CPlayer *pPlayer);
private:
List<IClientListener *> m_hooks;
@ -241,6 +253,8 @@ private:
IForward *m_cldisconnect_post;
IForward *m_clputinserver;
IForward *m_clcommand;
IForward *m_clcommandkv;
IForward *m_clcommandkv_post;
IForward *m_clinfochanged;
IForward *m_clauth;
IForward *m_onActivate;
@ -250,7 +264,7 @@ private:
int m_maxClients;
int m_PlayerCount;
int m_PlayersSinceActive;
bool m_FirstPass;
bool m_bServerActivated;
unsigned int *m_AuthQueue;
String m_PassInfoVar;
bool m_QueryLang;
@ -261,11 +275,14 @@ private:
bool m_bIsReplayActive;
int m_SourceTVUserId;
int m_ReplayUserId;
bool m_bInCCKVHook;
int m_ClientCount;
private:
static const int NETMSG_TYPE_BITS = 5; // SVC_Print overhead for netmsg type
static const int SVC_Print_BufferSize = 2048 - 1; // -1 for terminating \0
};
#if SOURCE_ENGINE == SE_DOTA
void CmdMaxplayersCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdMaxplayersCallback(const CCommand &command);
#else
void CmdMaxplayersCallback();

View File

@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2013 AlliedModders LLC. All rights reserved.
@ -34,6 +34,7 @@
#include <sh_list.h>
#include <google/protobuf/descriptor.h>
#include <amtl/am-string.h>
#define GETCHECK_FIELD() \
const protobuf::FieldDescriptor *field = msg->GetDescriptor()->FindFieldByName(pszFieldName); \
@ -117,6 +118,13 @@ public:
return msg;
}
inline bool HasField(const char *pszFieldName)
{
GETCHECK_FIELD();
CHECK_FIELD_NOT_REPEATED();
return msg->GetReflection()->HasField(*msg, field);
}
inline bool GetInt32(const char *pszFieldName, int32 *out)
{
GETCHECK_FIELD();
@ -340,6 +348,20 @@ public:
return true;
}
inline bool GetInt64OrUnsigned(const char *pszFieldName, int64 *out)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
*out = (int64)msg->GetReflection()->GetUInt64(*msg, field);
else
*out = msg->GetReflection()->GetInt64(*msg, field);
return true;
}
inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
{
@ -366,6 +388,24 @@ public:
return true;
}
inline bool SetInt64OrUnsigned(const char *pszFieldName, int64 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
{
msg->GetReflection()->SetUInt64(msg, field, (uint64)value);
}
else
{
msg->GetReflection()->SetInt64(msg, field, value);
}
return true;
}
inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out)
{
@ -383,6 +423,21 @@ public:
return true;
}
inline bool GetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 *out)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
*out = (int64)msg->GetReflection()->GetRepeatedUInt64(*msg, field, index);
else
*out = msg->GetReflection()->GetRepeatedInt64(*msg, field, index);
return true;
}
inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value)
{
@ -410,6 +465,25 @@ public:
return true;
}
inline bool SetRepeatedInt64OrUnsigned(const char *pszFieldName, int index, int64 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
{
msg->GetReflection()->SetRepeatedUInt64(msg, field, index, (uint64)value);
}
else
{
msg->GetReflection()->SetRepeatedInt64(msg, field, index, value);
}
return true;
}
inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
{
@ -436,6 +510,24 @@ public:
return true;
}
inline bool AddInt64OrUnsigned(const char *pszFieldName, int64 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE2(INT64, UINT64);
CHECK_FIELD_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT64)
{
msg->GetReflection()->AddUInt64(msg, field, (uint64)value);
}
else
{
msg->GetReflection()->AddInt64(msg, field, value);
}
return true;
}
inline bool GetBool(const char *pszFieldName, bool *out)
{
@ -672,7 +764,7 @@ public:
CHECK_FIELD_NOT_REPEATED();
std::string scratch;
strncopy(out, msg->GetReflection()->GetStringReference(*msg, field, &scratch).c_str(), size);
ke::SafeStrcpy(out, size, msg->GetReflection()->GetStringReference(*msg, field, &scratch).c_str());
return true;
}
@ -695,7 +787,7 @@ public:
CHECK_REPEATED_ELEMENT(index);
std::string scratch;
strncopy(out, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str(), size);
ke::SafeStrcpy(out, size, msg->GetReflection()->GetRepeatedStringReference(*msg, field, index, &scratch).c_str());
return true;
}

View File

@ -33,15 +33,14 @@
#include "sm_stringutil.h"
#include "logic_bridge.h"
#if SOURCE_ENGINE == SE_DOTA
#include <dota_usermessage_helpers.h>
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessage_helpers.h>
#endif
#include <amtl/am-string.h>
UserMessages g_UserMsgs;
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
#else
#if SOURCE_ENGINE >= SE_LEFT4DEAD
@ -94,7 +93,7 @@ void UserMessages::OnSourceModAllShutdown()
{
if (m_HookCount)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
#else
@ -109,10 +108,7 @@ void UserMessages::OnSourceModAllShutdown()
int UserMessages::GetMessageIndex(const char *msg)
{
#if SOURCE_ENGINE == SE_DOTA
// Can split this per engine and/or game later
return g_DotaUsermessageHelpers.GetIndex(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
// Can split this per engine and/or game later
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
#else
@ -150,15 +146,13 @@ int UserMessages::GetMessageIndex(const char *msg)
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
{
#ifdef USE_PROTOBUF_USERMESSAGES
#if SOURCE_ENGINE == SE_DOTA
const char *pszName = g_DotaUsermessageHelpers.GetName(msgid);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
#endif
if (!pszName)
return false;
strncopy(buffer, pszName, maxlength);
ke::SafeStrcpy(buffer, maxlength, pszName);
return true;
#else
if (m_FallbackSearch)
@ -171,7 +165,7 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
if (msg)
{
strncopy(buffer, msg, maxlength);
ke::SafeStrcpy(buffer, maxlength, msg);
return true;
}
@ -303,7 +297,7 @@ bool UserMessages::EndMessage()
return false;
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
@ -333,7 +327,7 @@ bool UserMessages::EndMessage()
} else {
engine->MessageEnd();
}
#endif // SE_CSGO || SE_DOTA
#endif // SE_CSGO
m_InExec = false;
m_CurFlags = 0;
@ -418,7 +412,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
if (!m_HookCount++)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
#else
@ -442,9 +436,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
#ifdef USE_PROTOBUF_USERMESSAGES
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
{
#if SOURCE_ENGINE == SE_DOTA
return g_DotaUsermessageHelpers.GetPrototype(msg_type);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
#endif
}
@ -495,7 +487,7 @@ void UserMessages::_DecRefCounter()
{
if (--m_HookCount == 0)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
#else
@ -507,12 +499,10 @@ void UserMessages::_DecRefCounter()
}
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
{
#if SOURCE_ENGINE == SE_DOTA
OnStartMessage_Pre(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
if (m_FakeMetaRes == MRES_SUPERCEDE)
@ -527,9 +517,7 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type,
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
}
#if SOURCE_ENGINE == SE_DOTA
OnStartMessage_Post(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
@ -563,7 +551,7 @@ void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type
RETURN_META(res)
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
@ -603,7 +591,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
@ -768,7 +756,7 @@ void UserMessages::OnMessageEnd_Pre()
if (!handled && intercepted)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
#else
bf_write *engine_bfw;
@ -780,11 +768,11 @@ void UserMessages::OnMessageEnd_Pre()
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
ENGINE_CALL(MessageEnd)();
#endif // SE_CSGO || SE_DOTA
#endif // SE_CSGO
}
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
int size = m_OrigBuffer->ByteSize();
uint8 *data = (uint8 *)stackalloc(size);
m_OrigBuffer->SerializePartialToArray(data, size);
@ -814,7 +802,7 @@ void UserMessages::OnMessageEnd_Pre()
iter++;
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
delete pTempMsg;
#endif
}

View File

@ -44,7 +44,7 @@
using namespace SourceHook;
using namespace SourceMod;
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
#define USE_PROTOBUF_USERMESSAGES
#endif
@ -102,12 +102,12 @@ public: //IUserMessages
bool intercept=false);
UserMessageType GetUserMessageType() const;
public:
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
#elif SOURCE_ENGINE >= SE_LEFT4DEAD

77
core/command_args.h Normal file
View File

@ -0,0 +1,77 @@
// vim: set ts=4 sw=4 tw=99 noet :
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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_CCOMMANDARGS_IMPL_H_
#define _INCLUDE_SOURCEMOD_CCOMMANDARGS_IMPL_H_
#include "sourcemm_api.h"
#include <IRootConsoleMenu.h>
#include <compat_wrappers.h>
#if SOURCE_ENGINE==SE_EPISODEONE || SOURCE_ENGINE==SE_DARKMESSIAH
class EngineArgs : public ICommandArgs
{
public:
EngineArgs(const CCommand& _cmd)
{
}
const char *Arg(int n) const
{
return engine->Cmd_Argv(n);
}
int ArgC() const
{
return engine->Cmd_Argc();
}
const char *ArgS() const
{
return engine->Cmd_Args();
}
};
#else
class EngineArgs : public ICommandArgs
{
const CCommand *cmd;
public:
EngineArgs(const CCommand& _cmd) : cmd(&_cmd)
{
}
const char *Arg(int n) const
{
return cmd->Arg(n);
}
int ArgC() const
{
return cmd->ArgC();
}
const char *ArgS() const
{
return cmd->ArgS();
}
};
#endif
#endif // _INCLUDE_SOURCEMOD_CCOMMANDARGS_IMPL_H_

View File

@ -1,33 +1,29 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
// vim: set ts=4 sw=4 tw=99 et:
// =============================================================================
// SourceMod
// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
// =============================================================================
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License, version 3.0, as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, AlliedModders LLC gives you permission to link the
// code of this program (as well as its derivative works) to "Half-Life 2," the
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
// by the Valve Corporation. You must obey the GNU General Public License in
// all respects for all other code used. Additionally, AlliedModders LLC grants
// this exception to all derivative works. AlliedModders LLC defines further
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
// or <http://www.sourcemod.net/license.php>.
#include "sm_globals.h"
#include <sh_list.h>
@ -36,10 +32,15 @@
#include "sm_stringutil.h"
#include "sourcemm_api.h"
#include "compat_wrappers.h"
#include <amtl/am-string.h>
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
#if SOURCE_ENGINE == SE_CSGO
SH_DECL_HOOK2_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *, bool);
#else
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
#endif
#else
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
#endif
@ -81,7 +82,11 @@ public:
#endif
}
#if SOURCE_ENGINE == SE_CSGO
void LinkConCommandBase(ConCommandBase *pBase, bool unknown)
#else
void LinkConCommandBase(ConCommandBase *pBase)
#endif
{
IConCommandLinkListener *listener = IConCommandLinkListener::head;
while (listener)
@ -103,41 +108,20 @@ public:
listener = listener->next;
}
if (pBase)
{
while (iter != tracked_bases.end())
{
if ((*iter)->pBase == pBase)
{
pInfo = (*iter);
iter = tracked_bases.erase(iter);
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
delete pInfo;
}
else
{
iter++;
}
}
}
else
{
while (iter != tracked_bases.end())
{
/* This is just god-awful! */
if (FindCommandBase((*iter)->name) != (*iter)->pBase)
{
pInfo = (*iter);
iter = tracked_bases.erase(iter);
pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false);
delete pInfo;
}
else
{
iter++;
}
}
}
while (iter != tracked_bases.end())
{
if ((*iter)->pBase == pBase)
{
pInfo = (*iter);
iter = tracked_bases.erase(iter);
pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName());
delete pInfo;
}
else
{
iter++;
}
}
}
void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
@ -146,7 +130,7 @@ public:
info->pBase = pBase;
info->cls = cls;
strncopy(info->name, pBase->GetName(), sizeof(info->name));
ke::SafeStrcpy(info->name, sizeof(info->name), pBase->GetName());
tracked_bases.push_back(info);
}

View File

@ -35,7 +35,7 @@
class IConCommandTracker
{
public:
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0;
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) = 0;
};
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);

View File

@ -1,551 +0,0 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: 2006-08-13 06:34:30 -0500 (Sun, 13 Aug 2006) $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//=============================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE
#elif _LINUX
#define FORCEINLINE_CVAR __inline__ FORCEINLINE
#else
#error "implement me"
#endif
// The default, no flags at all
#define FCVAR_NONE 0
// Command to ConVars and ConCommands
// ConVar Systems
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
#define FCVAR_LAUNCHER (1<<1) // defined by launcher
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system.
#define FCVAR_DATACACHE (1<<19) // Defined by the datacache system.
#define FCVAR_STUDIORENDER (1<<15) // Defined by the studiorender system.
#define FCVAR_FILESYSTEM (1<<21) // Defined by the file system.
#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin.
#define FCVAR_TOOLSYSTEM (1<<20) // Defined by an IToolSystem library
#define FCVAR_SOUNDSYSTEM (1<<23) // Defined by the soundsystem library
#define FCVAR_INPUTSYSTEM (1<<25) // Defined by the inputsystem dll
#define FCVAR_NETWORKSYSTEM (1<<26) // Defined by the network system
// NOTE!! if you add a cvar system, add it here too!!!!
// the engine lacks a cvar flag, but needs it for xbox
// an engine cvar is thus a cvar not marked with any other system
#define FCVAR_NON_ENGINE ((FCVAR_LAUNCHER|FCVAR_GAMEDLL|FCVAR_CLIENTDLL|FCVAR_MATERIAL_SYSTEM|FCVAR_DATACACHE|FCVAR_STUDIORENDER|FCVAR_FILESYSTEM|FCVAR_PLUGIN|FCVAR_TOOLSYSTEM|FCVAR_SOUNDSYSTEM|FCVAR_INPUTSYSTEM|FCVAR_NETWORKSYSTEM))
// ConVar only
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
#define FCVAR_USERINFO (1<<9) // changes the client's info string
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
// It's a ConVar that's shared between the client and the server.
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
// client, of course )
// If a change is requested it must come from the console (i.e., no remote client changes)
// If a value is changed while a server is active, it's replicated to all connected clients
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox
// #define FCVAR_AVAILABLE (1<<27)
// #define FCVAR_AVAILABLE (1<<28)
// #define FCVAR_AVAILABLE (1<<29)
// #define FCVAR_AVAILABLE (1<<30)
// #define FCVAR_AVAILABLE (1<<31)
class ConVar;
class ConCommand;
class ConCommandBase;
// Any executable that wants to use ConVars need to implement one of
// these to hook up access to console variables.
class IConCommandBaseAccessor
{
public:
// Flags is a combination of FCVAR flags in cvar.h.
// hOut is filled in with a handle to the variable.
virtual bool RegisterConCommandBase( ConCommandBase *pVar )=0;
};
// You don't have to instantiate one of these, just call its
// OneTimeInit function when your executable is initializing.
class ConCommandBaseMgr
{
public:
// Call this ONCE when the executable starts up.
static void OneTimeInit( IConCommandBaseAccessor *pAccessor );
#ifdef _XBOX
static bool Fixup( ConCommandBase* pConCommandBase );
#ifndef _RETAIL
static void PublishCommands( bool bForce );
#endif
#endif
};
// Called when a ConVar changes value
typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString );
// Called when a ConCommand needs to execute
typedef void ( *FnCommandCallback )( void );
#define COMMAND_COMPLETION_MAXITEMS 64
#define COMMAND_COMPLETION_ITEM_LENGTH 64
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
friend class ConVar;
friend class ConCommand;
public:
ConCommandBase( void );
ConCommandBase( char const *pName, char const *pHelpString = 0,
int flags = 0 );
virtual ~ConCommandBase( void );
virtual bool IsCommand( void ) const;
// Check flag
virtual bool IsBitSet( int flag ) const;
// Set flag
virtual void AddFlags( int flags );
// Return name of cvar
virtual char const *GetName( void ) const;
// Return help text for cvar
virtual char const *GetHelpText( void ) const;
// Deal with next pointer
const ConCommandBase *GetNext( void ) const;
void SetNext( ConCommandBase *next );
virtual bool IsRegistered( void ) const;
// Global methods
static ConCommandBase const *GetCommands( void );
static void AddToList( ConCommandBase *var );
static void RemoveFlaggedCommands( int flag );
static void RevertFlaggedCvars( int flag );
static ConCommandBase const *FindCommand( char const *name );
protected:
virtual void Create( char const *pName, char const *pHelpString = 0,
int flags = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
// Internal copy routine ( uses new operator from correct module )
char *CopyString( char const *from );
// Next ConVar in chain
ConCommandBase *m_pNext;
private:
// Has the cvar been added to the global list?
bool m_bRegistered;
// Static data
char const *m_pszName;
char const *m_pszHelpString;
// ConVar flags
int m_nFlags;
protected:
// ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through
// all the console variables and registers them.
static ConCommandBase *s_pConCommandBases;
// ConVars in this executable use this 'global' to access values.
static IConCommandBaseAccessor *s_pAccessor;
public: // Hackalicous
inline int GetFlags() const
{
return m_nFlags;
}
inline void SetFlags(int flags)
{
m_nFlags = flags;
}
};
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand : public ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
#ifdef _STATIC_LINKED
friend class G_ConCommand;
friend class C_ConCommand;
friend class M_ConCommand;
friend class S_ConCommand;
friend class D_ConCommand;
#endif
public:
typedef ConCommandBase BaseClass;
ConCommand( void );
ConCommand( char const *pName, FnCommandCallback callback,
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
virtual ~ConCommand( void );
virtual bool IsCommand( void ) const;
virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
virtual bool CanAutoComplete( void );
// Invoke the function
virtual void Dispatch( void );
private:
virtual void Create( char const *pName, FnCommandCallback callback,
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
// Call this function when executing the command
FnCommandCallback m_fnCommandCallback;
FnCommandCompletionCallback m_fnCompletionCallback;
bool m_bHasCompletionCallback;
public: // Hackalicous
inline FnCommandCallback GetCallback() const
{
return m_fnCommandCallback;
}
};
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
class ConVar : public ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
friend class CDefaultCvar;
#ifdef _STATIC_LINKED
friend class G_ConVar;
friend class C_ConVar;
friend class M_ConVar;
friend class S_ConVar;
friend class D_ConVar;
#endif
public:
typedef ConCommandBase BaseClass;
ConVar( char const *pName, char const *pDefaultValue, int flags = 0);
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, FnChangeCallback callback );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
FnChangeCallback callback );
virtual ~ConVar( void );
virtual bool IsBitSet( int flag ) const;
virtual char const* GetHelpText( void ) const;
virtual bool IsRegistered( void ) const;
virtual char const *GetName( void ) const;
virtual void AddFlags( int flags );
virtual bool IsCommand( void ) const;
// Install a change callback (there shouldn't already be one....)
void InstallChangeCallback( FnChangeCallback callback );
// Retrieve value
FORCEINLINE_CVAR float GetFloat( void ) const;
FORCEINLINE_CVAR int GetInt( void ) const;
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
FORCEINLINE_CVAR char const *GetString( void ) const;
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
// from alloc/free across dll/exe boundaries.
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
virtual void SetValue( char const *value );
virtual void SetValue( float value );
virtual void SetValue( int value );
// Reset to default value
void Revert( void );
// True if it has a min/max setting
bool GetMin( float& minVal ) const;
bool GetMax( float& maxVal ) const;
char const *GetDefault( void ) const;
static void RevertAll( void );
private:
// Called by CCvar when the value of a var is changing.
virtual void InternalSetValue(char const *value);
// For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue );
virtual bool ClampValue( float& value );
virtual void ChangeStringValue( char const *tempVal );
virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0,
char const *pHelpString = 0, bool bMin = false, float fMin = 0.0,
bool bMax = false, float fMax = false, FnChangeCallback callback = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
private:
// This either points to "this" or it points to the original declaration of a ConVar.
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
ConVar *m_pParent;
// Static data
char const *m_pszDefaultValue;
// Value
// Dynamically allocated
char *m_pszString;
int m_StringLength;
// Values
float m_fValue;
int m_nValue;
// Min/Max values
bool m_bHasMin;
float m_fMinVal;
bool m_bHasMax;
float m_fMaxVal;
// Call this function when ConVar changes
FnChangeCallback m_fnChangeCallback;
public: // Hackalicous
inline FnChangeCallback GetCallback() const
{
return m_fnChangeCallback;
}
inline void SetMin(bool set, float min=0.0)
{
m_bHasMin = set;
m_fMinVal = min;
}
inline void SetMax(bool set, float max=0.0)
{
m_bHasMax = set;
m_fMaxVal = max;
}
};
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
// Output : float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
{
return m_pParent->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
// Output : int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
{
return m_pParent->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
// Output : char const *
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR char const *ConVar::GetString( void ) const
{
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
{
return "FCVAR_NEVER_AS_STRING";
}
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
}
#ifdef _STATIC_LINKED
// identifies subsystem via piggybacking constructors with flags
class G_ConCommand : public ConCommand
{
public:
G_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_GAMEDLL, completionFunc) {}
};
class C_ConCommand : public ConCommand
{
public:
C_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_CLIENTDLL, completionFunc) {}
};
class M_ConCommand : public ConCommand
{
public:
M_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_MATERIAL_SYSTEM, completionFunc) {}
};
class S_ConCommand : public ConCommand
{
public:
S_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_STUDIORENDER, completionFunc) {}
};
class D_ConCommand : public ConCommand
{
public:
D_ConCommand(char const *pName, FnCommandCallback callback, char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ) : ConCommand(pName, callback, pHelpString, flags|FCVAR_DATACACHE, completionFunc) {}
};
typedef void ( *G_FnChangeCallback )( G_ConVar *var, char const *pOldString );
typedef void ( *C_FnChangeCallback )( C_ConVar *var, char const *pOldString );
typedef void ( *M_FnChangeCallback )( M_ConVar *var, char const *pOldString );
typedef void ( *S_FnChangeCallback )( S_ConVar *var, char const *pOldString );
typedef void ( *D_FnChangeCallback )( D_ConVar *var, char const *pOldString );
class G_ConVar : public ConVar
{
public:
G_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString ) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, (FnChangeCallback)callback ) {}
G_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, G_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_GAMEDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class C_ConVar : public ConVar
{
public:
C_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString ) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, (FnChangeCallback)callback ) {}
C_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, C_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_CLIENTDLL, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class M_ConVar : public ConVar
{
public:
M_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString ) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, (FnChangeCallback)callback ) {}
M_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_MATERIAL_SYSTEM, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class S_ConVar : public ConVar
{
public:
S_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString ) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, (FnChangeCallback)callback ) {}
S_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, S_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_STUDIORENDER, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
class D_ConVar : public ConVar
{
public:
D_ConVar( char const *pName, char const *pDefaultValue, int flags = 0) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString ) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, M_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, (FnChangeCallback)callback ) {}
D_ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, D_FnChangeCallback callback ) : ConVar(pName, pDefaultValue, flags|FCVAR_DATACACHE, pHelpString, bMin, fMin, bMax, fMax, (FnChangeCallback)callback ) {}
};
// redirect these declarations to their specific subsystem
#ifdef GAME_DLL
#define ConCommand G_ConCommand
#define ConVar G_ConVar
#endif
#ifdef CLIENT_DLL
#define ConCommand C_ConCommand
#define ConVar C_ConVar
#endif
#ifdef MATERIALSYSTEM_DLL
#define ConCommand M_ConCommand
#define ConVar M_ConVar
#endif
#ifdef STUDIORENDER_DLL
#define ConCommand S_ConCommand
#define ConVar S_ConVar
#endif
#ifdef DATACACHE_DLL
#define ConCommand D_ConCommand
#define ConVar D_ConVar
#endif
#endif // _STATIC_LINKED
//-----------------------------------------------------------------------------
// Purpose: Utility to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND( name, description ) \
static void name(); \
static ConCommand name##_command( #name, name, description ); \
static void name()
//-----------------------------------------------------------------------------
// Purpose: Utility to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND_F( name, description, flags ) \
static void name(); \
static ConCommand name##_command( #name, name, description, flags ); \
static void name()
#endif // CONVAR_H

File diff suppressed because it is too large Load Diff

View File

@ -1,718 +0,0 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//===========================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier1/iconvar.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "icvar.h"
#ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE
#elif defined _LINUX || defined __APPLE__
#define FORCEINLINE_CVAR inline
#else
#error "implement me"
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class ConVar;
class CCommand;
class ConCommand;
class ConCommandBase;
struct characterset_t;
//-----------------------------------------------------------------------------
// Any executable that wants to use ConVars need to implement one of
// these to hook up access to console variables.
//-----------------------------------------------------------------------------
class IConCommandBaseAccessor
{
public:
// Flags is a combination of FCVAR flags in cvar.h.
// hOut is filled in with a handle to the variable.
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
};
//-----------------------------------------------------------------------------
// Helper method for console development
//-----------------------------------------------------------------------------
#if defined( _X360 ) && !defined( _RETAIL )
void ConVar_PublishToVXConsole();
#endif
//-----------------------------------------------------------------------------
// Called when a ConCommand needs to execute
//-----------------------------------------------------------------------------
typedef void ( *FnCommandCallbackV1_t )( void );
typedef void ( *FnCommandCallback_t )( const CCommand &command );
#define COMMAND_COMPLETION_MAXITEMS 64
#define COMMAND_COMPLETION_ITEM_LENGTH 64
//-----------------------------------------------------------------------------
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
//-----------------------------------------------------------------------------
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
//-----------------------------------------------------------------------------
// Interface version
//-----------------------------------------------------------------------------
class ICommandCallback
{
public:
virtual void CommandCallback( const CCommand &command ) = 0;
};
class ICommandCompletionCallback
{
public:
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
friend class CCvar;
friend class ConVar;
friend class ConCommand;
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
friend void ConVar_PublishToVXConsole();
// FIXME: Remove when ConVar changes are done
friend class CDefaultCvar;
public:
ConCommandBase( void );
ConCommandBase( const char *pName, const char *pHelpString = 0,
int flags = 0 );
virtual ~ConCommandBase( void );
virtual bool IsCommand( void ) const;
// Check flag
virtual bool IsFlagSet( int flag ) const;
// Set flag
virtual void AddFlags( int flags );
// Remove flag
virtual void RemoveFlags( int flags );
// Get flags
virtual int GetFlags( void ) const;
// Return name of cvar
virtual const char *GetName( void ) const;
// Return help text for cvar
virtual const char *GetHelpText( void ) const;
// Deal with next pointer
const ConCommandBase *GetNext( void ) const;
ConCommandBase *GetNext( void );
inline void SetNext(ConCommandBase *pBase)
{
m_pNext = pBase;
}
virtual bool IsRegistered( void ) const;
// Returns the DLL identifier
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
protected:
virtual void Create( const char *pName, const char *pHelpString = 0,
int flags = 0 );
// Used internally by OneTimeInit to initialize/shutdown
virtual void Init();
void Shutdown();
// Internal copy routine ( uses new operator from correct module )
char *CopyString( const char *from );
private:
// Next ConVar in chain
// Prior to register, it points to the next convar in the DLL.
// Once registered, though, m_pNext is reset to point to the next
// convar in the global list
ConCommandBase *m_pNext;
// Has the cvar been added to the global list?
bool m_bRegistered;
// Static data
const char *m_pszName;
const char *m_pszHelpString;
// ConVar flags
int m_nFlags;
protected:
// ConVars add themselves to this list for the executable.
// Then ConVar_Register runs through all the console variables
// and registers them into a global list stored in vstdlib.dll
static ConCommandBase *s_pConCommandBases;
// ConVars in this executable use this 'global' to access values.
static IConCommandBaseAccessor *s_pAccessor;
public:
inline void SetFlags(int flags)
{
m_nFlags = flags;
}
};
//-----------------------------------------------------------------------------
// Command tokenizer
//-----------------------------------------------------------------------------
class CCommand
{
public:
CCommand();
CCommand( int nArgC, const char **ppArgV );
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
void Reset();
int ArgC() const;
const char **ArgV() const;
const char *ArgS() const; // All args that occur after the 0th arg, in string form
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
const char *operator[]( int nIndex ) const; // Gets at arguments
const char *Arg( int nIndex ) const; // Gets at arguments
// Helper functions to parse arguments to commands.
const char* FindArg( const char *pName ) const;
int FindArgInt( const char *pName, int nDefaultVal ) const;
static int MaxCommandLength();
static characterset_t* DefaultBreakSet();
private:
enum
{
COMMAND_MAX_ARGC = 64,
COMMAND_MAX_LENGTH = 512,
};
int m_nArgc;
int m_nArgv0Size;
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
};
inline int CCommand::MaxCommandLength()
{
return COMMAND_MAX_LENGTH - 1;
}
inline int CCommand::ArgC() const
{
return m_nArgc;
}
inline const char **CCommand::ArgV() const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
inline const char *CCommand::ArgS() const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
inline const char *CCommand::GetCommandString() const
{
return m_nArgc ? m_pArgSBuffer : "";
}
inline const char *CCommand::Arg( int nIndex ) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if ( nIndex < 0 || nIndex >= m_nArgc )
return "";
return m_ppArgv[nIndex];
}
inline const char *CCommand::operator[]( int nIndex ) const
{
return Arg( nIndex );
}
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand : public ConCommandBase
{
friend class CCvar;
public:
typedef ConCommandBase BaseClass;
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, FnCommandCallback_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, ICommandCallback *pCallback,
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
virtual ~ConCommand( void );
virtual bool IsCommand( void ) const;
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
virtual bool CanAutoComplete( void );
// Invoke the function
virtual void Dispatch( const CCommand &command );
private:
// NOTE: To maintain backward compat, we have to be very careful:
// All public virtual methods must appear in the same order always
// since engine code will be calling into this code, which *does not match*
// in the mod code; it's using slightly different, but compatible versions
// of this class. Also: Be very careful about adding new fields to this class.
// Those fields will not exist in the version of this class that is instanced
// in mod code.
// Call this function when executing the command
union
{
FnCommandCallbackV1_t m_fnCommandCallbackV1;
FnCommandCallback_t m_fnCommandCallback;
ICommandCallback *m_pCommandCallback;
};
union
{
FnCommandCompletionCallback m_fnCompletionCallback;
ICommandCompletionCallback *m_pCommandCompletionCallback;
};
bool m_bHasCompletionCallback : 1;
bool m_bUsingNewCommandCallback : 1;
bool m_bUsingCommandCallbackInterface : 1;
public:
inline FnCommandCallback_t GetCallback() const
{
return m_fnCommandCallback;
}
};
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
class ConVar : public ConCommandBase, public IConVar
{
friend class CCvar;
friend class ConVarRef;
public:
typedef ConCommandBase BaseClass;
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, FnChangeCallback_t callback );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
FnChangeCallback_t callback );
virtual ~ConVar( void );
virtual bool IsCommand( void ) const;
virtual bool IsFlagSet( int flag ) const;
virtual void AddFlags( int flags );
virtual int GetFlags( void ) const;
virtual const char *GetName( void ) const;
virtual const char* GetHelpText( void ) const;
virtual bool IsRegistered( void ) const;
// Install a change callback (there shouldn't already be one....)
void InstallChangeCallback( FnChangeCallback_t callback );
// Retrieve value
FORCEINLINE_CVAR float GetFloat( void ) const;
FORCEINLINE_CVAR int GetInt( void ) const;
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
FORCEINLINE_CVAR char const *GetString( void ) const;
// Used internally by OneTimeInit to initialize.
virtual void Init();
virtual const char *GetBaseName( void ) const;
virtual int GetSplitScreenPlayerSlot ( void ) const;
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
// from alloc/free across dll/exe boundaries.
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
virtual void SetValue( const char *value );
virtual void SetValue( float value );
virtual void SetValue( int value );
#if SOURCE_ENGINE >= SE_NUCLEARDAWN
virtual void SetValue( Color value );
#endif
// Reset to default value
void Revert( void );
// True if it has a min/max setting
bool GetMin( float& minVal ) const;
bool GetMax( float& maxVal ) const;
const char *GetDefault( void ) const;
private:
// Called by CCvar when the value of a var is changing.
virtual void InternalSetValue(const char *value);
// For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue );
#if SOURCE_ENGINE >= SE_LEFT4DEAD2
virtual void InternalSetColorValue( Color value );
#endif
virtual bool ClampValue( float& value );
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
private:
// This either points to "this" or it points to the original declaration of a ConVar.
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
ConVar *m_pParent;
// Static data
const char *m_pszDefaultValue;
// Value
// Dynamically allocated
char *m_pszString;
int m_StringLength;
// Values
float m_fValue;
int m_nValue;
// Min/Max values
bool m_bHasMin;
float m_fMinVal;
bool m_bHasMax;
float m_fMaxVal;
// Call this function when ConVar changes
FnChangeCallback_t m_fnChangeCallback;
public:
inline FnChangeCallback_t GetCallback() const
{
return m_fnChangeCallback;
}
inline void SetMin(bool set, float min=0.0)
{
m_bHasMin = set;
m_fMinVal = min;
}
inline void SetMax(bool set, float max=0.0)
{
m_bHasMax = set;
m_fMaxVal = max;
}
};
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
// Output : float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
{
return m_pParent->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
// Output : int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
{
return m_pParent->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
// Output : const char *
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
{
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
return "FCVAR_NEVER_AS_STRING";
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
}
//-----------------------------------------------------------------------------
// Used to read/write convars that already exist (replaces the FindVar method)
//-----------------------------------------------------------------------------
class ConVarRef
{
public:
ConVarRef( const char *pName );
ConVarRef( const char *pName, bool bIgnoreMissing );
ConVarRef( IConVar *pConVar );
void Init( const char *pName, bool bIgnoreMissing );
bool IsValid() const;
bool IsFlagSet( int nFlags ) const;
IConVar *GetLinkedConVar();
// Get/Set value
float GetFloat( void ) const;
int GetInt( void ) const;
bool GetBool() const { return !!GetInt(); }
const char *GetString( void ) const;
void SetValue( const char *pValue );
void SetValue( float flValue );
void SetValue( int nValue );
void SetValue( bool bValue );
const char *GetName() const;
const char *GetDefault() const;
private:
// High-speed method to read convar data
IConVar *m_pConVar;
ConVar *m_pConVarState;
};
//-----------------------------------------------------------------------------
// Did we find an existing convar of that name?
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
{
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
}
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
{
return m_pConVar;
}
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
{
return m_pConVar->GetName();
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
{
return m_pConVarState->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
{
return m_pConVarState->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
{
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
return m_pConVarState->m_pszString;
}
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
{
m_pConVar->SetValue( pValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
{
m_pConVar->SetValue( flValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
{
m_pConVar->SetValue( nValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
{
m_pConVar->SetValue( bValue ? 1 : 0 );
}
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
{
return m_pConVarState->m_pszDefaultValue;
}
//-----------------------------------------------------------------------------
// Called by the framework to register ConCommands with the ICVar
//-----------------------------------------------------------------------------
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
void ConVar_Unregister( );
//-----------------------------------------------------------------------------
// Utility methods
//-----------------------------------------------------------------------------
void ConVar_PrintFlags( const ConCommandBase *var );
void ConVar_PrintDescription( const ConCommandBase *pVar );
//-----------------------------------------------------------------------------
// Purpose: Utility class to quickly allow ConCommands to call member methods
//-----------------------------------------------------------------------------
#ifdef _MSC_VER
#pragma warning (disable : 4355 )
#endif
template< class T >
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
{
typedef ConCommand BaseClass;
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
public:
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
{
m_pOwner = pOwner;
m_Func = callback;
m_CompletionFunc = completionFunc;
}
~CConCommandMemberAccessor()
{
Shutdown();
}
void SetOwner( T* pOwner )
{
m_pOwner = pOwner;
}
virtual void CommandCallback( const CCommand &command )
{
Assert( m_pOwner && m_Func );
(m_pOwner->*m_Func)( command );
}
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
{
Assert( m_pOwner && m_CompletionFunc );
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
}
private:
T* m_pOwner;
FnMemberCommandCallback_t m_Func;
FnMemberCommandCompletionCallback_t m_CompletionFunc;
};
#ifdef _MSC_VER
#pragma warning ( default : 4355 )
#endif
//-----------------------------------------------------------------------------
// Purpose: Utility macros to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND( name, description ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description ); \
static void name( const CCommand &args )
#define CON_COMMAND_F( name, description, flags ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags ); \
static void name( const CCommand &args )
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags, completion ); \
static void name( const CCommand &args )
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description, flags ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
friend class CCommandMemberInitializer_##_funcname; \
class CCommandMemberInitializer_##_funcname \
{ \
public: \
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
{ \
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
} \
private: \
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
}; \
\
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
#endif // CONVAR_H

View File

@ -1,709 +0,0 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//===========================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier1/iconvar.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "icvar.h"
#ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE
#elif defined _LINUX || defined __APPLE__
#define FORCEINLINE_CVAR inline
#else
#error "implement me"
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class ConVar;
class CCommand;
class ConCommand;
class ConCommandBase;
struct characterset_t;
//-----------------------------------------------------------------------------
// Any executable that wants to use ConVars need to implement one of
// these to hook up access to console variables.
//-----------------------------------------------------------------------------
class IConCommandBaseAccessor
{
public:
// Flags is a combination of FCVAR flags in cvar.h.
// hOut is filled in with a handle to the variable.
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0;
};
//-----------------------------------------------------------------------------
// Helper method for console development
//-----------------------------------------------------------------------------
#if defined( _X360 ) && !defined( _RETAIL )
void ConVar_PublishToVXConsole();
#endif
//-----------------------------------------------------------------------------
// Called when a ConCommand needs to execute
//-----------------------------------------------------------------------------
typedef void ( *FnCommandCallbackV1_t )( void );
typedef void ( *FnCommandCallback_t )( const CCommand &command );
#define COMMAND_COMPLETION_MAXITEMS 64
#define COMMAND_COMPLETION_ITEM_LENGTH 64
//-----------------------------------------------------------------------------
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
//-----------------------------------------------------------------------------
typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
//-----------------------------------------------------------------------------
// Interface version
//-----------------------------------------------------------------------------
class ICommandCallback
{
public:
virtual void CommandCallback( const CCommand &command ) = 0;
};
class ICommandCompletionCallback
{
public:
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
friend class CCvar;
friend class ConVar;
friend class ConCommand;
friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor );
friend void ConVar_PublishToVXConsole();
// FIXME: Remove when ConVar changes are done
friend class CDefaultCvar;
public:
ConCommandBase( void );
ConCommandBase( const char *pName, const char *pHelpString = 0,
int flags = 0 );
virtual ~ConCommandBase( void );
virtual bool IsCommand( void ) const;
// Check flag
virtual bool IsFlagSet( int flag ) const;
// Set flag
virtual void AddFlags( int flags );
// Return name of cvar
virtual const char *GetName( void ) const;
// Return help text for cvar
virtual const char *GetHelpText( void ) const;
// Deal with next pointer
const ConCommandBase *GetNext( void ) const;
ConCommandBase *GetNext( void );
void SetNext(ConCommandBase *pBase)
{
m_pNext = pBase;
}
virtual bool IsRegistered( void ) const;
// Returns the DLL identifier
virtual CVarDLLIdentifier_t GetDLLIdentifier() const;
protected:
virtual void Create( const char *pName, const char *pHelpString = 0,
int flags = 0 );
// Used internally by OneTimeInit to initialize/shutdown
virtual void Init();
void Shutdown();
// Internal copy routine ( uses new operator from correct module )
char *CopyString( const char *from );
private:
// Next ConVar in chain
// Prior to register, it points to the next convar in the DLL.
// Once registered, though, m_pNext is reset to point to the next
// convar in the global list
ConCommandBase *m_pNext;
// Has the cvar been added to the global list?
bool m_bRegistered;
// Static data
const char *m_pszName;
const char *m_pszHelpString;
// ConVar flags
int m_nFlags;
protected:
// ConVars add themselves to this list for the executable.
// Then ConVar_Register runs through all the console variables
// and registers them into a global list stored in vstdlib.dll
static ConCommandBase *s_pConCommandBases;
// ConVars in this executable use this 'global' to access values.
static IConCommandBaseAccessor *s_pAccessor;
public: // Hackalicous
inline int GetFlags() const
{
return m_nFlags;
}
inline void SetFlags(int flags)
{
m_nFlags = flags;
}
};
//-----------------------------------------------------------------------------
// Command tokenizer
//-----------------------------------------------------------------------------
class CCommand
{
public:
CCommand();
CCommand( int nArgC, const char **ppArgV );
bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL );
void Reset();
int ArgC() const;
const char **ArgV() const;
const char *ArgS() const; // All args that occur after the 0th arg, in string form
const char *GetCommandString() const; // The entire command in string form, including the 0th arg
const char *operator[]( int nIndex ) const; // Gets at arguments
const char *Arg( int nIndex ) const; // Gets at arguments
// Helper functions to parse arguments to commands.
const char* FindArg( const char *pName ) const;
int FindArgInt( const char *pName, int nDefaultVal ) const;
static int MaxCommandLength();
static characterset_t* DefaultBreakSet();
private:
enum
{
COMMAND_MAX_ARGC = 64,
COMMAND_MAX_LENGTH = 512,
};
int m_nArgc;
int m_nArgv0Size;
char m_pArgSBuffer[ COMMAND_MAX_LENGTH ];
char m_pArgvBuffer[ COMMAND_MAX_LENGTH ];
const char* m_ppArgv[ COMMAND_MAX_ARGC ];
};
inline int CCommand::MaxCommandLength()
{
return COMMAND_MAX_LENGTH - 1;
}
inline int CCommand::ArgC() const
{
return m_nArgc;
}
inline const char **CCommand::ArgV() const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
inline const char *CCommand::ArgS() const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
inline const char *CCommand::GetCommandString() const
{
return m_nArgc ? m_pArgSBuffer : "";
}
inline const char *CCommand::Arg( int nIndex ) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if ( nIndex < 0 || nIndex >= m_nArgc )
return "";
return m_ppArgv[nIndex];
}
inline const char *CCommand::operator[]( int nIndex ) const
{
return Arg( nIndex );
}
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand : public ConCommandBase
{
friend class CCvar;
public:
typedef ConCommandBase BaseClass;
ConCommand( const char *pName, FnCommandCallbackV1_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, FnCommandCallback_t callback,
const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
ConCommand( const char *pName, ICommandCallback *pCallback,
const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 );
virtual ~ConCommand( void );
virtual bool IsCommand( void ) const;
virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands );
virtual bool CanAutoComplete( void );
// Invoke the function
virtual void Dispatch( const CCommand &command );
private:
// NOTE: To maintain backward compat, we have to be very careful:
// All public virtual methods must appear in the same order always
// since engine code will be calling into this code, which *does not match*
// in the mod code; it's using slightly different, but compatible versions
// of this class. Also: Be very careful about adding new fields to this class.
// Those fields will not exist in the version of this class that is instanced
// in mod code.
// Call this function when executing the command
union
{
FnCommandCallbackV1_t m_fnCommandCallbackV1;
FnCommandCallback_t m_fnCommandCallback;
ICommandCallback *m_pCommandCallback;
};
union
{
FnCommandCompletionCallback m_fnCompletionCallback;
ICommandCompletionCallback *m_pCommandCompletionCallback;
};
bool m_bHasCompletionCallback : 1;
bool m_bUsingNewCommandCallback : 1;
bool m_bUsingCommandCallbackInterface : 1;
public: // Hackalicous
inline FnCommandCallback_t GetCallback() const
{
return m_fnCommandCallback;
}
};
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
class ConVar : public ConCommandBase, public IConVar
{
friend class CCvar;
friend class ConVarRef;
public:
typedef ConCommandBase BaseClass;
ConVar( const char *pName, const char *pDefaultValue, int flags = 0);
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, FnChangeCallback_t callback );
ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
FnChangeCallback_t callback );
virtual ~ConVar( void );
virtual bool IsFlagSet( int flag ) const;
virtual const char* GetHelpText( void ) const;
virtual bool IsRegistered( void ) const;
virtual const char *GetName( void ) const;
virtual void AddFlags( int flags );
virtual bool IsCommand( void ) const;
// Install a change callback (there shouldn't already be one....)
void InstallChangeCallback( FnChangeCallback_t callback );
// Retrieve value
FORCEINLINE_CVAR float GetFloat( void ) const;
FORCEINLINE_CVAR int GetInt( void ) const;
FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); }
FORCEINLINE_CVAR char const *GetString( void ) const;
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
// from alloc/free across dll/exe boundaries.
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
virtual void SetValue( const char *value );
virtual void SetValue( float value );
virtual void SetValue( int value );
// Reset to default value
void Revert( void );
// True if it has a min/max setting
bool GetMin( float& minVal ) const;
bool GetMax( float& maxVal ) const;
const char *GetDefault( void ) const;
private:
// Called by CCvar when the value of a var is changing.
virtual void InternalSetValue(const char *value);
// For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue );
virtual bool ClampValue( float& value );
virtual void ChangeStringValue( const char *tempVal, float flOldValue );
virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0,
const char *pHelpString = 0, bool bMin = false, float fMin = 0.0,
bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
private:
// This either points to "this" or it points to the original declaration of a ConVar.
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
ConVar *m_pParent;
// Static data
const char *m_pszDefaultValue;
// Value
// Dynamically allocated
char *m_pszString;
int m_StringLength;
// Values
float m_fValue;
int m_nValue;
// Min/Max values
bool m_bHasMin;
float m_fMinVal;
bool m_bHasMax;
float m_fMaxVal;
// Call this function when ConVar changes
FnChangeCallback_t m_fnChangeCallback;
public: // Hackalicous
inline FnChangeCallback_t GetCallback() const
{
return m_fnChangeCallback;
}
inline void SetMin(bool set, float min=0.0)
{
m_bHasMin = set;
m_fMinVal = min;
}
inline void SetMax(bool set, float max=0.0)
{
m_bHasMax = set;
m_fMaxVal = max;
}
};
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
// Output : float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVar::GetFloat( void ) const
{
return m_pParent->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
// Output : int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVar::GetInt( void ) const
{
return m_pParent->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
// Output : const char *
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVar::GetString( void ) const
{
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
return "FCVAR_NEVER_AS_STRING";
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
}
//-----------------------------------------------------------------------------
// Used to read/write convars that already exist (replaces the FindVar method)
//-----------------------------------------------------------------------------
class ConVarRef
{
public:
ConVarRef( const char *pName );
ConVarRef( const char *pName, bool bIgnoreMissing );
ConVarRef( IConVar *pConVar );
void Init( const char *pName, bool bIgnoreMissing );
bool IsValid() const;
bool IsFlagSet( int nFlags ) const;
IConVar *GetLinkedConVar();
// Get/Set value
float GetFloat( void ) const;
int GetInt( void ) const;
bool GetBool() const { return !!GetInt(); }
const char *GetString( void ) const;
void SetValue( const char *pValue );
void SetValue( float flValue );
void SetValue( int nValue );
void SetValue( bool bValue );
const char *GetName() const;
const char *GetDefault() const;
private:
// High-speed method to read convar data
IConVar *m_pConVar;
ConVar *m_pConVarState;
};
//-----------------------------------------------------------------------------
// Did we find an existing convar of that name?
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const
{
return ( m_pConVar->IsFlagSet( nFlags ) != 0 );
}
FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar()
{
return m_pConVar;
}
FORCEINLINE_CVAR const char *ConVarRef::GetName() const
{
return m_pConVar->GetName();
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const
{
return m_pConVarState->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const
{
return m_pConVarState->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
//-----------------------------------------------------------------------------
FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const
{
Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) );
return m_pConVarState->m_pszString;
}
FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue )
{
m_pConVar->SetValue( pValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue )
{
m_pConVar->SetValue( flValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue )
{
m_pConVar->SetValue( nValue );
}
FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue )
{
m_pConVar->SetValue( bValue ? 1 : 0 );
}
FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const
{
return m_pConVarState->m_pszDefaultValue;
}
//-----------------------------------------------------------------------------
// Called by the framework to register ConCommands with the ICVar
//-----------------------------------------------------------------------------
void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL );
void ConVar_Unregister( );
//-----------------------------------------------------------------------------
// Utility methods
//-----------------------------------------------------------------------------
void ConVar_PrintFlags( const ConCommandBase *var );
void ConVar_PrintDescription( const ConCommandBase *pVar );
//-----------------------------------------------------------------------------
// Purpose: Utility class to quickly allow ConCommands to call member methods
//-----------------------------------------------------------------------------
#if defined _MSC_VER
#pragma warning (disable : 4355 )
#endif
template< class T >
class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback
{
typedef ConCommand BaseClass;
typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command );
typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands );
public:
CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0,
int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) :
BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL )
{
m_pOwner = pOwner;
m_Func = callback;
m_CompletionFunc = completionFunc;
}
~CConCommandMemberAccessor()
{
Shutdown();
}
void SetOwner( T* pOwner )
{
m_pOwner = pOwner;
}
virtual void CommandCallback( const CCommand &command )
{
Assert( m_pOwner && m_Func );
(m_pOwner->*m_Func)( command );
}
virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands )
{
Assert( m_pOwner && m_CompletionFunc );
return (m_pOwner->*m_CompletionFunc)( pPartial, commands );
}
private:
T* m_pOwner;
FnMemberCommandCallback_t m_Func;
FnMemberCommandCompletionCallback_t m_CompletionFunc;
};
#if defined _MSC_VER
#pragma warning ( default : 4355 )
#endif
//-----------------------------------------------------------------------------
// Purpose: Utility macros to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND( name, description ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description ); \
static void name( const CCommand &args )
#define CON_COMMAND_F( name, description, flags ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags ); \
static void name( const CCommand &args )
#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \
static void name( const CCommand &args ); \
static ConCommand name##_command( #name, name, description, flags, completion ); \
static void name( const CCommand &args )
#define CON_COMMAND_EXTERN( name, _funcname, description ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
static ConCommand name##_command( #name, _funcname, description, flags ); \
void _funcname( const CCommand &args )
#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \
void _funcname( const CCommand &args ); \
friend class CCommandMemberInitializer_##_funcname; \
class CCommandMemberInitializer_##_funcname \
{ \
public: \
CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \
{ \
m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \
} \
private: \
CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \
}; \
\
CCommandMemberInitializer_##_funcname m_##_funcname##_register; \
#endif // CONVAR_H

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -39,15 +39,19 @@
#include "AdminCache.h"
#include "Translator.h"
#include "common_logic.h"
#include "stringutil.h"
#include <bridge/include/ILogger.h>
#include <bridge/include/CoreProvider.h>
#include <bridge/include/IVEngineServerBridge.h>
#define LEVEL_STATE_NONE 0
#define LEVEL_STATE_LEVELS 1
#define LEVEL_STATE_FLAGS 2
AdminCache g_Admins;
char g_ReverseFlags[26];
char g_ReverseFlags[AdminFlags_TOTAL];
AdminFlag g_FlagLetters[26];
bool g_FlagSet[26];
bool g_FlagCharSet[26];
/* Default flags */
AdminFlag g_DefaultFlags[26] =
@ -71,9 +75,9 @@ public:
memcpy(g_FlagLetters, g_DefaultFlags, sizeof(AdminFlag) * 26);
for (unsigned int i=0; i<20; i++)
{
g_FlagSet[i] = true;
g_FlagCharSet[i] = true;
}
g_FlagSet[25] = true;
g_FlagCharSet[25] = true;
}
}
private:
@ -103,7 +107,7 @@ private:
{
m_LevelState = LEVEL_STATE_NONE;
m_IgnoreLevel = 0;
memset(g_FlagSet, 0, sizeof(g_FlagSet));
memset(g_FlagCharSet, 0, sizeof(g_FlagCharSet));
}
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
{
@ -163,7 +167,7 @@ private:
return SMCResult_Continue;
}
g_FlagSet[c] = true;
g_FlagCharSet[c] = true;
return SMCResult_Continue;
}
@ -267,6 +271,21 @@ void AdminCache::OnSourceModStartup(bool late)
NameFlag("custom4", Admin_Custom4);
NameFlag("custom5", Admin_Custom5);
NameFlag("custom6", Admin_Custom6);
auto sm_dump_admcache = [this] (int client, const ICommandArgs *args) -> bool {
char buffer[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt");
if (!DumpCache(buffer)) {
bridge->ConsolePrint("Could not open file for writing: %s", buffer);
return true;
}
bridge->ConsolePrint("Admin cache dumped to: %s", buffer);
return true;
};
bridge->DefineCommand("sm_dump_admcache", "Dumps the admin cache for debugging", sm_dump_admcache);
}
void AdminCache::OnSourceModAllInitialized()
@ -327,7 +346,7 @@ void AdminCache::AddCommandOverride(const char *cmd, OverrideType type, FlagBits
return;
map->insert(cmd, flags);
smcore.UpdateAdminCmdFlags(cmd, type, flags, false);
bridge->UpdateAdminCmdFlags(cmd, type, flags, false);
}
bool AdminCache::GetCommandOverride(const char *cmd, OverrideType type, FlagBits *pFlags)
@ -356,13 +375,13 @@ void AdminCache::UnsetCommandOverride(const char *cmd, OverrideType type)
void AdminCache::_UnsetCommandGroupOverride(const char *group)
{
m_CmdGrpOverrides.remove(group);
smcore.UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true);
bridge->UpdateAdminCmdFlags(group, Override_CommandGroup, 0, true);
}
void AdminCache::_UnsetCommandOverride(const char *cmd)
{
m_CmdOverrides.remove(cmd);
smcore.UpdateAdminCmdFlags(cmd, Override_Command, 0, true);
bridge->UpdateAdminCmdFlags(cmd, Override_Command, 0, true);
}
void AdminCache::DumpCommandOverrideCache(OverrideType type)
@ -981,7 +1000,6 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
{
List<IAdminListener *>::iterator iter;
IAdminListener *pListener;
cell_t result;
if (part == AdminCache_Overrides)
{
@ -995,7 +1013,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
pListener->OnRebuildOverrideCache();
}
m_pCacheFwd->PushCell(part);
m_pCacheFwd->Execute(&result);
m_pCacheFwd->Execute();
}
} else if (part == AdminCache_Groups || part == AdminCache_Admins) {
if (part == AdminCache_Groups)
@ -1009,7 +1027,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
pListener->OnRebuildGroupCache();
}
m_pCacheFwd->PushCell(part);
m_pCacheFwd->Execute(&result);
m_pCacheFwd->Execute();
}
}
InvalidateAdminCache(true);
@ -1021,7 +1039,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild)
pListener->OnRebuildAdminCache((part == AdminCache_Groups));
}
m_pCacheFwd->PushCell(AdminCache_Admins);
m_pCacheFwd->Execute(&result);
m_pCacheFwd->Execute();
playerhelpers->RecheckAnyAdmins();
}
}
@ -1063,22 +1081,29 @@ bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index)
bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen)
{
int len = strlen(ident);
/* If the id was a steam id strip off the STEAM_*: part */
if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_')
if (!strcmp(ident, "BOT"))
{
// non-bot/lan Steam2 Id
snprintf(out, maxlen, "%s", &ident[8]);
// Bots
strncopy(out, ident, maxlen);
return true;
}
else if (len >= 11 && !strncmp(ident, "STEAM_", 6) && ident[8] != '_')
{
// non-bot/lan Steam2 Id, strip off the STEAM_* part
ke::SafeStrcpy(out, maxlen, &ident[8]);
return true;
}
else if (len >= 7 && !strncmp(ident, "[U:", 3) && ident[len-1] == ']')
{
// Steam3 Id
// Steam3 Id, replicate the Steam2 Post-"STEAM_" part
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;
}
else
{
// 64-bit CSteamID, replicate the Steam2 Post-"STEAM_" part
// some constants from steamclientpublic.h
static const uint32_t k_EAccountTypeIndividual = 1;
static const int k_EUniverseInvalid = 0;
@ -1099,7 +1124,7 @@ bool AdminCache::GetUnifiedSteamIdentity(const char *ident, char *out, size_t ma
&& 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;
}
}
@ -1509,7 +1534,7 @@ bool AdminCache::CanAdminTarget(AdminId id, AdminId target)
}
/** Fourth, if the targeted admin is immune from targeting admin. */
int mode = smcore.GetImmunityMode();
int mode = bridge->GetImmunityMode();
switch (mode)
{
case 1:
@ -1577,7 +1602,7 @@ bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
{
if (c < 'a'
|| c > 'z'
|| !g_FlagSet[(unsigned)c - (unsigned)'a'])
|| !g_FlagCharSet[(unsigned)c - (unsigned)'a'])
{
return false;
}
@ -1592,17 +1617,13 @@ bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag)
bool AdminCache::FindFlagChar(AdminFlag flag, char *c)
{
if (!g_FlagSet[flag])
{
return false;
}
char flagchar = g_ReverseFlags[flag];
if (c)
{
*c = g_ReverseFlags[flag];
*c = flagchar;
}
return true;
return flagchar != '?';
}
FlagBits AdminCache::ReadFlagString(const char *flags, const char **end)
@ -1650,7 +1671,7 @@ bool AdminCache::CanAdminUseCommand(int client, const char *cmd)
cmd++;
}
if (!smcore.LookForCommandAdminFlags(cmd, &bits))
if (!bridge->LookForCommandAdminFlags(cmd, &bits))
{
if (!GetCommandOverride(cmd, otype, &bits))
{
@ -1725,7 +1746,7 @@ bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool o
bool found_command = false;
if (!override_only)
{
found_command = smcore.LookForCommandAdminFlags(cmd, &bits);
found_command = bridge->LookForCommandAdminFlags(cmd, &bits);
}
if (!found_command)

View File

@ -82,6 +82,10 @@ struct AuthMethod
{
return strcmp(name, method->name.c_str()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
struct UserAuth

244
core/logic/CDataPack.cpp Normal file
View File

@ -0,0 +1,244 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <stdlib.h>
#include <string.h>
#include "CDataPack.h"
#include <amtl/am-autoptr.h>
CDataPack::CDataPack()
{
Initialize();
}
CDataPack::~CDataPack()
{
Initialize();
}
static ke::Vector<ke::AutoPtr<CDataPack>> sDataPackCache;
CDataPack *CDataPack::New()
{
if (sDataPackCache.empty())
return new CDataPack();
CDataPack *pack = sDataPackCache.back().take();
sDataPackCache.pop();
pack->Initialize();
return pack;
}
void
CDataPack::Free(CDataPack *pack)
{
sDataPackCache.append(static_cast<CDataPack *>(pack));
}
void CDataPack::Initialize()
{
do
{
} while (this->RemoveItem());
elements.clear();
position = 0;
}
void CDataPack::ResetSize()
{
Initialize();
}
size_t CDataPack::CreateMemory(size_t size, void **addr)
{
InternalPack val;
val.type = CDataPackType::Raw;
val.pData.vval = new uint8_t[size + sizeof(size)];
reinterpret_cast<size_t *>(val.pData.vval)[0] = size;
elements.insert(position, val);
return position++;
}
void CDataPack::PackCell(cell_t cell)
{
InternalPack val;
val.type = CDataPackType::Cell;
val.pData.cval = cell;
elements.insert(position++, val);
}
void CDataPack::PackFunction(cell_t function)
{
InternalPack val;
val.type = CDataPackType::Function;
val.pData.cval = function;
elements.insert(position++, val);
}
void CDataPack::PackFloat(float floatval)
{
InternalPack val;
val.type = CDataPackType::Float;
val.pData.fval = floatval;
elements.insert(position++, val);
}
void CDataPack::PackString(const char *string)
{
InternalPack val;
val.type = CDataPackType::String;
ke::AString *sval = new ke::AString(string);
val.pData.sval = sval;
elements.insert(position++, val);
}
void CDataPack::Reset() const
{
position = 0;
}
size_t CDataPack::GetPosition() const
{
return position;
}
bool CDataPack::SetPosition(size_t pos) const
{
if (pos > elements.length())
return false;
position = pos;
return true;
}
cell_t CDataPack::ReadCell() const
{
if (!IsReadable() || elements[position].type != CDataPackType::Cell)
return 0;
return elements[position++].pData.cval;
}
cell_t CDataPack::ReadFunction() const
{
if (!IsReadable() || elements[position].type != CDataPackType::Function)
return 0;
return elements[position++].pData.cval;
}
float CDataPack::ReadFloat() const
{
if (!IsReadable() || elements[position].type != CDataPackType::Float)
return 0;
return elements[position++].pData.fval;
}
bool CDataPack::IsReadable(size_t bytes) const
{
return (position < elements.length());
}
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;
}

196
core/logic/CDataPack.h Normal file
View File

@ -0,0 +1,196 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_CDATAPACK_H_
#define _INCLUDE_SOURCEMOD_CDATAPACK_H_
#include <ISourceMod.h>
#include <amtl/am-vector.h>
#include <amtl/am-string.h>
using namespace SourceMod;
enum CDataPackType {
Raw,
Cell,
Float,
String,
Function
};
class CDataPack
{
public:
CDataPack();
~CDataPack();
static CDataPack *New();
static void Free(CDataPack *pack);
public: // Originally IDataReader
/**
* @brief Resets the position in the data stream to the beginning.
*/
void Reset() const;
/**
* @brief Retrieves the current stream position.
*
* @return Index into the stream.
*/
size_t GetPosition() const;
/**
* @brief Sets the current stream position.
*
* @param pos Index to set the stream at.
* @return True if succeeded, false if out of bounds.
*/
bool SetPosition(size_t pos) const;
/**
* @brief Reads one cell from the data stream.
*
* @return A cell read from the current position.
*/
cell_t ReadCell() const;
/**
* @brief Reads one float from the data stream.
*
* @return A float read from the current position.
*/
float ReadFloat() const;
/**
* @brief 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;
/**
* @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;
/**
* @brief Reads a function pointer from the data stream.
*
* @return A function pointer read from the current position.
*/
cell_t ReadFunction() const;
public: // Originally IDataPack
/**
* @brief Resets the used size of the stream back to zero.
*/
void ResetSize();
/**
* @brief Packs one cell into the data stream.
*
* @param cell Cell value to write.
*/
void PackCell(cell_t cell);
/**
* @brief Packs one float into the data stream.
*
* @param val Float value to write.
*/
void PackFloat(float val);
/**
* @brief Packs one string into the data stream.
* The length is recorded as well for buffer overrun protection.
*
* @param string String to write.
*/
void PackString(const char *string);
/**
* @brief Creates a generic block of memory in the stream.
*
* Note that the pointer it returns can be invalidated on further
* writing, since the stream size may grow. You may need to double back
* and fetch the pointer again.
*
* @param size Size of the memory to create in the stream.
* @param addr Optional pointer to store the relocated memory address.
* @return Current position of the stream beforehand.
*/
size_t CreateMemory(size_t size, void **addr);
/**
* @brief Packs one function pointer into the data stream.
*
* @param function The function pointer to write.
*/
void PackFunction(cell_t function);
public:
void Initialize();
inline size_t GetCapacity() const { return this->elements.length(); };
inline CDataPackType GetCurrentType(void) const { return this->elements[this->position].type; };
bool RemoveItem(size_t pos = -1);
private:
typedef union {
cell_t cval;
float fval;
uint8_t *vval;
ke::AString *sval;
} InternalPackValue;
typedef struct {
InternalPackValue pData;
CDataPackType type;
} InternalPack;
ke::Vector<InternalPack> elements;
mutable size_t position;
};
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_

View File

@ -34,10 +34,11 @@
#include <stdlib.h>
#include <string.h>
#include <ICellArray.h>
extern HandleType_t htCellArray;
class CellArray
class CellArray : public ICellArray
{
public:
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
@ -49,6 +50,31 @@ public:
free(m_Data);
}
/**
* @brief Creates a cell array object.
*
* @param blocksize The number of cells each member of the array can
* hold. For example, 32 cells is equivalent to:
* new Array[X][32]
* @return A new ICellArray object.
*/
static ICellArray *New(size_t blocksize)
{
return new CellArray(blocksize);
}
/**
* @brief Releases a cell array's resources.
*
* @param pack An ICellArray object to release.
*/
static void Free(ICellArray *arr)
{
delete arr;
}
// ICellArray
public:
size_t size() const
{
return m_Size;
@ -154,12 +180,18 @@ public:
return true;
}
CellArray *clone()
ICellArray *clone()
{
CellArray *array = new CellArray(m_BlockSize);
array->m_AllocSize = m_AllocSize;
array->m_Size = m_Size;
array->m_Data = (cell_t *)malloc(sizeof(cell_t) * m_BlockSize * m_AllocSize);
if (!array->m_Data)
{
delete array;
return NULL;
}
memcpy(array->m_Data, m_Data, sizeof(cell_t) * m_BlockSize * m_Size);
return array;
}
@ -195,11 +227,17 @@ private:
/* finally, allocate the new block */
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 {
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:
cell_t *m_Data;

View File

@ -36,6 +36,8 @@
#include "PluginSys.h"
#include <stdlib.h>
#include <IThreader.h>
#include <bridge/include/ILogger.h>
#include <bridge/include/CoreProvider.h>
#define DBPARSE_LEVEL_NONE 0
#define DBPARSE_LEVEL_MAIN 1
@ -46,8 +48,6 @@ static bool s_OneTimeThreaderErrorMsg = false;
DBManager::DBManager()
: m_Terminate(false),
m_ParseLevel(0),
m_ParseState(0),
m_pDefault(NULL)
{
}
@ -64,38 +64,29 @@ void DBManager::OnSourceModAllInitialized()
g_HandleSys.InitAccessDefaults(NULL, &sec);
sec.access[HandleAccess_Delete] |= HANDLE_RESTRICT_IDENTITY;
sec.access[HandleAccess_Clone] |= HANDLE_RESTRICT_IDENTITY;
m_DriverType = g_HandleSys.CreateType("IDriver", this, 0, NULL, &sec, g_pCoreIdent, NULL);
m_DatabaseType = g_HandleSys.CreateType("IDatabase", this, 0, NULL, NULL, g_pCoreIdent, NULL);
g_ShareSys.AddInterface(NULL, this);
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
g_PluginSys.AddPluginsListener(this);
m_Builder.SetPath(m_Filename);
g_PluginSys.AddPluginsListener(this);
g_pSM->AddGameFrameHook(&FrameHook);
auto sm_reload_databases = [this] (int client, const ICommandArgs *args) -> bool {
m_Builder.StartParse();
return true;
};
bridge->DefineCommand("sm_reload_databases", "Reparse database configurations file", sm_reload_databases);
}
void DBManager::OnSourceModLevelChange(const char *mapName)
{
SMCError err;
SMCStates states = {0, 0};
/* We lock and don't give up the lock until we're done.
* This way the thread's search won't be searching through a
* potentially empty/corrupt list, which would be very bad.
*/
ke::AutoLock lock(&m_ConfigLock);
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
{
logger->LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
if (err != SMCError_Custom)
{
const char *txt = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Line %d: %s", states.line, txt);
}
}
m_Builder.StartParse();
}
void DBManager::OnSourceModShutdown()
@ -105,7 +96,6 @@ void DBManager::OnSourceModShutdown()
g_PluginSys.RemovePluginsListener(this);
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
ClearConfigs();
}
unsigned int DBManager::GetInterfaceVersion()
@ -133,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)
{
ConfDbInfo *pInfo = GetDatabaseConf(name);
ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> pInfo = list->GetDatabaseConf(name);
if (!pInfo)
{
@ -281,11 +145,12 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
/* Try to assign a real driver pointer */
if (pInfo->info.driver[0] == '\0')
{
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;
} else {
pInfo->realDriver = FindOrLoadDriver(pInfo->info.driver);
@ -309,7 +174,6 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
*pdb = NULL;
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname);
return false;
}
@ -322,7 +186,7 @@ void DBManager::AddDriver(IDBDriver *pDriver)
*/
KillWorkerThread();
m_drivers.push_back(pDriver);
m_drivers.push_back(pDriver);
}
void DBManager::RemoveDriver(IDBDriver *pDriver)
@ -342,17 +206,17 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
}
}
/* Make sure NOTHING references this! */
List<ConfDbInfo *>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
ConfDbInfoList *list = m_Builder.GetConfigList();
for (size_t i = 0; i < list->length(); i++)
{
ConfDbInfo &db = *(*iter);
if (db.realDriver == pDriver)
ke::RefPtr<ConfDbInfo> current = list->at(i);
if (current->realDriver == pDriver)
{
db.realDriver = NULL;
current->realDriver = NULL;
}
}
/* Someone unloaded the default driver? Silly.. */
if (pDriver == m_pDefault)
{
@ -388,9 +252,11 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
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;
@ -453,10 +319,16 @@ IDBDriver *DBManager::GetDriver(unsigned int index)
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)
{
return NULL;
// couldn't find requested conf, return default if exists
info = list->GetDefaultConfiguration();
if (!info)
{
return NULL;
}
}
return &info->info;
@ -464,18 +336,9 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
{
List<ConfDbInfo *>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
{
ConfDbInfo &conf = *(*iter);
if (conf.name == name)
{
return &conf;
}
}
return NULL;
ConfDbInfoList *list = m_Builder.GetConfigList();
ke::RefPtr<ConfDbInfo> info(list->GetDatabaseConf(name));
return info;
}
IDBDriver *DBManager::FindOrLoadDriver(const char *name)
@ -519,7 +382,7 @@ void DBManager::KillWorkerThread()
m_QueueEvent.Notify();
}
m_Worker->Join();
m_Worker = NULL;
m_Worker = nullptr;
s_OneTimeThreaderErrorMsg = false;
m_Terminate = false;
}
@ -536,7 +399,9 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
if (!m_Worker)
{
m_Worker = new ke::Thread(this, "SM SQL Worker");
m_Worker = new ke::Thread([this]() -> void {
Run();
}, "SM SQL Worker");
if (!m_Worker->Succeeded())
{
if (!s_OneTimeThreaderErrorMsg)
@ -544,7 +409,7 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
logger->LogError("[SM] Unable to create db threader (error unknown)");
s_OneTimeThreaderErrorMsg = true;
}
m_Worker = NULL;
m_Worker = nullptr;
return false;
}
}
@ -692,7 +557,7 @@ void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
s_pAddBlock = NULL;
}
void DBManager::OnPluginUnloaded(IPlugin *plugin)
void DBManager::OnPluginWillUnload(IPlugin *plugin)
{
/* Kill the thread so we can flush everything into the think queue... */
KillWorkerThread();
@ -718,9 +583,7 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
}
}
for (iter = templist.begin();
iter != templist.end();
iter++)
for (iter = templist.begin(); iter != templist.end(); iter++)
{
IDBThreadOperation *op = (*iter);
op->RunThinkPart();
@ -728,23 +591,13 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
}
}
void DBManager::LockConfig()
ke::AString DBManager::GetDefaultDriverName()
{
m_ConfigLock.Lock();
}
void DBManager::UnlockConfig()
{
m_ConfigLock.Unlock();
}
const char *DBManager::GetDefaultDriverName()
{
return m_DefDriver.c_str();
ConfDbInfoList *list = m_Builder.GetConfigList();
return list->GetDefaultDriver();
}
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)
{
g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver);
}

View File

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

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

@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@ -29,6 +29,7 @@
* Version: $Id$
*/
#include <ISourceMod.h>
#include <IPluginSys.h>
#include <stdarg.h>
#include "DebugReporter.h"
@ -47,7 +48,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
char buffer[512];
va_start(ap, msg);
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
va_end(ap);
g_Logger.LogMessage("[SM] %s", buffer);
@ -65,7 +66,7 @@ void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, c
void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap)
{
char buffer[512];
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
ke::SafeVsprintf(buffer, sizeof(buffer), message, ap);
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
const char *error = g_pSourcePawn2->GetErrorString(err);
@ -99,7 +100,7 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
char buffer[512];
va_start(ap, message);
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
ke::SafeVsprintf(buffer, sizeof(buffer), message, ap);
va_end(ap);
const char *plname = pluginsys->FindPluginByContext(pContext->GetContext())->GetFilename();
@ -132,51 +133,6 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
}
}
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
{
const char *lastname;
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
int n_err = error->GetErrorCode();
if (n_err != SP_ERROR_NATIVE)
{
g_Logger.LogError("[SM] Plugin encountered error %d: %s",
n_err,
error->GetErrorString());
}
if ((lastname=error->GetLastNative(NULL)) != NULL)
{
const char *custerr;
if ((custerr=error->GetCustomErrorString()) != NULL)
{
g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
} else {
g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
}
}
if (!error->DebugInfoAvailable())
{
g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
_GetPluginIndex(ctx));
return;
}
CallStackInfo stk_info;
int i = 0;
g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
while (error->GetTraceInfo(&stk_info))
{
g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
i++,
stk_info.line,
stk_info.filename,
stk_info.function);
}
}
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
{
int id = 1;
@ -199,3 +155,92 @@ int DebugReport::_GetPluginIndex(IPluginContext *ctx)
return pluginsys->GetPluginCount() + 1;
}
void DebugReport::ReportError(const IErrorReport &report, IFrameIterator &iter)
{
// Don't log an error if a function wasn't runnable.
// This is necassary due to the way SM is handling and exposing
// scripted functions. It's too late to change that now.
if (report.Code() == SP_ERROR_NOT_RUNNABLE)
return;
const char *blame = nullptr;
if (report.Blame())
{
blame = report.Blame()->DebugName();
} else {
// Find the nearest plugin to blame.
for (; !iter.Done(); iter.Next())
{
if (iter.IsScriptedFrame())
{
IPlugin *plugin = pluginsys->FindPluginByContext(iter.Context()->GetContext());
if (plugin)
{
blame = plugin->GetFilename();
} else {
blame = iter.Context()->GetRuntime()->GetFilename();
}
break;
}
}
}
iter.Reset();
g_Logger.LogError("[SM] Exception reported: %s", report.Message());
if (blame)
{
g_Logger.LogError("[SM] Blaming: %s", blame);
}
ke::Vector<ke::AString> arr = GetStackTrace(&iter);
for (size_t i = 0; i < arr.length(); i++)
{
g_Logger.LogError("%s", arr[i].chars());
}
}
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();
if (!fn)
{
fn = "<unknown function>";
}
if (iter->IsNativeFrame())
{
g_pSM->Format(temp, sizeof(temp), "[SM] [%d] %s", index, fn);
trace.append(temp);
continue;
}
if (iter->IsScriptedFrame())
{
const char *file = iter->FilePath();
if (!file)
{
file = "<unknown>";
}
g_pSM->Format(temp, sizeof(temp), "[SM] [%d] Line %d, %s::%s",
index,
iter->LineNumber(),
file,
fn);
trace.append(temp);
}
}
}
return trace;
}

View File

@ -34,6 +34,8 @@
#include "sp_vm_api.h"
#include "common_logic.h"
#include <am-vector.h>
#include <am-string.h>
class DebugReport :
public SMGlobalClass,
@ -42,12 +44,13 @@ class DebugReport :
public: // SMGlobalClass
void OnSourceModAllInitialized();
public: // IDebugListener
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
void ReportError(const IErrorReport &report, IFrameIterator &iter);
void OnDebugSpew(const char *msg, ...);
public:
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
ke::Vector<ke::AString> GetStackTrace(IFrameIterator *iter);
private:
int _GetPluginIndex(IPluginContext *ctx);
};

View File

@ -36,12 +36,16 @@
#include "common_logic.h"
#include "PluginSys.h"
#include <am-utility.h>
#include <am-string.h>
#include <bridge/include/CoreProvider.h>
#include <bridge/include/ILogger.h>
CExtensionManager g_Extensions;
IdentityType_t g_ExtType;
void CExtension::Initialize(const char *filename, const char *path)
void CExtension::Initialize(const char *filename, const char *path, bool bRequired)
{
m_bRequired = bRequired;
m_pAPI = NULL;
m_pIdentToken = NULL;
unload_code = 0;
@ -59,7 +63,7 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena
m_pAPI = pAPI;
}
CLocalExtension::CLocalExtension(const char *filename)
CLocalExtension::CLocalExtension(const char *filename, bool bRequired)
{
m_PlId = 0;
m_pLib = NULL;
@ -69,74 +73,69 @@ CLocalExtension::CLocalExtension(const char *filename)
/* Special case for new bintools binary */
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,
smcore.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(smcore.gamesuffix, "2.tf2") == 0
|| strcmp(smcore.gamesuffix, "2.dods") == 0
|| strcmp(smcore.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(smcore.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,
smcore.gamesuffix);
/* Try the "normal" version */
if (!libsys->IsPathFile(path))
{
normal:
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s." PLATFORM_LIB_EXT,
filename);
}
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:
Initialize(filename, path);
if (!libsys->IsPathFile(path))
{
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
if (strcmp(bridge->gamesuffix, "2.tf2") == 0
|| strcmp(bridge->gamesuffix, "2.dods") == 0
|| strcmp(bridge->gamesuffix, "2.hl2dm") == 0
)
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%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);
}
bool CRemoteExtension::Load(char *error, size_t maxlength)
@ -172,7 +171,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
{
m_pLib->CloseLibrary();
m_pLib = NULL;
snprintf(error, maxlength, "Unable to find extension entry point");
ke::SafeStrcpy(error, maxlength, "Unable to find extension entry point");
return false;
}
@ -191,7 +190,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
if (m_pAPI->IsMetamodExtension())
{
bool ok;
m_PlId = smcore.LoadMMSPlugin(m_Path.c_str(), &ok, error, maxlength);
m_PlId = bridge->LoadMMSPlugin(m_Path.c_str(), &ok, error, maxlength);
if (!m_PlId || !ok)
{
@ -208,7 +207,7 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
{
if (m_PlId)
{
smcore.UnloadMMSPlugin(m_PlId);
bridge->UnloadMMSPlugin(m_PlId);
m_PlId = 0;
}
}
@ -229,7 +228,7 @@ void CLocalExtension::Unload()
{
if (m_pAPI != NULL && m_PlId)
{
smcore.UnloadMMSPlugin(m_PlId);
bridge->UnloadMMSPlugin(m_PlId);
m_PlId = 0;
}
@ -242,7 +241,7 @@ void CLocalExtension::Unload()
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;
}
@ -276,13 +275,13 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
{
if (!m_pAPI)
{
snprintf(error, maxlength, "No IExtensionInterface instance provided");
ke::SafeStrcpy(error, maxlength, "No IExtensionInterface instance provided");
return false;
}
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;
}
@ -292,18 +291,17 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
bool CExtension::Load(char *error, size_t maxlength)
{
CreateIdentity();
if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, maxlength, !smcore.IsMapLoading()))
if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, maxlength, !bridge->IsMapLoading()))
{
g_ShareSys.RemoveInterfaces(this);
DestroyIdentity();
return false;
}
else
/* Check if we're past load time */
if (!bridge->IsMapLoading())
{
/* Check if we're past load time */
if (!smcore.IsMapLoading())
{
m_pAPI->OnExtensionsAllLoaded();
}
m_pAPI->OnExtensionsAllLoaded();
}
return true;
@ -418,65 +416,20 @@ void CExtension::AddChildDependent(CExtension *pOther, SMInterface *iface)
m_ChildDeps.push_back(info);
}
// note: dependency iteration deprecated since 1.10
ITERATOR *CExtension::FindFirstDependency(IExtension **pOwner, SMInterface **pInterface)
{
List<IfaceInfo>::iterator iter = m_Deps.begin();
if (iter == m_Deps.end())
{
return NULL;
}
if (pOwner)
{
*pOwner = (*iter).owner;
}
if (pInterface)
{
*pInterface = (*iter).iface;
}
List<IfaceInfo>::iterator *pIter = new List<IfaceInfo>::iterator(iter);
return (ITERATOR *)pIter;
return nullptr;
}
bool CExtension::FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface)
{
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
List<IfaceInfo>::iterator _iter;
if (_iter == m_Deps.end())
{
return false;
}
_iter++;
if (pOwner)
{
*pOwner = (*_iter).owner;
}
if (pInterface)
{
*pInterface = (*_iter).iface;
}
*pIter = _iter;
if (_iter == m_Deps.end())
{
return false;
}
return true;
return false;
}
void CExtension::FreeDependencyIterator(ITERATOR *iter)
{
List<IfaceInfo>::iterator *pIter = (List<IfaceInfo>::iterator *)iter;
delete pIter;
}
void CExtension::AddInterface(SMInterface *pInterface)
@ -490,7 +443,7 @@ bool CExtension::IsRunning(char *error, size_t maxlength)
{
if (error)
{
snprintf(error, maxlength, "%s", m_Error.c_str());
ke::SafeStrcpy(error, maxlength, m_Error.c_str());
}
return false;
}
@ -503,6 +456,11 @@ void CExtension::AddLibrary(const char *library)
m_Libraries.push_back(library);
}
bool CExtension::IsRequired()
{
return m_bRequired;
}
/*********************
* EXTENSION MANAGER *
*********************/
@ -511,7 +469,7 @@ void CExtensionManager::OnSourceModAllInitialized()
{
g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
pluginsys->AddPluginsListener(this);
rootmenu->AddRootConsoleCommand("exts", "Manage extensions", this);
rootmenu->AddRootConsoleCommand3("exts", "Manage extensions", this);
g_ShareSys.AddInterface(NULL, this);
}
@ -567,7 +525,7 @@ void CExtensionManager::TryAutoload()
}
char file[PLATFORM_MAX_PATH];
len = smcore.Format(file, sizeof(file), "%s", lfile);
len = ke::SafeStrcpy(file, sizeof(file), lfile);
strcpy(&file[len - 9], ".ext");
LoadAutoExtension(file);
@ -583,7 +541,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{
char path2[PLATFORM_MAX_PATH];
smcore.Format(path2, sizeof(path2), "%s", path);
ke::SafeStrcpy(path2, sizeof(path2), path);
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadAutoExtension(path2, bErrorOnMissing);
}
@ -595,7 +553,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
}
char error[256];
CExtension *p = new CLocalExtension(path);
CExtension *p = new CLocalExtension(path, bErrorOnMissing);
/* We put us in the list beforehand so extensions that check for each other
* won't recursively load each other.
@ -675,7 +633,7 @@ IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{
char path2[PLATFORM_MAX_PATH];
smcore.Format(path2, sizeof(path2), "%s", file);
ke::SafeStrcpy(path2, sizeof(path2), file);
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadExtension(path2, error, maxlength);
}
@ -928,17 +886,18 @@ void CExtensionManager::AddDependency(IExtension *pSource, const char *file, boo
}
}
void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command)
{
int argcount = smcore.Argc(command);
int argcount = command->ArgC();
if (argcount >= 3)
{
const char *cmd = smcore.Arg(command, 2);
const char *cmd = command->Arg(2);
if (strcmp(cmd, "list") == 0)
{
List<CExtension *>::iterator iter;
CExtension *pExt;
unsigned int num = 1;
switch (m_Libs.size())
{
case 1:
@ -957,7 +916,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
break;
}
}
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++,num++)
for (iter = m_Libs.begin(); iter != m_Libs.end(); iter++,num++)
{
pExt = (*iter);
if (pExt->IsLoaded())
@ -975,9 +934,15 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
const char *descr = pAPI->GetExtensionDescription();
rootmenu->ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr);
}
} else {
}
else if(pExt->IsRequired() || libsys->PathExists(pExt->GetPath()))
{
rootmenu->ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
}
else
{
rootmenu->ConsolePrint("[%02d] <OPTIONAL> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
}
}
return;
}
@ -989,11 +954,11 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
return;
}
const char *filename = smcore.Arg(command, 3);
const char *filename = command->Arg(3);
char path[PLATFORM_MAX_PATH];
char error[256];
smcore.Format(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
ke::SafeSprintf(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
!strstr(filename, "." PLATFORM_LIB_EXT) ? "." PLATFORM_LIB_EXT : "");
if (FindExtensionByFile(path) != NULL)
@ -1020,7 +985,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
return;
}
const char *sId = smcore.Arg(command, 3);
const char *sId = command->Arg(3);
unsigned int id = atoi(sId);
if (id <= 0)
{
@ -1105,7 +1070,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
return;
}
const char *arg = smcore.Arg(command, 3);
const char *arg = command->Arg(3);
unsigned int num = atoi(arg);
CExtension *pExt = FindByOrder(num);
@ -1117,11 +1082,11 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
if (argcount > 4 && pExt->unload_code)
{
const char *unload = smcore.Arg(command, 4);
const char *unload = command->Arg(4);
if (pExt->unload_code == (unsigned)atoi(unload))
{
char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
}
@ -1136,7 +1101,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
|| (!pExt->m_ChildDeps.size() && !pExt->m_Dependents.size()))
{
char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
ke::SafeStrcpy(filename, PLATFORM_MAX_PATH, pExt->GetFilename());
UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
return;
@ -1171,7 +1136,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
/* Will our dependent care? */
if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface))
{
rootmenu->ConsolePrint(" -> %s", pExt->GetFilename());
rootmenu->ConsolePrint(" -> %s", pOther->GetFilename());
/* Add to plugin unload list */
List<CPlugin *>::iterator p_iter;
for (p_iter=pOther->m_Dependents.begin();
@ -1222,7 +1187,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
return;
}
const char *arg = smcore.Arg(command, 3);
const char *arg = command->Arg(3);
unsigned int num = atoi(arg);
CExtension *pExt = FindByOrder(num);
@ -1237,7 +1202,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
char filename[PLATFORM_MAX_PATH];
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)))
{

View File

@ -41,6 +41,7 @@
#include <IRootConsoleMenu.h>
#include "NativeOwner.h"
#include "ShareSys.h"
#include <bridge/include/IExtensionBridge.h>
class CPlayer;
@ -79,6 +80,7 @@ public:
void AddPlugin(CPlugin *pPlugin);
void MarkAllLoaded();
void AddLibrary(const char *library);
bool IsRequired();
public:
virtual bool Load(char *error, size_t maxlength);
virtual bool IsLoaded() =0;
@ -86,7 +88,7 @@ public:
virtual bool Reload(char *error, size_t maxlength) =0;
virtual bool IsSameFile(const char* file) =0;
protected:
void Initialize(const char *filename, const char *path);
void Initialize(const char *filename, const char *path, bool bRequired = true);
bool PerformAPICheck(char *error, size_t maxlength);
void CreateIdentity();
void DestroyIdentity();
@ -103,12 +105,13 @@ protected:
List<String> m_Libraries;
unsigned int unload_code;
bool m_bFullyLoaded;
bool m_bRequired;
};
class CLocalExtension : public CExtension
{
public:
CLocalExtension(const char *filename);
CLocalExtension(const char *filename, bool bRequired = true);
public:
bool Load(char *error, size_t maxlength);
bool IsLoaded();
@ -161,7 +164,7 @@ public: //IExtensionManager
public: //IPluginsListener
void OnPluginDestroyed(IPlugin *plugin);
public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override;
public:
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true);
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);

View File

@ -1,33 +1,29 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
// vim: set ts=4 sw=4 tw=99 noet :
// =============================================================================
// SourceMod
// Copyright (C) 2004-2015 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 <assert.h>
#include <stdarg.h>
@ -35,30 +31,16 @@
#include "ForwardSys.h"
#include "DebugReporter.h"
#include "common_logic.h"
#include <bridge/include/IScriptManager.h>
#include <amtl/am-string.h>
#include <ReentrantList.h>
using namespace ke;
CForwardManager g_Forwards;
/**
* Genesis turns to its source, reduction occurs stepwise although the essence is all one.
* End of line. FTL system check.
*
* :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST
* VARARG FUNCTIONS:
* - Pushing no varargs
*/
// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
CForwardManager::~CForwardManager()
{
CStack<CForward *>::iterator iter;
for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++)
{
delete (*iter);
}
m_FreeForwards.popall();
}
// Genesis turns to its source, reduction occurs stepwise although the essence
// is all one. End of line. FTL system check.
void CForwardManager::OnSourceModAllInitialized()
{
@ -68,11 +50,10 @@ void CForwardManager::OnSourceModAllInitialized()
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
{
CForward *fwd;
va_list ap;
va_start(ap, types);
fwd = CForward::CreateForward(name, et, num_params, types, ap);
CForward *fwd = CForward::CreateForward(name, et, num_params, types, ap);
va_end(ap);
@ -80,7 +61,7 @@ IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned
{
scripts->AddFunctionsToForward(name, fwd);
m_managed.push_back(fwd);
m_managed.append(fwd);
}
return fwd;
@ -88,17 +69,16 @@ IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned
IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...)
{
CForward *fwd;
va_list ap;
va_start(ap, types);
fwd = CForward::CreateForward(name, et, num_params, types, ap);
CForward *fwd = CForward::CreateForward(name, et, num_params, types, ap);
va_end(ap);
if (fwd)
{
m_unmanaged.push_back(fwd);
m_unmanaged.append(fwd);
}
return fwd;
@ -107,119 +87,69 @@ IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
{
/* Attach any globally managed forwards */
List<CForward *>::iterator iter;
CForward *fwd;
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
{
fwd = (*iter);
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
CForward *fwd = (*iter);
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
if (pFunc)
{
fwd->AddFunction(pFunc);
}
}
}
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
{
List<CForward *>::iterator iter;
CForward *fwd;
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
{
fwd = (*iter);
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
CForward *fwd = (*iter);
fwd->RemoveFunctionsOfPlugin(plugin);
}
for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
{
fwd = (*iter);
for (ForwardIter iter(m_unmanaged); !iter.done(); iter.next()) {
CForward *fwd = (*iter);
fwd->RemoveFunctionsOfPlugin(plugin);
}
}
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
{
List<CForward *>::iterator iter;
CForward *fwd;
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
{
fwd = (*iter);
if (strcmp(fwd->GetForwardName(), name) == 0)
{
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
CForward *fwd = (*iter);
if (strcmp(fwd->GetForwardName(), name) == 0) {
if (ifchng)
{
*ifchng = NULL;
}
return fwd;
}
}
for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
{
fwd = (*iter);
if (strcmp(fwd->GetForwardName(), name) == 0)
{
for (ForwardIter iter(m_unmanaged); !iter.done(); iter.next()) {
CForward *fwd = (*iter);
if (strcmp(fwd->GetForwardName(), name) == 0) {
if (ifchng)
{
*ifchng = fwd;
}
return fwd;
}
}
if (ifchng)
{
*ifchng = NULL;
}
return NULL;
}
void CForwardManager::ReleaseForward(IForward *forward)
void CForwardManager::ReleaseForward(IForward *aForward)
{
ForwardFree(static_cast<CForward *>(forward));
}
void CForwardManager::ForwardFree(CForward *fwd)
{
if (fwd == NULL)
{
return;
}
m_FreeForwards.push(fwd);
CForward *fwd = static_cast<CForward *>(aForward);
m_managed.remove(fwd);
m_unmanaged.remove(fwd);
}
CForward *CForwardManager::ForwardMake()
{
CForward *fwd;
if (m_FreeForwards.empty())
{
fwd = new CForward;
} else {
fwd = m_FreeForwards.front();
m_FreeForwards.pop();
}
return fwd;
delete fwd;
}
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
{
if(paused)
if (paused)
return;
/* Attach any globally managed forwards */
List<CForward *>::iterator iter;
CForward *fwd;
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
{
fwd = (*iter);
for (ForwardIter iter(m_managed); !iter.done(); iter.next()) {
CForward *fwd = (*iter);
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
// Only add functions, if they aren't registered yet!
if (pFunc && !fwd->IsFunctionRegistered(pFunc))
@ -233,6 +163,27 @@ void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
* ACTUAL FORWARD API IMPLEMENTATION *
*************************************/
CForward::CForward(ExecType et, const char *name, const ParamType *types, unsigned num_params)
: m_numparams(0),
m_varargs(0),
m_ExecType(et),
m_curparam(0),
m_errstate(SP_ERROR_NONE)
{
ke::SafeStrcpy(m_name, sizeof(m_name), name ? name : "");
for (unsigned i = 0; i < num_params; i++)
m_types[i] = types[i];
if (num_params && types[num_params - 1] == Param_VarArgs) {
m_varargs = num_params;
m_numparams = num_params - 1;
} else {
m_varargs = 0;
m_numparams = num_params;
}
}
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap)
{
ParamType _types[SP_MAX_EXEC_PARAMS];
@ -270,30 +221,7 @@ CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int nu
return NULL;
}
CForward *pForward = g_Forwards.ForwardMake();
pForward->m_IterGuard = NULL;
pForward->m_curparam = 0;
pForward->m_ExecType = et;
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
for (unsigned int i=0; i<num_params; i++)
{
pForward->m_types[i] = _types[i];
}
if (num_params && _types[num_params-1] == Param_VarArgs)
{
pForward->m_varargs = num_params--;
} else {
pForward->m_varargs = false;
}
pForward->m_numparams = num_params;
pForward->m_errstate = SP_ERROR_NONE;
pForward->m_functions.clear();
return pForward;
return new CForward(et, name, _types, num_params);
}
int CForward::Execute(cell_t *result, IForwardFilter *filter)
@ -305,8 +233,6 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
return err;
}
FuncIter iter = m_functions.begin();
IPluginFunction *func;
cell_t cur_result = 0;
cell_t high_result = 0;
cell_t low_result = 0;
@ -314,54 +240,38 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
unsigned int success=0;
unsigned int num_params = m_curparam;
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
FwdParamInfo *param;
ParamType type;
/* Save local, reset */
memcpy(temp_info, m_params, sizeof(m_params));
m_curparam = 0;
FuncIteratorGuard guard(&m_IterGuard, &iter);
while (iter != m_functions.end())
for (FuncIter iter(m_functions); !iter.done(); iter.next())
{
func = (*iter);
IPluginFunction *func = (*iter);
if (filter)
filter->Preprocess(func, temp_info);
if (func->GetParentRuntime()->IsPaused())
continue;
for (unsigned int i=0; i<num_params; i++)
{
int err = SP_ERROR_PARAM;
param = &temp_info[i];
FwdParamInfo *param = &temp_info[i];
ParamType type;
if (i >= m_numparams || m_types[i] == Param_Any)
{
type = param->pushedas;
}
else
{
type = m_types[i];
}
if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
{
/* If we're byref or we're vararg, we always push everything by ref.
* Even if they're byval, we must push them byref.
*/
if (type == Param_String)
{
err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
}
else if (type == Param_Float || type == Param_Cell)
{
err = func->PushCellByRef(&param->val);
}
else
{
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
}
* Even if they're byval, we must push them byref.
*/
err = _ExecutePushRef(func, type, param);
}
else
{
@ -421,9 +331,6 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
}
}
}
if (!guard.Triggered())
iter++;
}
done:
@ -463,6 +370,58 @@ done:
return SP_ERROR_NONE;
}
int CForward::_ExecutePushRef(IPluginFunction *func, ParamType type, FwdParamInfo *param)
{
/* If we're byref or we're vararg, we always push everything by ref.
* Even if they're byval, we must push them byref.
*/
int err;
IPluginRuntime *runtime = func->GetParentRuntime();
switch (type)
{
case Param_String:
// Normal string was pushed.
if (!param->isnull)
return func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
// If NULL_STRING was pushed, push the reference to the pubvar of the callee instead.
uint32_t null_string_idx;
err = runtime->FindPubvarByName("NULL_STRING", &null_string_idx);
if (err)
return err;
cell_t null_string;
err = runtime->GetPubvarAddrs(null_string_idx, &null_string, nullptr);
if (err)
return err;
return func->PushCell(null_string);
case Param_Float:
case Param_Cell:
return func->PushCellByRef(&param->val);
default:
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
// No NULL_VECTOR was pushed.
if (type != Param_Array || !param->isnull)
return func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
// If NULL_VECTOR was pushed, push the reference to the pubvar of the callee instead.
uint32_t null_vector_idx;
err = runtime->FindPubvarByName("NULL_VECTOR", &null_vector_idx);
if (err)
return err;
cell_t null_vector;
err = runtime->GetPubvarAddrs(null_vector_idx, &null_vector, nullptr);
if (err)
return err;
return func->PushCell(null_vector);
}
}
int CForward::PushCell(cell_t cell)
{
if (m_curparam < m_numparams)
@ -481,6 +440,7 @@ int CForward::PushCell(cell_t cell)
m_params[m_curparam].pushedas = Param_Cell;
}
m_params[m_curparam].isnull = false;
m_params[m_curparam++].val = cell;
return SP_ERROR_NONE;
@ -504,6 +464,7 @@ int CForward::PushFloat(float number)
m_params[m_curparam].pushedas = Param_Float;
}
m_params[m_curparam].isnull = false;
m_params[m_curparam++].val = *(cell_t *)&number;
return SP_ERROR_NONE;
@ -562,14 +523,22 @@ void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
m_params[m_curparam].byref.cells = cells;
m_params[m_curparam].byref.flags = flags;
m_params[m_curparam].byref.orig_addr = inarray;
m_params[m_curparam].isnull = false;
}
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
{
/* We don't allow this here */
/* Push a reference to the NULL_VECTOR pubvar if NULL was passed. */
if (!inarray)
{
return SetError(SP_ERROR_PARAM);
/* Make sure this was intentional. */
if (cells == 3)
{
return PushNullVector();
} else {
/* We don't allow this here */
return SetError(SP_ERROR_PARAM);
}
}
if (m_curparam < m_numparams)
@ -601,10 +570,17 @@ void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags
m_params[m_curparam].byref.flags = cp_flags;
m_params[m_curparam].byref.orig_addr = inarray;
m_params[m_curparam].byref.sz_flags = sz_flags;
m_params[m_curparam].isnull = false;
}
int CForward::PushString(const char *string)
{
/* Push a reference to the NULL_STRING pubvar if NULL was passed. */
if (!string)
{
return PushNullString();
}
if (m_curparam < m_numparams)
{
if (m_types[m_curparam] == Param_Any)
@ -651,6 +627,52 @@ int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_fla
return SP_ERROR_NONE;
}
int CForward::PushNullString()
{
if (m_curparam < m_numparams)
{
if (m_types[m_curparam] == Param_Any)
{
m_params[m_curparam].pushedas = Param_String;
} else if (m_types[m_curparam] != Param_String) {
return SetError(SP_ERROR_PARAM);
}
} else {
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
m_params[m_curparam].pushedas = Param_String;
}
m_params[m_curparam++].isnull = true;
return SP_ERROR_NONE;
}
int CForward::PushNullVector()
{
if (m_curparam < m_numparams)
{
if (m_types[m_curparam] == Param_Any)
{
m_params[m_curparam].pushedas = Param_Array;
} else if (m_types[m_curparam] != Param_Array) {
return SetError(SP_ERROR_PARAM);
}
} else {
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
m_params[m_curparam].pushedas = Param_Array;
}
m_params[m_curparam++].isnull = true;
return SP_ERROR_NONE;
}
void CForward::Cancel()
{
if (!m_curparam)
@ -688,93 +710,65 @@ bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index)
bool CForward::RemoveFunction(IPluginFunction *func)
{
bool found = false;
FuncIter iter;
List<IPluginFunction *> *lst;
ReentrantList<IPluginFunction *> *lst;
if (func->IsRunnable())
{
lst = &m_functions;
} else {
else
lst = &m_paused;
}
for (iter=lst->begin(); iter!=lst->end(); iter++)
{
if ((*iter) == func)
{
m_IterGuard->FixIteratorChain(iter);
bool found = false;
for (FuncIter iter(lst); !iter.done(); iter.next()) {
if (*iter == func) {
iter.remove();
found = true;
lst->erase(iter);
break;
}
}
/* Cancel a call, if any */
if (found || m_curparam)
{
func->Cancel();
}
return found;
}
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
{
FuncIter iter;
IPluginFunction *func;
unsigned int removed = 0;
IPluginContext *pContext = plugin->GetBaseContext();
for (iter=m_functions.begin(); iter!=m_functions.end();)
{
func = (*iter);
if (func->GetParentContext() == pContext)
{
iter = m_functions.erase(iter);
for (FuncIter iter(m_functions); !iter.done(); iter.next()) {
IPluginFunction *func = *iter;
if (func->GetParentContext() == plugin->GetBaseContext()) {
iter.remove();
removed++;
} else {
iter++;
}
}
return removed;
}
bool CForward::AddFunction(IPluginFunction *func)
{
if (m_curparam)
{
return false;
}
if (func->IsRunnable())
{
m_functions.push_back(func);
} else {
m_paused.push_back(func);
}
m_functions.append(func);
else
m_paused.append(func);
return true;
}
bool CForward::IsFunctionRegistered(IPluginFunction *func)
{
FuncIter iter;
List<IPluginFunction *> *lst;
ReentrantList<IPluginFunction *> *lst;
if (func->IsRunnable())
{
lst = &m_functions;
} else {
else
lst = &m_paused;
}
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
{
for (FuncIter iter(lst); !iter.done(); iter.next()) {
if ((*iter) == func)
{
return true;
}
}
return false;
}
@ -786,7 +780,7 @@ const char *CForward::GetForwardName()
unsigned int CForward::GetFunctionCount()
{
return m_functions.size();
return m_functions.length();
}
ExecType CForward::GetExecType()

View File

@ -1,33 +1,29 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
// vim: set ts=4 sw=4 tw=99 noet :
// =============================================================================
// SourceMod
// Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
// =============================================================================
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License, version 3.0, as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, AlliedModders LLC gives you permission to link the
// code of this program (as well as its derivative works) to "Half-Life 2," the
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
// by the Valve Corporation. You must obey the GNU General Public License in
// all respects for all other code used. Additionally, AlliedModders LLC grants
// this exception to all derivative works. AlliedModders LLC defines further
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
// or <http://www.sourcemod.net/license.php>.
#ifndef _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
#define _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
@ -35,61 +31,14 @@
#include <IForwardSys.h>
#include <IPluginSys.h>
#include "common_logic.h"
#include <sh_list.h>
#include <sh_stack.h>
#include "ISourceMod.h"
#include "ReentrantList.h"
using namespace SourceHook;
typedef List<IPluginFunction *>::iterator FuncIter;
typedef ReentrantList<IPluginFunction *>::iterator FuncIter;
/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
#define FORWARDS_NAME_MAX 64
class FuncIteratorGuard
{
bool triggered;
FuncIteratorGuard **pprev;
FuncIter *iter;
FuncIteratorGuard *next;
public:
FuncIteratorGuard(FuncIteratorGuard **pprev, FuncIter *iter)
: triggered(false), pprev(pprev), iter(iter), next(*pprev)
{
*pprev = this;
}
~FuncIteratorGuard()
{
*pprev = next;
}
inline bool Triggered()
{
bool t = triggered;
triggered = false;
return t;
}
/**
* This should not read from |this| before the NULL check, because FwdSys
* can call (NULL)->FixIteratorChain().
*/
void FixIteratorChain(FuncIter &other)
{
FuncIteratorGuard *guard = this;
while (guard != NULL)
{
if (*guard->iter == other)
{
*(guard->iter) = ++(*(guard->iter));
guard->triggered = true;
}
guard = guard->next;
}
}
};
class CForward : public IChangeableForward
{
public: //ICallable
@ -120,6 +69,12 @@ public:
va_list ap);
bool IsFunctionRegistered(IPluginFunction *func);
private:
CForward(ExecType et, const char *name,
const ParamType *types, unsigned num_params);
int PushNullString();
int PushNullVector();
int _ExecutePushRef(IPluginFunction *func, ParamType type, FwdParamInfo *param);
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags);
void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags);
inline int SetError(int err)
@ -128,12 +83,8 @@ private:
return err;
}
protected:
/* :TODO: I want a caching list type here.
* Destroying these things and using new/delete for their members feels bad.
*/
mutable List<IPluginFunction *> m_functions;
mutable List<IPluginFunction *> m_paused;
FuncIteratorGuard *m_IterGuard;
mutable ReentrantList<IPluginFunction *> m_functions;
mutable ReentrantList<IPluginFunction *> m_paused;
/* Type and name information */
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
@ -154,8 +105,6 @@ class CForwardManager :
public SMGlobalClass
{
friend class CForward;
public:
~CForwardManager();
public: //IForwardManager
IForward *CreateForward(const char *name,
ExecType et,
@ -175,13 +124,11 @@ public: //IPluginsListener
void OnPluginPauseChange(IPlugin *plugin, bool paused);
public: //SMGlobalClass
void OnSourceModAllInitialized();
protected:
CForward *ForwardMake();
void ForwardFree(CForward *fwd);
private:
CStack<CForward *> m_FreeForwards;
List<CForward *> m_managed;
List<CForward *> m_unmanaged;
ReentrantList<CForward *> m_managed;
ReentrantList<CForward *> m_unmanaged;
typedef ReentrantList<CForward *>::iterator ForwardIter;
};
extern CForwardManager g_Forwards;

View File

@ -1,65 +1,91 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourcePawn
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
#define _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
/**
* @file sp_typeutil.h
* @brief Defines type utility functions.
*/
#include "sp_vm_types.h"
/**
* @brief Reinterpret-casts a float to a cell (requires -fno-strict-aliasing for GCC).
*
* @param val Float value.
* @return Cell typed version.
*/
inline cell_t sp_ftoc(float val)
{
return *(cell_t *)&val;
}
/**
* @brief Reinterpret-casts a cell to a float (requires -fno-strict-aliasing for GCC).
*
* @param val Cell-packed float value.
* @return Float typed version.
*/
inline float sp_ctof(cell_t val)
{
return *(float *)&val;
}
#endif //_INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* 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>.
*
* Version: $Id$
*/
#include "FrameIterator.h"
SafeFrameIterator::SafeFrameIterator(IFrameIterator *it)
{
while (!it->Done())
{
FrameInfo info = FrameInfo(it);
frames.append(info);
it->Next();
}
it->Reset();
current = 0;
}
bool SafeFrameIterator::Done() const
{
return current >= frames.length();
}
bool SafeFrameIterator::Next()
{
current++;
return !this->Done();
}
void SafeFrameIterator::Reset()
{
current = 0;
}
int SafeFrameIterator::LineNumber() const
{
if (this->Done())
{
return -1;
}
return (int)frames[current].LineNumber;
}
const char *SafeFrameIterator::FunctionName() const
{
if (this->Done())
{
return NULL;
}
return frames[current].FunctionName.chars();
}
const char *SafeFrameIterator::FilePath() const
{
if (this->Done())
{
return NULL;
}
return frames[current].FilePath.chars();
}

View File

@ -0,0 +1,77 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* 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>.
*
* Version: $Id$
*/
#include "sp_vm_api.h"
#include <am-vector.h>
#include <am-string.h>
using namespace SourcePawn;
/**
* Frame iterator cache which is safe for plugins to hold handles to,
* unlike what you'd recieve from IPluginContext::CreateFrameIterator.
*/
class SafeFrameIterator
{
public:
/**
* Struct which holds all of the cached values for each individual frame.
*/
struct FrameInfo
{
ke::AString FunctionName;
ke::AString FilePath;
unsigned LineNumber;
FrameInfo(IFrameIterator *it)
{
LineNumber = it->LineNumber();
FunctionName = it->FunctionName();
FilePath = it->FilePath();
}
};
SafeFrameIterator(IFrameIterator *);
bool Done() const;
bool Next();
void Reset();
int LineNumber() const;
const char *FunctionName() const;
const char *FilePath() const;
private:
size_t current;
ke::Vector<FrameInfo> frames;
};

View File

@ -39,9 +39,13 @@
#include <IHandleSys.h>
#include <IMemoryUtils.h>
#include <ISourceMod.h>
#include <IRootConsoleMenu.h>
#include "common_logic.h"
#include "sm_crc32.h"
#include "MemoryUtils.h"
#include <am-string.h>
#include <bridge/include/ILogger.h>
#include <bridge/include/CoreProvider.h>
#if defined PLATFORM_POSIX
#include <dlfcn.h>
@ -62,26 +66,33 @@ static const char *g_pParseEngine = NULL;
#define PSTATE_GAMEDEFS_OFFSETS 3
#define PSTATE_GAMEDEFS_OFFSETS_OFFSET 4
#define PSTATE_GAMEDEFS_KEYS 5
#define PSTATE_GAMEDEFS_SUPPORTED 6
#define PSTATE_GAMEDEFS_SIGNATURES 7
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 8
#define PSTATE_GAMEDEFS_CRC 9
#define PSTATE_GAMEDEFS_CRC_BINARY 10
#define PSTATE_GAMEDEFS_CUSTOM 11
#define PSTATE_GAMEDEFS_ADDRESSES 12
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 13
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 14
#define PSTATE_GAMEDEFS_KEYS_PLATFORM 6
#define PSTATE_GAMEDEFS_SUPPORTED 7
#define PSTATE_GAMEDEFS_SIGNATURES 8
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 9
#define PSTATE_GAMEDEFS_CRC 10
#define PSTATE_GAMEDEFS_CRC_BINARY 11
#define PSTATE_GAMEDEFS_CUSTOM 12
#define PSTATE_GAMEDEFS_ADDRESSES 13
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 14
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 15
#if defined PLATFORM_X86
#define PLATFORM_ARCH_SUFFIX ""
#elif defined PLATFORM_X64
#define PLATFORM_ARCH_SUFFIX "64"
#endif
#if defined PLATFORM_WINDOWS
#define PLATFORM_NAME "windows"
#define PLATFORM_NAME "windows" PLATFORM_ARCH_SUFFIX
#define PLATFORM_SERVER_BINARY "server.dll"
#elif defined PLATFORM_LINUX
#define PLATFORM_NAME "linux"
#define PLATFORM_COMPAT_ALT "mac" /* Alternate platform name if game data is missing for primary one */
#define PLATFORM_NAME "linux" PLATFORM_ARCH_SUFFIX
#define PLATFORM_COMPAT_ALT "mac" PLATFORM_ARCH_SUFFIX /* Alternate platform name if game data is missing for primary one */
#define PLATFORM_SERVER_BINARY "server_i486.so"
#elif defined PLATFORM_APPLE
#define PLATFORM_NAME "mac"
#define PLATFORM_COMPAT_ALT "linux"
#define PLATFORM_NAME "mac" PLATFORM_ARCH_SUFFIX
#define PLATFORM_COMPAT_ALT "linux" PLATFORM_ARCH_SUFFIX
#define PLATFORM_SERVER_BINARY "server.dylib"
#endif
@ -150,7 +161,7 @@ CGameConfig::CGameConfig(const char *file, const char *engine)
m_CustomHandler = NULL;
if (!engine)
m_pEngine = smcore.GetSourceEngineName();
m_pEngine = bridge->GetSourceEngineName();
else
m_pEngine = engine;
@ -248,6 +259,13 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
}
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:
{
m_Prop[0] = '\0';
@ -271,7 +289,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
error[0] = '\0';
if (strcmp(name, "server") != 0)
{
smcore.Format(error, sizeof(error), "Unrecognized library \"%s\"", name);
ke::SafeSprintf(error, sizeof(error), "Unrecognized library \"%s\"", name);
}
else if (!s_ServerBinCRC_Ok)
{
@ -281,7 +299,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
g_pSM->BuildPath(Path_Game, path, sizeof(path), "bin/" PLATFORM_SERVER_BINARY);
if ((fp = fopen(path, "rb")) == NULL)
{
smcore.Format(error, sizeof(error), "Could not open binary: %s", path);
ke::SafeSprintf(error, sizeof(error), "Could not open binary: %s", path);
} else {
size_t size;
void *buffer;
@ -319,6 +337,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
m_Address[0] = '\0';
m_AddressSignature[0] = '\0';
m_AddressReadCount = 0;
m_AddressLastIsOffset = false;
strncopy(m_Address, name, sizeof(m_Address));
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
@ -333,7 +352,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
}
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] Unrecognized platform \"%s\"", name);
@ -344,7 +364,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
}
/* No sub-sections allowed:
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
case PSTATE_GAMEDEFS_KEYS:
case PSTATE_GAMEDEFS_KEYS_PLATFORM:
case PSTATE_GAMEDEFS_SUPPORTED:
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
case PSTATE_GAMEDEFS_CRC_BINARY:
@ -381,6 +401,13 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
ke::AString vstr(value);
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) {
if (strcmp(key, "game") == 0)
{
@ -426,10 +453,18 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
}
}
} else if (m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS || m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ) {
if (strcmp(key, "read") == 0) {
if (strcmp(key, "read") == 0 || strcmp(key, "offset") == 0) {
int limit = sizeof(m_AddressRead)/sizeof(m_AddressRead[0]);
if (m_AddressReadCount < limit)
if (m_AddressLastIsOffset)
{
logger->LogError("[SM] Error parsing Address \"%s\", 'offset' entry must be the last entry (gameconf \"%s\")", m_Address, m_CurFile);
}
else if (m_AddressReadCount < limit)
{
if (strcmp(key, "offset") == 0)
{
m_AddressLastIsOffset = true;
}
m_AddressRead[m_AddressReadCount] = atoi(value);
m_AddressReadCount++;
}
@ -486,6 +521,11 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
m_ParseState = PSTATE_GAMEDEFS;
break;
}
case PSTATE_GAMEDEFS_KEYS_PLATFORM:
{
m_ParseState = PSTATE_GAMEDEFS_KEYS;
break;
}
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
{
/* Parse the offset... */
@ -547,11 +587,11 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
void *addrInBase = NULL;
if (strcmp(s_TempSig.library, "server") == 0)
{
addrInBase = smcore.serverFactory;
addrInBase = bridge->serverFactory;
} else if (strcmp(s_TempSig.library, "engine") == 0) {
addrInBase = smcore.engineFactory;
addrInBase = bridge->engineFactory;
} else if (strcmp(s_TempSig.library, "matchmaking_ds") == 0) {
addrInBase = smcore.matchmakingDSFactory;
addrInBase = bridge->matchmakingDSFactory;
}
void *final_addr = NULL;
if (addrInBase == NULL)
@ -579,7 +619,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
void *handle = dlopen(info.dli_fname, RTLD_NOW);
if (handle)
{
if (smcore.SymbolsAreHidden())
if (bridge->SymbolsAreHidden())
final_addr = g_MemUtils.ResolveSymbol(handle, &s_TempSig.sig[1]);
else
final_addr = dlsym(handle, &s_TempSig.sig[1]);
@ -633,7 +673,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0')
{
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead);
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead, m_AddressLastIsOffset);
m_Addresses.replace(m_Address, addrConf);
}
@ -791,7 +831,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
if (!libsys->PathExists(path))
{
/* Nope, use the old mechanism. */
smcore.Format(path, sizeof(path), "%s.txt", m_File);
ke::SafeSprintf(path, sizeof(path), "%s.txt", m_File);
if (!EnterFile(path, error, maxlength))
{
return false;
@ -801,8 +841,13 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
g_pSM->BuildPath(Path_SM, path, sizeof(path), "gamedata/custom/%s.txt", m_File);
if (libsys->PathExists(path))
{
smcore.Format(path, sizeof(path), "custom/%s.txt", m_File);
return EnterFile(path, error, maxlength);
ke::SafeSprintf(path, sizeof(path), "custom/%s.txt", m_File);
bool success = EnterFile(path, error, maxlength);
if (success)
{
rootmenu->ConsolePrint("[SM] Parsed custom gamedata override file: %s", path);
}
return success;
}
return true;
}
@ -841,7 +886,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
List<String>::iterator iter;
for (iter = fileList.begin(); iter != fileList.end(); iter++)
{
smcore.Format(path, sizeof(path), "%s/%s", m_File, (*iter).c_str());
ke::SafeSprintf(path, sizeof(path), "%s/%s", m_File, (*iter).c_str());
if (!EnterFile(path, error, maxlength))
{
return false;
@ -875,13 +920,15 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
continue;
}
smcore.Format(path, sizeof(path), "%s/custom/%s", m_File, curFile);
ke::SafeSprintf(path, sizeof(path), "%s/custom/%s", m_File, curFile);
if (!EnterFile(path, error, maxlength))
{
libsys->CloseDirectory(customDir);
return false;
}
rootmenu->ConsolePrint("[SM] Parsed custom gamedata override file: %s", path);
customDir->NextEntry();
}
@ -986,12 +1033,17 @@ bool CGameConfig::GetAddress(const char *key, void **retaddr)
int offset = addrConf.read[i];
//NULLs in the middle of an indirection chain are bad, end NULL is ok
if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
*retaddr = NULL;
return false;
}
addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
//If lastIsOffset is set and this is the last iteration of the loop, don't deref
if (addrConf.lastIsOffset && i == addrConf.readCount-1) {
addr = reinterpret_cast<void*>(reinterpret_cast<uint8_t*>(addr) + offset);
} else {
addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
}
}
*retaddr = addr;
@ -1003,13 +1055,17 @@ static inline unsigned minOf(unsigned a, unsigned b)
return a <= b ? a : b;
}
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read)
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset)
{
unsigned readLimit = minOf(readCount, sizeof(this->read) / sizeof(this->read[0]));
strncopy(signatureName, sigName, sizeof(signatureName) / sizeof(signatureName[0]));
this->readCount = readLimit;
memcpy(&this->read[0], read, sizeof(this->read[0])*readLimit);
//For safety: if the readLimit isn't the same as the readCount, then the
//last read value was definitely discarded, so lastIsOffset should be ignored
this->lastIsOffset = readLimit < readCount ? false : lastIsOffset;
}
SendProp *CGameConfig::GetSendProp(const char *key)
@ -1038,8 +1094,8 @@ void GameConfigManager::OnSourceModStartup(bool late)
LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0);
strncopy(g_Game, g_pSM->GetGameFolderName(), sizeof(g_Game));
strncopy(g_GameDesc + 1, smcore.GetGameDescription(), sizeof(g_GameDesc) - 1);
smcore.GetGameName(g_GameName + 1, sizeof(g_GameName) - 1);
strncopy(g_GameDesc + 1, bridge->GetGameDescription(), sizeof(g_GameDesc) - 1);
bridge->GetGameName(g_GameName + 1, sizeof(g_GameName) - 1);
}
void GameConfigManager::OnSourceModAllInitialized()

View File

@ -40,7 +40,6 @@
#include <sm_namehashset.h>
using namespace SourceMod;
using namespace SourceHook;
class SendProp;
@ -73,6 +72,10 @@ public: //NameHashSet
{
return strcmp(key, value->m_File) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
private:
char m_File[PLATFORM_MAX_PATH];
char m_CurFile[PLATFORM_MAX_PATH];
@ -87,6 +90,7 @@ private:
char m_Prop[64];
char m_offset[64];
char m_Game[256];
char m_Key[64];
bool bShouldBeReadingDefault;
bool had_game;
bool matched_game;
@ -104,8 +108,9 @@ private:
char signatureName[64];
int readCount;
int read[8];
bool lastIsOffset;
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read);
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset);
AddressConf() {}
};
@ -114,6 +119,7 @@ private:
char m_AddressSignature[64];
int m_AddressReadCount;
int m_AddressRead[8];
bool m_AddressLastIsOffset;
StringHashMap<AddressConf> m_Addresses;
const char *m_pEngine;
const char *m_pBaseEngine;

View File

@ -36,6 +36,8 @@
#include "ShareSys.h"
#include "ExtensionSys.h"
#include "PluginSys.h"
#include <am-string.h>
#include <bridge/include/ILogger.h>
HandleSystem g_HandleSys;
@ -1064,11 +1066,23 @@ bool HandleSystem::TryAndFreeSomeHandles()
return scripts->UnloadPlugin(highest_owner);
}
void HandleSystem::Dump(HANDLE_REPORTER rep)
static void rep(const HandleReporter &fn, const char *fmt, ...)
{
va_list ap;
char buffer[1024];
va_start(ap, fmt);
ke::SafeVsprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
fn(buffer);
}
void HandleSystem::Dump(const HandleReporter &fn)
{
unsigned int total_size = 0;
rep("%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
rep("--------------------------------------------------------------------------");
rep(fn, "%-10.10s\t%-20.20s\t%-20.20s\t%-10.10s", "Handle", "Owner", "Type", "Memory");
rep(fn, "--------------------------------------------------------------------------");
for (unsigned int i = 1; i <= m_HandleTail; i++)
{
if (m_Handles[i].set != HandleSet_Used)
@ -1139,16 +1153,16 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|| !bresult)
{
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
}
else
{
char buffer[32];
smcore.Format(buffer, sizeof(buffer), "%d", size);
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
ke::SafeSprintf(buffer, sizeof(buffer), "%d", size);
rep(fn, "0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
total_size += size;
}
}
rep("-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
rep(fn, "-- Approximately %d bytes of memory are in use by Handles.\n", total_size);
}

View File

@ -35,10 +35,12 @@
#include <IHandleSys.h>
#include <stdio.h>
#include <sm_namehashset.h>
#include <am-string.h>
#include <amtl/am-autoptr.h>
#include <amtl/am-string.h>
#include <amtl/am-function.h>
#include "common_logic.h"
#define HANDLESYS_MAX_HANDLES (1<<14)
#define HANDLESYS_MAX_HANDLES (1<<15)
#define HANDLESYS_MAX_TYPES (1<<9)
#define HANDLESYS_MAX_SUBTYPES 0xF
#define HANDLESYS_SUBTYPE_MASK 0xF
@ -109,9 +111,13 @@ struct QHandleType
{
return type->name && type->name->compare(key) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};
typedef void (HANDLE_REPORTER)(const char *str, ...);
typedef ke::Lambda<void(const char *)> HandleReporter;
class HandleSystem :
public IHandleSys
@ -163,7 +169,7 @@ public: //IHandleSystem
const HandleAccess *pAccess,
HandleError *err);
void Dump(HANDLE_REPORTER rep);
void Dump(const HandleReporter &reporter);
/* Bypasses security checks. */
Handle_t FastCloneHandle(Handle_t hndl);

View File

@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@ -34,27 +34,16 @@
#include <stdarg.h>
#include <string.h>
#include <sm_platform.h>
#include "sm_stringutil.h"
#include "LibrarySys.h"
#include <amtl/am-string.h>
#include <amtl/os/am-path.h>
#include <amtl/os/am-fsutil.h>
LibrarySystem g_LibSys;
CLibrary::~CLibrary()
CLibrary::CLibrary(ke::RefPtr<ke::SharedLib> lib)
: lib_(lib)
{
if (m_lib)
{
#if defined PLATFORM_WINDOWS
FreeLibrary(m_lib);
#elif defined PLATFORM_POSIX
dlclose(m_lib);
#endif
m_lib = NULL;
}
}
CLibrary::CLibrary(LibraryHandle me)
{
m_lib = me;
}
void CLibrary::CloseLibrary()
@ -64,11 +53,7 @@ void CLibrary::CloseLibrary()
void *CLibrary::GetSymbolAddress(const char *symname)
{
#if defined PLATFORM_WINDOWS
return GetProcAddress(m_lib, symname);
#elif defined PLATFORM_POSIX
return dlsym(m_lib, symname);
#endif
return lib_->lookup(symname);
}
@ -81,7 +66,7 @@ CDirectory::CDirectory(const char *path)
{
#if defined PLATFORM_WINDOWS
char newpath[PLATFORM_MAX_PATH];
snprintf(newpath, sizeof(newpath), "%s\\*.*", path);
ke::SafeSprintf(newpath, sizeof(newpath), "%s\\*.*", path);
m_dir = FindFirstFileA(newpath, &m_fd);
if (!IsValid())
{
@ -93,7 +78,7 @@ CDirectory::CDirectory(const char *path)
{
/* :TODO: we need to read past "." and ".."! */
ep = readdir(m_dir);
snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path);
ke::SafeStrcpy(m_origpath, PLATFORM_MAX_PATH, path);
} else {
ep = NULL;
}
@ -140,8 +125,10 @@ bool CDirectory::IsEntryDirectory()
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
#elif defined PLATFORM_POSIX
char temppath[PLATFORM_MAX_PATH];
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
return g_LibSys.IsPathDirectory(temppath);
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);
#endif
}
@ -151,8 +138,10 @@ bool CDirectory::IsEntryFile()
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
#elif defined PLATFORM_POSIX
char temppath[PLATFORM_MAX_PATH];
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
return g_LibSys.IsPathFile(temppath);
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);
#endif
}
@ -187,75 +176,17 @@ bool CDirectory::IsValid()
bool LibrarySystem::PathExists(const char *path)
{
#if defined PLATFORM_WINDOWS
DWORD attr = GetFileAttributesA(path);
return (attr != INVALID_FILE_ATTRIBUTES);
#elif defined PLATFORM_POSIX
struct stat s;
return (stat(path, &s) == 0);
#endif
return ke::file::PathExists(path);
}
bool LibrarySystem::IsPathFile(const char *path)
{
#if defined PLATFORM_WINDOWS
DWORD attr = GetFileAttributes(path);
if (attr == INVALID_FILE_ATTRIBUTES)
{
return false;
}
if (attr & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
{
return false;
}
return true;
#elif defined PLATFORM_POSIX
struct stat s;
if (stat(path, &s) != 0)
{
return false;
}
return S_ISREG(s.st_mode) ? true : false;
#endif
return ke::file::IsFile(path);
}
bool LibrarySystem::IsPathDirectory(const char *path)
{
#if defined PLATFORM_WINDOWS
DWORD attr = GetFileAttributes(path);
if (attr == INVALID_FILE_ATTRIBUTES)
{
return false;
}
if (attr & FILE_ATTRIBUTE_DIRECTORY)
{
return true;
}
#elif defined PLATFORM_POSIX
struct stat s;
if (stat(path, &s) != 0)
{
return false;
}
if (S_ISDIR(s.st_mode))
{
return true;
}
#endif
return false;
return ke::file::IsDirectory(path);
}
IDirectory *LibrarySystem::OpenDirectory(const char *path)
@ -293,13 +224,13 @@ void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
maxlength,
NULL) == 0)
{
UTIL_Format(error, maxlength, "error code %08x", code);
ke::SafeSprintf(error, maxlength, "error code %08x", code);
}
#elif defined PLATFORM_LINUX
const char *ae = strerror_r(code, error, maxlength);
if (ae != error)
{
UTIL_Format(error, maxlength, "%s", ae);
ke::SafeStrcpy(error, maxlength, ae);
}
#elif defined PLATFORM_POSIX
strerror_r(code, error, maxlength);
@ -307,18 +238,6 @@ void LibrarySystem::GetPlatformErrorEx(int code, char *error, size_t maxlength)
}
}
void LibrarySystem::GetLoaderError(char *buffer, size_t maxlength)
{
#if defined PLATFORM_WINDOWS
GetPlatformError(buffer, maxlength);
#elif defined PLATFORM_POSIX
if (buffer != NULL && maxlength)
{
strncopy(buffer, dlerror(), maxlength);
}
#endif
}
void LibrarySystem::CloseDirectory(IDirectory *dir)
{
delete dir;
@ -326,19 +245,9 @@ void LibrarySystem::CloseDirectory(IDirectory *dir)
ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxlength)
{
LibraryHandle lib;
#if defined PLATFORM_WINDOWS
lib = LoadLibraryA(path);
#elif defined PLATFORM_POSIX
lib = dlopen(path, RTLD_NOW);
#endif
if (lib == NULL)
{
GetLoaderError(error, maxlength);
return NULL;
}
ke::RefPtr<ke::SharedLib> lib = ke::SharedLib::Open(path, error, maxlength);
if (!lib)
return nullptr;
return new CLibrary(lib);
}
@ -346,23 +255,8 @@ size_t LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t mylen = vsnprintf(buffer, len, fmt, ap);
size_t mylen = ke::path::FormatVa(buffer, len, fmt, ap);
va_end(ap);
if (mylen >= len)
{
mylen = len - 1;
buffer[mylen] = '\0';
}
for (size_t i=0; i<mylen; i++)
{
if (buffer[i] == PLATFORM_SEP_ALTCHAR)
{
buffer[i] = PLATFORM_SEP_CHAR;
}
}
return mylen;
}
@ -398,11 +292,7 @@ const char *LibrarySystem::GetFileExtension(const char *filename)
bool LibrarySystem::CreateFolder(const char *path)
{
#if defined PLATFORM_WINDOWS
return (mkdir(path) != -1);
#elif defined PLATFORM_POSIX
return (mkdir(path, 0775) != -1);
#endif
return ke::file::CreateDirectory(path, 0775);
}
size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char *path)
@ -419,12 +309,12 @@ size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char
#endif
)
{
return UTIL_Format(buffer, maxlength, "%s", &path[i+1]);
return ke::SafeStrcpy(buffer, maxlength, &path[i+1]);
}
}
/* We scanned and found no path separator */
return UTIL_Format(buffer, maxlength, "%s", path);
return ke::SafeStrcpy(buffer, maxlength, path);
}
bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime)

View File

@ -1,5 +1,5 @@
/**
* vim: set ts=4 :
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@ -33,16 +33,11 @@
#define _INCLUDE_SOURCEMOD_SYSTEM_LIBRARY_H_
#include <ILibrarySys.h>
#include <amtl/os/am-shared-library.h>
#include "sm_platform.h"
using namespace SourceMod;
#if defined PLATFORM_WINDOWS
typedef HMODULE LibraryHandle;
#elif defined PLATFORM_POSIX
typedef void * LibraryHandle;
#endif
class CDirectory : public IDirectory
{
public:
@ -71,13 +66,12 @@ private:
class CLibrary : public ILibrary
{
public:
CLibrary(LibraryHandle me);
~CLibrary();
CLibrary(ke::RefPtr<ke::SharedLib> lib);
public:
void CloseLibrary();
void *GetSymbolAddress(const char *symname);
void CloseLibrary() override;
void *GetSymbolAddress(const char *symname) override;
private:
LibraryHandle m_lib;
ke::RefPtr<ke::SharedLib> lib_;
};
class LibrarySystem : public ILibrarySys
@ -96,7 +90,6 @@ public:
bool CreateFolder(const char *path);
size_t GetFileFromPath(char *buffer, size_t maxlength, const char *path);
bool FileTime(const char *path, FileTimeType type, time_t *pTime);
void GetLoaderError(char *buffer, size_t maxlength);
};
extern LibrarySystem g_LibSys;

View File

@ -34,13 +34,12 @@
#include "Logger.h"
#include <sourcemod_version.h>
#include <ISourceMod.h>
#include <am-string.h>
#include <ILibrarySys.h>
#include <bridge/include/CoreProvider.h>
Logger g_Logger;
/**
* :TODO: This should be creating the log folder if it doesn't exist
*/
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
@ -57,7 +56,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
} else if (strcasecmp(value, "off") == 0) {
state = false;
} else {
smcore.Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
ke::SafeStrcpy(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
return ConfigResult_Reject;
}
@ -65,7 +64,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
{
state ? EnableLogging() : DisableLogging();
} else {
m_InitialState = state;
m_Active = state;
}
return ConfigResult_Accept;
@ -78,7 +77,7 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
} else if (strcasecmp(value, "game") == 0) {
m_Mode = LoggingMode_Game;
} else {
smcore.Format(error, maxlength, "Invalid value: must be [daily|map|game]");
ke::SafeStrcpy(error, maxlength, "Invalid value: must be [daily|map|game]");
return ConfigResult_Reject;
}
@ -90,7 +89,12 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
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()
@ -100,127 +104,7 @@ void Logger::OnSourceModAllShutdown()
void Logger::OnSourceModLevelChange(const char *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;
}
}
_MapChange(mapName);
}
void Logger::CloseLogger()
@ -228,6 +112,13 @@ void Logger::CloseLogger()
_CloseFile();
}
void Logger::_CloseFile()
{
_CloseNormal();
_CloseError();
_CloseFatal();
}
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
{
if (!m_Active)
@ -256,15 +147,10 @@ void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
{
if (!m_Active)
{
return;
}
static ConVar *sv_logecho = smcore.FindConVar("sv_logecho");
static ConVar *sv_logecho = bridge->FindConVar("sv_logecho");
char buffer[3072];
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
@ -273,30 +159,27 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
fprintf(fp, "L %s: %s\n", date, buffer);
if (!sv_logecho || smcore.GetCvarBool(sv_logecho))
if (!sv_logecho || bridge->GetCvarBool(sv_logecho))
{
static char conBuffer[4096];
smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
smcore.ConPrint(conBuffer);
ke::SafeSprintf(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
bridge->ConPrint(conBuffer);
}
fflush(fp);
}
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
{
if (!m_Active)
{
return;
}
char buffer[3072];
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
ke::SafeVsprintf(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer);
fflush(fp);
}
@ -321,63 +204,14 @@ void Logger::LogMessageEx(const char *vafmt, va_list ap)
return;
}
if (m_DelayedStart)
FILE *pFile = _OpenNormal();
if (!pFile)
{
m_DelayedStart = false;
_NewMapFile();
return;
}
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
FILE *fp = NULL;
if (m_Mode == LoggingMode_PerMap)
{
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
_NewMapFile();
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
goto print_error;
}
}
} else {
if (m_NrmCurDay != curtime->tm_mday)
{
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_NrmFileName.assign(_filename);
m_NrmCurDay = curtime->tm_mday;
m_DailyPrintHdr = true;
}
fp = fopen(m_NrmFileName.c_str(), "a+");
}
if (fp)
{
if (m_DailyPrintHdr)
{
char date[32];
m_DailyPrintHdr = false;
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
} else {
goto print_error;
}
return;
print_error:
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
LogToOpenFileEx(pFile, vafmt, ap);
fclose(pFile);
}
void Logger::LogError(const char *vafmt, ...)
@ -395,72 +229,20 @@ void Logger::LogErrorEx(const char *vafmt, va_list ap)
return;
}
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
if (curtime->tm_mday != m_ErrCurDay)
FILE *pFile = _OpenError();
if (!pFile)
{
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;
}
LogToOpenFileEx(pFile, vafmt, ap);
fclose(pFile);
}
void Logger::MapChange(const char *mapname)
void Logger::_MapChange(const char *mapname)
{
m_CurMapName.assign(mapname);
switch (m_Mode)
{
case LoggingMode_Daily:
{
LogMessage("-------- Mapchange to %s --------", mapname);
break;
}
case LoggingMode_PerMap:
{
_NewMapFile();
break;
}
default:
{
/* Do nothing... */
break;
}
}
if (m_ErrMapStart)
{
LogError("Error log file session closed.");
}
m_ErrMapStart = false;
m_CurrentMapName = mapname;
_UpdateFiles(true);
}
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
@ -474,31 +256,7 @@ void Logger::_PrintToGameLog(const char *fmt, va_list ap)
msg[len++] = '\n';
msg[len] = '\0';
smcore.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;
bridge->LogToGame(msg);
}
void Logger::EnableLogging()
@ -536,16 +294,161 @@ void Logger::LogFatalEx(const char *msg, va_list ap)
* It's already implemented twice which is bad.
*/
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
FILE *fp = fopen(path, "at");
if (fp)
FILE *pFile = _OpenFatal();
if (!pFile)
{
m_Active = true;
LogToOpenFileEx(fp, msg, ap);
m_Active = false;
fclose(fp);
return;
}
LogToOpenFileEx(pFile, msg, ap);
fclose(pFile);
}
void Logger::_UpdateFiles(bool bLevelChange)
{
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
if (!bLevelChange && curtime->tm_mday == m_Day)
{
return;
}
m_Day = curtime->tm_mday;
char buff[PLATFORM_MAX_PATH];
ke::SafeSprintf(buff, sizeof(buff), "%04d%02d%02d", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
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

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

View File

@ -1,108 +0,0 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ../..
MMSOURCE17 = ../../../mmsource-1.7
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
BINARY = sourcemod.logic.so
OBJECTS = \
common_logic.cpp \
smn_adt_array.cpp \
smn_sorting.cpp \
smn_maplists.cpp \
smn_adt_stack.cpp \
thread/ThreadWorker.cpp \
thread/BaseWorker.cpp \
thread/PosixThreads.cpp \
ThreadSupport.cpp \
smn_float.cpp \
TextParsers.cpp \
smn_textparse.cpp \
smn_adt_trie.cpp \
Profiler.cpp \
smn_functions.cpp \
sm_crc32.cpp \
smn_timers.cpp \
MemoryUtils.cpp \
smn_admin.cpp \
smn_banning.cpp \
stringutil.cpp \
Translator.cpp \
PhraseCollection.cpp \
smn_lang.cpp \
smn_string.cpp \
smn_handles.cpp \
smn_datapacks.cpp \
smn_gameconfigs.cpp \
GameConfigs.cpp \
smn_players.cpp \
smn_profiler.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc
LINK += -lpthread -static-libgcc
INCLUDE += -I. -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
-Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32 \
-DSM_LOGIC
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/thread
$(MAKE) -f Makefile sourcemod
sourcemod: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o $(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
default: all
clean:
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/thread/*.o
rm -rf $(BIN_DIR)/$(BINARY)

View File

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

View File

@ -33,11 +33,15 @@
#include <IShareSys.h>
#include <IHandleSys.h>
#include <am-autoptr.h>
#include <am-string.h>
#include <am-utility.h>
#include <am-refcounting.h>
#include <sm_stringhashmap.h>
#include "common_logic.h"
class CNativeOwner;
struct FakeNative
{
FakeNative(const char *name, IPluginFunction *fun)
@ -87,10 +91,14 @@ struct Native : public ke::Refcounted<Native>
return fake->name.chars();
}
static inline bool matches(const char *name, const ke::Ref<Native> &entry)
static inline bool matches(const char *name, const ke::RefPtr<Native> &entry)
{
return strcmp(name, entry->name()) == 0;
}
static inline uint32_t hash(const detail::CharsAndLength &key)
{
return key.hash();
}
};

View File

@ -1,360 +1,321 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourcePawn
* Copyright (C) 2004-2009 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 "NativeInvoker.h"
#include "ShareSys.h"
NativeInterface g_NInvoke;
NativeInvoker::NativeInvoker()
{
}
NativeInvoker::~NativeInvoker()
{
}
const char *NativeInterface::GetInterfaceName()
{
return SMINTERFACE_NINVOKE_NAME;
}
unsigned int NativeInterface::GetInterfaceVersion()
{
return SMINTERFACE_NINVOKE_VERSION;
}
void NativeInterface::OnSourceModAllInitialized()
{
sharesys->AddInterface(NULL, &g_NInvoke);
}
IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes)
{
return g_pSourcePawn2->CreateEmptyRuntime(name, bytes);
}
INativeInvoker *NativeInterface::CreateInvoker()
{
return new NativeInvoker();
}
bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
{
ke::Ref<Native> entry = g_ShareSys.FindNative(name);
if (!entry)
return false;
if (!entry->owner)
return false;
native_ = entry->func();
context_ = pContext;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
return true;
}
cell_t NativeInvoker::PushCell(cell_t cell)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
m_info[m_curparam].marked = false;
m_params[m_curparam] = cell;
m_curparam++;
return SP_ERROR_NONE;
}
int NativeInvoker::PushCellByRef(cell_t *cell, int flags)
{
return PushArray(cell, 1, flags);
}
int NativeInvoker::PushFloat(float number)
{
cell_t val = *(cell_t *)&number;
return PushCell(val);
}
int NativeInvoker::PushFloatByRef(float *number, int flags)
{
return PushCellByRef((cell_t *)number, flags);
}
int NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
info->flags = inarray ? copyback : 0;
info->marked = true;
info->size = cells;
info->str.is_sz = false;
info->orig_addr = inarray;
m_curparam++;
return SP_ERROR_NONE;
}
int NativeInvoker::PushString(const char *string)
{
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
}
int NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
return _PushString(buffer, sz_flags, cp_flags, length);
}
int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
info->marked = true;
info->orig_addr = (cell_t *)string;
info->flags = cp_flags;
info->size = len;
info->str.sz_flags = sz_flags;
info->str.is_sz = true;
m_curparam++;
return SP_ERROR_NONE;
}
void NativeInvoker::Cancel()
{
if (context_ == NULL)
return;
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
context_ = NULL;
native_ = NULL;
}
int NativeInvoker::SetError(int err)
{
m_errorstate = err;
return err;
}
int NativeInvoker::Invoke(cell_t *result)
{
int err = SP_ERROR_NONE;
if (context_ == NULL)
return SP_ERROR_INVALID_NATIVE;
if (m_errorstate != SP_ERROR_NONE)
{
err = m_errorstate;
Cancel();
return err;
}
cell_t tresult;
if (result == NULL)
{
result = &tresult;
}
//This is for re-entrancy!
IPluginContext *ctx = context_;
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
cell_t *temp_params = &_temp_params[1];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
unsigned int numparams = m_curparam;
unsigned int i;
bool docopies = true;
if (numparams)
{
//Save the info locally, then reset it for re-entrant calls.
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
}
m_curparam = 0;
context_ = NULL;
/* Initialize 0th parameter */
_temp_params[0] = numparams;
/* Browse the parameters and build arrays */
for (i = 0; i < numparams; i++)
{
/* Is this marked as an array? */
if (temp_info[i].marked)
{
if (!temp_info[i].str.is_sz)
{
/* Allocate a normal/generic array */
if ((err = ctx->HeapAlloc(temp_info[i].size,
&temp_info[i].local_addr,
&temp_info[i].phys_addr))
!= SP_ERROR_NONE)
{
break;
}
if (temp_info[i].orig_addr)
{
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
}
}
else
{
/* Calculate cells required for the string */
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
/* Allocate the buffer */
if ((err = ctx->HeapAlloc(cells,
&temp_info[i].local_addr,
&temp_info[i].phys_addr))
!= SP_ERROR_NONE)
{
break;
}
/* Copy original string if necessary */
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
{
/* Cut off UTF-8 properly */
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8)
{
if ((err = ctx->StringToLocalUTF8(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr,
NULL))
!= SP_ERROR_NONE)
{
break;
}
}
/* Copy a binary blob */
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
{
memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
}
/* Copy ASCII characters */
else
{
if ((err = ctx->StringToLocal(temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr))
!= SP_ERROR_NONE)
{
break;
}
}
}
} /* End array/string calculation */
/* Update the pushed parameter with the byref local address */
temp_params[i] = temp_info[i].local_addr;
}
else
{
/* Just copy the value normally */
temp_params[i] = m_params[i];
}
}
/* Make the call if we can */
if (err == SP_ERROR_NONE)
{
*result = native_(ctx, _temp_params);
if (ctx->GetLastNativeError() != SP_ERROR_NONE)
{
docopies = false;
ctx->ClearLastNativeError();
}
}
else
{
docopies = false;
}
/* i should be equal to the last valid parameter + 1 */
while (i--)
{
if (!temp_info[i].marked)
{
continue;
}
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK))
{
if (temp_info[i].orig_addr)
{
if (temp_info[i].str.is_sz)
{
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
}
else
{
if (temp_info[i].size == 1)
{
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
}
else
{
memcpy(temp_info[i].orig_addr,
temp_info[i].phys_addr,
temp_info[i].size * sizeof(cell_t));
}
}
}
}
if ((err = ctx->HeapPop(temp_info[i].local_addr)) != SP_ERROR_NONE)
{
return err;
}
}
return err;
}
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdio.h>
#include <string.h>
#include "NativeInvoker.h"
/********************
* FUNCTION CALLING *
********************/
NativeInvoker::NativeInvoker(IPluginContext *pContext, const ke::RefPtr<Native> &native)
: context_(pContext),
m_curparam(0),
m_errorstate(SP_ERROR_NONE),
native_(native)
{
}
NativeInvoker::~NativeInvoker()
{
Cancel();
}
bool
NativeInvoker::IsRunnable()
{
return true;
}
IPluginContext *
NativeInvoker::GetParentContext()
{
return context_;
}
int NativeInvoker::PushCell(cell_t cell)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
return SetError(SP_ERROR_PARAMS_MAX);
m_info[m_curparam].marked = false;
m_params[m_curparam] = cell;
m_curparam++;
return SP_ERROR_NONE;
}
int
NativeInvoker::PushCellByRef(cell_t *cell, int flags)
{
return PushArray(cell, 1, flags);
}
int
NativeInvoker::PushFloat(float number)
{
cell_t val = sp::FloatCellUnion(number).cell;
return PushCell(val);
}
int
NativeInvoker::PushFloatByRef(float *number, int flags)
{
return PushCellByRef((cell_t *)number, flags);
}
int
NativeInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
info->flags = inarray ? copyback : 0;
info->marked = true;
info->size = cells;
info->str.is_sz = false;
info->orig_addr = inarray;
m_curparam++;
return SP_ERROR_NONE;
}
int
NativeInvoker::PushString(const char *string)
{
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
}
int
NativeInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
return _PushString(buffer, sz_flags, cp_flags, length);
}
int
NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
return SetError(SP_ERROR_PARAMS_MAX);
ParamInfo *info = &m_info[m_curparam];
info->marked = true;
info->orig_addr = (cell_t *)string;
info->flags = cp_flags;
info->size = len;
info->str.sz_flags = sz_flags;
info->str.is_sz = true;
m_curparam++;
return SP_ERROR_NONE;
}
void
NativeInvoker::Cancel()
{
if (!m_curparam)
return;
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
}
int
NativeInvoker::Execute(cell_t *result, cell_t buffer, cell_t size)
{
context_->ClearLastNativeError();
// For backward compatibility, we have to clear the exception state.
// Otherwise code like this:
//
// static cell_t native(cx, params) {
// for (auto callback : callbacks) {
// callback->Execute();
// }
// }
//
// Could unintentionally leak a pending exception back to the caller,
// which wouldn't have happened before the Great Exception Refactoring.
SourcePawn::ExceptionHandler eh(context_);
eh.Debug(!size);
if (!Invoke(result)) {
if(size)
context_->StringToLocalUTF8(buffer, size, eh.Message(), NULL);
int Err = context_->GetLastNativeError();
context_->ClearLastNativeError();
return Err;
}
return SP_ERROR_NONE;
}
bool
NativeInvoker::Invoke(cell_t *result)
{
if (!IsRunnable()) {
Cancel();
context_->ReportErrorNumber(SP_ERROR_NOT_RUNNABLE);
return false;
}
if (int err = m_errorstate) {
Cancel();
context_->ReportErrorNumber(err);
return false;
}
//This is for re-entrancy!
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
cell_t *temp_params = &_temp_params[1];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
unsigned int numparams = m_curparam;
unsigned int i;
if (numparams)
{
//Save the info locally, then reset it for re-entrant calls.
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
}
m_curparam = 0;
/* Initialize 0th parameter */
_temp_params[0] = numparams;
/* Browse the parameters and build arrays */
bool ok = true;
for (i=0; i<numparams; i++) {
/* Is this marked as an array? */
if (temp_info[i].marked) {
if (!temp_info[i].str.is_sz) {
/* Allocate a normal/generic array */
int err = context_->HeapAlloc(
temp_info[i].size,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr));
if (err != SP_ERROR_NONE) {
context_->ReportErrorNumber(err);
ok = false;
break;
}
if (temp_info[i].orig_addr)
{
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
}
} else {
/* Calculate cells required for the string */
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
/* Allocate the buffer */
int err = context_->HeapAlloc(
cells,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr));
if (err != SP_ERROR_NONE) {
context_->ReportErrorNumber(err);
ok = false;
break;
}
/* Copy original string if necessary */
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
{
/* Cut off UTF-8 properly */
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) {
context_->StringToLocalUTF8(
temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr,
NULL);
}
/* Copy a binary blob */
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
{
memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
}
/* Copy ASCII characters */
else
{
context_->StringToLocal(
temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr);
}
}
} /* End array/string calculation */
/* Update the pushed parameter with the byref local address */
temp_params[i] = temp_info[i].local_addr;
} else {
/* Just copy the value normally */
temp_params[i] = m_params[i];
}
}
/* Make the call if we can */
if (ok)
{
*result = native_->func()(context_, _temp_params);
}
/* i should be equal to the last valid parameter + 1 */
bool docopies = ok;
while (i--) {
if (!temp_info[i].marked)
continue;
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK)) {
if (temp_info[i].orig_addr) {
if (temp_info[i].str.is_sz) {
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
} else {
if (temp_info[i].size == 1) {
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
} else {
memcpy(temp_info[i].orig_addr,
temp_info[i].phys_addr,
temp_info[i].size * sizeof(cell_t));
}
}
}
}
if (int err = context_->HeapPop(temp_info[i].local_addr))
context_->ReportErrorNumber(err);
}
return context_->GetLastNativeError() == SP_ERROR_NONE;
}
int
NativeInvoker::SetError(int err)
{
m_errorstate = err;
return err;
}
int NativeInvoker::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) { return 0; }
funcid_t NativeInvoker::GetFunctionID() { return 0; }
int NativeInvoker::Execute2(IPluginContext *ctx, cell_t *result) { return 0; }
int NativeInvoker::CallFunction2(IPluginContext *ctx, const cell_t *params, unsigned int num_params, cell_t *result) { return 0; }
IPluginRuntime *NativeInvoker::GetParentRuntime() { return NULL; }

View File

@ -1,102 +1,79 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#include <sp_vm_api.h>
#include <INativeInvoker.h>
#include "common_logic.h"
using namespace SourceMod;
using namespace SourcePawn;
struct ParamInfo
{
int flags; /* Copy-back flags */
bool marked; /* Whether this is marked as being used */
cell_t local_addr; /* Local address to free */
cell_t *phys_addr; /* Physical address of our copy */
cell_t *orig_addr; /* Original address to copy back to */
ucell_t size; /* Size of array in bytes */
struct
{
bool is_sz; /* is a string */
int sz_flags; /* has sz flags */
} str;
};
class NativeInvoker : public INativeInvoker
{
public:
NativeInvoker();
~NativeInvoker();
public: /* ICallable */
int PushCell(cell_t cell);
int PushCellByRef(cell_t *cell, int flags=SM_PARAM_COPYBACK);
int PushFloat(float number);
int PushFloatByRef(float *number, int flags=SM_PARAM_COPYBACK);
int PushArray(cell_t *inarray, unsigned int cells, int flags=0);
int PushString(const char *string);
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
void Cancel();
public: /* INativeInvoker */
bool Start(IPluginContext *pContext, const char *name);
int Invoke(cell_t *result);
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
IPluginContext *context_;
SPVM_NATIVE_FUNC native_;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
};
class NativeInterface :
public INativeInterface,
public SMGlobalClass
{
public: /* SMGlobalClass */
void OnSourceModAllInitialized();
public: /* SMInterface */
unsigned int GetInterfaceVersion();
const char *GetInterfaceName();
public: /* INativeInvoker */
IPluginRuntime *CreateRuntime(const char *name, size_t bytes);
INativeInvoker *CreateInvoker();
};
extern NativeInterface g_NInvoke;
#endif /* _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_ */
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#include <sp_vm_api.h>
#include <amtl/am-autoptr.h>
#include <amtl/am-refcounting.h>
#include "Native.h"
struct ParamInfo
{
int flags; /* Copy-back flags */
bool marked; /* Whether this is marked as being used */
cell_t local_addr; /* Local address to free */
cell_t *phys_addr; /* Physical address of our copy */
cell_t *orig_addr; /* Original address to copy back to */
ucell_t size; /* Size of array in bytes */
struct {
bool is_sz; /* is a string */
int sz_flags; /* has sz flags */
} str;
};
class NativeInvoker : public IPluginFunction
{
public:
NativeInvoker(IPluginContext *pContext, const ke::RefPtr<Native> &native);
virtual ~NativeInvoker();
public:
int PushCell(cell_t cell);
int PushCellByRef(cell_t *cell, int flags);
int PushFloat(float number);
int PushFloatByRef(float *number, int flags);
int PushArray(cell_t *inarray, unsigned int cells, int copyback);
int PushString(const char *string);
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
int Execute(cell_t *result, cell_t buffer=0, cell_t size=0);
void Cancel();
int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
IPluginContext *GetParentContext();
bool Invoke(cell_t *result);
bool IsRunnable();
funcid_t GetFunctionID();
int Execute2(IPluginContext *ctx, cell_t *result);
int CallFunction2(IPluginContext *ctx,
const cell_t *params,
unsigned int num_params,
cell_t *result);
IPluginRuntime *GetParentRuntime();
const char *DebugName() {
return native_->name();
}
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
IPluginContext *context_;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
ke::RefPtr<Native> native_;
};
#endif //_INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_

View File

@ -48,7 +48,8 @@ unsigned int CNativeOwner::GetMarkSerial()
void CNativeOwner::AddDependent(CPlugin *pPlugin)
{
m_Dependents.push_back(pPlugin);
if (m_Dependents.find(pPlugin) == m_Dependents.end())
m_Dependents.push_back(pPlugin);
}
void CNativeOwner::AddWeakRef(const WeakNative & ref)
@ -64,31 +65,16 @@ void CNativeOwner::AddNatives(const sp_nativeinfo_t *natives)
m_natives.append(natives);
}
void CNativeOwner::PropagateMarkSerial(unsigned int serial)
{
CNativeOwner *pOwner;
List<CPlugin *>::iterator iter;
for (iter = m_Dependents.begin();
iter != m_Dependents.end();
iter++)
{
pOwner = (*iter);
pOwner->SetMarkSerial(serial);
}
}
void CNativeOwner::UnbindWeakRef(const WeakNative &ref)
{
sp_native_t *native;
IPluginContext *pContext;
pContext = ref.pl->GetBaseContext();
if ((pContext->GetNativeByIndex(ref.idx, &native)) == SP_ERROR_NONE)
{
native->status = SP_NATIVE_UNBOUND;
native->pfn = NULL;
}
pContext->GetRuntime()->UpdateNativeBinding(
ref.idx,
nullptr,
SP_NTVFLAG_OPTIONAL,
nullptr);
}
void CNativeOwner::DropEverything()

View File

@ -37,6 +37,7 @@
#include <am-vector.h>
#include "common_logic.h"
#include "Native.h"
#include <bridge/include/IScriptManager.h>
struct Native;
class CPlugin;
@ -68,7 +69,6 @@ public:
public:
void SetMarkSerial(unsigned int serial);
unsigned int GetMarkSerial();
void PropagateMarkSerial(unsigned int serial);
public:
void AddDependent(CPlugin *pPlugin);
void AddWeakRef(const WeakNative & ref);
@ -81,7 +81,7 @@ protected:
unsigned int m_nMarkSerial;
List<WeakNative> m_WeakRefs;
ke::Vector<const sp_nativeinfo_t *> m_natives;
ke::Vector<ke::Ref<Native> > m_fakes;
ke::Vector<ke::RefPtr<Native> > m_fakes;
};
extern CNativeOwner g_CoreNatives;

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