Compare commits

..
Author SHA1 Message Date
David Anderson 5cb5a022b8 bumped version
--HG--
branch : sourcemod-1.0.3
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.3%402276
2008-06-25 02:59:37 +00:00
David Anderson d715e22162 patch for amb1776 regression
--HG--
branch : sourcemod-1.0.3
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.3%402274
2008-06-24 04:15:16 +00:00
David Anderson 0ffe92c346 patch for amb1765 - GivePlayerItem offsets for DoDS:Beta
--HG--
branch : sourcemod-1.0.3
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.3%402273
2008-06-24 04:13:55 +00:00
David Anderson b01b855992 bumped version
--HG--
branch : sourcemod-1.0.3
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.3%402269
2008-06-21 08:55:51 +00:00
David Anderson 91ea38fa54 temporarily branched 1.0.3 for tagging
--HG--
branch : sourcemod-1.0.3
2008-06-21 08:32:28 +00:00
David Anderson 8c36966d89 added changelog to branch
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402267
2008-06-21 08:20:31 +00:00
David Anderson 299a17cd26 fix for amb1776 - regression on orangebox, OnConfigsExecuted wouldn't execute
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402265
2008-06-21 07:35:58 +00:00
Matt Woodrow 3edc824bc2 Fixed ForcePlayerSuicide.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402264
2008-06-20 23:36:18 +00:00
David Anderson 22ec5c2e71 added a double-run barrier to the new config code
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402262
2008-06-20 05:23:35 +00:00
David Anderson c337bc512c fixed amb1750 - OnAutoConfigsBuffered() was executing before server.cfg
fixed OnConfigsExecuted() having a race condition with exec server.cfg

--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402261
2008-06-20 05:22:10 +00:00
David Anderson 42f01878f4 fixed amb1765 - GiveNamedItem was supported even though it's bad
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402259
2008-06-20 03:55:10 +00:00
Matt Woodrow 995a0545a9 Fixed gamedata files for the pyro update
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402258
2008-06-19 23:44:57 +00:00
Scott Ehlert 59b64ff19f Fixed rare crash in event manager when a null IGameEvent pointer was passed to the IGameEventManager2::FireEvent() hooks
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402246
2008-06-06 04:56:26 +00:00
Scott Ehlert f1f4b3df44 Fixed version number in version.tpl/version.inc
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402244
2008-06-02 22:16:57 +00:00
David Anderson af813cc71c phase0, new versioning. we don't use build numbers anymore except (VS_VERSIONINFO stays until phase 3 is done)
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402243
2008-06-02 05:04:02 +00:00
Matt Woodrow 65a98212a7 Fixed amb1734 - Escape characters are now enabled for the custom admin menu config.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402239
2008-06-01 22:23:59 +00:00
Scott Ehlert 8ad1cb0b8c Removed TF2_GivePlayerWeapon() and TF2_EquipPlayerClassWeapons() stocks as they no longer work at all
The 'weapons' paramater in the TF2_SetPlayerClass() class is now ignored since it no longer works
Bumped 1.0.2 versions for the final time

--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402236
2008-05-31 22:30:57 +00:00
David Anderson 32f2680181 bumped version on stable branch
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402234
2008-05-31 19:45:46 +00:00
David Anderson f7a8e4ceb1 bumped versions
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402232
2008-05-31 19:40:57 +00:00
David Anderson 415df6545b added links to the doc in the adminmenu configs
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402231
2008-05-31 19:02:05 +00:00
David Anderson e216bf49d9 fixed build
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402228
2008-05-31 09:27:25 +00:00
David Anderson 77737d319f removed dynamicmenu folder, names are now consistent
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402227
2008-05-31 08:01:11 +00:00
Scott Ehlert 13e620ec81 Fixed amb1727 - TF2_Disguise and TF2_RemoveDisguise had incorrect signatures
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402224
2008-05-30 22:38:55 +00:00
David Anderson b383d8c89e fixed amb1686 - ReplaceString or ReplaceStringEx with an empty search string would crash. it now throws an error instead.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402221
2008-05-29 05:39:58 +00:00
David Anderson 227a604ab1 removed gamedata definitions the tf2 extension does not use
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402216
2008-05-29 04:07:55 +00:00
David Anderson f153937038 removed TF2_Burn and calccritical from 1.0 branch
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402215
2008-05-29 04:06:16 +00:00
David Anderson 3d1fa83197 various unworthy syncs with trunk
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402214
2008-05-29 04:01:29 +00:00
David Anderson 0a4a60fe08 added amb1685 - GetTickInterval()
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402213
2008-05-29 03:59:00 +00:00
David Anderson 6c0325d7d8 added a forward that helps prevent against race conditions in map config plugins
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402212
2008-05-29 03:55:31 +00:00
David Anderson 55058ab0c7 fixed amb1684 - regression in password handling
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402211
2008-05-29 03:53:18 +00:00
David Anderson 1cf0b2c35b extensions now use global build # instead of local commit #
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402210
2008-05-29 03:52:39 +00:00
David Anderson 48bf766075 fixed a crash bug on unload introduced by the output manager
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402209
2008-05-29 03:51:09 +00:00
David Anderson e04d7f6b0c added amb1715 - tracehull
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402208
2008-05-29 03:50:36 +00:00
David Anderson 505687f748 fixed cases where the jit was underestimating space optimizations by one
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402207
2008-05-29 03:47:20 +00:00
David Anderson d2cfd39f80 added amb1694 - FindCharInString
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402206
2008-05-29 03:46:42 +00:00
Matt Woodrow a628f370e4 Fixed amb1713 - The tiniest of tiny mixups in description orders.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402193
2008-05-25 20:49:42 +00:00
Scott Ehlert 78567bda2f Fixed CrazyDebug not working with Episode One games
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402190
2008-05-25 12:45:12 +00:00
Matt Woodrow 8cb946cf59 Fixed amb1663 - Dynamic Menu didn't use the ExitBack functionality
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402188
2008-05-25 07:54:26 +00:00
Matt Woodrow c3065f7535 Fixed amb1709 - Dynamic Menu selections not resetting on exit
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402186
2008-05-25 07:44:53 +00:00
Matt Woodrow d56da0c3da Fixed amb1358 - Timeleft not reseting on TF2 restarts
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402182
2008-05-25 02:07:39 +00:00
David Anderson 3e244fcab2 fixed amb1706 - dod:s has the same tf menu bug
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402181
2008-05-24 09:59:56 +00:00
Scott Ehlert c5e7e1fa5d Added support for recent Day of Defeat Beta
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402176
2008-05-24 06:09:38 +00:00
Matt Woodrow aadf4f137b Added a load-block for incorrect mods to TF2 and cstrike extensions.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402172
2008-05-24 04:08:18 +00:00
Scott Ehlert eb6296b0c8 Bumped 1.0.x branch to 1.0.2
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402168
2008-05-21 04:06:35 +00:00
David Anderson 64e0403cd5 merged in bug fixes from trunk
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402164
2008-05-21 03:31:42 +00:00
David Anderson 68eeff311b forgotten commit that was in the pipeline
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402163
2008-05-21 03:31:27 +00:00
Scott Ehlert 05fa9268a3 Fixed amb1688 - Linux GivePlayerItem/GiveNamedItem offset for Day of Defeat was incorrect
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402160
2008-05-20 09:44:30 +00:00
Matt Woodrow 05044032da Fixed amb1687 - Infinite loop in Entity Outputs
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402159
2008-05-20 07:51:54 +00:00
Matt Woodrow abf0a4f508 Fixed amb1657 - Server should see admin version of sm_who
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402147
2008-05-14 22:40:20 +00:00
Scott Ehlert 4a98a25b75 Fixed up IGameHelpers.h such that it no longer requires HL2SDK headers if a function doesn't need them
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402143
2008-05-13 08:22:21 +00:00
Scott Ehlert eec65697a7 Err, fixed Linux build
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402138
2008-05-12 02:05:31 +00:00
Scott Ehlert 64d2ad9679 Symbols no longer stripped on Linux for easier debugging
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402136
2008-05-11 07:49:10 +00:00
Scott Ehlert 58d6a6793f Removed odd debug code, err, in CrazyDebug of all places
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402130
2008-05-09 08:22:22 +00:00
Scott Ehlert b2cc0869a5 CrazyDebug just got crazier!
1) Now works with SrcDS -console + DEP on Windows
2) Updated vcproj files for OB, Episode 1, etc

--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402128
2008-05-09 08:04:06 +00:00
Matt Woodrow 950300dffe A sad response to amb1655 - TF2_SetPlayerInvuln is broken and now removed.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402126
2008-05-08 23:42:31 +00:00
Borja Ferrer 1eaa48f978 removed these functions in tf2 for now to avoid more crashes
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402125
2008-05-04 15:52:34 +00:00
Scott Ehlert 4fe1c93e68 Attempted fix for amb1648 - stack corruption when GetClientEyeAngles() is called on Windows
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402123
2008-05-02 07:47:16 +00:00
Matt Woodrow 6bdb12f4bb Missing ! in sample_ext
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402114
2008-05-01 02:43:19 +00:00
Scott Ehlert c5cb4834f4 Updated TF2 virtual offsets for goldrush/medic update
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402108
2008-04-30 04:14:07 +00:00
David Anderson 0bd4474729 fixed amb1645 - command help typo
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402106
2008-04-29 15:14:39 +00:00
Matt Woodrow dabf9f3810 Fixed amb1644 - Forgot to make sure mapchooser worked on anything but TF2.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402105
2008-04-28 22:07:41 +00:00
Matt Woodrow 927e8b0ec9 Disabled Critical Hit hook in TF2 Extension (1.0 branch only)
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402103
2008-04-25 07:06:47 +00:00
Matt Woodrow f47fd11453 I love you gcc.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402101
2008-04-25 06:05:13 +00:00
Matt Woodrow 96f8590fda TF2 Round count mapchooser fix.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402099
2008-04-25 05:26:07 +00:00
Matt Woodrow b7cc3b7670 Cleaned up a few sdktools files.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402098
2008-04-25 05:21:19 +00:00
Scott Ehlert 7d524e4179 Added any tag to ADT array functions to fix potential tag mismatches
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402093
2008-04-24 10:25:27 +00:00
Matt Woodrow 485e56906a Fixed amb1634 - GetPlayerResourceData incorrectly memorising offsets.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402090
2008-04-22 22:04:46 +00:00
Matt Woodrow 611cf15433 Bail's pedantic parser made me do it.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402086
2008-04-19 10:34:56 +00:00
Matt Woodrow 443f5b16e3 Fixed linux build
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402084
2008-04-19 04:14:40 +00:00
Matt Woodrow a465569b22 Fixed amb1607 - TF2 extension critical hit crashes.
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402082
2008-04-19 03:40:30 +00:00
David Anderson cc207eae51 fixed some doc inconsistencies on ProcessTargetString
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402080
2008-04-19 00:44:11 +00:00
Scott Ehlert 1a21832cbb Gah, finalized the revised ILibrarySys::GetFileExtension() code
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402077
2008-04-17 09:28:27 +00:00
Scott Ehlert 00b81f343a Rewrote ILibrarySys::GetFileExtension() to fix the following issues:
- Crash when NULL was passed
- Crash when blank string '\0' was passed
- Incorrect result returned when file name began with a period. These files are now considered to not have any extension.

--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402076
2008-04-17 09:24:22 +00:00
Matt Woodrow b7ae818e7c Added Active support for TF2
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402070
2008-04-17 02:46:17 +00:00
David Anderson 75e673d6ff added amb1620 - ActivateEntity
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402069
2008-04-16 23:29:37 +00:00
Matt Woodrow b7edc558b3 Added amb1609 - Persistant option to TF2_SetPlayerClass
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402065
2008-04-16 05:41:04 +00:00
David Anderson 40046d8248 added amb1610 - StripQuotes()
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402064
2008-04-16 05:27:19 +00:00
David Anderson b51b34fbf4 fixed amb1615 (typo)
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402060
2008-04-14 14:15:32 +00:00
Matt Woodrow e6f854b760 Fixed minor player selection bug in tf2 extension
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402058
2008-04-14 03:13:02 +00:00
David Anderson 4d46aa34e9 fixed crash bug (regression) when extensions failed to load
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402054
2008-04-13 04:00:28 +00:00
Borja Ferrer d0182a01ac fixed amb1586 for real
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402053
2008-04-12 23:03:44 +00:00
David Anderson 57d5a67a95 crazydebug changes
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402051
2008-04-12 05:35:58 +00:00
David Anderson 993b3f62e4 fixed amb1591 - mods like IOS:S which, in listen server mode add bots before the player, caused crashes in SM
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402049
2008-04-12 02:16:41 +00:00
Borja Ferrer a82c86a7b6 fixed build
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402048
2008-04-12 02:11:16 +00:00
David Anderson bbb73091ed i have no idea why i'm even committing this
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402047
2008-04-12 02:08:37 +00:00
Borja Ferrer 7e5e57cad1 forgot to commit this
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402046
2008-04-12 01:58:07 +00:00
Borja Ferrer 7849f4df20 experimental fix for amb1586 - team native crash
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402045
2008-04-12 01:47:38 +00:00
David Anderson 73b77549cc fixed crash bug on shutdown
removed implementations from header

--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402042
2008-04-12 01:28:26 +00:00
Matt Woodrow 2341a8e756 Fixed amb1611 - Spy knife critical detour reading from wrong gamedata key
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402040
2008-04-12 00:57:33 +00:00
David Anderson 73888b137d fixed amb1583 - MySQL's FetchString() for prepared queries returned corrupt data
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402039
2008-04-12 00:08:13 +00:00
Scott Ehlert aff4431eea Added more missing svn:keywords properties to some files (this should be the last of them before I never have to do this again)
Moved sm_memtable files in sqlite extension to sdk directory (to be consistent with topmenus)
Some extension source files had an incorrect extension name in their headers
Updated copyright year on some rarely altered files

--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402038
2008-04-11 17:22:19 +00:00
Matt Woodrow be8146364f Fixed amb1601 - Wrong ConVar handle in vote FF menu
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402035
2008-04-11 08:03:53 +00:00
Matt Woodrow b1b2da3cb8 Fixed amb1594 - SetPlayerClass issues with spawning
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402033
2008-04-11 07:56:40 +00:00
Scott Ehlert f1c1d305d8 ara ara :\
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402032
2008-04-10 20:13:24 +00:00
Scott Ehlert a2470215ed Merged revs 2029 and 2030 from trunk - bit of cleaning and added svn:keywords property to some files that didn't have them yet
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402031
2008-04-10 20:12:12 +00:00
David Anderson bfb49a3c1b added util.cpp to makefile
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402028
2008-04-10 18:44:50 +00:00
David Anderson 61121914bc added dynamicmenu to packager
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402024
2008-04-10 17:20:59 +00:00
David Anderson b75a4d07be added debug output for fopen failure
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402022
2008-04-10 17:15:51 +00:00
Matt Woodrow e956248f29 Forgot a semicolon
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402020
2008-04-10 05:22:36 +00:00
David Anderson c434cd646a new macros actually work now
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402018
2008-04-10 05:20:56 +00:00
Matt Woodrow 0da38e0f04 Added Critical Hit hook to TF2 extension
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402017
2008-04-10 04:50:17 +00:00
David Anderson c437c6e01e added amb1558 - __BINARY_PATH__ and __BINARY_FILE__
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402014
2008-04-10 00:10:33 +00:00
Scott Ehlert d0cab7b717 Oh god, Spring Cleaning Part San (3) - Finaare
- Removed batsupport extension
 - Made EVERY makefile consistent with the changes originally made to the sample extensions's makefile
 - Sample MM:S extension now uses unified makefile
 - Various innumerable changes to VS project files

--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402013
2008-04-09 09:36:48 +00:00
David Anderson f58728c0a8 reverted compiler changes that didn't work out so well
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402010
2008-04-09 05:57:41 +00:00
David Anderson 83682230c0 fix for amb1594 part 1 - missing semicolons
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402008
2008-04-08 23:42:05 +00:00
David Anderson 888a1432f2 i have no idea how gcc/msvc both didn't catch the return false from earlier
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402006
2008-04-08 23:34:45 +00:00
David Anderson a0833bfd10 fix for amb1595
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402005
2008-04-08 23:24:30 +00:00
David Anderson 2c74333d47 fixed amb1590 - tf2 didn't autoload
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402003
2008-04-06 17:54:43 +00:00
David Anderson d52cf9bcc3 fixed amb1585 - url wasn't canonical
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402002
2008-04-06 17:21:49 +00:00
David Anderson ba3ff06236 synced versioning changes from trunk
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%402000
2008-04-06 08:22:17 +00:00
David Anderson 228029b20f synced trunk back to branch
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%401996
2008-04-06 07:57:42 +00:00
David Anderson 6e542f51f0 added more mod support for the new equip native
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%401991
2008-04-06 06:52:11 +00:00
David Anderson 54754f9e83 merged in selected changesets from 1.1 branch
--HG--
branch : sourcemod-1.0.x
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.x%401990
2008-04-06 05:40:11 +00:00
David Anderson 0b731c9bc0 renamed 1.0.1 to 1.0.x for rolling releases
--HG--
branch : sourcemod-1.0.x
2008-04-05 06:26:06 +00:00
David Anderson 37d72420e4 added %b for binary printing
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401985
2008-04-04 20:24:56 +00:00
Scott Ehlert 064f57e321 Fixed amb1580 - trailing comma wasn't allowed in multi-dimensional array initializations
Also bumped compiler copyright year, since the same file was, um, changed

--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401984
2008-04-04 20:24:46 +00:00
David Anderson bcb9bc988f fixed a gcc complaint in the admincache dump function
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401983
2008-04-04 20:24:26 +00:00
Scott Ehlert 1f071f7c80 Fixed amb1577 - CreateConVar return documentation was incorrect
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401981
2008-04-02 17:51:09 +00:00
David Anderson 52fdc87325 bumped header versions so they say 1.0.1
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401967
2008-03-27 05:16:39 +00:00
David Anderson aa5f1c4f03 implemented sm_dump_admcache
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401966
2008-03-27 05:15:09 +00:00
David Anderson adbd79633b added bad trie iteration
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401963
2008-03-27 04:34:54 +00:00
Scott Ehlert 1e1ebc981a Changed the environment variable used in the include paths from SOURCEMM -> SOURCEMM16
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401962
2008-03-27 04:11:49 +00:00
Scott Ehlert 44065ac939 Bumped modules.versions
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401959
2008-03-21 04:42:17 +00:00
Scott Ehlert 3ecd914647 Fixed amb1539 - Crash on The Ship due to unavailable IFileSystem functions which are used in KeyValues::LoadFromFile()
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401957
2008-03-21 03:36:13 +00:00
Scott Ehlert 54b49dafbf Copied over this super minor change - removed debug code or something
--HG--
branch : sourcemod-1.0.1
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.0.1%401956
2008-03-21 01:20:22 +00:00
Scott Ehlert 23c2f9b54e Created 1.0.1 branch
--HG--
branch : sourcemod-1.0.1
2008-03-21 01:07:08 +00:00
2727 changed files with 113002 additions and 887474 deletions
-5
View File
@@ -1,5 +0,0 @@
{
"project_id" : "sourcemod",
"conduit_uri" : "https://phabricator.alliedmods.net/",
"history.immutable" : false
}
-37
View File
@@ -1,37 +0,0 @@
# Binaries
*.dll
*.dylib
*.exe
*.so
# Files generated by Visual Studio
*.aps
*.ipch
*.ncb
*.opensdf
*.sdf
*.suo
*.user
# Build directories
CrazyDebug*/
Debug*/
Release*/
LIB-Release/
LIB-Debug/
# Files generated by Mac OS X Finder
.DS_Store
# Files generated by Windows Explorer
[Dd]esktop.ini
[Tt]humbs.db
# AMBuild build directories
build/
obj-*/
*~
*.rej
*.orig
*.smx
*.swp
-11
View File
@@ -1,11 +0,0 @@
language: cpp
compiler:
- clang
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
-514
View File
@@ -1,514 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os, sys
class SDK(object):
def __init__(self, sdk, ext, aDef, name, platform, dir):
self.folder = 'hl2sdk-' + dir
self.envvar = sdk
self.ext = ext
self.code = aDef
self.define = name
self.platform = platform
self.name = dir
self.path = None # Actual path
WinOnly = ['windows']
WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac']
PossibleSDKs = {
'episode1': SDK('HL2SDK', '1.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'),
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '15', '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'),
}
def ResolveEnvPath(env, folder):
if env in os.environ:
path = os.environ[env]
if os.path.isdir(path):
return path
return None
head = os.getcwd()
oldhead = None
while head != None and head != oldhead:
path = os.path.join(head, folder)
if os.path.isdir(path):
return path
oldhead = head
head, tail = os.path.split(head)
return None
def Normalize(path):
return os.path.abspath(os.path.normpath(path))
class SMConfig(object):
def __init__(self):
self.sdks = {}
self.binaries = []
self.extensions = []
self.generated_headers = None
self.mms_root = None
self.mysql_root = None
self.spcomp = None
self.smx_files = {}
self.versionlib = None
def use_auto_versioning(self):
return builder.backend == 'amb2'
@property
def tag(self):
if builder.options.debug == '1':
return 'Debug'
return 'Release'
def detectProductVersion(self):
builder.AddConfigureFile('product.version')
# For OS X dylib versioning
import re
with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
productContents = fp.read()
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
if m == None:
self.productVersion = '1.0.0'
else:
major, minor, release = m.groups()
self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
def detectSDKs(self):
sdk_list = builder.options.sdks.split(',')
use_all = sdk_list[0] == 'all'
use_present = sdk_list[0] == 'present'
for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name]
if builder.target_platform in sdk.platform:
if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
else:
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
if sdk_path is None or not os.path.isdir(sdk_path):
if use_all or sdk_name in sdk_list:
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
continue
if use_all or use_present or sdk_name in sdk_list:
sdk.path = Normalize(sdk_path)
self.sdks[sdk_name] = sdk
if len(self.sdks) < 1:
raise Exception('At least one SDK must be available.')
if builder.options.mms_path:
self.mms_root = builder.options.mms_path
else:
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
if not self.mms_root or not os.path.isdir(self.mms_root):
raise Exception('Could not find a source copy of Metamod:Source')
self.mms_root = Normalize(self.mms_root)
if builder.options.hasMySql:
if builder.options.mysql_path:
self.mysql_root = builder.options.mysql_path
else:
for i in range(7):
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
if self.mysql_root:
break
if not self.mysql_root or not os.path.isdir(self.mysql_root):
raise Exception('Could not find a path to MySQL!')
self.mysql_root = Normalize(self.mysql_root)
def configure(self):
builder.AddConfigureFile('pushbuild.txt')
cxx = builder.DetectCompilers()
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-uninitialized',
'-Wno-unused',
'-Wno-switch',
'-Wno-format',
'-Wno-format-security',
'-msse',
'-m32',
]
have_gcc = cxx.vendor == 'gcc'
have_clang = cxx.vendor == 'clang'
if have_clang or (have_gcc and cxx.version >= '4'):
cxx.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.version >= '4.6'):
cxx.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
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',
]
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
if builder.options.opt == '1':
cxx.defines += ['NDEBUG']
if cxx.like('gcc'):
cxx.cflags += ['-O3']
elif cxx.like('msvc'):
cxx.cflags += ['/Ox']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
# Debugging
if builder.options.debug == '1':
cxx.defines += ['DEBUG', '_DEBUG']
if cxx.like('msvc'):
cxx.cflags += ['/Od', '/RTC1']
if cxx.version >= 1600:
cxx.cflags += ['/d2Zi+']
# 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']
# Finish up.
cxx.defines += [
'SOURCEMOD_BUILD',
'SM_USE_VERSIONLIB',
]
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')]
def AddVersioning(self, binary):
if builder.target_platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'RC_COMPILE',
]
if self.use_auto_versioning():
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
elif builder.target_platform == 'mac':
if binary.type == 'library':
binary.compiler.postlink += [
'-compatibility_version', '1.0.0',
'-current_version', self.productVersion
]
if self.use_auto_versioning():
binary.compiler.linkflags += [self.versionlib]
binary.compiler.sourcedeps += SM.generated_headers
return binary
def Library(self, context, name):
binary = context.compiler.Library(name)
return self.AddVersioning(binary)
def Program(self, context, name):
binary = context.compiler.Program(name)
return self.AddVersioning(binary)
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, 'public', 'amtl'),
]
return compiler
def ExtLibrary(self, context, name):
binary = context.compiler.Library(name)
self.ConfigureForExtension(context, binary.compiler)
return self.AddVersioning(binary)
def ConfigureForHL2(self, binary, sdk):
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')
compiler.cxxincludes += [
os.path.join(mms_path),
os.path.join(mms_path, 'sourcehook'),
]
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines
paths = [
['public'],
['public', 'engine'],
['public', 'mathlib'],
['public', 'vstdlib'],
['public', 'tier0'],
['public', 'tier1']
]
if sdk.name == 'episode1' or sdk.name == 'darkm':
paths.append(['public', 'dlls'])
paths.append(['game_shared'])
else:
paths.append(['public', 'game', 'server'])
paths.append(['public', 'toolframework'])
paths.append(['game', 'shared'])
paths.append(['common'])
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name == 'sdk2013' 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')
compiler.defines.remove('_snprintf=snprintf')
compiler.defines.remove('_vsnprintf=vsnprintf')
if compiler.like('msvc'):
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
else:
compiler.defines += ['COMPILER_GCC']
# 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']:
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']:
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
if sdk.name == 'csgo' and builder.target_platform == 'linux':
compiler.linkflags += ['-lstdc++']
for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
if builder.target_platform == 'linux':
if sdk.name == 'episode1':
lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name == 'sdk2013':
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target_platform == 'mac':
if sdk.name == 'sdk2013':
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target_platform in ['linux', 'mac']:
if sdk.name == 'sdk2013':
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
]
else:
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
]
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
self.AddVersioning(binary)
dynamic_libs = []
if builder.target_platform == 'linux':
compiler.linkflags[0:0] = ['-lm']
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'nucleardawn', 'l4d2']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac':
compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
libs.append('interfaces')
for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
compiler.linkflags.append(compiler.Dep(lib_path))
for library in dynamic_libs:
source_path = os.path.join(lib_folder, library)
output_path = os.path.join(binary.localFolder, library)
def make_linker(source_path, output_path):
def link(context, binary):
cmd_node, (output,) = context.AddSymlink(source_path, output_path)
return output
return link
linker = make_linker(source_path, output_path)
compiler.linkflags[0:0] = [compiler.Dep(library, linker)]
return binary
def HL2Library(self, context, name, sdk):
binary = context.compiler.Library(name)
self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(binary, sdk)
def HL2Project(self, context, name):
project = context.compiler.LibraryProject(name)
self.ConfigureForExtension(context, project.compiler)
return project
def HL2Config(self, project, name, sdk):
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
return self.ConfigureForHL2(binary, sdk)
SM = SMConfig()
SM.detectProductVersion()
SM.detectSDKs()
SM.configure()
if SM.use_auto_versioning():
SM.generated_headers = builder.RunScript(
'tools/buildbot/Versioning',
{ 'SM': SM }
)
SM.versionlib = builder.RunScript(
'versionlib/AMBuilder',
{ 'SM': SM }
)
BuildScripts = [
'loader/AMBuilder',
'core/AMBuilder',
'core/logic/AMBuilder',
'extensions/bintools/AMBuilder',
'extensions/clientprefs/AMBuilder',
'extensions/curl/AMBuilder',
'extensions/cstrike/AMBuilder',
'extensions/geoip/AMBuilder',
'extensions/mysql/AMBuilder',
'extensions/regex/AMBuilder',
'extensions/sdkhooks/AMBuilder',
'extensions/sdktools/AMBuilder',
'extensions/sqlite/AMBuilder',
'extensions/tf2/AMBuilder',
'extensions/topmenus/AMBuilder',
'extensions/updater/AMBuilder',
'sourcepawn/compiler/AMBuilder',
'sourcepawn/jit/AMBuilder',
]
if builder.backend == 'amb2':
BuildScripts += [
'plugins/AMBuilder',
'tools/buildbot/PackageScript',
]
builder.RunBuildScripts(BuildScripts, { 'SM': SM })
if builder.options.breakpad_dump:
builder.RunScript('tools/buildbot/BreakpadSymbols', { 'SM': SM })
-6
View File
@@ -1,6 +0,0 @@
Contributing
------------
Please visit [our wiki](https://wiki.alliedmods.net/Contributing_to_SourceMod) for information on how to contribute to Sourcemod.
As a sidenote, [Travis](https://travis-ci.org/alliedmodders/sourcemod) will automatically build your PR to make sure it compiles on Linux.
+36
View File
@@ -0,0 +1,36 @@
We now use svn:keywords "Id" on all .c/.cpp/.h/.inc/.sp/ files.
Please make sure your client is configured properly.
WINDOWS:
- Open your Application Data directory.
Windows XP/2000: C:\Documents and Settings\<user>\Application Data
Windows Vista: C:\Users\<user>\AppData\Roaming
- Now go to the Subversion directory.
- Open the "config" file with a text editor.
LINUX:
- Open ~/.subversion/config with your favorite text editor.
Under [miscellany], uncomment this line:
# enable-auto-props = yes
Under [auto-props], add these lines:
*.c = svn:keywords=Id
*.cpp = svn:keywords=Id
*.h = svn:keywords=Id
*.inc = svn:keywords=Id
*.sp = svn:keywords=Id
If you find a file with one of the above extensions that does not have the svn:keywords property...
TORTOISE SVN:
- Right click on the file(s) that do not have the property.
- In the context menu that appears, select TortoiseSVN -> Properties.
- A properties window should appear. Click the Add button.
- Select "svn:keywords" from the "Property name" combo box and type "Id" in the "Property value" text area.
- Click OK on both windows and commit the change(s).
CLI SVN CLIENT:
- Execute the following command: svn propset svn:keywords Id <files>
-17
View File
@@ -1,17 +0,0 @@
SourceMod
=========
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
Development
-----------
- [Issue tracker](https://bugs.alliedmods.net): 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 extension development](https://wiki.alliedmods.net/Category:SourceMod_Development): C++ examples and introduction to various extension interfaces
-1029
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -9,4 +9,4 @@
"Commands" "Commands"
{ {
} }
+3 -3
View File
@@ -16,7 +16,7 @@
// "@Full Admins" // "@Full Admins"
// //
// You can also specify immunity values. Two examples: // You can also specify immunity values. Two examples:
// "83:abcdefgh" //Immunity is 83, flags are abcdefgh // "83:abcdefg" //Immunity is 83, flags are abcefgh
// "6:@Full Admins" //Immunity is 6, group is "Full Admins" // "6:@Full Admins" //Immunity is 6, group is "Full Admins"
// //
// Immunity values can be any number. An admin cannot target an admin with // Immunity values can be any number. An admin cannot target an admin with
@@ -37,9 +37,9 @@
//////////////////////////////// ////////////////////////////////
// Examples: (do not put // in front of real lines, as // means 'comment') // Examples: (do not put // in front of real lines, as // means 'comment')
// //
// "STEAM_0:1:16" "bce" //generic, kick, unban for this steam ID, no immunity // "STEAM_0:1:16" "bce" //kick, ban, slay for this steam ID, no immunity
// "!127.0.0.1" "99:z" //all permissions for this ip, immunity value is 99 // "!127.0.0.1" "99:z" //all permissions for this ip, immunity value is 99
// "BAILOPAN" "abc" "Gab3n" //name BAILOPAN, password "Gab3n": gets reservation, generic, kick // "BAILOPAN" "abc" "Gab3n" //name BAILOPAN, password "Gab3n": gets reservation, kick, ban
// //
//////////////////////////////// ////////////////////////////////
-16
View File
@@ -1,16 +0,0 @@
"banreasons"
{
"Abusive" "Abusive"
"Racism" "Racism"
"General cheating/exploits" "General cheating/exploits"
"Wallhack" "Wallhack"
"Aimbot" "Aimbot"
"Speedhacking" "Speedhacking"
"Mic spamming" "Mic spamming"
"Admin disrespect" "Admin disrespect"
"Camping" "Camping"
"Team killing" "Team killing"
"Unacceptable Spray" "Unacceptable Spray"
"Breaking Server Rules" "Breaking Server Rules"
"Other" "Other"
}
-1
View File
@@ -1,7 +1,6 @@
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents //This file unloads all plugins, re-loads a few "safe" ones, and then prevents
//any more plugins from being loaded. //any more plugins from being loaded.
sm plugins unload_all sm plugins unload_all
sm plugins load_unlock
sm plugins load basebans.smx sm plugins load basebans.smx
sm plugins load basecommands.smx sm plugins load basecommands.smx
sm plugins load admin-flatfile.smx sm plugins load admin-flatfile.smx
+3 -28
View File
@@ -80,21 +80,21 @@ sm_reserve_type 0
sm_reserved_slots 0 sm_reserved_slots 0
// Specifies whether or not reserved slots will be hidden (subtracted from max // Specifies whether or not reserved slots will be hidden (subtracted from max
// slot count). Valid values are 0 (Visible) or 1 (Hidden). // slot count). Valid values are 0 (visible) or 1 (hidden).
// -- // --
// Requires: reservedslots.smx // Requires: reservedslots.smx
// Default: 0 // Default: 0
sm_hide_slots 0 sm_hide_slots 0
// Specifies whether or not non-admins can send messages to admins using // Specifies whether or not non-admins can send messages to admins using
// say_team @<message>. Valid values are 0 (Disabled) or 1 (Enabled) // say_team @<message>. Valid values are 0 (disabled) or 1 (enabled)
// -- // --
// Requires: basechat.smx // Requires: basechat.smx
// Default: 1 // Default: 1
sm_chat_mode 1 sm_chat_mode 1
// Specifies whether or not "timeleft" will automaticly be triggered every // Specifies whether or not "timeleft" will automaticly be triggered every
// x seconds. Valid values are 0 (Disabled) to 1800 seconds. // x seconds. Valid values are 0 (disabled) to 1800 seconds.
// -- // --
// Requires: basetriggers.smx // Requires: basetriggers.smx
// Default: 0 // Default: 0
@@ -107,28 +107,3 @@ sm_timeleft_interval 0
// Requires: basetriggers.smx // Requires: basetriggers.smx
// Default: 1 // Default: 1
sm_trigger_show 1 sm_trigger_show 1
// Specifies whether or not to display vote progress to clients in the
// "hint" box (near the bottom of the screen in most games).
// Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_hintbox 0
// Specifies whether or not to display vote progress to clients in the
// chat area. Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_chat 0
// Specifies whether or not to display vote progress in the server console.
// Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_console 0
// Specifies whether or not to display vote progress to clients in the
// client console. Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_client_console 0
+8 -53
View File
@@ -4,6 +4,14 @@
*/ */
"Core" "Core"
{ {
/**
* Relative path to SourceMod's base directory. This is relative to the game/mod directory.
* Only change this if you have installed SourceMod in a non-default location.
*
* The default value is "addons/sourcemod"
*/
"BasePath" "addons/sourcemod"
/** /**
* This option determines if SourceMod logging is enabled. * This option determines if SourceMod logging is enabled.
* *
@@ -80,57 +88,4 @@
* "off" - Translate using default server's language * "off" - Translate using default server's language
*/ */
"AllowClLanguageVar" "On" "AllowClLanguageVar" "On"
/**
* Enables or Disables SourceMod's automatic gamedata updating.
*
* The default value is "no". A value of "yes" will block the Auto Updater.
*/
"DisableAutoUpdate" "no"
/**
* If set to yes, a successful gamedata update will attempt to restart SourceMod.
* SourceMod is unloaded and reloaded, and the map is changed to the current map.
* Since gamedata updates occur when the server loads, impact should be minimal.
* But to be safe, this option is disabled by default.
*/
"ForceRestartAfterUpdate" "no"
/**
* URL to use for retrieving update information.
* SSL is not yet supported.
*/
"AutoUpdateURL" "http://update.sourcemod.net/update/"
/**
* Whether to show debug spew.
* Currently this will log details about the gamedata updating process.
*/
"DebugSpew" "no"
/**
* If set to yes, SourceMod will validate steamid auth strings with the Steam backend before giving out admin access.
* This can prevent malicious users from impersonating admins with stolen Steam apptickets.
* If Steam is down, admins will not be authenticated until Steam comes back up.
* This option increases the security of your server, but is still experimental.
*/
"SteamAuthstringValidation" "yes"
/**
* Enables or disables whether SourceMod blocks known or potentially malicious plugins from loading.
* It is STRONGLY advised that this is left enabled, there have been cases in the past with plugins that
* allow anyone to delete files on the server, gain full rcon control, etc.
*
* "yes" - Block malware or illegal plugins from loading (default)
* "no" - Warn about malware or illegal plugins loading
*/
"BlockBadPlugins" "yes"
/**
* If a plugin takes too long to execute, hanging or freezing the game server in the process,
* SourceMod will attempt to terminate that plugin after the specified timeout length has
* passed. You can disable this feature by setting the value to "0".
*/
"SlowScriptTimeout" "8"
} }
-13
View File
@@ -2,8 +2,6 @@
{ {
"driver_default" "mysql" "driver_default" "mysql"
// When specifying "host", you may use an IP address, a hostname, or a socket file path
"default" "default"
{ {
"driver" "default" "driver" "default"
@@ -20,15 +18,4 @@
"driver" "sqlite" "driver" "sqlite"
"database" "sourcemod-local" "database" "sourcemod-local"
} }
"clientprefs"
{
"driver" "sqlite"
"host" "localhost"
"database" "clientprefs-sqlite"
"user" "root"
"pass" ""
//"timeout" "0"
//"port" "0"
}
} }
Binary file not shown.
+2
View File
@@ -1,4 +1,6 @@
"Languages" "Languages"
{ {
"en" "English" "en" "English"
"es" "Español"
} }
+2 -2
View File
@@ -51,8 +51,8 @@
"target" "default" "target" "default"
} }
/* For the "nominations" plugin */ /* For the "rockthevote" plugin */
"nominations" "rockthevote"
{ {
"target" "default" "target" "default"
} }
+38
View File
@@ -0,0 +1,38 @@
/**
* Each sub-section of "Plugins" should have a title which specifies a plugin filename.
* Filenames have a wildcard of *. Appending .smx is not required.
* If the filename has no explicit path, it will be patched to any sub-path in the plugins folder.
*
* Available properties for plugins are:
* "pause" - Whether or not the plugin should load paused - "yes" or "no" (default)
* "lifetime" - Lifetime of the plugin. Options:
* "mapsync" - Plugins should be reloaded on mapchange if changed (default)
* "global" - Plugin will never be unloaded or updated
* "blockload" - Plugin will always be blocked from loading. Implicit (automatic) loads
* produce no error, but explicit (manual) loads will show an error message.
* (Options are one of "yes" or "no")
*
* You can also have an "Options" section declaring options to pass onto the JIT:
* "debug" - Whether or not to load the plugin in debug mode
* "profile" - Bit flags for profiling level. Add flags together to reach a value.
* WARNING: Profiler is _ALPHA_ software! Use it at your own risk for
* development cycles only (not production setups).
* See the wiki article "SourceMod Profiler" for more information.
* 1 - Profile natives
* 2 - Profile callbacks
* 4 - Profile internal plugin function calls
*/
"Plugins"
{
"*"
{
"pause" "no"
"lifetime" "mapsync"
"Options"
{
"debug" "no"
}
}
}
@@ -1,17 +0,0 @@
CREATE TABLE sm_cookies
(
id INTEGER unsigned NOT NULL auto_increment,
name varchar(30) NOT NULL UNIQUE,
description varchar(255),
access INTEGER,
PRIMARY KEY (id)
);
CREATE TABLE sm_cookie_cache
(
player varchar(65) NOT NULL,
cookie_id int(10) NOT NULL,
value varchar(100),
timestamp int NOT NULL,
PRIMARY KEY (player, cookie_id)
);
@@ -1,16 +0,0 @@
CREATE TABLE sm_cookies
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name varchar(30) NOT NULL UNIQUE,
description varchar(255),
access INTEGER
);
CREATE TABLE sm_cookie_cache
(
player varchar(65) NOT NULL,
cookie_id int(10) NOT NULL,
value varchar(100),
timestamp int,
PRIMARY KEY (player, cookie_id)
);
-34
View File
@@ -1,34 +0,0 @@
# vim: set ts=2 sw=2 tw=99 noet:
import sys
try:
from ambuild2 import run
except:
try:
import ambuild
sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n')
sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n')
except:
sys.stderr.write('AMBuild must be installed to build this project.\n')
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,
help='Root search folder for HL2SDKs')
run.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,
help='Path to Metamod:Source')
run.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',
help='Enable optimization')
run.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',
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',
default=False, help='Dump and upload breakpad symbols')
run.Configure()
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -30,6 +30,7 @@
*/ */
#include "ADTFactory.h" #include "ADTFactory.h"
#include "sm_globals.h"
#include "ShareSys.h" #include "ShareSys.h"
ADTFactory g_AdtFactory; ADTFactory g_AdtFactory;
@@ -56,30 +57,32 @@ IBasicTrie *ADTFactory::CreateBasicTrie()
BaseTrie::BaseTrie() BaseTrie::BaseTrie()
{ {
m_pTrie = sm_trie_create();
} }
BaseTrie::~BaseTrie() BaseTrie::~BaseTrie()
{ {
sm_trie_destroy(m_pTrie);
} }
bool BaseTrie::Insert(const char *key, void *value) bool BaseTrie::Insert(const char *key, void *value)
{ {
return map_.insert(key, value); return sm_trie_insert(m_pTrie, key, value);
} }
bool BaseTrie::Retrieve(const char *key, void **value) bool BaseTrie::Retrieve(const char *key, void **value)
{ {
return map_.retrieve(key, value); return sm_trie_retrieve(m_pTrie, key, value);
} }
bool BaseTrie::Delete(const char *key) bool BaseTrie::Delete(const char *key)
{ {
return map_.remove(key); return sm_trie_delete(m_pTrie, key);
} }
void BaseTrie::Clear() void BaseTrie::Clear()
{ {
map_.clear(); sm_trie_clear(m_pTrie);
} }
void BaseTrie::Destroy() void BaseTrie::Destroy()
@@ -89,5 +92,5 @@ void BaseTrie::Destroy()
bool BaseTrie::Replace(const char *key, void *value) bool BaseTrie::Replace(const char *key, void *value)
{ {
return map_.replace(key, value); return sm_trie_replace(m_pTrie, key, value);
} }
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -33,8 +33,8 @@
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_ #define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
#include <IADTFactory.h> #include <IADTFactory.h>
#include "common_logic.h" #include "sm_globals.h"
#include <sm_stringhashmap.h> #include "sm_trie.h"
using namespace SourceMod; using namespace SourceMod;
@@ -50,7 +50,7 @@ public:
virtual void Clear(); virtual void Clear();
virtual void Destroy(); virtual void Destroy();
private: private:
StringHashMap<void *> map_; Trie *m_pTrie;
}; };
class ADTFactory : class ADTFactory :
-118
View File
@@ -1,118 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
project = SM.HL2Project(builder, 'sourcemod')
project.sources += [
'MenuStyle_Valve.cpp',
'logic_bridge.cpp',
'smn_entities.cpp',
'sm_stringutil.cpp',
'MenuVoting.cpp',
'smn_events.cpp',
'smn_menus.cpp',
'CDataPack.cpp',
'frame_hooks.cpp',
'smn_nextmap.cpp',
'sourcemm_api.cpp',
'ChatTriggers.cpp',
'smn_player.cpp',
'sourcemod.cpp',
'concmd_cleaner.cpp',
'HalfLife2.cpp',
'NextMap.cpp',
'ConCmdManager.cpp',
'ConVarManager.cpp',
'LibrarySys.cpp',
'PlayerManager.cpp',
'TimerSys.cpp',
'CoreConfig.cpp',
'Logger.cpp',
'smn_halflife.cpp',
'smn_console.cpp',
'UserMessages.cpp',
'MenuManager.cpp',
'smn_core.cpp',
'smn_hudtext.cpp',
'smn_usermsgs.cpp',
'MenuStyle_Base.cpp',
'smn_keyvalues.cpp',
'smn_vector.cpp',
'EventManager.cpp',
'MenuStyle_Radio.cpp',
'sm_autonatives.cpp',
'sm_srvcmds.cpp',
'ConsoleDetours.cpp'
]
for sdk_name in SM.sdks:
sdk = SM.sdks[sdk_name]
binary_name = 'sourcemod.' + sdk.ext
binary = SM.HL2Config(project, binary_name, sdk)
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')
]
if builder.target_platform == 'linux':
compiler.postlink += ['-lpthread', '-lrt']
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 '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 += [
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'),
]
SM.binaries += builder.Add(project)
File diff suppressed because it is too large Load Diff
+208 -226
View File
@@ -1,226 +1,208 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * 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 * the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation. * Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * 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 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
* *
* As a special exception, AlliedModders LLC gives you permission to link the * 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 * 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 * "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 * by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants * all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
* *
* Version: $Id$ * Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_ #ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_ #define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
#include "common_logic.h" #include "sm_memtable.h"
#include <IAdminSystem.h> #include <sm_trie.h>
#include "sm_memtable.h" #include <sh_list.h>
#include <sm_trie.h> #include <sh_string.h>
#include <sh_list.h> #include <IAdminSystem.h>
#include <sh_string.h> #include "sm_globals.h"
#include <IForwardSys.h> #include <IForwardSys.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h> using namespace SourceHook;
using namespace SourceHook; #define GRP_MAGIC_SET 0xDEADFADE
#define GRP_MAGIC_UNSET 0xFACEFACE
#define GRP_MAGIC_SET 0xDEADFADE #define USR_MAGIC_SET 0xDEADFACE
#define GRP_MAGIC_UNSET 0xFACEFACE #define USR_MAGIC_UNSET 0xFADEDEAD
#define USR_MAGIC_SET 0xDEADFACE
#define USR_MAGIC_UNSET 0xFADEDEAD struct AdminGroup
{
typedef StringHashMap<OverrideRule> OverrideMap; uint32_t magic; /* Magic flag, for memory validation (ugh) */
unsigned int immunity_level; /* Immunity level */
struct AdminGroup /* Immune from target table (-1 = nonexistent)
{ * [0] = number of entries
uint32_t magic; /* Magic flag, for memory validation (ugh) */ * [1...N] = immune targets
unsigned int immunity_level; /* Immunity level */ */
/* Immune from target table (-1 = nonexistent) int immune_table;
* [0] = number of entries Trie *pCmdTable; /* Command override table (can be NULL) */
* [1...N] = immune targets Trie *pCmdGrpTable; /* Command group override table (can be NULL) */
*/ int next_grp; /* Next group in the chain */
int immune_table; int prev_grp; /* Previous group in the chain */
OverrideMap *pCmdTable; /* Command override table (can be NULL) */ int nameidx; /* Name */
OverrideMap *pCmdGrpTable; /* Command group override table (can be NULL) */ FlagBits addflags; /* Additive flags */
int next_grp; /* Next group in the chain */ };
int prev_grp; /* Previous group in the chain */
int nameidx; /* Name */ struct AuthMethod
FlagBits addflags; /* Additive flags */ {
}; String name;
Trie *table;
struct AuthMethod };
{
String name; struct UserAuth
StringHashMap<AdminId> identities; {
unsigned int index; /* Index into auth table */
AuthMethod(const char *name) int identidx; /* Index into the string table */
: name(name) };
{
} struct AdminUser
{
static inline bool matches(const char *name, const AuthMethod *method) uint32_t magic; /* Magic flag, for memory validation */
{ FlagBits flags; /* Flags */
return strcmp(name, method->name.c_str()) == 0; FlagBits eflags; /* Effective flags */
} int nameidx; /* Name index */
}; int password; /* Password index */
unsigned int grp_count; /* Number of groups */
struct UserAuth unsigned int grp_size; /* Size of groups table */
{ int grp_table; /* Group table itself */
unsigned int index; /* Index into auth table */ int next_user; /* Next user in the list */
int identidx; /* Index into the string table */ int prev_user; /* Previous user in the list */
}; UserAuth auth; /* Auth method for this user */
unsigned int immunity_level; /* Immunity level */
struct AdminUser unsigned int serialchange; /* Serial # for changes */
{ };
uint32_t magic; /* Magic flag, for memory validation */
FlagBits flags; /* Flags */ class AdminCache :
FlagBits eflags; /* Effective flags */ public IAdminSystem,
int nameidx; /* Name index */ public SMGlobalClass
int password; /* Password index */ {
unsigned int grp_count; /* Number of groups */ public:
unsigned int grp_size; /* Size of groups table */ AdminCache();
int grp_table; /* Group table itself */ ~AdminCache();
int next_user; /* Next user in the list */ public: //SMGlobalClass
int prev_user; /* Previous user in the list */ void OnSourceModStartup(bool late);
UserAuth auth; /* Auth method for this user */ void OnSourceModAllInitialized();
unsigned int immunity_level; /* Immunity level */ void OnSourceModLevelChange(const char *mapName);
unsigned int serialchange; /* Serial # for changes */ void OnSourceModShutdown();
}; void OnSourceModPluginsLoaded();
public: //IAdminSystem
class AdminCache : /** Command cache stuff */
public IAdminSystem, void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
public SMGlobalClass bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
{ void UnsetCommandOverride(const char *cmd, OverrideType type);
public: /** Group cache stuff */
AdminCache(); GroupId AddGroup(const char *group_name);
~AdminCache(); GroupId FindGroupByName(const char *group_name);
public: //SMGlobalClass void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
void OnSourceModStartup(bool late); bool GetGroupAddFlag(GroupId id, AdminFlag flag);
void OnSourceModAllInitialized(); FlagBits GetGroupAddFlags(GroupId id);
void OnSourceModLevelChange(const char *mapName); void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
void OnSourceModShutdown(); bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
void OnSourceModPluginsLoaded(); void InvalidateGroup(GroupId id);
public: //IAdminSystem void AddGroupImmunity(GroupId id, GroupId other_id);
/** Command cache stuff */ unsigned int GetGroupImmunityCount(GroupId id);
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags); GroupId GetGroupImmunity(GroupId id, unsigned int number);
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags); void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
void UnsetCommandOverride(const char *cmd, OverrideType type); bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
/** Group cache stuff */ void DumpAdminCache(AdminCachePart part, bool rebuild);
GroupId AddGroup(const char *group_name); void AddAdminListener(IAdminListener *pListener);
GroupId FindGroupByName(const char *group_name); void RemoveAdminListener(IAdminListener *pListener);
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled); /** User stuff */
bool GetGroupAddFlag(GroupId id, AdminFlag flag); void RegisterAuthIdentType(const char *name);
FlagBits GetGroupAddFlags(GroupId id); AdminId CreateAdmin(const char *name);
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled); const char *GetAdminName(AdminId id);
bool GetGroupGenericImmunity(GroupId id, ImmunityType type); bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
void InvalidateGroup(GroupId id); virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
void AddGroupImmunity(GroupId id, GroupId other_id); bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
unsigned int GetGroupImmunityCount(GroupId id); FlagBits GetAdminFlags(AdminId id, AccessMode mode);
GroupId GetGroupImmunity(GroupId id, unsigned int number); bool AdminInheritGroup(AdminId id, GroupId gid);
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule); unsigned int GetAdminGroupCount(AdminId id);
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule); GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
void DumpAdminCache(AdminCachePart part, bool rebuild); void SetAdminPassword(AdminId id, const char *password);
void AddAdminListener(IAdminListener *pListener); const char *GetAdminPassword(AdminId id);
void RemoveAdminListener(IAdminListener *pListener); AdminId FindAdminByIdentity(const char *auth, const char *identity);
/** User stuff */ bool InvalidateAdmin(AdminId id);
void RegisterAuthIdentType(const char *name); unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
AdminId CreateAdmin(const char *name); FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
const char *GetAdminName(AdminId id); FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident); unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled); bool CheckAdminFlags(AdminId id, FlagBits bits);
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode); bool CanAdminTarget(AdminId id, AdminId target);
FlagBits GetAdminFlags(AdminId id, AccessMode mode); void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
bool AdminInheritGroup(AdminId id, GroupId gid); bool FindFlag(const char *str, AdminFlag *pFlag);
unsigned int GetAdminGroupCount(AdminId id); bool FindFlag(char c, AdminFlag *pAdmFlag);
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name); FlagBits ReadFlagString(const char *flags, const char **end);
void SetAdminPassword(AdminId id, const char *password); size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen);
const char *GetAdminPassword(AdminId id); unsigned int GetAdminSerialChange(AdminId id);
AdminId FindAdminByIdentity(const char *auth, const char *identity); bool CanAdminUseCommand(int client, const char *cmd);
bool InvalidateAdmin(AdminId id); const char *GetGroupName(GroupId gid);
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize); unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize); unsigned int GetGroupImmunityLevel(GroupId gid);
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags); unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize); unsigned int GetAdminImmunityLevel(AdminId id);
bool CheckAdminFlags(AdminId id, FlagBits bits); bool CheckAccess(int client,
bool CanAdminTarget(AdminId id, AdminId target); const char *cmd,
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits); FlagBits flags,
bool FindFlag(const char *str, AdminFlag *pFlag); bool override_only);
bool FindFlag(char c, AdminFlag *pAdmFlag); bool FindFlagChar(AdminFlag flag, char *c);
FlagBits ReadFlagString(const char *flags, const char **end); public:
size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen); bool IsValidAdmin(AdminId id);
unsigned int GetAdminSerialChange(AdminId id); void DumpCache(FILE *fp);
bool CanAdminUseCommand(int client, const char *cmd); AdminGroup *GetGroup(GroupId gid);
const char *GetGroupName(GroupId gid); AdminUser *GetUser(AdminId id);
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level); const char *GetString(int idx);
unsigned int GetGroupImmunityLevel(GroupId gid); private:
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level); void _UnsetCommandOverride(const char *cmd);
unsigned int GetAdminImmunityLevel(AdminId id); void _UnsetCommandGroupOverride(const char *group);
bool CheckAccess(int client, void InvalidateGroupCache();
const char *cmd, void InvalidateAdminCache(bool unlink_admins);
FlagBits flags, void DumpCommandOverrideCache(OverrideType type);
bool override_only); Trie *GetMethodByIndex(unsigned int index);
bool FindFlagChar(AdminFlag flag, char *c); bool GetMethodIndex(const char *name, unsigned int *_index);
bool IsValidAdmin(AdminId id); const char *GetMethodName(unsigned int index);
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags); void NameFlag(const char *str, AdminFlag flag);
public: public:
void DumpCache(FILE *fp); BaseStringTable *m_pStrings;
AdminGroup *GetGroup(GroupId gid); BaseMemTable *m_pMemory;
AdminUser *GetUser(AdminId id); Trie *m_pCmdOverrides;
const char *GetString(int idx); Trie *m_pCmdGrpOverrides;
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags); int m_FirstGroup;
private: int m_LastGroup;
void _UnsetCommandOverride(const char *cmd); int m_FreeGroupList;
void _UnsetCommandGroupOverride(const char *group); Trie *m_pGroups;
void InvalidateGroupCache(); List<IAdminListener *> m_hooks;
void InvalidateAdminCache(bool unlink_admins); List<AuthMethod> m_AuthMethods;
void DumpCommandOverrideCache(OverrideType type); Trie *m_pAuthTables;
AuthMethod *GetMethodByIndex(unsigned int index); IForward *m_pCacheFwd;
bool GetMethodIndex(const char *name, unsigned int *_index); int m_FirstUser;
const char *GetMethodName(unsigned int index); int m_LastUser;
void NameFlag(const char *str, AdminFlag flag); int m_FreeUserList;
public: bool m_InvalidatingAdmins;
typedef StringHashMap<FlagBits> FlagMap; bool m_destroying;
Trie *m_pLevelNames;
BaseStringTable *m_pStrings; };
BaseMemTable *m_pMemory;
FlagMap m_CmdOverrides; extern AdminCache g_Admins;
FlagMap m_CmdGrpOverrides;
int m_FirstGroup; #endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
int m_LastGroup;
int m_FreeGroupList;
StringHashMap<GroupId> m_Groups;
List<IAdminListener *> m_hooks;
List<AuthMethod *> m_AuthMethods;
NameHashSet<AuthMethod *> m_AuthTables;
IForward *m_pCacheFwd;
int m_FirstUser;
int m_LastUser;
int m_FreeUserList;
bool m_InvalidatingAdmins;
bool m_destroying;
StringHashMap<AdminFlag> m_LevelNames;
};
extern AdminCache g_Admins;
#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
+2 -2
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -29,7 +29,7 @@
* Version: $Id$ * Version: $Id$
*/ */
#include <stdlib.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include "CDataPack.h" #include "CDataPack.h"
+1 -1
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
+3 -19
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -29,10 +29,7 @@
* Version: $Id$ * Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_CELLARRAY_H_ #include <malloc.h>
#define _INCLUDE_SOURCEMOD_CELLARRAY_H_
#include <stdlib.h>
#include <string.h> #include <string.h>
extern HandleType_t htCellArray; extern HandleType_t htCellArray;
@@ -43,17 +40,14 @@ public:
CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0) CellArray(size_t blocksize) : m_Data(NULL), m_BlockSize(blocksize), m_AllocSize(0), m_Size(0)
{ {
} }
~CellArray() ~CellArray()
{ {
free(m_Data); free(m_Data);
} }
size_t size() const size_t size() const
{ {
return m_Size; return m_Size;
} }
cell_t *push() cell_t *push()
{ {
if (!GrowIfNeeded(1)) if (!GrowIfNeeded(1))
@@ -64,22 +58,18 @@ public:
m_Size++; m_Size++;
return arr; return arr;
} }
cell_t *at(size_t b) const cell_t *at(size_t b) const
{ {
return &m_Data[b * m_BlockSize]; return &m_Data[b * m_BlockSize];
} }
size_t blocksize() const size_t blocksize() const
{ {
return m_BlockSize; return m_BlockSize;
} }
void clear() void clear()
{ {
m_Size = 0; m_Size = 0;
} }
bool swap(size_t item1, size_t item2) bool swap(size_t item1, size_t item2)
{ {
/* Make sure there is extra space available */ /* Make sure there is extra space available */
@@ -100,7 +90,6 @@ public:
return true; return true;
} }
void remove(size_t index) void remove(size_t index)
{ {
/* If we're at the end, take the easy way out */ /* If we're at the end, take the easy way out */
@@ -118,7 +107,6 @@ public:
m_Size--; m_Size--;
} }
cell_t *insert_at(size_t index) cell_t *insert_at(size_t index)
{ {
/* Make sure it'll fit */ /* Make sure it'll fit */
@@ -136,7 +124,6 @@ public:
return src; return src;
} }
bool resize(size_t count) bool resize(size_t count)
{ {
if (count <= m_Size) if (count <= m_Size)
@@ -145,7 +132,7 @@ public:
return true; return true;
} }
if (!GrowIfNeeded(count - m_Size)) if(!GrowIfNeeded(count - m_Size))
{ {
return false; return false;
} }
@@ -207,6 +194,3 @@ private:
size_t m_AllocSize; size_t m_AllocSize;
size_t m_Size; size_t m_Size;
}; };
#endif /* _INCLUDE_SOURCEMOD_CELLARRAY_H_ */
+3 -21
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -44,11 +44,7 @@ public: //IRecipientFilter
bool IsReliable() const; bool IsReliable() const;
bool IsInitMessage() const; bool IsInitMessage() const;
int GetRecipientCount() const; int GetRecipientCount() const;
#if SOURCE_ENGINE == SE_DOTA
CEntityIndex GetRecipientIndex(int slot) const;
#else
int GetRecipientIndex(int slot) const; int GetRecipientIndex(int slot) const;
#endif
public: public:
void Initialize(const cell_t *ptr, size_t count); void Initialize(const cell_t *ptr, size_t count);
void SetToReliable(bool isreliable); void SetToReliable(bool isreliable);
@@ -83,27 +79,13 @@ inline int CellRecipientFilter::GetRecipientCount() const
return m_Size; return m_Size;
} }
#if SOURCE_ENGINE == SE_DOTA
inline CEntityIndex CellRecipientFilter::GetRecipientIndex(int slot) const
#else
inline int CellRecipientFilter::GetRecipientIndex(int slot) const inline int CellRecipientFilter::GetRecipientIndex(int slot) const
#endif
{ {
int ret;
if ((slot < 0) || (slot >= GetRecipientCount())) if ((slot < 0) || (slot >= GetRecipientCount()))
{ {
ret = -1; return -1;
} }
else return static_cast<int>(m_Players[slot]);
{
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) inline void CellRecipientFilter::SetToInit(bool isinitmsg)
+144 -224
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,40 +34,39 @@
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "ConCmdManager.h" #include "ConCmdManager.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "Translator.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "logic_bridge.h"
#include "sourcemod.h"
#if SOURCE_ENGINE == SE_DOTA /* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &); * While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
#elif SOURCE_ENGINE >= SE_ORANGEBOX * can technically be compiled against any MM:S version after 1.4.2.
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); */
#elif SOURCE_ENGINE == SE_DARKMESSIAH #if defined ORANGEBOX_BUILD
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
#else #else
# if SH_IMPL_VERSION >= 4 extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); #if SH_IMPL_VERSION >= 5
# else extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate0<void>);
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); #elif SH_IMPL_VERSION == 4
# endif extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); #elif SH_IMPL_VERSION == 3
#endif extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
#endif //SH_IMPL_VERSION
#endif //ORANGEBOX_BUILD
ChatTriggers g_ChatTriggers; ChatTriggers g_ChatTriggers;
bool g_bSupressSilentFails = false; bool g_bSupressSilentFails = false;
CPhraseFile *g_pFloodPhrases = NULL;
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false), ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL) m_bTriggerWasSilent(false), m_ReplyTo(SM_REPLY_CONSOLE)
{ {
m_PubTrigger = sm_strdup("!"); m_PubTrigger = sm_strdup("!");
m_PrivTrigger = sm_strdup("/"); m_PrivTrigger = sm_strdup("/");
m_PubTriggerSize = 1; m_PubTriggerSize = 1;
m_PrivTriggerSize = 1; m_PrivTriggerSize = 1;
m_bIsChatTrigger = false; m_bIsChatTrigger = false;
m_bPluginIgnored = true;
#if SOURCE_ENGINE == SE_EPISODEONE
m_bIsINS = false;
#endif
} }
ChatTriggers::~ChatTriggers() ChatTriggers::~ChatTriggers()
@@ -76,8 +75,6 @@ ChatTriggers::~ChatTriggers()
m_PubTrigger = NULL; m_PubTrigger = NULL;
delete [] m_PrivTrigger; delete [] m_PrivTrigger;
m_PrivTrigger = NULL; m_PrivTrigger = NULL;
delete [] m_ArgSBackup;
m_ArgSBackup = NULL;
} }
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key, ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
@@ -111,94 +108,76 @@ ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
void ChatTriggers::OnSourceModAllInitialized() void ChatTriggers::OnSourceModAllInitialized()
{ {
m_pShouldFloodBlock = forwardsys->CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell); m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
m_pDidFloodBlock = forwardsys->CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell); m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
m_pOnClientSayCmd = forwardsys->CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String);
m_pOnClientSayCmd_Post = forwardsys->CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
} }
void ChatTriggers::OnSourceModAllInitialized_Post() void ChatTriggers::OnSourceModAllInitialized_Post()
{ {
logicore.AddCorePhraseFile("antiflood.phrases"); unsigned int file_id;
file_id = g_Translator.FindOrAddPhraseFile("antiflood.phrases.txt");
g_pFloodPhrases = g_Translator.GetFileByIndex(file_id);
} }
void ChatTriggers::OnSourceModGameInitialized() void ChatTriggers::OnSourceModGameInitialized()
{ {
m_pSayCmd = FindCommand("say"); unsigned int total = 2;
m_pSayTeamCmd = FindCommand("say_team"); ConCommandBase *pCmd = icvar->GetCommands();
const char *name;
while (pCmd)
{
if (pCmd->IsCommand())
{
name = pCmd->GetName();
if (!m_pSayCmd && strcmp(name, "say") == 0)
{
m_pSayCmd = (ConCommand *)pCmd;
if (--total == 0)
{
break;
}
} else if (!m_pSayTeamCmd && strcmp(name, "say_team") == 0) {
m_pSayTeamCmd = (ConCommand *)pCmd;
if (--total == 0)
{
break;
}
}
}
pCmd = const_cast<ConCommandBase *>(pCmd->GetNext());
}
if (m_pSayCmd) if (m_pSayCmd)
{ {
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
} }
if (m_pSayTeamCmd) if (m_pSayTeamCmd)
{ {
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
} }
#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);
}
}
#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);
}
#endif
} }
void ChatTriggers::OnSourceModShutdown() 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) if (m_pSayTeamCmd)
{ {
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true); SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false); SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
}
if (m_pSayCmd)
{
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
} }
#if SOURCE_ENGINE == SE_EPISODEONE g_Forwards.ReleaseForward(m_pShouldFloodBlock);
if (m_bIsINS && m_pSay2Cmd) g_Forwards.ReleaseForward(m_pDidFloodBlock);
{
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
forwardsys->ReleaseForward(m_pShouldFloodBlock);
forwardsys->ReleaseForward(m_pDidFloodBlock);
forwardsys->ReleaseForward(m_pOnClientSayCmd);
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
} }
#if SOURCE_ENGINE == SE_DOTA #if defined ORANGEBOX_BUILD
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Pre(const CCommand &command) void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{ {
#else #else
@@ -206,95 +185,28 @@ void ChatTriggers::OnSayCommand_Pre()
{ {
CCommand command; CCommand command;
#endif #endif
int client = g_ConCmds.GetCommandClient(); int client;
CPlayer *pPlayer;
client = g_ConCmds.GetCommandClient();
m_bIsChatTrigger = false; m_bIsChatTrigger = false;
m_bWasFloodedMessage = false; m_bWasFloodedMessage = false;
m_bPluginIgnored = true;
const char *args = command.ArgS();
if (!args)
{
RETURN_META(MRES_IGNORED);
}
/* 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);
size_t len = strlen(args);
#if SOURCE_ENGINE == SE_EPISODEONE
if (m_bIsINS)
{
if (strcmp(m_Arg0Backup, "say2") == 0 && len >= 4)
{
args += 4;
len -= 4;
}
if (len == 0)
{
RETURN_META(MRES_SUPERCEDE);
}
}
#endif
/* The first pair of quotes are stripped from client say commands, but not console ones.
* We do not want the forwards to differ from what is displayed.
* So only strip the first pair of quotes from client say commands. */
bool is_quoted = false;
if (
#if SOURCE_ENGINE == SE_EPISODEONE
!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);
}
args++;
len--;
is_quoted = true;
}
/* Some? engines strip the last quote when printing the string to chat.
* This results in having a double-quoted message passed to the OnClientSayCommand ("message") forward,
* but losing the last quote in the OnClientSayCommand_Post ("message) forward.
* To compensate this, we copy the args into our own buffer where the engine won't mess with
* and strip the quotes. */
delete [] m_ArgSBackup;
m_ArgSBackup = new char[CCommand::MaxCommandLength()+1];
memcpy(m_ArgSBackup, args, len+1);
/* Strip the quotes from the argument */
if (is_quoted)
{
if (m_ArgSBackup[len-1] == '"')
{
m_ArgSBackup[--len] = '\0';
}
}
/* The server console cannot do this */ /* The server console cannot do this */
if (client == 0) if (client == 0 || (pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
{ {
if (CallOnClientSayCommand(client) >= Pl_Handled)
{
RETURN_META(MRES_SUPERCEDE);
}
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
/* We guarantee the client is connected */ /* We guarantee the client is connected */
if (!pPlayer || !pPlayer->IsConnected()) if (!pPlayer->IsConnected())
{
RETURN_META(MRES_IGNORED);
}
const char *args = command.ArgS();
if (!args)
{ {
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@@ -304,8 +216,18 @@ void ChatTriggers::OnSayCommand_Pre()
{ {
char buffer[128]; char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client)) /* :TODO: log an error? */
if (g_Translator.CoreTransEx(g_pFloodPhrases,
client,
buffer,
sizeof(buffer),
"Flooding the server",
NULL,
NULL)
!= Trans_Okay)
{
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!"); UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
}
/* :TODO: we should probably kick people who spam too much. */ /* :TODO: we should probably kick people who spam too much. */
@@ -318,41 +240,62 @@ void ChatTriggers::OnSayCommand_Pre()
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
/* Handle quoted string sets */
bool is_quoted = false;
if (args[0] == '"')
{
args++;
is_quoted = true;
}
bool is_trigger = false; bool is_trigger = false;
bool is_silent = false; bool is_silent = false;
/* Check for either trigger */ /* Check for either trigger */
if (m_PubTriggerSize && strncmp(m_ArgSBackup, m_PubTrigger, m_PubTriggerSize) == 0) if (m_PubTriggerSize && strncmp(args, m_PubTrigger, m_PubTriggerSize) == 0)
{ {
is_trigger = true; is_trigger = true;
args = &m_ArgSBackup[m_PubTriggerSize]; args = &args[m_PubTriggerSize];
} }
else if (m_PrivTriggerSize && strncmp(m_ArgSBackup, m_PrivTrigger, m_PrivTriggerSize) == 0) else if (m_PrivTriggerSize && strncmp(args, m_PrivTrigger, m_PrivTriggerSize) == 0)
{ {
is_trigger = true; is_trigger = true;
is_silent = true; is_silent = true;
args = &m_ArgSBackup[m_PrivTriggerSize]; args = &args[m_PrivTriggerSize];
}
if (!is_trigger)
{
RETURN_META(MRES_IGNORED);
} }
/** /**
* Test if this is actually a command! * Test if this is actually a command!
*/ */
if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args)) if (!PreProcessTrigger(engine->PEntityOfEntIndex(client), args, is_quoted))
{ {
m_bIsChatTrigger = true; CPlayer *pPlayer;
if (is_silent
/** && g_bSupressSilentFails
* We'll execute it in post. && client != 0
*/ && (pPlayer = g_Players.GetPlayerByIndex(client)) != NULL
m_bWillProcessInPost = true; && pPlayer->GetAdminId() != INVALID_ADMIN_ID)
{
RETURN_META(MRES_SUPERCEDE);
}
RETURN_META(MRES_IGNORED);
} }
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID))) m_bIsChatTrigger = true;
{
RETURN_META(MRES_SUPERCEDE);
}
if (CallOnClientSayCommand(client) >= Pl_Handled) /**
* We'll execute it in post.
*/
m_bWillProcessInPost = true;
m_bTriggerWasSilent = is_silent;
/* If we're silent, block */
if (is_silent)
{ {
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
@@ -361,44 +304,28 @@ void ChatTriggers::OnSayCommand_Pre()
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
#if SOURCE_ENGINE == SE_DOTA #if defined ORANGEBOX_BUILD
void ChatTriggers::OnSayCommand_Post(const CCommandContext &context, const CCommand &command)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Post(const CCommand &command) void ChatTriggers::OnSayCommand_Post(const CCommand &command)
#else #else
void ChatTriggers::OnSayCommand_Post() void ChatTriggers::OnSayCommand_Post()
#endif #endif
{ {
int client = g_ConCmds.GetCommandClient(); m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
if (m_bWillProcessInPost) if (m_bWillProcessInPost)
{ {
/* Reset this for re-entrancy */ /* Reset this for re-entrancy */
m_bWillProcessInPost = false; m_bWillProcessInPost = false;
/* Execute the cached command */ /* Execute the cached command */
int client = g_ConCmds.GetCommandClient();
unsigned int old = SetReplyTo(SM_REPLY_CHAT); unsigned int old = SetReplyTo(SM_REPLY_CHAT);
#if SOURCE_ENGINE == SE_DOTA serverpluginhelpers->ClientCommand(engine->PEntityOfEntIndex(client), m_ToExecute);
engine->ClientCommand(client, "%s", m_ToExecute);
#else
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
#endif
SetReplyTo(old); SetReplyTo(old);
} }
if (!m_bPluginIgnored && m_pOnClientSayCmd_Post->GetFunctionCount() != 0)
{
m_pOnClientSayCmd_Post->PushCell(client);
m_pOnClientSayCmd_Post->PushString(m_Arg0Backup);
m_pOnClientSayCmd_Post->PushString(m_ArgSBackup);
m_pOnClientSayCmd_Post->Execute(NULL);
}
m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
} }
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args) bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted)
{ {
/* Extract a command. This is kind of sloppy. */ /* Extract a command. This is kind of sloppy. */
char cmd_buf[64]; char cmd_buf[64];
@@ -440,12 +367,12 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
{ {
return false; return false;
} }
prepended = true; prepended = true;
} }
/* See if we need to do extra string manipulation */ /* See if we need to do extra string manipulation */
if (prepended) if (is_quoted || prepended)
{ {
size_t len; size_t len;
@@ -456,6 +383,15 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
} else { } else {
len = strncopy(m_ToExecute, args, sizeof(m_ToExecute)); len = strncopy(m_ToExecute, args, sizeof(m_ToExecute));
} }
/* Check if we need to strip a quote */
if (is_quoted)
{
if (m_ToExecute[len-1] == '"')
{
m_ToExecute[--len] = '\0';
}
}
} else { } else {
strncopy(m_ToExecute, args, sizeof(m_ToExecute)); strncopy(m_ToExecute, args, sizeof(m_ToExecute));
} }
@@ -463,22 +399,6 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
return true; return true;
} }
cell_t ChatTriggers::CallOnClientSayCommand(int client)
{
cell_t res = Pl_Continue;
if (m_pOnClientSayCmd->GetFunctionCount() != 0)
{
m_pOnClientSayCmd->PushCell(client);
m_pOnClientSayCmd->PushString(m_Arg0Backup);
m_pOnClientSayCmd->PushString(m_ArgSBackup);
m_pOnClientSayCmd->Execute(&res);
}
m_bPluginIgnored = (res >= Pl_Stop);
return res;
}
unsigned int ChatTriggers::SetReplyTo(unsigned int reply) unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
{ {
unsigned int old = m_ReplyTo; unsigned int old = m_ReplyTo;
+4 -20
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -54,10 +54,7 @@ public: //SMGlobalClass
char *error, char *error,
size_t maxlength); size_t maxlength);
private: //ConCommand private: //ConCommand
#if SOURCE_ENGINE == SE_DOTA #if defined ORANGEBOX_BUILD
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_Pre(const CCommand &command);
void OnSayCommand_Post(const CCommand &command); void OnSayCommand_Post(const CCommand &command);
#else #else
@@ -70,36 +67,23 @@ public:
bool IsChatTrigger(); bool IsChatTrigger();
bool WasFloodedMessage(); bool WasFloodedMessage();
private: private:
bool PreProcessTrigger(edict_t *pEdict, const char *args); bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
bool ClientIsFlooding(int client); bool ClientIsFlooding(int client);
cell_t CallOnClientSayCommand(int client);
private: private:
ConCommand *m_pSayCmd; ConCommand *m_pSayCmd;
ConCommand *m_pSayTeamCmd; ConCommand *m_pSayTeamCmd;
#if SOURCE_ENGINE == SE_EPISODEONE
ConCommand *m_pSay2Cmd;
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
ConCommand *m_pSaySquadCmd;
#endif
char *m_PubTrigger; char *m_PubTrigger;
size_t m_PubTriggerSize; size_t m_PubTriggerSize;
char *m_PrivTrigger; char *m_PrivTrigger;
size_t m_PrivTriggerSize; size_t m_PrivTriggerSize;
bool m_bWillProcessInPost; bool m_bWillProcessInPost;
bool m_bTriggerWasSilent;
bool m_bIsChatTrigger; bool m_bIsChatTrigger;
bool m_bWasFloodedMessage; bool m_bWasFloodedMessage;
bool m_bPluginIgnored;
unsigned int m_ReplyTo; unsigned int m_ReplyTo;
char m_ToExecute[300]; char m_ToExecute[300];
const char *m_Arg0Backup;
char *m_ArgSBackup;
IForward *m_pShouldFloodBlock; IForward *m_pShouldFloodBlock;
IForward *m_pDidFloodBlock; IForward *m_pDidFloodBlock;
IForward *m_pOnClientSayCmd;
IForward *m_pOnClientSayCmd_Post;
#if SOURCE_ENGINE == SE_EPISODEONE
bool m_bIsINS;
#endif
}; };
extern ChatTriggers g_ChatTriggers; extern ChatTriggers g_ChatTriggers;
+562 -260
View File
File diff suppressed because it is too large Load Diff
+34 -57
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,90 +34,71 @@
#include "sm_globals.h" #include "sm_globals.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <IForwardSys.h> #include "ForwardSys.h"
#include "sm_trie.h"
#include "sm_memtable.h"
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.h> #include <sh_string.h>
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include <IAdminSystem.h> #include <IAdminSystem.h>
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include <sm_stringhashmap.h>
#include <am-utility.h>
#include <am-inlinelist.h>
#include <am-linkedlist.h>
#include <am-refcounting.h>
using namespace SourceHook; using namespace SourceHook;
struct CmdHook; enum CmdType
struct ConCmdInfo;
struct CommandGroup : public ke::Refcounted<CommandGroup>
{ {
ke::LinkedList<CmdHook *> hooks; Cmd_Server,
Cmd_Console,
Cmd_Admin,
}; };
struct AdminCmdInfo struct AdminCmdInfo
{ {
AdminCmdInfo(const ke::Ref<CommandGroup> &group, FlagBits flags) AdminCmdInfo()
: group(group),
flags(flags),
eflags(0)
{ {
cmdGrpId = -1;
flags = 0;
eflags = 0;
} }
ke::Ref<CommandGroup> group; int cmdGrpId; /* index into cmdgroup string table */
FlagBits flags; /* default flags */ FlagBits flags; /* default flags */
FlagBits eflags; /* effective flags */ FlagBits eflags; /* effective flags */
}; };
struct CmdHook : public ke::InlineListNode<CmdHook> struct CmdHook
{ {
enum Type { CmdHook()
Server,
Client
};
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description)
: type(type),
info(cmd),
pf(fun),
helptext(description)
{ {
pf = NULL;
pAdmin = NULL;
} }
IPluginFunction *pf; /* function hook */
Type type; String helptext; /* help text */
ConCmdInfo *info; AdminCmdInfo *pAdmin; /* admin requirements, if any */
IPluginFunction *pf; /* function hook */
ke::AString helptext; /* help text */
ke::AutoPtr<AdminCmdInfo> admin; /* admin requirements, if any */
}; };
typedef ke::InlineList<CmdHook> CmdHookList;
struct ConCmdInfo struct ConCmdInfo
{ {
ConCmdInfo() ConCmdInfo()
{ {
sourceMod = false; sourceMod = false;
pCmd = NULL; pCmd = NULL;
eflags = 0;
} }
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */ bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
ConCommand *pCmd; /**< Pointer to the command itself */ ConCommand *pCmd; /**< Pointer to the command itself */
CmdHookList hooks; /**< Hook list */ List<CmdHook *> srvhooks; /**< Hooks as a server command */
FlagBits eflags; /**< Effective admin flags */ List<CmdHook *> conhooks; /**< Hooks as a console command */
AdminCmdInfo admin; /**< Admin info, if any */
bool is_admin_set; /**< Whether or not admin info is set */
}; };
typedef List<ConCmdInfo *> ConCmdList;
class ConCmdManager : class ConCmdManager :
public SMGlobalClass, public SMGlobalClass,
public IRootConsoleCommand, public IRootConsoleCommand,
public IPluginsListener, public IPluginsListener,
public IConCommandTracker public IConCommandTracker
{ {
#if SOURCE_ENGINE == SE_DOTA #if defined ORANGEBOX_BUILD
friend void CommandCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
friend void CommandCallback(const CCommand &command); friend void CommandCallback(const CCommand &command);
#else #else
friend void CommandCallback(); friend void CommandCallback();
@@ -136,6 +117,7 @@ public: //IConCommandTracker
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe); void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
public: public:
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags); bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
bool AddConsoleCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
bool AddAdminCommand(IPluginFunction *pFunction, bool AddAdminCommand(IPluginFunction *pFunction,
const char *name, const char *name,
const char *group, const char *group,
@@ -146,6 +128,7 @@ public:
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove); void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool LookForSourceModCommand(const char *cmd); bool LookForSourceModCommand(const char *cmd);
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags); bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
bool CheckCommandAccess(int client, const char *cmd, FlagBits flags);
private: private:
void InternalDispatch(const CCommand &command); void InternalDispatch(const CCommand &command);
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args); ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
@@ -153,13 +136,9 @@ private:
void SetCommandClient(int client); void SetCommandClient(int client);
void AddToCmdList(ConCmdInfo *info); 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 is_read_safe, bool untrack);
void RemoveConCmds(List<CmdHook *> &cmdlist);
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
// Case insensitive
ConCmdList::iterator FindInList(const char *name);
// Case sensitive
ConCmdInfo *FindInTrie(const char *name);
public: public:
inline int GetCommandClient() inline int GetCommandClient()
{ {
@@ -170,15 +149,13 @@ public:
return m_CmdList; return m_CmdList;
} }
private: private:
typedef StringHashMap<ke::Ref<CommandGroup> > GroupMap; Trie *m_pCmds; /* command lookup */
Trie *m_pCmdGrps; /* command group lookup */
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */ List<ConCmdInfo *> m_CmdList; /* command list */
GroupMap m_CmdGrps; /* command group map */
ConCmdList m_CmdList; /* command list */
int m_CmdClient; /* current client */ int m_CmdClient; /* current client */
BaseStringTable m_Strings; /* string table */
}; };
extern ConCmdManager g_ConCmds; extern ConCmdManager g_ConCmds;
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_ #endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
-89
View File
@@ -1,89 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2010 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_CON_COMMAND_BASE_ITERATOR_H_
#define _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
#if SOURCE_ENGINE >= SE_LEFT4DEAD
class ConCommandBaseIterator
{
public:
inline ConCommandBaseIterator() : iter(icvar)
{
iter.SetFirst();
}
inline bool IsValid()
{
return iter.IsValid();
}
inline void Next()
{
iter.Next();
}
inline ConCommandBase *Get()
{
return iter.Get();
}
private:
ICvar::Iterator iter;
};
#else
class ConCommandBaseIterator
{
public:
inline ConCommandBaseIterator()
{
iter = icvar->GetCommands();
}
inline bool IsValid()
{
return iter != NULL;
}
inline void Next()
{
iter = const_cast<ConCommandBase *>(iter->GetNext());
}
inline ConCommandBase *Get()
{
return iter;
}
private:
ConCommandBase *iter;
};
#endif
#endif /* _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_ */
+80 -200
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -25,69 +25,38 @@
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/ */
#include "ConVarManager.h" #include "ConVarManager.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "PluginSys.h"
#include "ForwardSys.h"
#include "HandleSys.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include <sh_vector.h> #include <sh_vector.h>
#include <sm_namehashset.h> #include <sm_trie_tpl.h>
#include "logic_bridge.h"
ConVarManager g_ConVarManager; ConVarManager g_ConVarManager;
#if SOURCE_ENGINE >= SE_ORANGEBOX #if !defined ORANGEBOX_BUILD
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float); #define CallGlobalChangeCallbacks CallGlobalChangeCallback
#else #endif
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *);
#if defined ORANGEBOX_BUILD
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
#else
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
#endif #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(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 *); 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}; const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
typedef List<const ConVar *> ConVarList; typedef List<const ConVar *> ConVarList;
NameHashSet<ConVarInfo *> convar_cache; KTrie<ConVarInfo *> convar_cache;
class ConVarReentrancyGuard
{
ConVar *cvar;
ConVarReentrancyGuard *up;
public:
static ConVarReentrancyGuard *chain;
ConVarReentrancyGuard(ConVar *cvar)
: cvar(cvar), up(chain)
{
chain = this;
}
~ConVarReentrancyGuard()
{
assert(chain == this);
chain = up;
}
static bool IsCvarInChain(ConVar *cvar)
{
ConVarReentrancyGuard *guard = chain;
while (guard != NULL)
{
if (guard->cvar == cvar)
return true;
guard = guard->up;
}
return false;
}
};
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false) ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
{ {
@@ -107,7 +76,7 @@ void ConVarManager::OnSourceModStartup(bool late)
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER; sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
/* Create the 'ConVar' handle type */ /* Create the 'ConVar' handle type */
m_ConVarType = handlesys->CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL); m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
} }
void ConVarManager::OnSourceModAllInitialized() void ConVarManager::OnSourceModAllInitialized()
@@ -115,23 +84,15 @@ void ConVarManager::OnSourceModAllInitialized()
/** /**
* Episode 2 has this function by default, but the older versions do not. * Episode 2 has this function by default, but the older versions do not.
*/ */
#if SOURCE_ENGINE == SE_EPISODEONE #if !defined ORANGEBOX_BUILD
if (g_SMAPI->GetGameDLLVersion() >= 6) if (g_SMAPI->GetGameDLLVersion() >= 6)
{ {
SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsDLLQueryHooked = true; m_bIsDLLQueryHooked = true;
} }
#endif #endif
g_Players.AddClientListener(this); SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
#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 */ /* Add the 'convars' option to the 'sm' console command */
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this); g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
@@ -149,10 +110,10 @@ void ConVarManager::OnSourceModShutdown()
iter = m_ConVars.erase(iter); iter = m_ConVars.erase(iter);
handlesys->FreeHandle(pInfo->handle, &sec); g_HandleSys.FreeHandle(pInfo->handle, &sec);
if (pInfo->pChangeForward != NULL) if (pInfo->pChangeForward != NULL)
{ {
forwardsys->ReleaseForward(pInfo->pChangeForward); g_Forwards.ReleaseForward(pInfo->pChangeForward);
} }
if (pInfo->sourceMod) if (pInfo->sourceMod)
{ {
@@ -180,37 +141,25 @@ void ConVarManager::OnSourceModShutdown()
} }
convar_cache.clear(); convar_cache.clear();
#if SOURCE_ENGINE != SE_DARKMESSIAH
/* Unhook things */ /* Unhook things */
if (m_bIsDLLQueryHooked) if (m_bIsDLLQueryHooked)
{ {
SH_REMOVE_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false); SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsDLLQueryHooked = false; m_bIsDLLQueryHooked = false;
} }
else if (m_bIsVSPQueryHooked) else if (m_bIsVSPQueryHooked)
{ {
#if SOURCE_ENGINE != SE_DOTA SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
SH_REMOVE_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
#endif
m_bIsVSPQueryHooked = false; m_bIsVSPQueryHooked = false;
} }
#endif
g_Players.RemoveClientListener(this); SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
#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 */ /* Remove the 'convars' option from the 'sm' console command */
g_RootMenu.RemoveRootConsoleCommand("cvars", this); g_RootMenu.RemoveRootConsoleCommand("cvars", this);
scripts->RemovePluginsListener(this);
/* Remove the 'ConVar' handle type */ /* Remove the 'ConVar' handle type */
handlesys->RemoveType(m_ConVarType, g_pCoreIdent); g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
} }
/** /**
@@ -227,7 +176,7 @@ void ConVarManager::OnSourceModVSPReceived()
} }
/* For later MM:S versions, use the updated API, since it's cleaner. */ /* For later MM:S versions, use the updated API, since it's cleaner. */
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 #if defined METAMOD_PLAPI_VERSION
int engine = g_SMAPI->GetSourceEngineBuild(); int engine = g_SMAPI->GetSourceEngineBuild();
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2) if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
{ {
@@ -240,15 +189,22 @@ void ConVarManager::OnSourceModVSPReceived()
} }
#endif #endif
#if SOURCE_ENGINE != SE_DARKMESSIAH && SOURCE_ENGINE != SE_DOTA SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
m_bIsVSPQueryHooked = true; m_bIsVSPQueryHooked = true;
#endif
} }
bool convar_cache_lookup(const char *name, ConVarInfo **pVar) bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
{ {
return convar_cache.retrieve(name, pVar); ConVarInfo **pLookup = convar_cache.retrieve(name);
if (pLookup != NULL)
{
*pVar = *pLookup;
return true;
}
else
{
return false;
}
} }
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
@@ -267,7 +223,7 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
convar_cache.remove(name); convar_cache.remove(name);
/* Now make sure no plugins are referring to this pointer */ /* Now make sure no plugins are referring to this pointer */
IPluginIterator *pl_iter = scripts->GetPluginIterator(); IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
while (pl_iter->MorePlugins()) while (pl_iter->MorePlugins())
{ {
IPlugin *pl = pl_iter->GetPlugin(); IPlugin *pl = pl_iter->GetPlugin();
@@ -283,51 +239,19 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
} }
/* Free resources */ /* Free resources */
handlesys->FreeHandle(pInfo->handle, &sec); g_HandleSys.FreeHandle(pInfo->handle, &sec);
delete pInfo; delete pInfo;
} }
void ConVarManager::OnPluginUnloaded(IPlugin *plugin) void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
{ {
ConVarList *pConVarList; ConVarList *pConVarList;
List<ConVarQuery>::iterator iter;
/* If plugin has a convar list, free its memory */ /* If plugin has a convar list, free its memory */
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true)) if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
{ {
delete pConVarList; delete pConVarList;
} }
const IPluginRuntime * pRuntime = plugin->GetRuntime();
/* Remove convar queries for this plugin that haven't returned results yet */
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
{
ConVarQuery &query = (*iter);
if (query.pCallback->GetParentRuntime() == pRuntime)
{
iter = m_ConVarQueries.erase(iter);
continue;
}
++iter;
}
}
void ConVarManager::OnClientDisconnected(int client)
{
/* Remove convar queries for this client that haven't returned results yet */
for (List<ConVarQuery>::iterator iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
{
ConVarQuery &query = (*iter);
if (query.client == client)
{
iter = m_ConVarQueries.erase(iter);
continue;
}
++iter;
}
} }
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object) void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
@@ -345,18 +269,11 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
int argcount = command.ArgC(); int argcount = command.ArgC();
if (argcount >= 3) if (argcount >= 3)
{ {
bool wantReset = false;
/* Get plugin index that was passed */ /* 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);
}
/* Get plugin object */ /* Get plugin object */
IPlugin *plugin = scripts->FindPluginByConsoleArg(arg); CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
if (!plugin) if (!plugin)
{ {
@@ -378,34 +295,21 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
return; return;
} }
if (!wantReset) g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
{ g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]"); /* Iterate convar list and display each one */
}
/* Iterate convar list and display/reset each one */
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++) for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
{ {
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter); const ConVar *pConVar = (*iter);
if (!wantReset) g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
{
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
} else {
pConVar->Revert();
}
}
if (wantReset)
{
g_RootMenu.ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname);
} }
return; return;
} }
/* Display usage of subcommand */ /* Display usage of subcommand */
g_RootMenu.ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>"); g_RootMenu.ConsolePrint("[SM] Usage: sm convars <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) 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)
@@ -437,7 +341,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
pInfo->pVar = pConVar; pInfo->pVar = pConVar;
/* If we don't, then create a new handle from the convar */ /* If we don't, then create a new handle from the convar */
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE) if (hndl == BAD_HANDLE)
{ {
delete pInfo; delete pInfo;
@@ -455,10 +359,17 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
} }
} }
/* Prevent creating a convar that has the same name as a console command */ /* To prevent creating a convar that has the same name as a console command... ugh */
if (FindCommand(name)) ConCommandBase *pBase = icvar->GetCommands();
while (pBase)
{ {
return BAD_HANDLE; if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
{
return BAD_HANDLE;
}
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
} }
/* Create and initialize ConVarInfo structure */ /* Create and initialize ConVarInfo structure */
@@ -468,7 +379,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
pInfo->pChangeForward = NULL; pInfo->pChangeForward = NULL;
/* Create a handle from the new convar */ /* Create a handle from the new convar */
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE) if (hndl == BAD_HANDLE)
{ {
delete pInfo; delete pInfo;
@@ -497,13 +408,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
ConVarInfo *pInfo; ConVarInfo *pInfo;
Handle_t hndl; Handle_t hndl;
/* Check convar cache to find out if we already have a handle */ /* Search for convar */
if (convar_cache_lookup(name, &pInfo))
{
return pInfo->handle;
}
/* Couldn't find it in cache, so search for it */
pConVar = icvar->FindVar(name); pConVar = icvar->FindVar(name);
/* If it doesn't exist, then return an invalid handle */ /* If it doesn't exist, then return an invalid handle */
@@ -512,6 +417,12 @@ Handle_t ConVarManager::FindConVar(const char *name)
return BAD_HANDLE; return BAD_HANDLE;
} }
/* At this point, the convar exists. So, find out if we already have a handle */
if (convar_cache_lookup(name, &pInfo))
{
return pInfo->handle;
}
/* Create and initialize ConVarInfo structure */ /* Create and initialize ConVarInfo structure */
pInfo = new ConVarInfo(); pInfo = new ConVarInfo();
pInfo->sourceMod = false; pInfo->sourceMod = false;
@@ -519,7 +430,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
pInfo->pVar = pConVar; pInfo->pVar = pConVar;
/* If we don't have a handle, then create a new one */ /* If we don't have a handle, then create a new one */
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE) if (hndl == BAD_HANDLE)
{ {
delete pInfo; delete pInfo;
@@ -577,7 +488,7 @@ void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction
/* If forward does not exist, create it */ /* If forward does not exist, create it */
if (!pForward) if (!pForward)
{ {
pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS); pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
pInfo->pChangeForward = pForward; pInfo->pChangeForward = pForward;
} }
@@ -613,11 +524,10 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
} }
/* If the forward now has 0 functions in it... */ /* If the forward now has 0 functions in it... */
if (pForward->GetFunctionCount() == 0 && if (pForward->GetFunctionCount() == 0)
!ConVarReentrancyGuard::IsCvarInChain(pConVar))
{ {
/* Free this forward */ /* Free this forward */
forwardsys->ReleaseForward(pForward); g_Forwards.ReleaseForward(pForward);
pInfo->pChangeForward = NULL; pInfo->pChangeForward = NULL;
} }
} }
@@ -625,35 +535,24 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl) QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
{ {
QueryCvarCookie_t cookie = 0; QueryCvarCookie_t cookie;
#if SOURCE_ENGINE != SE_DARKMESSIAH
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */ /* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
if (m_bIsDLLQueryHooked) if (m_bIsDLLQueryHooked)
{ {
#if SOURCE_ENGINE == SE_DOTA
cookie = engine->StartQueryCvarValue(CEntityIndex(IndexOfEdict(pPlayer)), name);
#else
cookie = engine->StartQueryCvarValue(pPlayer, name); cookie = engine->StartQueryCvarValue(pPlayer, name);
#endif
} }
#if SOURCE_ENGINE != SE_DOTA
else if (m_bIsVSPQueryHooked) else if (m_bIsVSPQueryHooked)
{ {
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name); cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
} }
#endif
else else
{ {
return InvalidQueryCvarCookie; return InvalidQueryCvarCookie;
} }
if (pCallback != NULL) ConVarQuery query = {cookie, pCallback, hndl};
{ m_ConVarQueries.push_back(query);
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
m_ConVarQueries.push_back(query);
}
#endif
return cookie; return cookie;
} }
@@ -665,7 +564,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
bool inserted = false; bool inserted = false;
const char *orig = pConVar->GetName(); const char *orig = pConVar->GetName();
IPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext()); IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
/* Check plugin for an existing convar list */ /* Check plugin for an existing convar list */
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList)) if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
@@ -696,7 +595,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
} }
} }
#if SOURCE_ENGINE >= SE_ORANGEBOX #if defined ORANGEBOX_BUILD
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue) void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
#else #else
void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue) void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
@@ -724,7 +623,7 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
i != pInfo->changeListeners.end(); i != pInfo->changeListeners.end();
i++) i++)
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX #if defined ORANGEBOX_BUILD
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue); (*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
#else #else
(*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue)); (*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
@@ -734,8 +633,6 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
if (pForward != NULL) if (pForward != NULL)
{ {
ConVarReentrancyGuard guard(pConVar);
/* Now call forwards in plugins that have hooked this */ /* Now call forwards in plugins that have hooked this */
pForward->PushCell(pInfo->handle); pForward->PushCell(pInfo->handle);
pForward->PushString(oldValue); pForward->PushString(oldValue);
@@ -749,20 +646,8 @@ bool ConVarManager::IsQueryingSupported()
return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked); return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
} }
#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) void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
#endif // SE_DOTA
{ {
#if SOURCE_ENGINE == SE_CSGO
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
{
return;
}
#endif
IPluginFunction *pCallback = NULL; IPluginFunction *pCallback = NULL;
cell_t value = 0; cell_t value = 0;
List<ConVarQuery>::iterator iter; List<ConVarQuery>::iterator iter;
@@ -783,11 +668,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
cell_t ret; cell_t ret;
pCallback->PushCell(cookie); pCallback->PushCell(cookie);
#if SOURCE_ENGINE == SE_DOTA pCallback->PushCell(engine->IndexOfEdict(pPlayer));
pCallback->PushCell(player.Get());
#else
pCallback->PushCell(IndexOfEdict(pPlayer));
#endif
pCallback->PushCell(result); pCallback->PushCell(result);
pCallback->PushString(cvarName); pCallback->PushString(cvarName);
@@ -806,14 +687,13 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
m_ConVarQueries.erase(iter); m_ConVarQueries.erase(iter);
} }
} }
#endif
HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar) HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
{ {
ConVarInfo *pInfo; ConVarInfo *pInfo;
HandleError error; HandleError error;
if ((error = handlesys->ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None) if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
{ {
return error; return error;
} }
+4 -25
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -39,15 +39,8 @@
#include <IForwardSys.h> #include <IForwardSys.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include <IPlayerHelpers.h>
#include <compat_wrappers.h> #include <compat_wrappers.h>
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include "PlayerManager.h"
#if SOURCE_ENGINE == SE_DARKMESSIAH
class EQueryCvarValueStatus;
typedef int QueryCvarCookie_t;
#endif
using namespace SourceHook; using namespace SourceHook;
@@ -67,11 +60,6 @@ struct ConVarInfo
IChangeableForward *pChangeForward; /**< Forward associated with convar */ IChangeableForward *pChangeForward; /**< Forward associated with convar */
ConVar *pVar; /**< The actual convar */ ConVar *pVar; /**< The actual convar */
List<IConVarChangeListener *> changeListeners; List<IConVarChangeListener *> changeListeners;
static inline bool matches(const char *name, const ConVarInfo *info)
{
return strcmp(name, info->pVar->GetName()) == 0;
}
}; };
/** /**
@@ -82,7 +70,6 @@ struct ConVarQuery
QueryCvarCookie_t cookie; /**< Cookie that identifies query */ QueryCvarCookie_t cookie; /**< Cookie that identifies query */
IPluginFunction *pCallback; /**< Function that will be called when query is finished */ IPluginFunction *pCallback; /**< Function that will be called when query is finished */
cell_t value; /**< Optional value passed to query function */ cell_t value; /**< Optional value passed to query function */
cell_t client; /**< Only used for cleaning up on client disconnection */
}; };
class ConVarManager : class ConVarManager :
@@ -90,8 +77,7 @@ class ConVarManager :
public IHandleTypeDispatch, public IHandleTypeDispatch,
public IPluginsListener, public IPluginsListener,
public IRootConsoleCommand, public IRootConsoleCommand,
public IConCommandTracker, public IConCommandTracker
public IClientListener
{ {
public: public:
ConVarManager(); ConVarManager();
@@ -110,8 +96,6 @@ public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command); void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
public: //IConCommandTracker public: //IConCommandTracker
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe); void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
public: //IClientListener
void OnClientDisconnected(int client);
public: public:
/** /**
* Create a convar and return a handle to it. * Create a convar and return a handle to it.
@@ -156,7 +140,7 @@ private:
/** /**
* Static callback that Valve's ConVar object executes when the convar's value changes. * Static callback that Valve's ConVar object executes when the convar's value changes.
*/ */
#if SOURCE_ENGINE >= SE_ORANGEBOX #if defined ORANGEBOX_BUILD
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue); static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
#else #else
static void OnConVarChanged(ConVar *pConVar, const char *oldValue); static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
@@ -165,13 +149,8 @@ private:
/** /**
* Callback for when StartQueryCvarValue() has finished. * 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, void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue); const char *cvarName, const char *cvarValue);
#endif
private: private:
HandleType_t m_ConVarType; HandleType_t m_ConVarType;
List<ConVarInfo *> m_ConVars; List<ConVarInfo *> m_ConVars;
-739
View File
@@ -1,739 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* 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$
*/
/**
* On SourceHook v4.3 or lower, there are no DVP hooks. Very sad, right?
* Only do this on newer versions. For the older code, we'll do an incredibly
* hacky detour.
*
* The idea of the "non-hacky" (yeah... no) code is that every unique
* ConCommand vtable gets its own DVP hook. We watch for unloading and
* loading commands to remove stale hooks from SH.
*/
#include "sourcemod.h"
#include "sourcemm_api.h"
#include "Logger.h"
#include "compat_wrappers.h"
#include "ConsoleDetours.h"
#include <IGameConfigs.h>
#include "sm_stringutil.h"
#include "ConCmdManager.h"
#include "HalfLife2.h"
#include "ConCommandBaseIterator.h"
#include "logic_bridge.h"
#include <am-utility.h>
#if defined PLATFORM_POSIX
# include <dlfcn.h>
# include <sys/mman.h>
# include <stdint.h>
# 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
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>);
#endif
#if SH_IMPL_VERSION >= 4
class GenericCommandHooker : public IConCommandLinkListener
{
struct HackInfo
{
void **vtable;
int hook;
unsigned int refcount;
};
CVector<HackInfo> vtables;
bool enabled;
SourceHook::MemFuncInfo dispatch;
inline void **GetVirtualTable(ConCommandBase *pBase)
{
return *reinterpret_cast<void***>(reinterpret_cast<char*>(pBase) +
dispatch.thisptroffs +
dispatch.vtbloffs);
}
inline bool FindVtable(void **ptr, size_t& index)
{
for (size_t i = 0; i < vtables.size(); i++)
{
if (vtables[i].vtable == ptr)
{
index = i;
return true;
}
}
return false;
}
void MakeHookable(ConCommandBase *pBase)
{
if (!pBase->IsCommand())
return;
ConCommand *cmd = (ConCommand*)pBase;
void **vtable = GetVirtualTable(cmd);
size_t index;
if (!FindVtable(vtable, index))
{
HackInfo hack;
hack.vtable = vtable;
hack.hook = SH_ADD_VPHOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &GenericCommandHooker::Dispatch), false);
hack.refcount = 1;
vtables.push_back(hack);
}
else
{
vtables[index].refcount++;
}
}
# if SOURCE_ENGINE == SE_DOTA
void Dispatch(const CCommandContext &context, const CCommand& args)
# elif SOURCE_ENGINE >= SE_ORANGEBOX
void Dispatch(const CCommand& args)
# else
void Dispatch()
# endif
{
cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand)
# if SOURCE_ENGINE >= SE_ORANGEBOX
, args
# endif
);
if (res >= Pl_Handled)
RETURN_META(MRES_SUPERCEDE);
}
void ReparseCommandList()
{
for (size_t i = 0; i < vtables.size(); i++)
vtables[i].refcount = 0;
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
MakeHookable(iter.Get());
CVector<HackInfo>::iterator iter = vtables.begin();
while (iter != vtables.end())
{
if ((*iter).refcount)
{
iter++;
continue;
}
/* Damn it. This event happens AFTER the plugin has unloaded!
* There's two options. Remove the hook now and hope SH's memory
* protection will prevent a crash. Otherwise, we can wait until
* the server shuts down and more likely crash then.
*
* This situation only arises if:
* 1) Someone has used AddCommandFilter()
* 2) ... on a Dark Messiah server (mm:s new api)
* 3) ... and another MM:S plugin that uses ConCommands has unloaded.
*
* Even though the impact is really small, we'll wait until the
* server shuts down, so normal operation isn't interrupted.
*
* See bug 4018.
*/
iter = vtables.erase(iter);
}
}
void UnhookCommand(ConCommandBase *pBase)
{
if (!pBase->IsCommand())
return;
ConCommand *cmd = (ConCommand*)pBase;
void **vtable = GetVirtualTable(cmd);
size_t index;
if (!FindVtable(vtable, index))
{
g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
return;
}
assert(vtables[index].refcount > 0);
vtables[index].refcount--;
if (vtables[index].refcount == 0)
{
SH_REMOVE_HOOK_ID(vtables[index].hook);
vtables.erase(vtables.iterAt(index));
}
}
public:
GenericCommandHooker() : enabled(false)
{
}
bool Enable()
{
SourceHook::GetFuncInfo(&ConCommand::Dispatch, dispatch);
if (dispatch.thisptroffs < 0)
{
g_Logger.LogError("Command filter could not determine ConCommand layout");
return false;
}
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
MakeHookable(iter.Get());
if (!vtables.size())
{
g_Logger.LogError("Command filter could not find any cvars!");
return false;
}
enabled = true;
return true;
}
void Disable()
{
for (size_t i = 0; i < vtables.size(); i++)
SH_REMOVE_HOOK_ID(vtables[i].hook);
vtables.clear();
}
virtual void OnLinkConCommand(ConCommandBase *pBase)
{
if (!enabled)
return;
MakeHookable(pBase);
}
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
{
if (!enabled)
return;
if (pBase == NULL)
ReparseCommandList();
else
UnhookCommand(pBase);
}
};
/**
* 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.
*/
#define FEATURECAP_COMMANDLISTENER "command listener"
static GenericCommandHooker s_GenericHooker;
ConsoleDetours g_ConsoleDetours;
ConsoleDetours::ConsoleDetours() : status(FeatureStatus_Unknown)
{
}
void ConsoleDetours::OnSourceModAllInitialized()
{
m_pForward = forwardsys->CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
sharesys->AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
}
void ConsoleDetours::OnSourceModShutdown()
{
for (StringHashMap<IChangeableForward *>::iterator iter = m_Listeners.iter();
!iter.empty();
iter.next())
{
forwardsys->ReleaseForward(iter->value);
}
forwardsys->ReleaseForward(m_pForward);
s_GenericHooker.Disable();
}
FeatureStatus ConsoleDetours::GetFeatureStatus(FeatureType type, const char *name)
{
return GetStatus();
}
FeatureStatus ConsoleDetours::GetStatus()
{
if (status == FeatureStatus_Unknown)
{
status = s_GenericHooker.Enable() ? FeatureStatus_Available : FeatureStatus_Unavailable;
}
return status;
}
bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
{
if (GetStatus() != FeatureStatus_Available)
return false;
if (command == NULL)
{
m_pForward->AddFunction(fun);
}
else
{
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
IChangeableForward *forward;
if (!m_Listeners.retrieve(str, &forward))
{
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
m_Listeners.insert(str, forward);
}
forward->AddFunction(fun);
}
return true;
}
bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
{
if (command == NULL)
{
return m_pForward->RemoveFunction(fun);
}
else
{
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
IChangeableForward *forward;
if (!m_Listeners.retrieve(str, &forward))
return false;
return forward->RemoveFunction(fun);
}
}
cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
{
char name[255];
const char *realname = args.Arg(0);
size_t len = strlen(realname);
// Disallow command strings that are too long, for now.
if (len >= sizeof(name) - 1)
return Pl_Continue;
for (size_t i = 0; i < len; i++)
{
if (realname[i] >= 'A' && realname[i] <= 'Z')
name[i] = tolower(realname[i]);
else
name[i] = realname[i];
}
name[len] = '\0';
cell_t result = Pl_Continue;
m_pForward->PushCell(client);
m_pForward->PushString(name);
m_pForward->PushCell(args.ArgC() - 1);
m_pForward->Execute(&result, NULL);
/* Don't let plugins block this. */
if (strcmp(name, "sm") == 0)
result = Pl_Continue;
if (result >= Pl_Handled)
return result;
IChangeableForward *forward;
if (!m_Listeners.retrieve(name, &forward))
return result;
if (forward->GetFunctionCount() == 0)
return result;
cell_t result2 = Pl_Continue;
forward->PushCell(client);
forward->PushString(name);
forward->PushCell(args.ArgC() - 1);
forward->Execute(&result2, NULL);
if (result2 > result)
result = result2;
/* "sm" should not have flown through the above. */
assert(strcmp(name, "sm") != 0 || result == Pl_Continue);
return result;
}
#if SOURCE_ENGINE >= SE_ORANGEBOX
cell_t ConsoleDetours::Dispatch(ConCommand *pBase, const CCommand& args)
{
#else
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)
{
/* 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);
}
else
{
/* Make sure the command gets invoked. See bug 4019 on making this better. */
pBase->Dispatch();
}
#endif
return res;
}
-78
View File
@@ -1,78 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* 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_CONSOLE_DETOURS_H_
#define _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
#include "sm_globals.h"
#include "sourcemm_api.h"
#include <IForwardSys.h>
#include <sm_stringhashmap.h>
class ConsoleDetours :
public SMGlobalClass,
public IFeatureProvider
{
friend class PlayerManager;
friend class GenericCommandHooker;
public:
ConsoleDetours();
public: //SMGlobalClass
void OnSourceModAllInitialized();
void OnSourceModShutdown();
public: //IFeatureProvider
FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
public:
bool AddListener(IPluginFunction *fun, const char *command);
bool RemoveListener(IPluginFunction *fun, const char *command);
private:
cell_t InternalDispatch(int client, const CCommand& args);
#if SOURCE_ENGINE >= SE_ORANGEBOX
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
#else
static cell_t Dispatch(ConCommand *pBase);
#endif
public:
FeatureStatus GetStatus();
bool IsEnabled()
{
return status == FeatureStatus_Available;
}
private:
FeatureStatus status;
IChangeableForward *m_pForward;
StringHashMap<IChangeableForward *> m_Listeners;
};
extern ConsoleDetours g_ConsoleDetours;
#endif /* _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_ */
+62 -124
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,16 +34,16 @@
#include "sourcemod.h" #include "sourcemod.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include "sm_version.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "LibrarySys.h" #include "LibrarySys.h"
#include "Logger.h" #include "Logger.h"
#include "frame_hooks.h" #include "PluginSys.h"
#include "logic_bridge.h" #include "ForwardSys.h"
#include <sourcemod_version.h>
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file"); ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
#elif defined PLATFORM_LINUX || defined PLATFORM_APPLE #elif defined PLATFORM_LINUX
ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file"); ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file");
#endif #endif
@@ -60,40 +60,30 @@ ConVar *g_ServerCfgFile = NULL;
void CheckAndFinalizeConfigs(); void CheckAndFinalizeConfigs();
#if SOURCE_ENGINE == SE_DOTA #if defined ORANGEBOX_BUILD
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
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
void Hook_ExecDispatchPre(const CCommand &cmd) void Hook_ExecDispatchPre(const CCommand &cmd)
#elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
void Hook_ExecDispatchPre()
#else #else
# if SH_IMPL_VERSION >= 4 extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
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>); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
void Hook_ExecDispatchPre() void Hook_ExecDispatchPre()
#endif #endif
{ {
#if SOURCE_ENGINE <= SE_DARKMESSIAH #if !defined ORANGEBOX_BUILD
CCommand cmd; CCommand cmd;
#endif #endif
const char *arg = cmd.Arg(1); const char *arg = cmd.Arg(1);
if (!g_bServerExecd && arg != NULL && strcmp(arg, g_ServerCfgFile->GetString()) == 0) if (!g_bServerExecd
&& arg != NULL
&& strcmp(arg, g_ServerCfgFile->GetString()) == 0)
{ {
g_bGotTrigger = true; g_bGotTrigger = true;
} }
} }
#if SOURCE_ENGINE == SE_DOTA #if defined ORANGEBOX_BUILD
void Hook_ExecDispatchPost(const CCommandContext &context, const CCommand &cmd)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void Hook_ExecDispatchPost(const CCommand &cmd) void Hook_ExecDispatchPost(const CCommand &cmd)
#else #else
void Hook_ExecDispatchPost() void Hook_ExecDispatchPost()
@@ -109,39 +99,34 @@ void Hook_ExecDispatchPost()
void CheckAndFinalizeConfigs() void CheckAndFinalizeConfigs()
{ {
if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart) if ((g_bServerExecd || g_ServerCfgFile == NULL)
&& g_bGotServerStart)
{ {
g_PendingInternalPush = true; /* 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");
} }
} }
void CoreConfig::OnSourceModAllInitialized() void CoreConfig::OnSourceModAllInitialized()
{ {
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this); g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL); g_pOnServerCfg = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL); g_pOnConfigsExecuted = g_Forwards.CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL); g_pOnAutoConfigsBuffered = g_Forwards.CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
}
CoreConfig::CoreConfig()
{
}
CoreConfig::~CoreConfig()
{
} }
void CoreConfig::OnSourceModShutdown() void CoreConfig::OnSourceModShutdown()
{ {
g_RootMenu.RemoveRootConsoleCommand("config", this); g_RootMenu.RemoveRootConsoleCommand("config", this);
forwardsys->ReleaseForward(g_pOnServerCfg); g_Forwards.ReleaseForward(g_pOnServerCfg);
forwardsys->ReleaseForward(g_pOnConfigsExecuted); g_Forwards.ReleaseForward(g_pOnConfigsExecuted);
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered); g_Forwards.ReleaseForward(g_pOnAutoConfigsBuffered);
if (g_pExecPtr != NULL) if (g_pExecPtr != NULL)
{ {
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false); SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true); SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
g_pExecPtr = NULL; g_pExecPtr = NULL;
} }
} }
@@ -152,22 +137,24 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName)
if (!already_checked) if (!already_checked)
{ {
if (engine->IsDedicatedServer()) g_ServerCfgFile = icvar->FindVar("servercfgfile");
{
g_ServerCfgFile = icvar->FindVar("servercfgfile");
}
else
{
g_ServerCfgFile = icvar->FindVar("lservercfgfile");
}
if (g_ServerCfgFile != NULL) if (g_ServerCfgFile != NULL)
{ {
g_pExecPtr = FindCommand("exec"); ConCommandBase *pBase = icvar->GetCommands();
while (pBase != NULL)
{
if (pBase->IsCommand() && strcmp(pBase->GetName(), "exec") == 0)
{
break;
}
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
}
g_pExecPtr = (ConCommand *)pBase;
if (g_pExecPtr != NULL) if (g_pExecPtr != NULL)
{ {
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false); SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true); SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
} }
else else
{ {
@@ -197,30 +184,17 @@ void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &comma
if (res == ConfigResult_Reject) if (res == ConfigResult_Reject)
{ {
g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\". (%s)", option, value, error); g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\" (%s)", option, value, error);
} else if (res == ConfigResult_Ignore) { } else if (res == ConfigResult_Ignore) {
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option); g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
} else { } else {
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" successfully set to \"%s\".", option, value); g_RootMenu.ConsolePrint("Config option \"%s\" successfully set to \"%s.\"", option, value);
} }
return;
} else if (argcount >= 3) {
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);
} else {
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" is set to \"%s\".", option, value);
}
return; return;
} }
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> [value]"); g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
} }
void CoreConfig::Initialize() void CoreConfig::Initialize()
@@ -231,31 +205,14 @@ void CoreConfig::Initialize()
/* Try to get command line value of core config convar */ /* Try to get command line value of core config convar */
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile"); const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
/* If sm_corecfgfile is on the command line, use that /* If sm_corecfgfile not specified on command line, use default value */
* If sm_corecfgfile isn't there, check sm_basepath on the command line and build the path off that if (!corecfg)
* If sm_basepath isn't there, just use the default path for the cfg
*/
if (corecfg)
{ {
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg); corecfg = sm_corecfgfile.GetDefault();
}
else
{
const char *basepath = icvar->GetCommandLineValue("sm_basepath");
/* Format path to config file */
if (basepath)
{
g_LibSys.PathFormat(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());
}
} }
/* Reset cached key values */ /* Format path to config file */
m_KeyValues.clear(); g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
/* Parse config file */ /* Parse config file */
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay) if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
@@ -295,20 +252,9 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
pBase = pBase->m_pGlobalClassNext; pBase = pBase->m_pGlobalClassNext;
} }
ke::AString vstr(value);
m_KeyValues.replace(option, ke::Move(vstr));
return ConfigResult_Ignore; return ConfigResult_Ignore;
} }
const char *CoreConfig::GetCoreConfigValue(const char *key)
{
StringHashMap<ke::AString>::Result r = m_KeyValues.find(key);
if (!r.found())
return NULL;
return r->value.chars();
}
bool SM_AreConfigsExecuted() bool SM_AreConfigsExecuted()
{ {
return g_bConfigsExecd; return g_bConfigsExecd;
@@ -318,12 +264,12 @@ inline bool IsPathSepChar(char c)
{ {
#if defined PLATFORM_WINDOWS #if defined PLATFORM_WINDOWS
return (c == '\\' || c == '/'); return (c == '\\' || c == '/');
#elif defined PLATFORM_LINUX || defined PLATFORM_POSIX #elif defined PLATFORM_LINUX
return (c == '/'); return (c == '/');
#endif #endif
} }
bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create) bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
{ {
bool will_create = false; bool will_create = false;
@@ -410,7 +356,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
FILE *fp = fopen(file, "wt"); FILE *fp = fopen(file, "wt");
if (fp) if (fp)
{ {
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SOURCEMOD_VERSION); fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SVN_FULL_VERSION);
fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename()); fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
fprintf(fp, "\n\n"); fprintf(fp, "\n\n");
@@ -467,11 +413,6 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
can_create = false; can_create = false;
fclose(fp); fclose(fp);
} }
else
{
g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
return can_create;
}
} }
} }
@@ -502,10 +443,10 @@ void SM_DoSingleExecFwds(IPluginContext *ctx)
void SM_ConfigsExecuted_Plugin(unsigned int serial) void SM_ConfigsExecuted_Plugin(unsigned int serial)
{ {
IPluginIterator *iter = scripts->GetPluginIterator(); IPluginIterator *iter = g_PluginSys.GetPluginIterator();
while (iter->MorePlugins()) while (iter->MorePlugins())
{ {
IPlugin *plugin = iter->GetPlugin(); CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
if (plugin->GetSerial() == serial) if (plugin->GetSerial() == serial)
{ {
SM_DoSingleExecFwds(plugin->GetBaseContext()); SM_DoSingleExecFwds(plugin->GetBaseContext());
@@ -518,7 +459,7 @@ void SM_ConfigsExecuted_Plugin(unsigned int serial)
void SM_ExecuteForPlugin(IPluginContext *ctx) void SM_ExecuteForPlugin(IPluginContext *ctx)
{ {
SMPlugin *plugin = scripts->FindPluginByContext(ctx->GetContext()); CPlugin *plugin = (CPlugin *)g_PluginSys.GetPluginByCtx(ctx->GetContext());
unsigned int num = plugin->GetConfigCount(); unsigned int num = plugin->GetConfigCount();
if (!num) if (!num)
@@ -547,17 +488,23 @@ void SM_ExecuteAllConfigs()
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n"); engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
AutoPluginList plugins(scripts); IPluginIterator *iter = g_PluginSys.GetPluginIterator();
for (size_t i = 0; i < plugins->size(); i++) while (iter->MorePlugins())
{ {
SMPlugin *plugin = plugins->at(i); CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
unsigned int num = plugin->GetConfigCount(); unsigned int num = plugin->GetConfigCount();
bool can_create = true; bool can_create = true;
for (unsigned int i=0; i<num; i++) for (unsigned int i=0; i<num; i++)
{ {
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create); can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
} }
iter->NextPlugin();
} }
iter->Release();
#if defined ORANGEBOX_BUILD
engine->ServerExecute();
#endif
g_bGotServerStart = true; g_bGotServerStart = true;
CheckAndFinalizeConfigs(); CheckAndFinalizeConfigs();
@@ -575,12 +522,3 @@ void SM_ConfigsExecuted_Global()
g_pOnServerCfg->Execute(NULL); g_pOnServerCfg->Execute(NULL);
g_pOnConfigsExecuted->Execute(NULL); g_pOnConfigsExecuted->Execute(NULL);
} }
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");
g_PendingInternalPush = false;
}
+2 -11
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -35,8 +35,6 @@
#include "sm_globals.h" #include "sm_globals.h"
#include <ITextParsers.h> #include <ITextParsers.h>
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include <am-string.h>
#include <sm_stringhashmap.h>
using namespace SourceMod; using namespace SourceMod;
@@ -45,9 +43,6 @@ class CoreConfig :
public ITextListener_SMC, public ITextListener_SMC,
public IRootConsoleCommand public IRootConsoleCommand
{ {
public:
CoreConfig();
~CoreConfig();
public: // SMGlobalClass public: // SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown(); void OnSourceModShutdown();
@@ -61,14 +56,11 @@ public:
* Initializes CoreConfig by reading from core.cfg file * Initializes CoreConfig by reading from core.cfg file
*/ */
void Initialize(); void Initialize();
const char *GetCoreConfigValue(const char *key);
private: private:
/** /**
* Sets configuration option by notifying SourceMod components that rely on core.cfg * Sets configuration option by notifying SourceMod components that rely on core.cfg
*/ */
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength); ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
private:
StringHashMap<ke::AString> m_KeyValues;
}; };
extern bool SM_AreConfigsExecuted(); extern bool SM_AreConfigsExecuted();
@@ -76,7 +68,6 @@ extern void SM_ExecuteAllConfigs();
extern void SM_ExecuteForPlugin(IPluginContext *ctx); extern void SM_ExecuteForPlugin(IPluginContext *ctx);
extern void SM_ConfigsExecuted_Global(); extern void SM_ConfigsExecuted_Global();
extern void SM_ConfigsExecuted_Plugin(unsigned int serial); extern void SM_ConfigsExecuted_Plugin(unsigned int serial);
extern void SM_InternalCmdTrigger();
extern CoreConfig g_CoreConfig; extern CoreConfig g_CoreConfig;
+121 -152
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -30,12 +30,14 @@
*/ */
#include "Database.h" #include "Database.h"
#include "ISourceMod.h"
#include "HandleSys.h" #include "HandleSys.h"
#include "ShareSys.h"
#include "sourcemod.h"
#include "sm_stringutil.h"
#include "Logger.h"
#include "ExtensionSys.h" #include "ExtensionSys.h"
#include "PluginSys.h"
#include <stdlib.h> #include <stdlib.h>
#include <IThreader.h> #include "ThreadSupport.h"
#define DBPARSE_LEVEL_NONE 0 #define DBPARSE_LEVEL_NONE 0
#define DBPARSE_LEVEL_MAIN 1 #define DBPARSE_LEVEL_MAIN 1
@@ -45,18 +47,10 @@ DBManager g_DBMan;
static bool s_OneTimeThreaderErrorMsg = false; static bool s_OneTimeThreaderErrorMsg = false;
DBManager::DBManager() DBManager::DBManager()
: m_Terminate(false), : m_StrTab(512), m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
m_ParseLevel(0),
m_ParseState(0),
m_pDefault(NULL)
{ {
} }
static void FrameHook(bool simulating)
{
g_DBMan.RunFrame();
}
void DBManager::OnSourceModAllInitialized() void DBManager::OnSourceModAllInitialized()
{ {
HandleAccess sec; HandleAccess sec;
@@ -70,11 +64,13 @@ void DBManager::OnSourceModAllInitialized()
g_ShareSys.AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg"); g_SourceMod.BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
m_pConfigLock = g_pThreader->MakeMutex();
m_pThinkLock = g_pThreader->MakeMutex();
m_pQueueLock = g_pThreader->MakeMutex();
g_PluginSys.AddPluginsListener(this); g_PluginSys.AddPluginsListener(this);
g_pSM->AddGameFrameHook(&FrameHook);
} }
void DBManager::OnSourceModLevelChange(const char *mapName) void DBManager::OnSourceModLevelChange(const char *mapName)
@@ -86,26 +82,28 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
* This way the thread's search won't be searching through a * This way the thread's search won't be searching through a
* potentially empty/corrupt list, which would be very bad. * potentially empty/corrupt list, which would be very bad.
*/ */
ke::AutoLock lock(&m_ConfigLock); m_pConfigLock->Lock();
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay) if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
{ {
smcore.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename); g_Logger.LogError("[SM] Detected parse error(s) in file \"%s\"", m_Filename);
if (err != SMCError_Custom) if (err != SMCError_Custom)
{ {
const char *txt = textparsers->GetSMCErrorString(err); const char *txt = textparsers->GetSMCErrorString(err);
smcore.LogError("[SM] Line %d: %s", states.line, txt); g_Logger.LogError("[SM] Line %d: %s", states.line, txt);
} }
} }
m_pConfigLock->Unlock();
} }
void DBManager::OnSourceModShutdown() void DBManager::OnSourceModShutdown()
{ {
g_pSM->RemoveGameFrameHook(&FrameHook);
KillWorkerThread(); KillWorkerThread();
g_PluginSys.RemovePluginsListener(this); g_PluginSys.RemovePluginsListener(this);
m_pConfigLock->DestroyThis();
m_pThinkLock->DestroyThis();
m_pQueueLock->DestroyThis();
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent); g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent); g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
ClearConfigs();
} }
unsigned int DBManager::GetInterfaceVersion() unsigned int DBManager::GetInterfaceVersion()
@@ -135,20 +133,13 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
void DBManager::ReadSMC_ParseStart() void DBManager::ReadSMC_ParseStart()
{ {
ClearConfigs(); m_confs.clear();
m_ParseLevel = 0; m_ParseLevel = 0;
m_ParseState = DBPARSE_LEVEL_NONE; m_ParseState = DBPARSE_LEVEL_NONE;
m_StrTab.Reset();
m_DefDriver.clear(); 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; ConfDbInfo s_CurInfo;
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name) SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
{ {
@@ -168,7 +159,7 @@ SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *nam
} }
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) { } else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
s_CurInfo = ConfDbInfo(); s_CurInfo = ConfDbInfo();
s_CurInfo.name = name; s_CurInfo.name = m_StrTab.AddString(name);
m_ParseState = DBPARSE_LEVEL_DATABASE; m_ParseState = DBPARSE_LEVEL_DATABASE;
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) { } else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
m_ParseLevel++; m_ParseLevel++;
@@ -195,16 +186,16 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
{ {
if (strcmp(value, "default") != 0) if (strcmp(value, "default") != 0)
{ {
s_CurInfo.driver = value; s_CurInfo.driver = m_StrTab.AddString(value);
} }
} else if (strcmp(key, "database") == 0) { } else if (strcmp(key, "database") == 0) {
s_CurInfo.database = value; s_CurInfo.database = m_StrTab.AddString(value);
} else if (strcmp(key, "host") == 0) { } else if (strcmp(key, "host") == 0) {
s_CurInfo.host = value; s_CurInfo.host = m_StrTab.AddString(value);
} else if (strcmp(key, "user") == 0) { } else if (strcmp(key, "user") == 0) {
s_CurInfo.user = value; s_CurInfo.user = m_StrTab.AddString(value);
} else if (strcmp(key, "pass") == 0) { } else if (strcmp(key, "pass") == 0) {
s_CurInfo.pass = value; s_CurInfo.pass = m_StrTab.AddString(value);
} else if (strcmp(key, "timeout") == 0) { } else if (strcmp(key, "timeout") == 0) {
s_CurInfo.info.maxTimeout = atoi(value); s_CurInfo.info.maxTimeout = atoi(value);
} else if (strcmp(key, "port") == 0) { } else if (strcmp(key, "port") == 0) {
@@ -215,6 +206,13 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
return SMCResult_Continue; return SMCResult_Continue;
} }
#define ASSIGN_VAR(var) \
if (s_CurInfo.var == -1) { \
s_CurInfo.info.var = ""; \
} else { \
s_CurInfo.info.var = m_StrTab.GetString(s_CurInfo.var); \
}
SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states) SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
{ {
if (m_ParseLevel) if (m_ParseLevel)
@@ -225,26 +223,17 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
if (m_ParseState == DBPARSE_LEVEL_DATABASE) if (m_ParseState == DBPARSE_LEVEL_DATABASE)
{ {
ConfDbInfo *cdb = new ConfDbInfo(); /* Set all of the info members to either a blank string
* or the string pointer from the string table.
cdb->name = s_CurInfo.name; */
cdb->driver = s_CurInfo.driver; ASSIGN_VAR(driver);
cdb->host = s_CurInfo.host; ASSIGN_VAR(database);
cdb->user = s_CurInfo.user; ASSIGN_VAR(host);
cdb->pass = s_CurInfo.pass; ASSIGN_VAR(user);
cdb->database = s_CurInfo.database; ASSIGN_VAR(pass);
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.. */ /* Save it.. */
m_confs.push_back(cdb); m_confs.push_back(s_CurInfo);
/* Go up one level */ /* Go up one level */
m_ParseState = DBPARSE_LEVEL_MAIN; m_ParseState = DBPARSE_LEVEL_MAIN;
@@ -255,6 +244,7 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
return SMCResult_Continue; return SMCResult_Continue;
} }
#undef ASSIGN_VAR
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed) void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
{ {
@@ -271,7 +261,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
*pdr = NULL; *pdr = NULL;
} }
*pdb = NULL; *pdb = NULL;
g_pSM->Format(error, maxlength, "Configuration \"%s\" not found", name); UTIL_Format(error, maxlength, "Configuration \"%s\" not found", name);
return false; return false;
} }
@@ -308,7 +298,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
} }
*pdb = NULL; *pdb = NULL;
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname); UTIL_Format(error, maxlength, "Driver \"%s\" not found", dname);
return false; return false;
} }
@@ -343,22 +333,16 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
} }
/* Make sure NOTHING references this! */ /* Make sure NOTHING references this! */
List<ConfDbInfo *>::iterator iter; List<ConfDbInfo>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++) for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
{ {
ConfDbInfo &db = *(*iter); ConfDbInfo &db = (*iter);
if (db.realDriver == pDriver) if (db.realDriver == pDriver)
{ {
db.realDriver = NULL; db.realDriver = NULL;
} }
} }
/* Someone unloaded the default driver? Silly.. */
if (pDriver == m_pDefault)
{
m_pDefault = NULL;
}
/* Now that the driver is gone, we have to test the think queue. /* Now that the driver is gone, we have to test the think queue.
* Whatever happens therein is up to the db op! * Whatever happens therein is up to the db op!
*/ */
@@ -464,12 +448,12 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
ConfDbInfo *DBManager::GetDatabaseConf(const char *name) ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
{ {
List<ConfDbInfo *>::iterator iter; List<ConfDbInfo>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++) for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
{ {
ConfDbInfo &conf = *(*iter); ConfDbInfo &conf = (*iter);
if (conf.name == name) if (strcmp(m_StrTab.GetString(conf.name), name) == 0)
{ {
return &conf; return &conf;
} }
@@ -490,7 +474,7 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
} }
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
g_pSM->Format(filename, sizeof(filename), "dbi.%s.ext", name); UTIL_Format(filename, sizeof(filename), "dbi.%s.ext", name);
IExtension *pExt = g_Extensions.LoadAutoExtension(filename); IExtension *pExt = g_Extensions.LoadAutoExtension(filename);
if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size) if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size)
@@ -511,17 +495,12 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
void DBManager::KillWorkerThread() void DBManager::KillWorkerThread()
{ {
if (m_Worker) if (m_pWorker)
{ {
{ m_pWorker->Stop(false);
ke::AutoLock lock(&m_QueueEvent); g_pThreader->DestroyWorker(m_pWorker);
m_Terminate = true; m_pWorker = NULL;
m_QueueEvent.Notify();
}
m_Worker->Join();
m_Worker = NULL;
s_OneTimeThreaderErrorMsg = false; s_OneTimeThreaderErrorMsg = false;
m_Terminate = false;
} }
} }
@@ -534,106 +513,99 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
return false; return false;
} }
if (!m_Worker) if (!m_pWorker)
{ {
m_Worker = new ke::Thread(this, "SM SQL Worker"); m_pWorker = g_pThreader->MakeWorker(this, true);
if (!m_Worker->Succeeded()) if (!m_pWorker)
{ {
if (!s_OneTimeThreaderErrorMsg) if (!s_OneTimeThreaderErrorMsg)
{ {
smcore.LogError("[SM] Unable to create db threader (error unknown)"); g_Logger.LogError("[SM] Unable to create db threader (error unknown)");
s_OneTimeThreaderErrorMsg = true; s_OneTimeThreaderErrorMsg = true;
} }
m_Worker = NULL; return false;
}
if (!m_pWorker->Start())
{
if (!s_OneTimeThreaderErrorMsg)
{
g_Logger.LogError("[SM] Unable to start db threader (error unknown)");
s_OneTimeThreaderErrorMsg = true;
}
g_pThreader->DestroyWorker(m_pWorker);
m_pWorker = NULL;
return false; return false;
} }
} }
/* Add to the queue */ /* Add to the queue */
{ {
ke::AutoLock lock(&m_QueueEvent); m_pQueueLock->Lock();
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio); Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio);
queue.push(op); queue.push(op);
m_QueueEvent.Notify(); m_pQueueLock->Unlock();
} }
/* Make the thread */
m_pWorker->MakeThread(this);
return true; return true;
} }
void DBManager::Run() void DBManager::OnWorkerStart(IThreadWorker *pWorker)
{ {
// Initialize DB threadsafety. m_drSafety.clear();
for (size_t i=0; i < m_drivers.size(); i++) for (size_t i=0; i<m_drivers.size(); i++)
{ {
if (m_drivers[i]->IsThreadSafe()) if (m_drivers[i]->IsThreadSafe())
{
m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety()); m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety());
else } else {
m_drSafety.push_back(false); m_drSafety.push_back(false);
}
} }
}
// Run actual worker thread logic. void DBManager::OnWorkerStop(IThreadWorker *pWorker)
ThreadMain(); {
// Shutdown DB threadsafety.
for (size_t i=0; i<m_drivers.size(); i++) for (size_t i=0; i<m_drivers.size(); i++)
{ {
if (m_drSafety[i]) if (m_drSafety[i])
{
m_drivers[i]->ShutdownThreadSafety(); m_drivers[i]->ShutdownThreadSafety();
}
} }
m_drSafety.clear(); m_drSafety.clear();
} }
void DBManager::ThreadMain() void DBManager::RunThread(IThreadHandle *pThread)
{ {
ke::AutoLock lock(&m_QueueEvent); IDBThreadOperation *op = NULL;
while (true) { /* Get something from the queue */
// The lock has been acquired. Grab everything we can out of the {
// queue. Since we want to flush the queue even if we're terminated, m_pQueueLock->Lock();
// we process all operations we can before checking to terminate. Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
// There's no risk of starvation since the main thread blocks on us if (!queue.empty())
// terminating.
while (true)
{ {
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue(); op = queue.first();
if (queue.empty())
break;
IDBThreadOperation *op = queue.first();
queue.pop(); queue.pop();
// Unlock the queue when we run the query, so the main thread can
// keep pumping events. We re-acquire the lock to check for more
// items. It's okay if we terminate while unlocked; the main
// thread would be blocked and we'd need to flush the queue
// anyway, so after we've depleted the queue here, we'll just
// reach the terminate at the top of the loop.
{
ke::AutoUnlock unlock(&m_QueueEvent);
op->RunThreadPart();
ke::AutoLock lock(&m_ThinkLock);
m_ThinkQueue.push(op);
}
if (!m_Terminate)
{
ke::AutoUnlock unlock(&m_QueueEvent);
#ifdef _WIN32
Sleep(20);
#else
usleep(20000);
#endif
}
} }
m_pQueueLock->Unlock();
if (m_Terminate)
return;
// Release the lock and wait for a signal.
m_QueueEvent.Wait();
} }
/* whoa. hi. did we get something? we should have. */
if (!op)
{
/* wtf? */
return;
}
op->RunThreadPart();
m_pThinkLock->Lock();
m_ThinkQueue.push(op);
m_pThinkLock->Unlock();
} }
void DBManager::RunFrame() void DBManager::RunFrame()
@@ -645,16 +617,19 @@ void DBManager::RunFrame()
} }
/* Dump one thing per-frame so the server stays sane. */ /* Dump one thing per-frame so the server stays sane. */
IDBThreadOperation *op; m_pThinkLock->Lock();
{ IDBThreadOperation *op = m_ThinkQueue.first();
ke::AutoLock lock(&m_ThinkLock); m_ThinkQueue.pop();
op = m_ThinkQueue.first(); m_pThinkLock->Unlock();
m_ThinkQueue.pop();
}
op->RunThinkPart(); op->RunThinkPart();
op->Destroy(); op->Destroy();
} }
void DBManager::OnTerminate(IThreadHandle *pThread, bool cancel)
{
/* Do nothing */
}
void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken) void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
{ {
s_pAddBlock = pToken; s_pAddBlock = pToken;
@@ -730,21 +705,15 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
void DBManager::LockConfig() void DBManager::LockConfig()
{ {
m_ConfigLock.Lock(); m_pConfigLock->Lock();
} }
void DBManager::UnlockConfig() void DBManager::UnlockConfig()
{ {
m_ConfigLock.Unlock(); m_pConfigLock->Unlock();
} }
const char *DBManager::GetDefaultDriverName() const char *DBManager::GetDefaultDriverName()
{ {
return m_DefDriver.c_str(); return m_DefDriver.c_str();
} }
void DBManager::AddDependency(IExtension *myself, IDBDriver *driver)
{
g_Extensions.AddRawDependency(myself, driver->GetIdentity(), driver);
}
+28 -25
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -33,29 +33,30 @@
#define _INCLUDE_DATABASE_MANAGER_H_ #define _INCLUDE_DATABASE_MANAGER_H_
#include <IDBDriver.h> #include <IDBDriver.h>
#include "common_logic.h" #include "sm_globals.h"
#include <sh_vector.h> #include <sh_vector.h>
#include <sh_string.h> #include <sh_string.h>
#include <sh_list.h> #include <sh_list.h>
#include <ITextParsers.h> #include <ITextParsers.h>
#include "sm_memtable.h"
#include <IThreader.h> #include <IThreader.h>
#include <IPluginSys.h>
#include <am-thread-utils.h>
#include "sm_simple_prioqueue.h" #include "sm_simple_prioqueue.h"
#include "PluginSys.h"
using namespace SourceHook; using namespace SourceHook;
struct ConfDbInfo struct ConfDbInfo
{ {
ConfDbInfo() : realDriver(NULL) ConfDbInfo() : name(-1), driver(-1), host(-1), user(-1), pass(-1),
database(-1), realDriver(NULL)
{ {
} }
String name; int name;
String driver; int driver;
String host; int host;
String user; int user;
String pass; int pass;
String database; int database;
IDBDriver *realDriver; IDBDriver *realDriver;
DatabaseInfo info; DatabaseInfo info;
}; };
@@ -65,8 +66,9 @@ class DBManager :
public SMGlobalClass, public SMGlobalClass,
public IHandleTypeDispatch, public IHandleTypeDispatch,
public ITextListener_SMC, public ITextListener_SMC,
public IPluginsListener, public IThread,
public ke::IRunnable public IThreadWorkerCallbacks,
public IPluginsListener
{ {
public: public:
DBManager(); DBManager();
@@ -90,16 +92,18 @@ public: //IDBManager
Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken); Handle_t CreateHandle(DBHandleType type, void *ptr, IdentityToken_t *pToken);
HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr); HandleError ReadHandle(Handle_t hndl, DBHandleType type, void **ptr);
HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token); HandleError ReleaseHandle(Handle_t hndl, DBHandleType type, IdentityToken_t *token);
void AddDependency(IExtension *myself, IDBDriver *driver);
public: //ITextListener_SMC public: //ITextListener_SMC
void ReadSMC_ParseStart(); void ReadSMC_ParseStart();
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states); SMCResult ReadSMC_LeavingSection(const SMCStates *states);
void ReadSMC_ParseEnd(bool halted, bool failed); void ReadSMC_ParseEnd(bool halted, bool failed);
public: //ke::IRunnable public: //IThread
void Run(); void RunThread(IThreadHandle *pThread);
void ThreadMain(); void OnTerminate(IThreadHandle *pThread, bool cancel);
public: //IThreadWorkerCallbacks
void OnWorkerStart(IThreadWorker *pWorker);
void OnWorkerStop(IThreadWorker *pWorker);
public: //IPluginsListener public: //IPluginsListener
void OnPluginUnloaded(IPlugin *plugin); void OnPluginUnloaded(IPlugin *plugin);
public: public:
@@ -116,7 +120,6 @@ public:
return m_DatabaseType; return m_DatabaseType;
} }
private: private:
void ClearConfigs();
void KillWorkerThread(); void KillWorkerThread();
private: private:
CVector<IDBDriver *> m_drivers; CVector<IDBDriver *> m_drivers;
@@ -125,16 +128,16 @@ private:
PrioQueue<IDBThreadOperation *> m_OpQueue; PrioQueue<IDBThreadOperation *> m_OpQueue;
Queue<IDBThreadOperation *> m_ThinkQueue; Queue<IDBThreadOperation *> m_ThinkQueue;
CVector<bool> m_drSafety; /* which drivers are safe? */ CVector<bool> m_drSafety; /* which drivers are safe? */
ke::AutoPtr<ke::Thread> m_Worker; IThreadWorker *m_pWorker; /* Worker thread object */
ke::ConditionVariable m_QueueEvent; IMutex *m_pConfigLock; /* Configuration lock */
ke::Mutex m_ConfigLock; IMutex *m_pQueueLock; /* Queue safety lock */
ke::Mutex m_ThinkLock; IMutex *m_pThinkLock; /* Think-queue lock */
bool m_Terminate;
List<ConfDbInfo *> m_confs; List<ConfDbInfo> m_confs;
HandleType_t m_DriverType; HandleType_t m_DriverType;
HandleType_t m_DatabaseType; HandleType_t m_DatabaseType;
String m_DefDriver; String m_DefDriver;
BaseStringTable m_StrTab;
char m_Filename[PLATFORM_MAX_PATH]; char m_Filename[PLATFORM_MAX_PATH];
unsigned int m_ParseLevel; unsigned int m_ParseLevel;
unsigned int m_ParseState; unsigned int m_ParseState;
@@ -29,54 +29,43 @@
* Version: $Id$ * Version: $Id$
*/ */
#include <IPluginSys.h>
#include <stdarg.h>
#include "DebugReporter.h" #include "DebugReporter.h"
#include "Logger.h"
#include "PluginSys.h"
#include "sm_stringutil.h"
DebugReport g_DbgReporter; DebugReport g_DbgReporter;
/* I'm really lazy. This should probably be exported to ISourcePawnEngine someday,
* but we need to make sure the JIT will deal with the version bump.
*/
extern const char *GetSourcePawnErrorMessage(int error);
void DebugReport::OnSourceModAllInitialized() void DebugReport::OnSourceModAllInitialized()
{ {
g_pSourcePawn->SetDebugListener(this); g_pSourcePawn->SetDebugListener(this);
} }
void DebugReport::OnDebugSpew(const char *msg, ...)
{
va_list ap;
char buffer[512];
va_start(ap, msg);
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
va_end(ap);
smcore.Log("[SM] %s", buffer);
}
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...) void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
{ {
va_list ap; va_list ap;
char buffer[512];
va_start(ap, message); va_start(ap, message);
GenerateErrorVA(ctx, func_idx, err, message, ap); UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
va_end(ap); va_end(ap);
}
void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap) const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
{ const char *error = GetSourcePawnErrorMessage(err);
char buffer[512];
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
const char *error = g_pSourcePawn2->GetErrorString(err);
if (error) if (error)
{ {
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
} else { } else {
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
} }
smcore.LogError("[SM] %s", buffer); g_Logger.LogError("[SM] %s", buffer);
if (func_idx != -1) if (func_idx != -1)
{ {
@@ -84,9 +73,9 @@ void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err,
{ {
func_idx >>= 1; func_idx >>= 1;
sp_public_t *function; sp_public_t *function;
if (ctx->GetRuntime()->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE) if (ctx->GetPublicByIndex(func_idx, &function) == SP_ERROR_NONE)
{ {
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name); g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", function->name);
} }
} }
} }
@@ -98,26 +87,26 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
char buffer[512]; char buffer[512];
va_start(ap, message); va_start(ap, message);
smcore.FormatArgs(buffer, sizeof(buffer), message, ap); UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
va_end(ap); va_end(ap);
const char *plname = pluginsys->FindPluginByContext(pContext->GetContext())->GetFilename(); const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
const char *error = g_pSourcePawn2->GetErrorString(err); const char *error = GetSourcePawnErrorMessage(err);
if (error) if (error)
{ {
smcore.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error); g_Logger.LogError("[SM] Plugin \"%s\" encountered error %d: %s", plname, err, error);
} else { } else {
smcore.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err); g_Logger.LogError("[SM] Plugin \"%s\" encountered unknown error %d", plname, err);
} }
smcore.LogError("[SM] %s", buffer); g_Logger.LogError("[SM] %s", buffer);
IPluginDebugInfo *pDebug; IPluginDebugInfo *pDebug;
if ((pDebug = pContext->GetRuntime()->GetDebugInfo()) == NULL) if ((pDebug = pContext->GetDebugInfo()) == NULL)
{ {
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
_GetPluginIndex(pContext)); _GetPluginIndex(pContext));
return; return;
} }
@@ -125,21 +114,21 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
const char *name; const char *name;
if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE) if (pDebug->LookupFunction(code_addr, &name) == SP_ERROR_NONE)
{ {
smcore.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name); g_Logger.LogError("[SM] Unable to call function \"%s\" due to above error(s).", name);
} else { } else {
smcore.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr); g_Logger.LogError("[SM] Unable to call function (name unknown, address \"%x\").", code_addr);
} }
} }
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error) void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
{ {
const char *lastname; const char *lastname;
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename(); const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
int n_err = error->GetErrorCode(); int n_err = error->GetErrorCode();
if (n_err != SP_ERROR_NATIVE) if (n_err != SP_ERROR_NATIVE)
{ {
smcore.LogError("[SM] Plugin encountered error %d: %s", g_Logger.LogError("[SM] Plugin encountered error %d: %s",
n_err, n_err,
error->GetErrorString()); error->GetErrorString());
} }
@@ -149,26 +138,26 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
const char *custerr; const char *custerr;
if ((custerr=error->GetCustomErrorString()) != NULL) if ((custerr=error->GetCustomErrorString()) != NULL)
{ {
smcore.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr); g_Logger.LogError("[SM] Native \"%s\" reported: %s", lastname, custerr);
} else { } else {
smcore.LogError("[SM] Native \"%s\" encountered a generic error.", lastname); g_Logger.LogError("[SM] Native \"%s\" encountered a generic error.", lastname);
} }
} }
if (!error->DebugInfoAvailable()) if (!error->DebugInfoAvailable())
{ {
smcore.LogError("[SM] Debug mode is not enabled for \"%s\"", plname); g_Logger.LogError("[SM] Debug mode is not enabled for \"%s\"", plname);
smcore.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on", g_Logger.LogError("[SM] To enable debug mode, edit plugin_settings.cfg, or type: sm plugins debug %d on",
_GetPluginIndex(ctx)); _GetPluginIndex(ctx));
return; return;
} }
CallStackInfo stk_info; CallStackInfo stk_info;
int i = 0; int i = 0;
smcore.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname); g_Logger.LogError("[SM] Displaying call stack trace for plugin \"%s\":", plname);
while (error->GetTraceInfo(&stk_info)) while (error->GetTraceInfo(&stk_info))
{ {
smcore.LogError("[SM] [%d] Line %d, %s::%s()", g_Logger.LogError("[SM] [%d] Line %d, %s::%s()",
i++, i++,
stk_info.line, stk_info.line,
stk_info.filename, stk_info.filename,
@@ -179,7 +168,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
int DebugReport::_GetPluginIndex(IPluginContext *ctx) int DebugReport::_GetPluginIndex(IPluginContext *ctx)
{ {
int id = 1; int id = 1;
IPluginIterator *iter = pluginsys->GetPluginIterator(); IPluginIterator *iter = g_PluginSys.GetPluginIterator();
for (; iter->MorePlugins(); iter->NextPlugin(), id++) for (; iter->MorePlugins(); iter->NextPlugin(), id++)
{ {
@@ -195,6 +184,6 @@ int DebugReport::_GetPluginIndex(IPluginContext *ctx)
/* If we don't know which plugin this is, it's one being loaded. Fake its index for now. */ /* If we don't know which plugin this is, it's one being loaded. Fake its index for now. */
return pluginsys->GetPluginCount() + 1; return g_PluginSys.GetPluginCount() + 1;
} }
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -33,7 +33,7 @@
#define _INCLUDE_SOURCEMOD_CDBGREPORTER_H_ #define _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
#include "sp_vm_api.h" #include "sp_vm_api.h"
#include "common_logic.h" #include "sm_globals.h"
class DebugReport : class DebugReport :
public SMGlobalClass, public SMGlobalClass,
@@ -43,10 +43,7 @@ public: // SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
public: // IDebugListener public: // IDebugListener
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error); void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error);
void OnDebugSpew(const char *msg, ...);
public:
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...); void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...); void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
private: private:
int _GetPluginIndex(IPluginContext *ctx); int _GetPluginIndex(IPluginContext *ctx);
+52 -97
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -30,8 +30,10 @@
*/ */
#include "EventManager.h" #include "EventManager.h"
#include "ForwardSys.h"
#include "HandleSys.h"
#include "PluginSys.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "logic_bridge.h"
EventManager g_EventManager; EventManager g_EventManager;
@@ -40,26 +42,16 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *,
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell}; const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
typedef List<EventHook *> EventHookList; typedef List<EventHook *> EventHookList;
class EventForwardFilter : public IForwardFilter
{
EventInfo *pEventInfo;
public:
EventForwardFilter(EventInfo *pEventInfo) : pEventInfo(pEventInfo)
{
}
void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
{
params[2].val = pEventInfo->bDontBroadcast ? 1 : 0;
}
};
EventManager::EventManager() : m_EventType(0) EventManager::EventManager() : m_EventType(0)
{ {
/* Create an event lookup trie */
m_EventHooks = sm_trie_create();
} }
EventManager::~EventManager() EventManager::~EventManager()
{ {
sm_trie_destroy(m_EventHooks);
/* Free memory used by EventInfo structs if any */ /* Free memory used by EventInfo structs if any */
CStack<EventInfo *>::iterator iter; CStack<EventInfo *>::iterator iter;
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++) for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
@@ -73,8 +65,8 @@ EventManager::~EventManager()
void EventManager::OnSourceModAllInitialized() void EventManager::OnSourceModAllInitialized()
{ {
/* Add a hook for IGameEventManager2::FireEvent() */ /* Add a hook for IGameEventManager2::FireEvent() */
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false); SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true); SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
HandleAccess sec; HandleAccess sec;
@@ -84,17 +76,17 @@ void EventManager::OnSourceModAllInitialized()
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER; sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
/* Create the 'GameEvent' handle type */ /* Create the 'GameEvent' handle type */
m_EventType = handlesys->CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL); m_EventType = g_HandleSys.CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
} }
void EventManager::OnSourceModShutdown() void EventManager::OnSourceModShutdown()
{ {
/* Remove hook for IGameEventManager2::FireEvent() */ /* Remove hook for IGameEventManager2::FireEvent() */
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false); SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true); SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
/* Remove the 'GameEvent' handle type */ /* Remove the 'GameEvent' handle type */
handlesys->RemoveType(m_EventType, g_pCoreIdent); g_HandleSys.RemoveType(m_EventType, g_pCoreIdent);
/* Remove ourselves as listener for events */ /* Remove ourselves as listener for events */
gameevents->RemoveListener(this); gameevents->RemoveListener(this);
@@ -132,12 +124,12 @@ void EventManager::OnPluginUnloaded(IPlugin *plugin)
{ {
if (pHook->pPreHook) if (pHook->pPreHook)
{ {
forwardsys->ReleaseForward(pHook->pPreHook); g_Forwards.ReleaseForward(pHook->pPreHook);
} }
if (pHook->pPostHook) if (pHook->pPostHook)
{ {
forwardsys->ReleaseForward(pHook->pPostHook); g_Forwards.ReleaseForward(pHook->pPostHook);
} }
delete pHook; delete pHook;
@@ -155,13 +147,6 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */ 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
int EventManager::GetEventDebugID()
{
return EVENT_DEBUG_ID_INIT;
}
#endif
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode) EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
{ {
EventHook *pHook; EventHook *pHook;
@@ -178,10 +163,10 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
} }
/* If a hook structure does not exist... */ /* If a hook structure does not exist... */
if (!m_EventHooks.retrieve(name, &pHook)) if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
{ {
EventHookList *pHookList; EventHookList *pHookList;
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext()); IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Check plugin for an existing EventHook list */ /* Check plugin for an existing EventHook list */
if (!plugin->GetProperty("EventHooks", (void **)&pHookList)) if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
@@ -196,27 +181,24 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
if (mode == EventHookMode_Pre) if (mode == EventHookMode_Pre)
{ {
/* Create forward for a pre hook */ /* Create forward for a pre hook */
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS); pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS);
/* Add to forward list */ /* Add to forward list */
pHook->pPreHook->AddFunction(pFunction); pHook->pPreHook->AddFunction(pFunction);
} else { } else {
/* Create forward for a post hook */ /* Create forward for a post hook */
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS); pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
/* Should we copy data from a pre hook to the post hook? */ /* Should we copy data from a pre hook to the post hook? */
pHook->postCopy = (mode == EventHookMode_Post); pHook->postCopy = (mode == EventHookMode_Post);
/* Add to forward list */ /* Add to forward list */
pHook->pPostHook->AddFunction(pFunction); pHook->pPostHook->AddFunction(pFunction);
} }
/* Cache the name for post hooks */
pHook->name = name;
/* Increase reference count */ /* Increase reference count */
pHook->refCount++; pHook->refCount++;
/* Add hook structure to hook lists */ /* Add hook structure to hook lists */
pHookList->push_back(pHook); pHookList->push_back(pHook);
m_EventHooks.insert(name, pHook); sm_trie_insert(m_EventHooks, name, pHook);
return EventHookErr_Okay; return EventHookErr_Okay;
} }
@@ -228,7 +210,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
/* Create pre hook forward if necessary */ /* Create pre hook forward if necessary */
if (!pHook->pPreHook) if (!pHook->pPreHook)
{ {
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS); pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
} }
/* Add plugin function to forward list */ /* Add plugin function to forward list */
@@ -237,7 +219,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
/* Create post hook forward if necessary */ /* Create post hook forward if necessary */
if (!pHook->pPostHook) if (!pHook->pPostHook)
{ {
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS); pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
} }
/* If postCopy is false, then we may want to set it to true */ /* If postCopy is false, then we may want to set it to true */
@@ -262,7 +244,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
IChangeableForward **pEventForward; IChangeableForward **pEventForward;
/* If hook does not exist at all */ /* If hook does not exist at all */
if (!m_EventHooks.retrieve(name, &pHook)) if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
{ {
return EventHookErr_NotActive; return EventHookErr_NotActive;
} }
@@ -284,7 +266,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
/* If forward's list contains 0 functions now, free it */ /* If forward's list contains 0 functions now, free it */
if ((*pEventForward)->GetFunctionCount() == 0) if ((*pEventForward)->GetFunctionCount() == 0)
{ {
forwardsys->ReleaseForward(*pEventForward); g_Forwards.ReleaseForward(*pEventForward);
*pEventForward = NULL; *pEventForward = NULL;
} }
@@ -294,7 +276,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
/* If reference count is now 0, free hook structure */ /* If reference count is now 0, free hook structure */
EventHookList *pHookList; EventHookList *pHookList;
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext()); IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Get plugin's event hook list */ /* Get plugin's event hook list */
if (!plugin->GetProperty("EventHooks", (void**)&pHookList)) if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
@@ -312,7 +294,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
pHookList->remove(pHook); pHookList->remove(pHook);
/* Delete entry in trie */ /* Delete entry in trie */
m_EventHooks.remove(name); sm_trie_delete(m_EventHooks, name);
/* And finally free structure memory */ /* And finally free structure memory */
delete pHook; delete pHook;
@@ -339,7 +321,6 @@ EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name,
pInfo->pEvent = pEvent; pInfo->pEvent = pEvent;
pInfo->pOwner = pContext->GetIdentity(); pInfo->pOwner = pContext->GetIdentity();
pInfo->bDontBroadcast = false;
return pInfo; return pInfo;
} }
@@ -378,49 +359,39 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
IChangeableForward *pForward; IChangeableForward *pForward;
const char *name; const char *name;
cell_t res = Pl_Continue; cell_t res = Pl_Continue;
bool broadcast = bDontBroadcast;
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
if (!pEvent) if (!pEvent)
{ {
RETURN_META_VALUE(MRES_IGNORED, false); RETURN_META_VALUE(MRES_IGNORED, false);
} }
name = pEvent->GetName();
if (m_EventHooks.retrieve(name, &pHook)) /* Get the event name, we're going to need this for passing to post hooks */
{ name = pEvent->GetName();
/* Push the event onto the event stack. The reference count is increased to make sure
* the structure is not garbage collected in between now and the post hook.
*/
pHook->refCount++;
m_EventStack.push(pHook);
m_EventNames.push(name);
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
{
pForward = pHook->pPreHook; pForward = pHook->pPreHook;
if (pForward) if (pForward)
{ {
EventInfo info(pEvent, NULL); EventInfo info = { pEvent, NULL };
HandleSecurity sec(NULL, g_pCoreIdent);
Handle_t hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
info.bDontBroadcast = bDontBroadcast;
EventForwardFilter filter(&info);
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
pForward->PushCell(hndl); pForward->PushCell(hndl);
pForward->PushString(name); pForward->PushString(name);
pForward->PushCell(bDontBroadcast); pForward->PushCell(bDontBroadcast);
pForward->Execute(&res, &filter); pForward->Execute(&res, NULL);
broadcast = info.bDontBroadcast; HandleSecurity sec(NULL, g_pCoreIdent);
g_HandleSys.FreeHandle(hndl, &sec);
handlesys->FreeHandle(hndl, &sec);
} }
if (pHook->postCopy) if (pHook->postCopy)
{ {
m_EventCopies.push(gameevents->DuplicateEvent(pEvent)); pHook->pEventCopy = gameevents->DuplicateEvent(pEvent);
} }
if (res) if (res)
@@ -429,13 +400,6 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
RETURN_META_VALUE(MRES_SUPERCEDE, false); RETURN_META_VALUE(MRES_SUPERCEDE, false);
} }
} }
else
{
m_EventStack.push(NULL);
}
if (broadcast != bDontBroadcast)
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent, (pEvent, broadcast));
RETURN_META_VALUE(MRES_IGNORED, true); RETURN_META_VALUE(MRES_IGNORED, true);
} }
@@ -443,9 +407,10 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
/* IGameEventManager2::FireEvent post hook */ /* IGameEventManager2::FireEvent post hook */
bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{ {
IGameEvent *pEventCopy = NULL;
EventHook *pHook; EventHook *pHook;
EventInfo info;
IChangeableForward *pForward; IChangeableForward *pForward;
const char *name;
Handle_t hndl = 0; Handle_t hndl = 0;
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
@@ -454,27 +419,26 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
RETURN_META_VALUE(MRES_IGNORED, false); RETURN_META_VALUE(MRES_IGNORED, false);
} }
pHook = m_EventStack.front(); name = m_EventNames.front();
if (pHook != NULL) if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
{ {
pForward = pHook->pPostHook; pForward = pHook->pPostHook;
if (pForward) if (pForward)
{ {
EventInfo info = { pHook->pEventCopy, NULL };
if (pHook->postCopy) if (pHook->postCopy)
{ {
info.bDontBroadcast = bDontBroadcast; hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
info.pEvent = m_EventCopies.front();
info.pOwner = NULL;
hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
pForward->PushCell(hndl); pForward->PushCell(hndl);
} else { } else {
pForward->PushCell(BAD_HANDLE); pForward->PushCell(BAD_HANDLE);
} }
pForward->PushString(pHook->name.chars()); pForward->PushString(name);
pForward->PushCell(bDontBroadcast); pForward->PushCell(bDontBroadcast);
pForward->Execute(NULL); pForward->Execute(NULL);
@@ -482,25 +446,16 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{ {
/* Free handle */ /* Free handle */
HandleSecurity sec(NULL, g_pCoreIdent); HandleSecurity sec(NULL, g_pCoreIdent);
handlesys->FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
/* Free event structure */ /* Free event structure */
gameevents->FreeEvent(info.pEvent); gameevents->FreeEvent(pEventCopy);
m_EventCopies.pop(); pHook->pEventCopy = NULL;
} }
} }
/* Decrement reference count, check if a delayed delete is needed */
if (--pHook->refCount == 0)
{
assert(pHook->pPostHook == NULL);
assert(pHook->pPreHook == NULL);
m_EventHooks.remove(pHook->name.chars());
delete pHook;
}
} }
m_EventStack.pop(); m_EventNames.pop();
RETURN_META_VALUE(MRES_IGNORED, true); RETURN_META_VALUE(MRES_IGNORED, true);
} }
+7 -22
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,7 +34,7 @@
#include "sm_globals.h" #include "sm_globals.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <sm_namehashset.h> #include "sm_trie.h"
#include <sh_list.h> #include <sh_list.h>
#include <sh_stack.h> #include <sh_stack.h>
#include <IHandleSys.h> #include <IHandleSys.h>
@@ -45,15 +45,8 @@ using namespace SourceHook;
struct EventInfo struct EventInfo
{ {
EventInfo()
{
}
EventInfo(IGameEvent *ev, IdentityToken_t *owner) : pEvent(ev), pOwner(owner)
{
}
IGameEvent *pEvent; IGameEvent *pEvent;
IdentityToken_t *pOwner; IdentityToken_t *pOwner;
bool bDontBroadcast;
}; };
struct EventHook struct EventHook
@@ -63,18 +56,14 @@ struct EventHook
pPreHook = NULL; pPreHook = NULL;
pPostHook = NULL; pPostHook = NULL;
postCopy = false; postCopy = false;
pEventCopy = NULL;
refCount = 0; refCount = 0;
} }
IChangeableForward *pPreHook; IChangeableForward *pPreHook;
IChangeableForward *pPostHook; IChangeableForward *pPostHook;
bool postCopy; bool postCopy;
IGameEvent *pEventCopy;
unsigned int refCount; unsigned int refCount;
ke::AString name;
static inline bool matches(const char *name, const EventHook *hook)
{
return strcmp(name, hook->name.chars()) == 0;
}
}; };
enum EventHookMode enum EventHookMode
@@ -110,9 +99,6 @@ public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin); void OnPluginUnloaded(IPlugin *plugin);
public: // IGameEventListener2 public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent); void FireGameEvent(IGameEvent *pEvent);
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
int GetEventDebugID();
#endif
public: public:
/** /**
* Get the 'GameEvent' handle type ID. * Get the 'GameEvent' handle type ID.
@@ -132,10 +118,9 @@ private: // IGameEventManager2 hooks
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast); bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
private: private:
HandleType_t m_EventType; HandleType_t m_EventType;
NameHashSet<EventHook *> m_EventHooks; Trie *m_EventHooks;
CStack<EventInfo *> m_FreeEvents; CStack<EventInfo *> m_FreeEvents;
CStack<EventHook *> m_EventStack; CStack<const char *> m_EventNames;
CStack<IGameEvent *> m_EventCopies;
}; };
extern EventManager g_EventManager; extern EventManager g_EventManager;
+195 -337
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,20 +32,26 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "GameConfigs.h" #include "GameConfigs.h"
//#include "sm_stringutil.h" #include "sm_stringutil.h"
//#include "sourcemod.h" #include "sourcemod.h"
//#include "sourcemm_api.h" #include "sourcemm_api.h"
//#include "HalfLife2.h" #include "HalfLife2.h"
//#include "Logger.h" #include "Logger.h"
//#include "ShareSys.h" #include "ShareSys.h"
//#include "MemoryUtils.h" #include "MemoryUtils.h"
//#include "LibrarySys.h" #include "LibrarySys.h"
//#include "HandleSys.h" #include "HandleSys.h"
//#include "sm_crc32.h" #include "sm_crc32.h"
//#if defined PLATFORM_LINUX #if defined PLATFORM_LINUX
//#include <dlfcn.h> #include <dlfcn.h>
//#endif #endif
GameConfigManager g_GameConfigs;
IGameConfig *g_pGameConf = NULL;
char g_Game[256];
char g_GameDesc[256] = {'!', '\0'};
char g_GameName[256] = {'$', '\0'};
#define PSTATE_NONE 0 #define PSTATE_NONE 0
#define PSTATE_GAMES 1 #define PSTATE_GAMES 1
@@ -58,53 +64,47 @@
#define PSTATE_GAMEDEFS_SIGNATURES_SIG 8 #define PSTATE_GAMEDEFS_SIGNATURES_SIG 8
#define PSTATE_GAMEDEFS_CRC 9 #define PSTATE_GAMEDEFS_CRC 9
#define PSTATE_GAMEDEFS_CRC_BINARY 10 #define PSTATE_GAMEDEFS_CRC_BINARY 10
#define PSTATE_GAMEDEFS_CUSTOM 11
#define WIN 0
#define LIN 1
#if defined PLATFORM_WINDOWS
#define PLATFORM_NAME "windows"
#define PLATFORM_SERVER_BINARY "server.dll"
#elif defined PLATFORM_LINUX
#define PLATFORM_NAME "linux" #define PLATFORM_NAME "linux"
#define PLATFORM_SERVER_BINARY "server_i486.so" #define PLATFORM_SERVER_BINARY "server_i486.so"
#endif
Offset *tempOffset; struct TempSigInfo
Sig *tempSig; {
void Reset()
{
library[0] = '\0';
sig[0] = '\0';
}
char sig[512];
char library[64];
} s_TempSig;
unsigned int s_ServerBinCRC; unsigned int s_ServerBinCRC;
bool s_ServerBinCRC_Ok = false; bool s_ServerBinCRC_Ok = false;
bool /*CGameConfig::*/DoesGameMatch(const char *value) CGameConfig::CGameConfig(const char *file)
{ {
if (strcmp(value, /*m_gdcG*/game) == 0) m_pFile = sm_strdup(file);
{ m_pOffsets = sm_trie_create();
return true; m_pProps = sm_trie_create();
} m_pKeys = sm_trie_create();
return false; m_pSigs = sm_trie_create();
} m_pStrings = new BaseStringTable(512);
bool /*CGameConfig::*/DoesEngineMatch(const char *value)
{
if (strcmp(value, /*m_gdcE*/engine) == 0)
{
return true;
}
return false;
}
CGameConfig::CGameConfig()//const char *file)//, const char *game, const char *engine)
{
// strncopy(m_File, file, sizeof(m_File));
// strncopy(m_gdcGame, game, sizeof(m_gdcGame));
// strncopy(m_gdcEngine, engine, sizeof(m_gdcEngine));
//m_pStrings = new BaseStringTable(512);
m_RefCount = 0; m_RefCount = 0;
m_CustomLevel = 0;
m_CustomHandler = NULL;
} }
CGameConfig::~CGameConfig() CGameConfig::~CGameConfig()
{ {
// delete m_pStrings; sm_trie_destroy(m_pOffsets);
sm_trie_destroy(m_pProps);
sm_trie_destroy(m_pKeys);
sm_trie_destroy(m_pSigs);
delete [] m_pFile;
delete m_pStrings;
} }
SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name) SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name)
@@ -129,9 +129,11 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
} }
case PSTATE_GAMES: case PSTATE_GAMES:
{ {
if (strcmp(name, "*") == 0 || if ((strcmp(name, "*") == 0)
strcmp(name, "#default") == 0 || || (strcmp(name, "#default") == 0)
DoesGameMatch(name)) || (strcasecmp(name, g_Game) == 0)
|| (strcasecmp(name, g_GameDesc) == 0)
|| (strcasecmp(name, g_GameName) == 0))
{ {
bShouldBeReadingDefault = true; bShouldBeReadingDefault = true;
m_ParseState = PSTATE_GAMEDEFS; m_ParseState = PSTATE_GAMEDEFS;
@@ -151,15 +153,12 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
{ {
m_ParseState = PSTATE_GAMEDEFS_KEYS; m_ParseState = PSTATE_GAMEDEFS_KEYS;
} }
else if ((strcmp(name, "#supported") == 0) && (strcmp(m_Game, "#default") == 0)) else if ((strcmp(name, "#supported") == 0)
&& (strcmp(m_Game, "#default") == 0))
{ {
m_ParseState = PSTATE_GAMEDEFS_SUPPORTED; m_ParseState = PSTATE_GAMEDEFS_SUPPORTED;
/* Ignore this section unless we get a game. */ /* Ignore this section unless we get a game. */
bShouldBeReadingDefault = false; bShouldBeReadingDefault = false;
had_game = false;
matched_game = false;
had_engine = false;
matched_engine = false;
} }
else if (strcmp(name, "Signatures") == 0) else if (strcmp(name, "Signatures") == 0)
{ {
@@ -167,25 +166,12 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
} }
else if (strcmp(name, "CRC") == 0) else if (strcmp(name, "CRC") == 0)
{ {
#if 0
m_ParseState = PSTATE_GAMEDEFS_CRC; m_ParseState = PSTATE_GAMEDEFS_CRC;
bShouldBeReadingDefault = false; bShouldBeReadingDefault = false;
#endif
} }
else else
{ {
#if 0 m_IgnoreLevel++;
ITextListener_SMC **pListen = g_GameConfigs.m_customHandlers.retrieve(name);
if (pListen != NULL)
{
m_CustomLevel = 0;
m_ParseState = PSTATE_GAMEDEFS_CUSTOM;
m_CustomHandler = *pListen;
m_CustomHandler->ReadSMC_ParseStart();
break;
}
#endif
} }
break; break;
} }
@@ -193,19 +179,17 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
{ {
m_Prop[0] = '\0'; m_Prop[0] = '\0';
m_Class[0] = '\0'; m_Class[0] = '\0';
tempOffset = new Offset(); strncopy(m_offset, name, sizeof(m_offset));
tempOffset->setName(name);
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET; m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
break; break;
} }
case PSTATE_GAMEDEFS_SIGNATURES: case PSTATE_GAMEDEFS_SIGNATURES:
{ {
tempSig = new Sig(); strncopy(m_offset, name, sizeof(m_offset));
tempSig->setName(name); s_TempSig.Reset();
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG; m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
break; break;
} }
#if 0
case PSTATE_GAMEDEFS_CRC: case PSTATE_GAMEDEFS_CRC:
{ {
char error[255]; char error[255];
@@ -236,26 +220,18 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
s_ServerBinCRC = UTIL_CRC32(buffer, size); s_ServerBinCRC = UTIL_CRC32(buffer, size);
free(buffer); free(buffer);
s_ServerBinCRC_Ok = true; s_ServerBinCRC_Ok = true;
fclose(fp);
} }
} }
if (error[0] != '\0') if (error[0] != '\0')
{ {
m_IgnoreLevel = 1; m_IgnoreLevel = 1;
g_Logger.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile); g_Logger.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_pFile);
g_Logger.LogError("[SM] %s", error); g_Logger.LogError("[SM] %s", error);
} else { } else {
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY; m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
} }
break; break;
} }
case PSTATE_GAMEDEFS_CUSTOM:
{
m_CustomLevel++;
return m_CustomHandler->ReadSMC_NewSection(states, name);
break;
}
#endif
/* No sub-sections allowed: /* No sub-sections allowed:
case PSTATE_GAMEDEFS_OFFSETS_OFFSET: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
case PSTATE_GAMEDEFS_KEYS: case PSTATE_GAMEDEFS_KEYS:
@@ -288,46 +264,29 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
strncopy(m_Class, value, sizeof(m_Class)); strncopy(m_Class, value, sizeof(m_Class));
} else if (strcmp(key, "prop") == 0) { } else if (strcmp(key, "prop") == 0) {
strncopy(m_Prop, value, sizeof(m_Prop)); strncopy(m_Prop, value, sizeof(m_Prop));
} else /*if (strcmp(key, PLATFORM_NAME) == 0) */ { } else if (strcmp(key, PLATFORM_NAME) == 0) {
int val = atoi(value); int val = atoi(value);
// sm_trie_replace(m_pOffsets, m_offset, (void *)val); sm_trie_replace(m_pOffsets, m_offset, (void *)val);
if (strcmp(key, "windows") == 0) tempOffset->setWin(val);
else if (strcmp(key, "linux") == 0) tempOffset->setLin(val);
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { } else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
m_Keys[key] = value; int id = m_pStrings->AddString(value);
// printf("Inserting %s - %s\n", key, value); sm_trie_replace(m_pKeys, key, (void *)id);
// int id = m_pStrings->AddString(value);
// sm_trie_replace(m_pKeys, key, (void *)id);
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) { } else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
if (strcmp(key, "game") == 0) if (strcmp(key, "game") == 0
&& (strcasecmp(value, g_Game) == 0
|| strcasecmp(value, g_GameDesc) == 0
|| strcasecmp(value, g_GameName) == 0)
)
{ {
had_game = true; bShouldBeReadingDefault = true;
if (DoesGameMatch(value))
{
matched_game = true;
}
if ((!had_engine && matched_game) || (matched_engine && matched_game))
{
bShouldBeReadingDefault = true;
}
}
else if (strcmp(key, "engine") == 0)
{
had_engine = true;
if (DoesEngineMatch(value))
{
matched_engine = true;
}
if ((!had_game && matched_engine) || (matched_game && matched_engine))
{
bShouldBeReadingDefault = true;
}
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) { } else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
if (strcmp(key, "windows") == 0) tempSig->setWin(value); if (strcmp(key, PLATFORM_NAME) == 0)
else if (strcmp(key, "linux") == 0) tempSig->setLin(value); {
else if (strcmp(key, "library") == 0) tempSig->setLib(value); strncopy(s_TempSig.sig, value, sizeof(s_TempSig.sig));
} else if (strcmp(key, "library") == 0) {
strncopy(s_TempSig.library, value, sizeof(s_TempSig.library));
}
} else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) { } else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) {
if (strcmp(key, PLATFORM_NAME) == 0 if (strcmp(key, PLATFORM_NAME) == 0
&& s_ServerBinCRC_Ok && s_ServerBinCRC_Ok
@@ -340,8 +299,6 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
bShouldBeReadingDefault = true; bShouldBeReadingDefault = true;
} }
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) {
return m_CustomHandler->ReadSMC_KeyValue(states, key, value);
} }
return SMCResult_Continue; return SMCResult_Continue;
@@ -355,13 +312,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
return SMCResult_Continue; return SMCResult_Continue;
} }
if (m_CustomLevel)
{
m_CustomLevel--;
m_CustomHandler->ReadSMC_LeavingSection(states);
return SMCResult_Continue;
}
switch (m_ParseState) switch (m_ParseState)
{ {
case PSTATE_GAMES: case PSTATE_GAMES:
@@ -374,12 +324,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
m_ParseState = PSTATE_GAMES; m_ParseState = PSTATE_GAMES;
break; break;
} }
case PSTATE_GAMEDEFS_CUSTOM:
{
m_ParseState = PSTATE_GAMEDEFS;
m_CustomHandler->ReadSMC_ParseEnd(false, false);
break;
}
case PSTATE_GAMEDEFS_KEYS: case PSTATE_GAMEDEFS_KEYS:
case PSTATE_GAMEDEFS_OFFSETS: case PSTATE_GAMEDEFS_OFFSETS:
{ {
@@ -388,8 +332,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
} }
case PSTATE_GAMEDEFS_OFFSETS_OFFSET: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
{ {
m_Offsets.push_back(*tempOffset);
#if 0
/* Parse the offset... */ /* Parse the offset... */
if (m_Class[0] != '\0' if (m_Class[0] != '\0'
&& m_Prop[0] != '\0') && m_Prop[0] != '\0')
@@ -408,12 +350,11 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")", g_Logger.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
m_Class, m_Class,
m_Prop, m_Prop,
m_CurFile, m_pFile,
m_Game); m_Game);
} }
} }
} }
#endif
m_ParseState = PSTATE_GAMEDEFS_OFFSETS; m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
break; break;
} }
@@ -442,8 +383,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
} }
case PSTATE_GAMEDEFS_SIGNATURES_SIG: case PSTATE_GAMEDEFS_SIGNATURES_SIG:
{ {
m_Sigs.push_back(*tempSig);
#if 0
if (s_TempSig.library[0] == '\0') if (s_TempSig.library[0] == '\0')
{ {
/* assume server */ /* assume server */
@@ -461,7 +400,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
{ {
g_Logger.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", g_Logger.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
s_TempSig.library, s_TempSig.library,
m_CurFile); m_pFile);
} else { } else {
#if defined PLATFORM_LINUX #if defined PLATFORM_LINUX
if (s_TempSig.sig[0] == '@') if (s_TempSig.sig[0] == '@')
@@ -478,12 +417,12 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
} else { } else {
g_Logger.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")", g_Logger.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
s_TempSig.library, s_TempSig.library,
m_File); m_pFile);
} }
} else { } else {
g_Logger.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", g_Logger.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
s_TempSig.library, s_TempSig.library,
m_File); m_pFile);
} }
} }
if (final_addr) if (final_addr)
@@ -538,7 +477,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
skip_find: skip_find:
#endif #endif
sm_trie_replace(m_pSigs, m_offset, final_addr); sm_trie_replace(m_pSigs, m_offset, final_addr);
#endif
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES; m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
break; break;
@@ -548,220 +486,48 @@ skip_find:
return SMCResult_Continue; return SMCResult_Continue;
} }
#define MSTATE_NONE 0
#define MSTATE_MAIN 1
#define MSTATE_FILE 2
class MasterReader : public ITextListener_SMC
{
public:
virtual void ReadSMC_ParseStart()
{
state = MSTATE_NONE;
ignoreLevel = 0;
}
virtual SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name)
{
if (ignoreLevel)
{
return SMCResult_Continue;
}
if (state == MSTATE_NONE)
{
if (strcmp(name, "Game Master") == 0)
{
state = MSTATE_MAIN;
}
else
{
ignoreLevel++;
}
}
else if (state == MSTATE_MAIN)
{
strncopy(cur_file, name, sizeof(cur_file));
had_engine = false;
matched_engine = false;
had_game = false;
matched_game = false;
state = MSTATE_FILE;
}
else if (state == MSTATE_FILE)
{
ignoreLevel++;
}
return SMCResult_Continue;
}
virtual SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{
if (ignoreLevel || state != MSTATE_FILE)
{
return SMCResult_Continue;
}
if (strcmp(key, "engine") == 0)
{
had_engine = true;
if (DoesEngineMatch(value))
{
matched_engine = true;
}
}
else if (strcmp(key, "game") == 0)
{
had_game = true;
if (DoesGameMatch(value))
{
matched_game = true;
}
}
return SMCResult_Continue;
}
virtual SMCResult ReadSMC_LeavingSection(const SMCStates *states)
{
if (ignoreLevel)
{
ignoreLevel--;
return SMCResult_Continue;
}
if (state == MSTATE_FILE)
{
/* The four success conditions:
* 1. Needed nothing.
* 2. Needed game only.
* 3. Needed engine only.
* 4. Needed both engine and game.
* Final result is minimized via k-map.
*/
#if 0
if ((!had_engine && !had_game) ||
(!had_engine && (had_game && matched_game)) ||
(!had_game && (had_engine && matched_engine)) ||
((had_game && had_engine) && (matched_game && matched_engine)))
#endif
if ((!had_engine && !had_game) ||
(!had_engine && matched_game) ||
(!had_game && matched_engine) ||
(matched_engine && matched_game))
{
fileList->push_back(cur_file);
}
state = MSTATE_MAIN;
}
else if (state == MSTATE_MAIN)
{
state = MSTATE_NONE;
}
return SMCResult_Continue;
}
public:
list<char*> *fileList;
unsigned int state;
unsigned int ignoreLevel;
char cur_file[PLATFORM_MAX_PATH];
bool had_engine;
bool matched_engine;
bool had_game;
bool matched_game;
};
static MasterReader master_reader;
bool CGameConfig::Reparse(char *error, size_t maxlength) bool CGameConfig::Reparse(char *error, size_t maxlength)
{ {
/* Reset cached data */ SMCError err;
// m_pStrings->Reset(); SMCStates state = {0, 0};
m_Offsets.clear();
m_Sigs.clear();
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s.txt", m_pFile);
/* See if we can use the extended gamedata format. */ /* Backwards compatibility */
//TODO pass in path to gamedata somehow if (!g_LibSys.PathExists(path))
// g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s/master.games.txt", m_File);
/* Otherwise, it's time to parse the master. */
SMCError err;
SMCStates state = {0, 0};
list<char*> fileList;
master_reader.fileList = &fileList;
err = textparsers->ParseSMCFile(path, &master_reader, &state, error, maxlength);
if (err != SMCError_Okay)
{ {
const char *msg = textparsers->GetSMCErrorString(err); g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/gamedata/%s.txt", m_pFile);
printf("[SM] Error parsing master gameconf file \"%s\":", path);
printf("[SM] Error %d on line %d, col %d: %s",
err,
state.line,
state.col,
msg ? msg : "Unknown error");
exit(PARSE_ERROR);
} }
/* Go through each file we found and parse it. */
list<char*>::iterator iter;
for (iter = fileList.begin(); iter != fileList.end(); iter++)
{
UTIL_Format(path, sizeof(path), "%s/%s", m_File, *iter);
if (!EnterFile(path, error, maxlength))
{
return false;
}
}
return true;
}
bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
{
SMCError err;
SMCStates state = {0, 0};
/* Initialize parse states */ /* Initialize parse states */
m_IgnoreLevel = 0; m_IgnoreLevel = 0;
bShouldBeReadingDefault = true; bShouldBeReadingDefault = true;
m_ParseState = PSTATE_NONE; m_ParseState = PSTATE_NONE;
/* Reset cached data */
m_pStrings->Reset();
sm_trie_clear(m_pOffsets);
sm_trie_clear(m_pProps);
sm_trie_clear(m_pKeys);
if ((err=textparsers->ParseSMCFile(file, this, &state, error, maxlength)) if ((err=textparsers->ParseSMCFile(path, this, &state, error, maxlength))
!= SMCError_Okay) != SMCError_Okay)
{ {
const char *msg; const char *msg;
msg = textparsers->GetSMCErrorString(err); msg = textparsers->GetSMCErrorString(err);
printf("[SM] Error parsing gameconfig file \"%s\":\n", file); g_Logger.LogError("[SM] Error parsing gameconfig file \"%s\":", path);
printf("[SM] Error %d on line %d, col %d: %s\n", g_Logger.LogError("[SM] Error %d on line %d, col %d: %s",
err, err,
state.line, state.line,
state.col, state.col,
msg ? msg : "Unknown error"); msg ? msg : "Unknown error");
return false;
if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM)
{
//error occurred while parsing a custom section
m_CustomHandler->ReadSMC_ParseEnd(true, true);
m_CustomHandler = NULL;
m_CustomLevel = 0;
}
exit(PARSE_ERROR);
} }
return true; return true;
} }
#if 0
bool CGameConfig::GetOffset(const char *key, int *value) bool CGameConfig::GetOffset(const char *key, int *value)
{ {
void *obj; void *obj;
@@ -813,16 +579,108 @@ unsigned int CGameConfig::DecRefCount()
m_RefCount--; m_RefCount--;
return m_RefCount; return m_RefCount;
} }
#endif
const char *CGameConfig::GetKeyValue(const char *key) GameConfigManager::GameConfigManager()
{ {
map<const char*,const char*,cmp_str>::iterator it = m_Keys.find(key); m_pLookup = sm_trie_create();
if (it == m_Keys.end()) return NULL;
return it->second;
} }
list<Offset> CGameConfig::GetOffsets() { return m_Offsets; } GameConfigManager::~GameConfigManager()
list<Sig> CGameConfig::GetSigs() { return m_Sigs; } {
sm_trie_destroy(m_pLookup);
}
void GameConfigManager::OnSourceModStartup(bool late)
{
LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0);
strncopy(g_Game, g_SourceMod.GetGameFolderName(), sizeof(g_Game));
strncopy(g_GameDesc + 1, SERVER_CALL(GetGameDescription)(), sizeof(g_GameDesc) - 1);
KeyValues *pGameInfo = new KeyValues("GameInfo");
if (g_HL2.KVLoadFromFile(pGameInfo, basefilesystem, "gameinfo.txt"))
{
const char *str;
if ((str = pGameInfo->GetString("game", NULL)) != NULL)
{
strncopy(g_GameName + 1, str, sizeof(g_GameName) - 1);
}
}
pGameInfo->deleteThis();
}
void GameConfigManager::OnSourceModAllInitialized()
{
/* NOW initialize the game file */
CGameConfig *pGameConf = (CGameConfig *)g_pGameConf;
char error[255];
if (!pGameConf->Reparse(error, sizeof(error)))
{
/* :TODO: log */
}
g_ShareSys.AddInterface(NULL, this);
}
void GameConfigManager::OnSourceModAllShutdown()
{
CloseGameConfigFile(g_pGameConf);
}
bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pConfig, char *error, size_t maxlength)
{
CGameConfig *pConfig;
if (sm_trie_retrieve(m_pLookup, file, (void **)&pConfig))
{
pConfig->IncRefCount();
*_pConfig = pConfig;
return true;
}
pConfig = new CGameConfig(file);
/* :HACKHACK: Don't parse the main config file */
bool retval = true;
if (_pConfig != &g_pGameConf)
{
retval = pConfig->Reparse(error, maxlength);
}
m_cfgs.push_back(pConfig);
sm_trie_insert(m_pLookup, file, pConfig);
pConfig->IncRefCount();
*_pConfig = pConfig;
return retval;
}
void GameConfigManager::CloseGameConfigFile(IGameConfig *cfg)
{
CGameConfig *pConfig = (CGameConfig *)cfg;
if (pConfig->DecRefCount() == 0)
{
sm_trie_delete(m_pLookup, pConfig->m_pFile);
delete pConfig;
}
}
extern HandleType_t g_GameConfigsType;
IGameConfig *GameConfigManager::ReadHandle(Handle_t hndl, IdentityToken_t *ident, HandleError *err)
{
HandleSecurity sec(ident, g_pCoreIdent);
IGameConfig *conf = NULL;
HandleError _err = g_HandleSys.ReadHandle(hndl, g_GameConfigsType, &sec, (void **)&conf);
if (err)
{
*err = _err;
}
return conf;
}
+20 -62
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet: * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,12 +32,12 @@
#ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_ #ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
#define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_ #define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
#include "common_logic.h"
#include <IGameConfigs.h> #include <IGameConfigs.h>
#include <ITextParsers.h> #include <ITextParsers.h>
#include <am-refcounting.h> #include <sh_list.h>
#include <sm_stringhashmap.h> #include "sm_trie.h"
#include <sm_namehashset.h> #include "sm_globals.h"
#include "sm_memtable.h"
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook; using namespace SourceHook;
@@ -46,18 +46,14 @@ class SendProp;
class CGameConfig : class CGameConfig :
public ITextListener_SMC, public ITextListener_SMC,
public IGameConfig, public IGameConfig
public ke::Refcounted<CGameConfig>
{ {
friend class GameConfigManager; friend class GameConfigManager;
public: public:
CGameConfig(const char *file, const char *engine = NULL); CGameConfig(const char *file);
~CGameConfig(); ~CGameConfig();
public: public:
bool Reparse(char *error, size_t maxlength); bool Reparse(char *error, size_t maxlength);
bool EnterFile(const char *file, char *error, size_t maxlength);
void SetBaseEngine(const char *engine);
void SetParseEngine(const char *engine);
public: //ITextListener_SMC public: //ITextListener_SMC
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
@@ -67,19 +63,17 @@ public: //IGameConfig
bool GetOffset(const char *key, int *value); bool GetOffset(const char *key, int *value);
SendProp *GetSendProp(const char *key); SendProp *GetSendProp(const char *key);
bool GetMemSig(const char *key, void **addr); bool GetMemSig(const char *key, void **addr);
bool GetAddress(const char *key, void **addr); public:
public: //NameHashSet void IncRefCount();
static inline bool matches(const char *key, const CGameConfig *value) unsigned int DecRefCount();
{
return strcmp(key, value->m_File) == 0;
}
private: private:
char m_File[PLATFORM_MAX_PATH]; BaseStringTable *m_pStrings;
char m_CurFile[PLATFORM_MAX_PATH]; char *m_pFile;
StringHashMap<int> m_Offsets; Trie *m_pOffsets;
StringHashMap<SendProp *> m_Props; Trie *m_pProps;
StringHashMap<ke::AString> m_Keys; Trie *m_pKeys;
StringHashMap<void *> m_Sigs; Trie *m_pSigs;
unsigned int m_RefCount;
/* Parse states */ /* Parse states */
int m_ParseState; int m_ParseState;
unsigned int m_IgnoreLevel; unsigned int m_IgnoreLevel;
@@ -88,35 +82,6 @@ private:
char m_offset[64]; char m_offset[64];
char m_Game[256]; char m_Game[256];
bool bShouldBeReadingDefault; bool bShouldBeReadingDefault;
bool had_game;
bool matched_game;
bool had_engine;
bool matched_engine;
bool matched_platform;
/* Custom Sections */
unsigned int m_CustomLevel;
ITextListener_SMC *m_CustomHandler;
/* Support for reading Addresses */
struct AddressConf
{
char signatureName[64];
int readCount;
int read[8];
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read);
AddressConf() {}
};
char m_Address[64];
char m_AddressSignature[64];
int m_AddressReadCount;
int m_AddressRead[8];
StringHashMap<AddressConf> m_Addresses;
const char *m_pEngine;
const char *m_pBaseEngine;
}; };
class GameConfigManager : class GameConfigManager :
@@ -132,20 +97,13 @@ public: //IGameConfigManager
IGameConfig *ReadHandle(Handle_t hndl, IGameConfig *ReadHandle(Handle_t hndl,
IdentityToken_t *ident, IdentityToken_t *ident,
HandleError *err); HandleError *err);
void AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener);
void AcquireLock();
void ReleaseLock();
public: //SMGlobalClass public: //SMGlobalClass
void OnSourceModStartup(bool late); void OnSourceModStartup(bool late);
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModAllShutdown(); void OnSourceModAllShutdown();
public:
void RemoveCachedConfig(CGameConfig *config);
private: private:
NameHashSet<CGameConfig *> m_Lookup; List<CGameConfig *> m_cfgs;
public: Trie *m_pLookup;
StringHashMap<ITextListener_SMC *> m_customHandlers;
}; };
extern GameConfigManager g_GameConfigs; extern GameConfigManager g_GameConfigs;
+82 -813
View File
File diff suppressed because it is too large Load Diff
+13 -96
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -35,21 +35,14 @@
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.h> #include <sh_string.h>
#include <sh_tinyhash.h> #include <sh_tinyhash.h>
#include <am-utility.h> #include <sm_trie_tpl.h>
#include <am-hashmap.h> #include "sm_trie.h"
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
#include "sm_globals.h" #include "sm_globals.h"
#include "sm_queue.h" #include "sm_queue.h"
#include <IGameHelpers.h> #include <IGameHelpers.h>
#include <KeyValues.h> #include <KeyValues.h>
#include <server_class.h> #include <server_class.h>
#include <datamap.h> #include <datamap.h>
#include <ihandleentity.h>
#include <tier0/icommandline.h>
#if SOURCE_ENGINE >= SE_PORTAL2
#include <string_t.h>
#endif
class CCommand; class CCommand;
@@ -61,38 +54,16 @@ using namespace SourceMod;
struct DataTableInfo struct DataTableInfo
{ {
struct SendPropPolicy
{
static inline bool matches(const char *name, const sm_sendprop_info_t &info)
{
return strcmp(name, info.prop->GetName()) == 0;
}
};
static inline bool matches(const char *name, const DataTableInfo *info)
{
return strcmp(name, info->sc->GetName()) == 0;
}
DataTableInfo(ServerClass *sc)
: sc(sc)
{
}
ServerClass *sc; ServerClass *sc;
NameHashSet<sm_sendprop_info_t, SendPropPolicy> lookup; KTrie<sm_sendprop_info_t> lookup;
}; };
struct DataMapCachePolicy struct DataMapTrie
{ {
static inline bool matches(const char *name, const sm_datatable_info_t &info) DataMapTrie() : trie(NULL) {}
{ Trie *trie;
return strcmp(name, info.prop->fieldName) == 0;
}
}; };
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
struct DelayedFakeCliCmd struct DelayedFakeCliCmd
{ {
String cmd; String cmd;
@@ -103,32 +74,11 @@ struct DelayedFakeCliCmd
struct CachedCommandInfo struct CachedCommandInfo
{ {
const CCommand *args; const CCommand *args;
#if SOURCE_ENGINE <= SE_DARKMESSIAH #if !defined ORANGEBOX_BUILD
char cmd[300]; char cmd[300];
#endif #endif
}; };
struct DelayedKickInfo
{
int userid;
int client;
char buffer[384];
};
// copy from game/shared/entitylist_base.h
class CEntInfo
{
public:
IHandleEntity *m_pEntity;
int m_SerialNumber;
CEntInfo *m_pPrev;
CEntInfo *m_pNext;
#if (SOURCE_ENGINE >= SE_PORTAL2) && (SOURCE_ENGINE != SE_DOTA)
string_t m_iName;
string_t m_iClassName;
#endif
};
class CHalfLife2 : class CHalfLife2 :
public SMGlobalClass, public SMGlobalClass,
public IGameHelpers public IGameHelpers
@@ -139,7 +89,6 @@ public:
public: public:
void OnSourceModStartup(bool late); void OnSourceModStartup(bool late);
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModAllInitialized_Post();
/*void OnSourceModAllShutdown();*/ /*void OnSourceModAllShutdown();*/
public: //IGameHelpers public: //IGameHelpers
SendProp *FindInSendTable(const char *classname, const char *offset); SendProp *FindInSendTable(const char *classname, const char *offset);
@@ -147,33 +96,12 @@ public: //IGameHelpers
datamap_t *GetDataMap(CBaseEntity *pEntity); datamap_t *GetDataMap(CBaseEntity *pEntity);
ServerClass *FindServerClass(const char *classname); ServerClass *FindServerClass(const char *classname);
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset); typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable);
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset); void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
bool TextMsg(int client, int dest, const char *msg); bool TextMsg(int client, int dest, const char *msg);
bool HintTextMsg(int client, const char *msg); bool HintTextMsg(int client, const char *msg);
bool HintTextMsg(cell_t *players, int count, const char *msg);
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show); bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
bool IsLANServer(); bool IsLANServer();
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL); bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
edict_t *EdictOfIndex(int index);
int IndexOfEdict(edict_t *pEnt);
edict_t *GetHandleEntity(CBaseHandle &hndl);
void SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt);
const char *GetCurrentMap();
void ServerCommand(const char *buffer);
CBaseEntity *ReferenceToEntity(cell_t entRef);
cell_t EntityToReference(CBaseEntity *pEntity);
cell_t IndexToReference(int entIndex);
int ReferenceToIndex(cell_t entRef);
cell_t ReferenceToBCompatRef(cell_t entRef);
CEntInfo *LookupEntity(int entIndex);
cell_t EntityToBCompatRef(CBaseEntity *pEntity);
void *GetGlobalEntityList();
int GetSendPropOffset(SendProp *prop);
ICommandLine *GetValveCommandLine();
const char *GetEntityClassname(edict_t *pEdict);
const char *GetEntityClassname(CBaseEntity *pEntity);
bool IsMapValid(const char *map);
public: public:
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd); void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
void ProcessFakeCliCmdQueue(); void ProcessFakeCliCmdQueue();
@@ -182,34 +110,23 @@ public:
void PopCommandStack(); void PopCommandStack();
const CCommand *PeekCommandStack(); const CCommand *PeekCommandStack();
const char *CurrentCommandName(); const char *CurrentCommandName();
void AddDelayedKick(int client, int userid, const char *msg); #if !defined METAMOD_PLAPI_VERSION
void ProcessDelayedKicks();
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
bool IsOriginalEngine(); bool IsOriginalEngine();
#endif #endif
private: private:
DataTableInfo *_FindServerClass(const char *classname); DataTableInfo *_FindServerClass(const char *classname);
private: private:
void InitLogicalEntData(); Trie *m_pClasses;
void InitCommandLine(); List<DataTableInfo *> m_Tables;
private: THash<datamap_t *, DataMapTrie> m_Maps;
typedef ke::HashMap<datamap_t *, DataMapCache *, ke::PointerPolicy<datamap_t> > DataTableMap;
NameHashSet<DataTableInfo *> m_Classes;
DataTableMap m_Maps;
int m_MsgTextMsg; int m_MsgTextMsg;
int m_HinTextMsg; int m_HinTextMsg;
int m_SayTextMsg;
int m_VGUIMenu; int m_VGUIMenu;
Queue<DelayedFakeCliCmd *> m_CmdQueue; Queue<DelayedFakeCliCmd *> m_CmdQueue;
CStack<DelayedFakeCliCmd *> m_FreeCmds; CStack<DelayedFakeCliCmd *> m_FreeCmds;
CStack<CachedCommandInfo> m_CommandStack; CStack<CachedCommandInfo> m_CommandStack;
Queue<DelayedKickInfo> m_DelayedKicks;
void *m_pGetCommandLine;
}; };
extern CHalfLife2 g_HL2; extern CHalfLife2 g_HL2;
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData);
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_ #endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
+24 -92
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,15 +34,12 @@
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "Logger.h" #include "Logger.h"
#include "LibrarySys.h" #include "systems/LibrarySys.h"
#include "TimerSys.h" #include "TimerSys.h"
#include "logic_bridge.h" #include "sm_version.h"
#include <sourcemod_version.h>
Logger g_Logger; Logger g_Logger;
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
/** /**
* :TODO: This should be creating the log folder if it doesn't exist * :TODO: This should be creating the log folder if it doesn't exist
*/ */
@@ -94,27 +91,14 @@ ConfigResult Logger::OnSourceModConfigChanged(const char *key,
return ConfigResult_Ignore; return ConfigResult_Ignore;
} }
static void HookLogPrint(const char *message)
{
g_in_game_log_hook = true;
bool stopped = logicore.OnLogPrint(message);
g_in_game_log_hook = false;
if (stopped)
RETURN_META(MRES_SUPERCEDE);
}
void Logger::OnSourceModStartup(bool late) void Logger::OnSourceModStartup(bool late)
{ {
InitLogger(m_Mode); InitLogger(m_Mode);
SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
} }
void Logger::OnSourceModAllShutdown() void Logger::OnSourceModAllShutdown()
{ {
CloseLogger(); CloseLogger();
SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
} }
void Logger::OnSourceModLevelChange(const char *mapName) void Logger::OnSourceModLevelChange(const char *mapName)
@@ -165,7 +149,7 @@ void Logger::_NewMapFile()
} else { } else {
char date[32]; char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION); 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, SVN_FULL_VERSION);
fclose(fp); fclose(fp);
} }
} }
@@ -212,8 +196,7 @@ void Logger::InitLogger(LoggingMode mode)
time_t t; time_t t;
GetAdjustedTime(&t); GetAdjustedTime(&t);
tm *curtime = localtime(&t); tm *curtime = localtime(&t);
m_NrmCurDay = curtime->tm_mday; m_CurDay = curtime->tm_mday;
m_ErrCurDay = curtime->tm_mday;
char _filename[256]; char _filename[256];
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
@@ -262,19 +245,6 @@ void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
va_end(ap); va_end(ap);
} }
void Logger::LogToFileOnly(FILE *fp, const char *msg, ...)
{
if (!m_Active)
{
return;
}
va_list ap;
va_start(ap, msg);
LogToFileOnlyEx(fp, msg, ap);
va_end(ap);
}
void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap) void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
{ {
if (!m_Active) if (!m_Active)
@@ -282,8 +252,6 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
return; return;
} }
static ConVar *sv_logecho = icvar->FindVar("sv_logecho");
char buffer[3072]; char buffer[3072];
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
@@ -294,42 +262,10 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer); fprintf(fp, "L %s: %s\n", date, buffer);
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
if (!sv_logecho || sv_logecho->GetBool())
{
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
}
}
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
{
if (!m_Active)
{
return;
}
char buffer[3072];
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t;
GetAdjustedTime(&t);
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);
} }
void Logger::LogMessage(const char *vafmt, ...) void Logger::LogMessage(const char *vafmt, ...)
{
va_list ap;
va_start(ap, vafmt);
LogMessageEx(vafmt, ap);
va_end(ap);
}
void Logger::LogMessageEx(const char *vafmt, va_list ap)
{ {
if (!m_Active) if (!m_Active)
{ {
@@ -338,7 +274,10 @@ void Logger::LogMessageEx(const char *vafmt, va_list ap)
if (m_Mode == LoggingMode_Game) if (m_Mode == LoggingMode_Game)
{ {
va_list ap;
va_start(ap, vafmt);
_PrintToGameLog(vafmt, ap); _PrintToGameLog(vafmt, ap);
va_end(ap);
return; return;
} }
@@ -366,12 +305,12 @@ void Logger::LogMessageEx(const char *vafmt, va_list ap)
} }
} }
} else { } else {
if (m_NrmCurDay != curtime->tm_mday) if (m_CurDay != curtime->tm_mday)
{ {
char _filename[256]; char _filename[256];
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); g_SourceMod.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_NrmFileName.assign(_filename);
m_NrmCurDay = curtime->tm_mday; m_CurDay = curtime->tm_mday;
m_DailyPrintHdr = true; m_DailyPrintHdr = true;
} }
fp = fopen(m_NrmFileName.c_str(), "a+"); fp = fopen(m_NrmFileName.c_str(), "a+");
@@ -384,9 +323,12 @@ void Logger::LogMessageEx(const char *vafmt, va_list ap)
char date[32]; char date[32];
m_DailyPrintHdr = false; m_DailyPrintHdr = false;
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: 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); 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, SVN_FULL_VERSION);
} }
va_list ap;
va_start(ap, vafmt);
LogToOpenFileEx(fp, vafmt, ap); LogToOpenFileEx(fp, vafmt, ap);
va_end(ap);
fclose(fp); fclose(fp);
} else { } else {
goto print_error; goto print_error;
@@ -403,14 +345,6 @@ print_error:
} }
void Logger::LogError(const char *vafmt, ...) void Logger::LogError(const char *vafmt, ...)
{
va_list ap;
va_start(ap, vafmt);
LogErrorEx(vafmt, ap);
va_end(ap);
}
void Logger::LogErrorEx(const char *vafmt, va_list ap)
{ {
if (!m_Active) if (!m_Active)
{ {
@@ -421,12 +355,12 @@ void Logger::LogErrorEx(const char *vafmt, va_list ap)
GetAdjustedTime(&t); GetAdjustedTime(&t);
tm *curtime = localtime(&t); tm *curtime = localtime(&t);
if (curtime->tm_mday != m_ErrCurDay) if (curtime->tm_mday != m_CurDay)
{ {
char _filename[256]; char _filename[256];
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday); g_SourceMod.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_ErrFileName.assign(_filename);
m_ErrCurDay = curtime->tm_mday; m_CurDay = curtime->tm_mday;
m_ErrMapStart = false; m_ErrMapStart = false;
} }
@@ -441,7 +375,10 @@ void Logger::LogErrorEx(const char *vafmt, va_list ap)
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); 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; m_ErrMapStart = true;
} }
va_list ap;
va_start(ap, vafmt);
LogToOpenFileEx(fp, vafmt, ap); LogToOpenFileEx(fp, vafmt, ap);
va_end(ap);
fclose(fp); fclose(fp);
} }
else else
@@ -545,20 +482,13 @@ void Logger::DisableLogging()
} }
void Logger::LogFatal(const char *msg, ...) void Logger::LogFatal(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
LogFatalEx(msg, ap);
va_end(ap);
}
void Logger::LogFatalEx(const char *msg, va_list ap)
{ {
/* :TODO: make this print all pretty-like /* :TODO: make this print all pretty-like
* In fact, the pretty log printing function should be abstracted. * In fact, the pretty log printing function should be abstracted.
* It's already implemented twice which is bad. * It's already implemented twice which is bad.
*/ */
va_list ap;
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log"); g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
@@ -567,7 +497,9 @@ void Logger::LogFatalEx(const char *msg, va_list ap)
if (fp) if (fp)
{ {
m_Active = true; m_Active = true;
va_start(ap, msg);
LogToOpenFileEx(fp, msg, ap); LogToOpenFileEx(fp, msg, ap);
va_end(ap);
m_Active = false; m_Active = false;
fclose(fp); fclose(fp);
} }
+2 -9
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -74,16 +74,10 @@ public:
void EnableLogging(); void EnableLogging();
void DisableLogging(); void DisableLogging();
void LogMessage(const char *msg, ...); void LogMessage(const char *msg, ...);
void LogMessageEx(const char *msg, va_list ap);
void LogError(const char *msg, ...); void LogError(const char *msg, ...);
void LogErrorEx(const char *msg, va_list ap);
void LogFatal(const char *msg, ...); void LogFatal(const char *msg, ...);
void LogFatalEx(const char *msg, va_list ap);
void LogToOpenFile(FILE *fp, const char *msg, ...); void LogToOpenFile(FILE *fp, const char *msg, ...);
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap); void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
/* 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); void MapChange(const char *mapname);
const char *GetLogFileName(LogType type) const; const char *GetLogFileName(LogType type) const;
LoggingMode GetLoggingMode() const; LoggingMode GetLoggingMode() const;
@@ -96,8 +90,7 @@ private:
String m_ErrFileName; String m_ErrFileName;
String m_CurMapName; String m_CurMapName;
LoggingMode m_Mode; LoggingMode m_Mode;
int m_NrmCurDay; int m_CurDay;
int m_ErrCurDay;
bool m_ErrMapStart; bool m_ErrMapStart;
bool m_Active; bool m_Active;
bool m_DelayedStart; bool m_DelayedStart;
+60 -129
View File
@@ -2,41 +2,38 @@
# Makefile written by David "BAILOPAN" Anderson # Makefile written by David "BAILOPAN" Anderson
SMSDK = .. SMSDK = ..
SRCDS_BASE = ~/srcds
HL2SDK_ORIG = ../../hl2sdk HL2SDK_ORIG = ../../hl2sdk
HL2SDK_OB = ../../hl2sdk-ob HL2SDK_OB = ../../hl2sdk-ob
HL2SDK_CSS = ../../hl2sdk-css SOURCEMM14 = ../../sourcemm-1.4
HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve SOURCEMM16 = ../../sourcemm-1.6
HL2SDK_L4D = ../../hl2sdk-l4d
HL2SDK_L4D2 = ../../hl2sdk-l4d2
HL2SDK_CSGO = ../../hl2sdk-csgo
MMSOURCE = ../../mmsource-central
##################################### #####################################
### EDIT BELOW FOR OTHER PROJECTS ### ### EDIT BELOW FOR OTHER PROJECTS ###
##################################### #####################################
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \ OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
Database.cpp DebugReporter.cpp EventManager.cpp HalfLife2.cpp Logger.cpp \ Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
PlayerManager.cpp TimerSys.cpp UserMessages.cpp \ MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
sm_autonatives.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \ sm_autonatives.cpp sm_memtable.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.cpp \
sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \ sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp \ MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
frame_hooks.cpp concmd_cleaner.cpp NextMap.cpp \ frame_hooks.cpp concmd_cleaner.cpp Profiler.cpp
NativeOwner.cpp logic_bridge.cpp ConsoleDetours.cpp OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
OBJECTS += smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \ smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
smn_database.cpp smn_entities.cpp smn_events.cpp \ smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
smn_fakenatives.cpp smn_filesystem.cpp smn_halflife.cpp \ smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp smn_maplists.cpp \
smn_keyvalues.cpp smn_player.cpp \ smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
smn_usermsgs.cpp smn_menus.cpp smn_vector.cpp \ smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp \
smn_hudtext.cpp smn_nextmap.cpp smn_adt_trie.cpp smn_hudtext.cpp
OBJECTS += ExtensionSys.cpp \ OBJECTS += systems/ExtensionSys.cpp systems/ForwardSys.cpp systems/HandleSys.cpp \
ForwardSys.cpp \ systems/LibrarySys.cpp systems/PluginInfoDatabase.cpp systems/PluginSys.cpp \
HandleSys.cpp \ systems/ShareSys.cpp vm/sp_vm_basecontext.cpp vm/sp_vm_engine.cpp \
LibrarySys.cpp \ vm/sp_vm_function.cpp
PluginInfoDatabase.cpp \ OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
PluginSys.cpp \ OBJECTS += zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/deflate.c zlib/gzio.c \
ShareSys.cpp \ zlib/infback.c zlib/inffast.c zlib/inflate.c zlib/inftrees.c zlib/trees.c \
NativeInvoker.cpp zlib/uncompr.c zlib/zutil.c
############################################## ##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
@@ -46,122 +43,46 @@ C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3 C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc CPP = gcc-4.1
override ENGSET = false override ENGSET = false
ifneq (,$(filter original orangebox css orangeboxvalve left4dead left4dead2 csgo,$(ENGINE)))
override ENGSET = true
endif
ifeq "$(ENGINE)" "original" ifeq "$(ENGINE)" "original"
HL2SDK = $(HL2SDK_ORIG) HL2SDK = $(HL2SDK_ORIG)
HL2LIB = $(HL2SDK)/linux_sdk HL2PUB = $(HL2SDK_ORIG)/public
CFLAGS += -DSOURCE_ENGINE=1 HL2LIB = $(HL2SDK_ORIG)/linux_sdk
METAMOD = $(MMSOURCE)/core-legacy METAMOD = $(SOURCEMM14)
INCLUDE += -I$(HL2SDK)/public/dlls INCLUDE += -I$(HL2SDK)/public/dlls
SRCDS = $(SRCDS_BASE)
BINARY = sourcemod.1.ep1.so BINARY = sourcemod.1.ep1.so
override ENGSET = true
endif endif
ifeq "$(ENGINE)" "orangebox" ifeq "$(ENGINE)" "orangebox"
HL2SDK = $(HL2SDK_OB) HL2SDK = $(HL2SDK_OB)
HL2LIB = $(HL2SDK)/lib/linux HL2PUB = $(HL2SDK_OB)/public
CFLAGS += -DSOURCE_ENGINE=3 HL2LIB = $(HL2SDK_OB)/linux_sdk
METAMOD = $(MMSOURCE)/core CFLAGS += -DORANGEBOX_BUILD
METAMOD = $(SOURCEMM16)
INCLUDE += -I$(HL2SDK)/public/game/server INCLUDE += -I$(HL2SDK)/public/game/server
SRCDS = $(SRCDS_BASE)/orangebox
BINARY = sourcemod.2.ep2.so BINARY = sourcemod.2.ep2.so
endif override ENGSET = true
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 endif
HL2PUB = $(HL2SDK)/public LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so \
tier0_i486.so -lpthread -static-libgcc
OS := $(shell uname -s) INCLUDE_SMSDK = -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
ifeq "$(OS)" "Darwin" INCLUDE_SM16 = -I. -I.. -I$(SOURCEMM16)/sourcehook $(INCLUDE_SMSDK)
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 \ 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$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook \
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(METAMOD)/sourcemm -Isystems $(INCLUDE_SMSDK)
CFLAGS += -D_LINUX -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \ 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 \ -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 \ -Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32
-DSM_DEFAULT_THREADER -m32 -DCOMPILER_GCC CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
CPPFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -fno-threadsafe-statics -fno-exceptions -fno-rtti
################################################ ################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### ### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
@@ -181,9 +102,13 @@ ifeq "$(GCC_VERSION)" "4"
CPPFLAGS += $(CPP_GCC4_FLAGS) CPPFLAGS += $(CPP_GCC4_FLAGS)
endif endif
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) OBJ_LINUX := $(OBJECTS:%vm_engine.cpp=$(BIN_DIR)/%vm_engine.o)
OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o) OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
$(BIN_DIR)/%vm_engine.o: %vm_engine.cpp
$(CPP) $(INCLUDE_SM16) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.cpp $(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
@@ -191,15 +116,17 @@ $(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all: check all: check
mkdir -p $(BIN_DIR) mkdir -p $(BIN_DIR)/systems
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX) mkdir -p $(BIN_DIR)/vm
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX) mkdir -p $(BIN_DIR)/zlib
mkdir -p $(BIN_DIR)/thread
ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
$(MAKE) -f Makefile sourcemod $(MAKE) -f Makefile sourcemod
check: check:
if [ "$(ENGSET)" = "false" ]; then \ if [ "$(ENGSET)" == "false" ]; then \
echo "You must supply one of the following values for ENGINE:"; \ echo "You must supply ENGINE=orangebox or ENGINE=original"; \
echo "csgo, left4dead2, left4dead, orangeboxvalve, css, orangebox, or original"; \
exit 1; \ exit 1; \
fi fi
@@ -213,4 +140,8 @@ default: all
clean: check clean: check
rm -rf $(BIN_DIR)/*.o rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/systems/*.o
rm -rf $(BIN_DIR)/zlib/*.o
rm -rf $(BIN_DIR)/vm/*.o
rm -rf $(BIN_DIR)/thread/*.o
rm -rf $(BIN_DIR)/$(BINARY) rm -rf $(BIN_DIR)/$(BINARY)
+220
View File
@@ -0,0 +1,220 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2007 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 "MemoryUtils.h"
#include "ShareSys.h"
#ifdef PLATFORM_LINUX
#include <string.h>
#include <elf.h>
#endif
MemoryUtils g_MemUtils;
#if 0
MemoryUtils::MemoryUtils()
{
#ifdef PLATFORM_WINDOWS
SYSTEM_INFO info;
GetSystemInfo(&info);
m_PageSize = info.dwPageSize;
#elif defined PLATFORM_POSIX
m_PageSize = sysconf(_SC_PAGE_SIZE);
#endif
}
#endif
void MemoryUtils::OnSourceModAllInitialized()
{
g_ShareSys.AddInterface(NULL, this);
}
void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len)
{
DynLibInfo lib;
bool found;
char *ptr, *end;
memset(&lib, 0, sizeof(DynLibInfo));
if (!GetLibraryInfo(libPtr, lib))
{
return NULL;
}
ptr = reinterpret_cast<char *>(lib.baseAddress);
end = ptr + lib.memorySize;
while (ptr < end)
{
found = true;
for (register size_t i = 0; i < len; i++)
{
if (pattern[i] != '\x2A' && pattern[i] != ptr[i])
{
found = false;
break;
}
}
if (found)
return ptr;
ptr++;
}
return NULL;
}
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
{
unsigned long baseAddr;
if (libPtr == NULL)
{
return false;
}
#ifdef PLATFORM_WINDOWS
MEMORY_BASIC_INFORMATION info;
IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *pe;
IMAGE_FILE_HEADER *file;
IMAGE_OPTIONAL_HEADER *opt;
if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
{
return false;
}
baseAddr = reinterpret_cast<unsigned long>(info.AllocationBase);
/* All this is for our insane sanity checks :o */
dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr);
pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew);
file = &pe->FileHeader;
opt = &pe->OptionalHeader;
/* Check PE magic and signature */
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
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)
{
return false;
}
/* For our purposes, this must be a dynamic library */
if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
{
return false;
}
/* Finally, we can do this */
lib.memorySize = opt->SizeOfImage;
#elif defined PLATFORM_LINUX
Dl_info info;
Elf32_Ehdr *file;
Elf32_Phdr *phdr;
uint16_t phdrCount;
if (!dladdr(libPtr, &info))
{
return false;
}
if (!info.dli_fbase || !info.dli_fname)
{
return false;
}
/* This is for our insane sanity checks :o */
baseAddr = reinterpret_cast<unsigned long>(info.dli_fbase);
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
/* Check ELF magic */
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
{
return false;
}
/* Check ELF version */
if (file->e_ident[EI_VERSION] != EV_CURRENT)
{
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)
{
return false;
}
/* For our purposes, this must be a dynamic library/shared object */
if (file->e_type != ET_DYN)
{
return false;
}
phdrCount = file->e_phnum;
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
/* Add up the memory sizes of segments marked as PT_LOAD as those are the only ones that should be in memory */
for (uint16_t i = 0; i < phdrCount; i++)
{
Elf32_Phdr &hdr = phdr[i];
if (hdr.p_type == PT_LOAD)
{
lib.memorySize += hdr.p_memsz;
}
}
#endif
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
return true;
}
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -25,64 +25,34 @@
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_ #ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_ #define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
#include "common_logic.h"
#include <IMemoryUtils.h> #include <IMemoryUtils.h>
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE #include "sm_globals.h"
#include <sh_vector.h>
#include "sm_symtable.h"
using namespace SourceHook;
#endif
using namespace SourceMod; using namespace SourceMod;
#ifdef PLATFORM_APPLE
#include <CoreServices/CoreServices.h>
#endif
struct DynLibInfo struct DynLibInfo
{ {
void *baseAddress; void *baseAddress;
size_t memorySize; size_t memorySize;
}; };
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
struct LibSymbolTable
{
SymbolTable table;
uintptr_t lib_base;
uint32_t last_pos;
};
#endif
class MemoryUtils : class MemoryUtils :
public IMemoryUtils, public IMemoryUtils,
public SMGlobalClass public SMGlobalClass
{ {
public:
MemoryUtils();
~MemoryUtils();
public: // SMGlobalClass public: // SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
public: // IMemoryUtils public: // IMemoryUtils
void *FindPattern(const void *libPtr, const char *pattern, size_t len); void *FindPattern(const void *libPtr, const char *pattern, size_t len);
void *ResolveSymbol(void *handle, const char *symbol);
public:
bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
private: private:
CVector<LibSymbolTable *> m_SymTables; bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
#ifdef PLATFORM_APPLE
struct dyld_all_image_infos *m_ImageList;
SInt32 m_OSXMajor;
SInt32 m_OSXMinor;
#endif
#endif
}; };
extern MemoryUtils g_MemUtils; extern MemoryUtils g_MemUtils;
+17 -64
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -38,8 +38,9 @@
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "MenuStyle_Valve.h" #include "MenuStyle_Valve.h"
#include "ShareSys.h"
#include "HandleSys.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "logic_bridge.h"
MenuManager g_Menus; MenuManager g_Menus;
VoteMenuHandler s_VoteHandler; VoteMenuHandler s_VoteHandler;
@@ -54,24 +55,24 @@ MenuManager::MenuManager()
void MenuManager::OnSourceModAllInitialized() void MenuManager::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
HandleAccess access; HandleAccess access;
handlesys->InitAccessDefaults(NULL, &access); g_HandleSys.InitAccessDefaults(NULL, &access);
/* Deny cloning to menus */ /* Deny cloning to menus */
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY; access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
m_MenuType = handlesys->CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL); m_MenuType = g_HandleSys.CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
/* Also deny deletion to styles */ /* Also deny deletion to styles */
access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY; access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
m_StyleType = handlesys->CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL); m_StyleType = g_HandleSys.CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
} }
void MenuManager::OnSourceModAllShutdown() void MenuManager::OnSourceModAllShutdown()
{ {
handlesys->RemoveType(m_MenuType, g_pCoreIdent); g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
handlesys->RemoveType(m_StyleType, g_pCoreIdent); g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
} }
void MenuManager::OnHandleDestroy(HandleType_t type, void *object) void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
@@ -110,7 +111,7 @@ Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
return BAD_HANDLE; return BAD_HANDLE;
} }
return handlesys->CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL); return g_HandleSys.CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
} }
Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style) Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
@@ -120,7 +121,7 @@ Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
return BAD_HANDLE; return BAD_HANDLE;
} }
return handlesys->CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL); return g_HandleSys.CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
} }
HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu) HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
@@ -130,7 +131,7 @@ HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
sec.pOwner = NULL; sec.pOwner = NULL;
return handlesys->ReadHandle(handle, m_MenuType, &sec, (void **)menu); return g_HandleSys.ReadHandle(handle, m_MenuType, &sec, (void **)menu);
} }
HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style) HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
@@ -140,7 +141,7 @@ HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
sec.pOwner = g_pCoreIdent; sec.pOwner = g_pCoreIdent;
return handlesys->ReadHandle(handle, m_StyleType, &sec, (void **)style); return g_HandleSys.ReadHandle(handle, m_StyleType, &sec, (void **)style);
} }
bool MenuManager::SetDefaultStyle(IMenuStyle *style) bool MenuManager::SetDefaultStyle(IMenuStyle *style)
@@ -229,7 +230,6 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
unsigned int pgn = menu->GetPagination(); unsigned int pgn = menu->GetPagination();
unsigned int maxItems = style->GetMaxPageItems(); unsigned int maxItems = style->GetMaxPageItems();
bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT; bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
bool novoteButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_NOVOTE) == MENUFLAG_BUTTON_NOVOTE;
if (pgn != MENU_NO_PAGINATION) if (pgn != MENU_NO_PAGINATION)
{ {
@@ -240,11 +240,6 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
maxItems--; maxItems--;
} }
if (novoteButton)
{
maxItems--;
}
/* This is very not allowed! */ /* This is very not allowed! */
if (maxItems < 2) if (maxItems < 2)
{ {
@@ -440,20 +435,6 @@ skip_search:
/* Draw the item according to the order */ /* Draw the item according to the order */
menu_slots_t *slots = md.slots; menu_slots_t *slots = md.slots;
unsigned int position = 0; /* Keep track of the last position */ unsigned int position = 0; /* Keep track of the last position */
if (novoteButton)
{
char text[50];
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "No Vote", &client))
{
UTIL_Format(text, sizeof(text), "No Vote");
}
ItemDrawInfo dr(text, 0);
position = panel->DrawItem(dr);
slots[position].type = ItemSel_Exit;
position++;
}
if (order == ItemOrder_Ascending) if (order == ItemOrder_Ascending)
{ {
md.item_on_page = drawItems[0].position; md.item_on_page = drawItems[0].position;
@@ -604,20 +585,14 @@ skip_search:
{ {
if (exitBackButton) if (exitBackButton)
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client)) CorePlayerTranslate(client, text, sizeof(text), "Back", NULL);
{
UTIL_Format(text, sizeof(text), "Back");
}
dr.style = ITEMDRAW_CONTROL; dr.style = ITEMDRAW_CONTROL;
position = panel->DrawItem(dr); position = panel->DrawItem(dr);
slots[position].type = ItemSel_ExitBack; slots[position].type = ItemSel_ExitBack;
} }
else else
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client)) CorePlayerTranslate(client, text, sizeof(text), "Previous", NULL);
{
UTIL_Format(text, sizeof(text), "Previous");
}
dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL; dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
position = panel->DrawItem(dr); position = panel->DrawItem(dr);
slots[position].type = ItemSel_Back; slots[position].type = ItemSel_Back;
@@ -635,10 +610,7 @@ skip_search:
/* NEXT */ /* NEXT */
if (displayNext || canDrawDisabled) if (displayNext || canDrawDisabled)
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client)) CorePlayerTranslate(client, text, sizeof(text), "Next", NULL);
{
UTIL_Format(text, sizeof(text), "Next");
}
dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL; dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
position = panel->DrawItem(dr); position = panel->DrawItem(dr);
slots[position].type = ItemSel_Next; slots[position].type = ItemSel_Next;
@@ -666,10 +638,7 @@ skip_search:
/* EXIT */ /* EXIT */
if (exitButton) if (exitButton)
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client)) CorePlayerTranslate(client, text, sizeof(text), "Exit", NULL);
{
UTIL_Format(text, sizeof(text), "Exit");
}
dr.style = ITEMDRAW_CONTROL; dr.style = ITEMDRAW_CONTROL;
position = panel->DrawItem(dr); position = panel->DrawItem(dr);
slots[position].type = ItemSel_Exit; slots[position].type = ItemSel_Exit;
@@ -808,19 +777,3 @@ unsigned int MenuManager::GetRemainingVoteDelay()
{ {
return s_VoteHandler.GetRemainingVoteDelay(); return s_VoteHandler.GetRemainingVoteDelay();
} }
bool MenuManager::IsClientInVotePool(int client)
{
return s_VoteHandler.IsClientInVotePool(client);
}
bool MenuManager::RedrawClientVoteMenu(int client)
{
return RedrawClientVoteMenu2(client, true);
}
bool MenuManager::RedrawClientVoteMenu2(int client, bool revote)
{
return s_VoteHandler.RedrawToClient(client, revote);
}
+2 -4
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -37,6 +37,7 @@
#include <sh_stack.h> #include <sh_stack.h>
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.h> #include <sh_string.h>
#include "sm_memtable.h"
#include "sm_globals.h" #include "sm_globals.h"
using namespace SourceMod; using namespace SourceMod;
@@ -88,9 +89,6 @@ public:
bool IsVoteInProgress(); bool IsVoteInProgress();
void CancelVoting(); void CancelVoting();
unsigned int GetRemainingVoteDelay(); unsigned int GetRemainingVoteDelay();
bool IsClientInVotePool(int client);
bool RedrawClientVoteMenu(int client);
bool RedrawClientVoteMenu2(int client, bool revote);
public: //IHandleTypeDispatch public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object); void OnHandleDestroy(HandleType_t type, void *object);
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize); bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
+48 -39
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,12 +34,11 @@
#include "MenuStyle_Base.h" #include "MenuStyle_Base.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "MenuManager.h" #include "MenuManager.h"
#include "HandleSys.h"
#include "CellRecipientFilter.h" #include "CellRecipientFilter.h"
#if defined MENU_DEBUG #if defined MENU_DEBUG
#include "Logger.h" #include "Logger.h"
#endif #endif
#include "logic_bridge.h"
#include "AutoHandleRooter.h"
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE) BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
{ {
@@ -315,7 +314,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
if (sound != NULL) if (sound != NULL)
{ {
edict_t *pEdict = PEntityOfEntIndex(client); edict_t *pEdict = engine->PEntityOfEntIndex(client);
if (pEdict) if (pEdict)
{ {
ICollideable *pCollideable = pEdict->GetCollideable(); ICollideable *pCollideable = pEdict->GetCollideable();
@@ -323,24 +322,15 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
if (pCollideable) if (pCollideable)
{ {
const Vector & pos = pCollideable->GetCollisionOrigin(); const Vector & pos = pCollideable->GetCollisionOrigin();
enginesound->EmitSound(filter, enginesound->EmitSound(filter,
client, client,
CHAN_AUTO, CHAN_AUTO,
#if SOURCE_ENGINE >= SE_PORTAL2
sound,
-1,
#endif
sound, sound,
VOL_NORM, VOL_NORM,
ATTN_NORM, ATTN_NORM,
#if SOURCE_ENGINE >= SE_PORTAL2
0,
#endif
0, 0,
PITCH_NORM, PITCH_NORM,
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2
0,
#endif
&pos); &pos);
} }
} }
@@ -387,9 +377,6 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
RemoveClientFromWatch(client); RemoveClientFromWatch(client);
} }
Handle_t hndl = menu ? menu->GetHandle() : BAD_HANDLE;
AutoHandleRooter ahr(hndl);
if (cancel) if (cancel)
{ {
mh->OnMenuCancel(menu, client, reason); mh->OnMenuCancel(menu, client, reason);
@@ -604,7 +591,7 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
} }
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) : CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
m_pStyle(pStyle), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false), m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false), m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT) m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
{ {
@@ -627,74 +614,94 @@ Handle_t CBaseMenu::GetHandle()
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw) bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
{ {
if (m_Pagination == (unsigned)MENU_NO_PAGINATION if (m_Pagination == (unsigned)MENU_NO_PAGINATION
&& m_items.length() >= m_pStyle->GetMaxPageItems()) && m_items.size() >= m_pStyle->GetMaxPageItems())
{ {
return false; return false;
} }
CItem item; CItem item;
item.info = info; item.infoString = m_Strings.AddString(info);
if (draw.display) if (draw.display)
item.display = new ke::AString(draw.display); {
item.displayString = m_Strings.AddString(draw.display);
}
item.style = draw.style; item.style = draw.style;
m_items.append(ke::Move(item)); m_items.push_back(item);
return true; return true;
} }
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw) bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
{ {
if (m_Pagination == (unsigned)MENU_NO_PAGINATION && if (m_Pagination == (unsigned)MENU_NO_PAGINATION
m_items.length() >= m_pStyle->GetMaxPageItems()) && m_items.size() >= m_pStyle->GetMaxPageItems())
{ {
return false; return false;
} }
if (position >= m_items.length()) if (position >= m_items.size())
{
return false; return false;
}
CItem item; CItem item;
item.info = info; item.infoString = m_Strings.AddString(info);
if (draw.display) if (draw.display)
item.display = new ke::AString(draw.display); {
item.displayString = m_Strings.AddString(draw.display);
}
item.style = draw.style; item.style = draw.style;
m_items.insert(position, ke::Move(item)); CVector<CItem>::iterator iter = m_items.iterAt(position);
m_items.insert(iter, item);
return true; return true;
} }
bool CBaseMenu::RemoveItem(unsigned int position) bool CBaseMenu::RemoveItem(unsigned int position)
{ {
if (position >= m_items.length()) if (position >= m_items.size())
{
return false; return false;
}
m_items.erase(m_items.iterAt(position));
if (m_items.size() == 0)
{
m_Strings.Reset();
}
m_items.remove(position);
return true; return true;
} }
void CBaseMenu::RemoveAllItems() void CBaseMenu::RemoveAllItems()
{ {
m_items.clear(); m_items.clear();
m_Strings.Reset();
} }
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */) const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
{ {
if (position >= m_items.length()) if (position >= m_items.size())
{
return NULL; return NULL;
}
if (draw) if (draw)
{ {
draw->display = m_items[position].display->chars(); draw->display = m_Strings.GetString(m_items[position].displayString);
draw->style = m_items[position].style; draw->style = m_items[position].style;
} }
return m_items[position].info.chars(); return m_Strings.GetString(m_items[position].infoString);
} }
unsigned int CBaseMenu::GetItemCount() unsigned int CBaseMenu::GetItemCount()
{ {
return m_items.length(); return m_items.size();
} }
bool CBaseMenu::SetPagination(unsigned int itemsPerPage) bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
@@ -727,12 +734,12 @@ IMenuStyle *CBaseMenu::GetDrawStyle()
void CBaseMenu::SetDefaultTitle(const char *message) void CBaseMenu::SetDefaultTitle(const char *message)
{ {
m_Title = message; m_Title.assign(message);
} }
const char *CBaseMenu::GetDefaultTitle() const char *CBaseMenu::GetDefaultTitle()
{ {
return m_Title.chars(); return m_Title.c_str();
} }
void CBaseMenu::Cancel() void CBaseMenu::Cancel()
@@ -799,7 +806,7 @@ void CBaseMenu::InternalDelete()
m_hHandle = BAD_HANDLE; m_hHandle = BAD_HANDLE;
m_bDeleting = true; m_bDeleting = true;
handlesys->FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
} }
m_pHandler->OnMenuDestroy(this); m_pHandler->OnMenuDestroy(this);
@@ -824,5 +831,7 @@ IMenuHandler *CBaseMenu::GetHandler()
unsigned int CBaseMenu::GetBaseMemUsage() unsigned int CBaseMenu::GetBaseMemUsage()
{ {
return m_Title.length() + (m_items.length() * sizeof(CItem)); return m_Title.size()
+ m_Strings.GetMemTable()->GetMemUsage()
+ (m_items.size() * sizeof(CItem));
} }
+13 -28
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,45 +34,29 @@
#include <IMenuManager.h> #include <IMenuManager.h>
#include <IPlayerHelpers.h> #include <IPlayerHelpers.h>
#include <am-string.h> #include <sh_string.h>
#include <am-vector.h> #include <sh_vector.h>
#include "sm_memtable.h"
#include "sm_fastlink.h" #include "sm_fastlink.h"
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook;
class CItem class CItem
{ {
public: public:
CItem() CItem()
{ {
infoString = -1;
displayString = -1;
style = 0; style = 0;
access = 0; access = 0;
} }
CItem(ke::Moveable<CItem> other)
: info(ke::Move(other->info)),
display(ke::Move(other->display))
{
style = other->style;
access = other->access;
}
CItem & operator =(ke::Moveable<CItem> other)
{
info = ke::Move(other->info);
display = ke::Move(other->display);
style = other->style;
access = other->access;
return *this;
}
public: public:
ke::AString info; int infoString;
ke::AutoPtr<ke::AString> display; int displayString;
unsigned int style; unsigned int style;
unsigned int access; unsigned int access;
private:
CItem(const CItem &other) KE_DELETE;
CItem &operator =(const CItem &other) KE_DELETE;
}; };
class CBaseMenuPlayer class CBaseMenuPlayer
@@ -155,10 +139,11 @@ public:
private: private:
void InternalDelete(); void InternalDelete();
protected: protected:
ke::AString m_Title; String m_Title;
IMenuStyle *m_pStyle; IMenuStyle *m_pStyle;
BaseStringTable m_Strings;
unsigned int m_Pagination; unsigned int m_Pagination;
ke::Vector<CItem> m_items; CVector<CItem> m_items;
bool m_bShouldDelete; bool m_bShouldDelete;
bool m_bCancelling; bool m_bCancelling;
IdentityToken_t *m_pOwner; IdentityToken_t *m_pOwner;
+7 -76
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,20 +32,11 @@
#include "MenuStyle_Radio.h" #include "MenuStyle_Radio.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "UserMessages.h" #include "UserMessages.h"
#include <IGameConfigs.h> #include "GameConfigs.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#if defined MENU_DEBUG #if defined MENU_DEBUG
#include "Logger.h" #include "Logger.h"
#endif #endif
#include "logic_bridge.h"
#ifdef USE_PROTOBUF_USERMESSAGES
#include <google/protobuf/descriptor.h>
#endif
#if SOURCE_ENGINE == SE_CSGO
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
#endif
extern const char *g_RadioNumTable[]; extern const char *g_RadioNumTable[];
CRadioStyle g_RadioMenuStyle; CRadioStyle g_RadioMenuStyle;
@@ -53,14 +44,6 @@ int g_ShowMenuId = -1;
bool g_bRadioInit = false; bool g_bRadioInit = false;
unsigned int g_RadioMenuTimeout = 0; unsigned int g_RadioMenuTimeout = 0;
// back, next, exit
#define MAX_PAGINATION_OPTIONS 3
#define MAX_MENUSLOT_KEYS 10
static unsigned int s_RadioMaxPageItems = MAX_MENUSLOT_KEYS;
CRadioStyle::CRadioStyle() CRadioStyle::CRadioStyle()
{ {
m_players = new CRadioMenuPlayer[256+1]; m_players = new CRadioMenuPlayer[256+1];
@@ -106,18 +89,6 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
g_RadioMenuTimeout = 0; g_RadioMenuTimeout = 0;
} }
const char *items = g_pGameConf->GetKeyValue("RadioMenuMaxPageItems");
if (items != NULL)
{
int value = atoi(items);
// Only override the mostly-safe default if it's a sane value
if (value > MAX_PAGINATION_OPTIONS && value <= MAX_MENUSLOT_KEYS)
{
s_RadioMaxPageItems = value;
}
}
g_Menus.AddStyle(this); g_Menus.AddStyle(this);
g_Menus.SetDefaultStyle(this); g_Menus.SetDefaultStyle(this);
@@ -138,11 +109,7 @@ void CRadioStyle::OnSourceModShutdown()
bool CRadioStyle::IsSupported() bool CRadioStyle::IsSupported()
{ {
#if SOURCE_ENGINE == SE_DOTA
return false;
#else
return (g_ShowMenuId != -1); return (g_ShowMenuId != -1);
#endif
} }
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd) bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
@@ -167,23 +134,13 @@ static unsigned int g_last_holdtime = 0;
static unsigned int g_last_client_count = 0; static unsigned int g_last_client_count = 0;
static int g_last_clients[256]; static int g_last_clients[256];
#ifdef USE_PROTOBUF_USERMESSAGES
void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter)
#else
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter) void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
#endif
{ {
#if SOURCE_ENGINE != SE_DOTA
int count = pFilter->GetRecipientCount(); int count = pFilter->GetRecipientCount();
#ifdef USE_PROTOBUF_USERMESSAGES
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
#else
bf_read br(bf->GetBasePointer(), 3); bf_read br(bf->GetBasePointer(), 3);
br.ReadWord(); br.ReadWord();
int c = br.ReadChar(); int c = br.ReadChar();
#endif
g_last_holdtime = (c == -1) ? 0 : (unsigned)c; g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
@@ -191,7 +148,6 @@ void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFil
{ {
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i); g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
} }
#endif
} }
void CRadioStyle::OnUserMessageSent(int msg_id) void CRadioStyle::OnUserMessageSent(int msg_id)
@@ -232,7 +188,7 @@ IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwn
unsigned int CRadioStyle::GetMaxPageItems() unsigned int CRadioStyle::GetMaxPageItems()
{ {
return s_RadioMaxPageItems; return 10;
} }
const char *CRadioStyle::GetStyleName() const char *CRadioStyle::GetStyleName()
@@ -350,7 +306,7 @@ unsigned int CRadioDisplay::GetCurrentKey()
bool CRadioDisplay::SetCurrentKey(unsigned int key) bool CRadioDisplay::SetCurrentKey(unsigned int key)
{ {
if (key < m_NextPos || m_NextPos > s_RadioMaxPageItems) if (key < m_NextPos || m_NextPos > 10)
{ {
return false; return false;
} }
@@ -386,7 +342,7 @@ void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item) unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
{ {
if (m_NextPos > s_RadioMaxPageItems || !CanDrawItem(item.style)) if (m_NextPos > 10 || !CanDrawItem(item.style))
{ {
return 0; return 0;
} }
@@ -479,8 +435,7 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
void CRadioMenuPlayer::Radio_Refresh() void CRadioMenuPlayer::Radio_Refresh()
{ {
#if SOURCE_ENGINE != SE_DOTA cell_t players[1] = {m_index};
cell_t players[1] = { (cell_t)m_index };
char *ptr = display_pkt; char *ptr = display_pkt;
char save = 0; char save = 0;
size_t len = display_len; size_t len = display_len;
@@ -496,15 +451,6 @@ void CRadioMenuPlayer::Radio_Refresh()
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime); 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
// 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);
msg->set_display_time(time);
msg->set_menu_string(ptr);
g_UserMsgs.EndMessage();
#else
while (true) while (true)
{ {
if (len > 240) if (len > 240)
@@ -512,8 +458,7 @@ void CRadioMenuPlayer::Radio_Refresh()
save = ptr[240]; save = ptr[240];
ptr[240] = '\0'; ptr[240] = '\0';
} }
bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
bf_write *buffer = g_UserMsgs.StartBitBufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
buffer->WriteWord(display_keys); buffer->WriteWord(display_keys);
buffer->WriteChar(time ? time : -1); buffer->WriteChar(time ? time : -1);
buffer->WriteByte( (len > 240) ? 1 : 0 ); buffer->WriteByte( (len > 240) ? 1 : 0 );
@@ -530,10 +475,8 @@ void CRadioMenuPlayer::Radio_Refresh()
break; break;
} }
} }
#endif
display_last_refresh = gpGlobals->curtime; display_last_refresh = gpGlobals->curtime;
#endif // !DOTA
} }
int CRadioDisplay::GetAmountRemaining() int CRadioDisplay::GetAmountRemaining()
@@ -567,7 +510,6 @@ unsigned int CRadioDisplay::GetApproxMemUsage()
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner) CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
{ {
m_Pagination = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
} }
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr) bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
@@ -608,17 +550,6 @@ bool CRadioMenu::DisplayAtItem(int client,
time); time);
} }
bool CRadioMenu::SetPagination(unsigned int itemsPerPage)
{
const unsigned int maxPerPage = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
if (itemsPerPage > maxPerPage)
{
return false;
}
return CBaseMenu::SetPagination(itemsPerPage);
}
void CRadioMenu::Cancel_Finally() void CRadioMenu::Cancel_Finally()
{ {
g_RadioMenuStyle.CancelMenu(this); g_RadioMenuStyle.CancelMenu(this);
+3 -12
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -37,7 +37,7 @@
#include "MenuStyle_Base.h" #include "MenuStyle_Base.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <IPlayerHelpers.h> #include <IPlayerHelpers.h>
#include "UserMessages.h" #include <IUserMessages.h>
#include "sm_fastlink.h" #include "sm_fastlink.h"
#include <sh_stack.h> #include <sh_stack.h>
#include <compat_wrappers.h> #include <compat_wrappers.h>
@@ -65,11 +65,7 @@ private:
class CRadioStyle : class CRadioStyle :
public BaseMenuStyle, public BaseMenuStyle,
public SMGlobalClass, public SMGlobalClass,
#ifdef USE_PROTOBUF_USERMESSAGES public IUserMessageListener
public IProtobufUserMessageListener
#else
public IBitBufUserMessageListener
#endif
{ {
public: public:
CRadioStyle(); CRadioStyle();
@@ -88,11 +84,7 @@ public: //IMenuStyle
unsigned int GetMaxPageItems(); unsigned int GetMaxPageItems();
unsigned int GetApproxMemUsage(); unsigned int GetApproxMemUsage();
public: //IUserMessageListener public: //IUserMessageListener
#ifdef USE_PROTOBUF_USERMESSAGES
void OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter);
#else
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter); void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
#endif
void OnUserMessageSent(int msg_id); void OnUserMessageSent(int msg_id);
public: public:
bool IsSupported(); bool IsSupported();
@@ -150,7 +142,6 @@ public:
unsigned int time, unsigned int time,
unsigned int start_item, unsigned int start_item,
IMenuHandler *alt_handler/* =NULL */); IMenuHandler *alt_handler/* =NULL */);
bool SetPagination(unsigned int itemsPerPage);
void Cancel_Finally(); void Cancel_Finally();
unsigned int GetApproxMemUsage(); unsigned int GetApproxMemUsage();
}; };
+6 -9
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,6 +32,7 @@
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "MenuStyle_Valve.h" #include "MenuStyle_Valve.h"
#include "Translator.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "ConCmdManager.h" #include "ConCmdManager.h"
@@ -65,20 +66,16 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom
void ValveMenuStyle::OnSourceModAllInitialized() void ValveMenuStyle::OnSourceModAllInitialized()
{ {
#if SOURCE_ENGINE != SE_DOTA
g_Players.AddClientListener(this); g_Players.AddClientListener(this);
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false); SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers); g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
#endif
} }
void ValveMenuStyle::OnSourceModShutdown() void ValveMenuStyle::OnSourceModShutdown()
{ {
#if SOURCE_ENGINE != SE_DOTA
SH_RELEASE_CALLCLASS(g_pSPHCC); SH_RELEASE_CALLCLASS(g_pSPHCC);
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false); SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
g_Players.RemoveClientListener(this); g_Players.RemoveClientListener(this);
#endif
} }
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict, void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
@@ -91,7 +88,7 @@ void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
return; return;
} }
int client = IndexOfEdict(pEdict); int client = engine->IndexOfEdict(pEdict);
if (client < 1 || client > 256) if (client < 1 || client > 256)
{ {
return; return;
@@ -328,7 +325,7 @@ void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int ti
m_pKv->SetInt("time", time ? time : 200); m_pKv->SetInt("time", time ? time : 200);
SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)( SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
PEntityOfEntIndex(client), engine->PEntityOfEntIndex(client),
DIALOG_MENU, DIALOG_MENU,
m_pKv, m_pKv,
vsp_interface); vsp_interface);
+1 -1
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
+17 -305
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,57 +34,10 @@
#include "MenuVoting.h" #include "MenuVoting.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <sourcemod.h>
#include <Logger.h>
#include <HalfLife2.h>
#include <mathlib.h>
#include <const.h>
#include <ITranslator.h>
#include "logic_bridge.h"
float g_next_vote = 0.0f; float g_next_vote = 0.0f;
#define VOTE_NOT_VOTING -2 #if defined ORANGEBOX_BUILD
#define VOTE_PENDING -1
ConVar sm_vote_hintbox("sm_vote_progress_hintbox",
"0",
0,
"Show current vote progress in a hint box",
true,
0.0,
true,
1.0);
ConVar sm_vote_chat("sm_vote_progress_chat",
"0",
0,
"Show current vote progress as chat messages",
true,
0.0,
true,
1.0);
ConVar sm_vote_console("sm_vote_progress_console",
"0",
0,
"Show current vote progress as console messages",
true,
0.0,
true,
1.0);
ConVar sm_vote_client_console("sm_vote_progress_client_console",
"0",
0,
"Show current vote progress as console messages to clients",
true,
0.0,
true,
1.0);
#if SOURCE_ENGINE >= SE_ORANGEBOX
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue); void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
#else #else
void OnVoteDelayChange(ConVar *cvar, const char *value); void OnVoteDelayChange(ConVar *cvar, const char *value);
@@ -99,7 +52,7 @@ ConVar sm_vote_delay("sm_vote_delay",
0.0, 0.0,
OnVoteDelayChange); OnVoteDelayChange);
#if SOURCE_ENGINE >= SE_ORANGEBOX #if defined ORANGEBOX_BUILD
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue) void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
#else #else
void OnVoteDelayChange(ConVar *cvar, const char *value) void OnVoteDelayChange(ConVar *cvar, const char *value)
@@ -160,19 +113,14 @@ void VoteMenuHandler::OnClientDisconnected(int client)
return; return;
} }
/* Wipe out their vote if they had one. We have to make sure the the the /* Wipe out their vote if they had one */
* newly connected client is not allowed to vote.
*/
int item; int item;
if ((item = m_ClientVotes[client]) >= VOTE_PENDING) if ((item = m_ClientVotes[client]) >= 0)
{ {
if (item >= 0) assert((unsigned)item < m_Items);
{ assert(m_Votes[item] > 0);
assert((unsigned)item < m_Items); m_Votes[item]--;
assert(m_Votes[item] > 0); m_ClientVotes[client] = -1;
m_Votes[item]--;
}
m_ClientVotes[client] = VOTE_NOT_VOTING;
} }
} }
@@ -181,28 +129,18 @@ bool VoteMenuHandler::IsVoteInProgress()
return (m_pCurMenu != NULL); return (m_pCurMenu != NULL);
} }
bool VoteMenuHandler::StartVote(IBaseMenu *menu, bool VoteMenuHandler::StartVote(IBaseMenu *menu, unsigned int num_clients, int clients[], unsigned int max_time, unsigned int flags/* =0 */)
unsigned int num_clients,
int clients[],
unsigned int max_time,
unsigned int flags/* =0 */)
{ {
if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags)) if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
{ {
return false; return false;
} }
/* Note: we can use game time and not universal time because
* if we're voting then players are in-game.
*/
float fVoteDelay = sm_vote_delay.GetFloat(); float fVoteDelay = sm_vote_delay.GetFloat();
if (fVoteDelay < 1.0) if (fVoteDelay < 1.0)
{ {
g_next_vote = 0.0; g_next_vote = 0.0;
} } else {
else
{
/* This little trick breaks for infinite votes! /* This little trick breaks for infinite votes!
* However, we just ignore that since those 1) shouldn't exist and * However, we just ignore that since those 1) shouldn't exist and
* 2) people must be checking IsVoteInProgress() beforehand anyway. * 2) people must be checking IsVoteInProgress() beforehand anyway.
@@ -210,15 +148,8 @@ bool VoteMenuHandler::StartVote(IBaseMenu *menu,
g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time; g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time;
} }
m_fStartTime = gpGlobals->curtime;
m_nMenuTime = max_time;
for (unsigned int i=0; i<num_clients; i++) for (unsigned int i=0; i<num_clients; i++)
{ {
if (clients[i] < 1 || clients[i] > 256)
{
continue;
}
menu->Display(clients[i], max_time, this); menu->Display(clients[i], max_time, this);
} }
@@ -227,72 +158,6 @@ bool VoteMenuHandler::StartVote(IBaseMenu *menu,
return true; return true;
} }
bool VoteMenuHandler::IsClientInVotePool(int client)
{
if (client < 1
|| client > g_Players.MaxClients()
|| m_pCurMenu == NULL)
{
return false;
}
return (m_ClientVotes[client] > VOTE_NOT_VOTING);
}
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
{
if (!IsClientInVotePool(client)
|| m_ClientVotes[client] == VOTE_PENDING)
{
return false;
}
*pItem = m_ClientVotes[client];
return true;
}
bool VoteMenuHandler::RedrawToClient(int client, bool revotes)
{
unsigned int time_limit;
if (!IsClientInVotePool(client))
{
return false;
}
if (m_ClientVotes[client] >= 0)
{
if ((m_VoteFlags & VOTEFLAG_NO_REVOTES) == VOTEFLAG_NO_REVOTES || !revotes)
{
return false;
}
assert((unsigned)m_ClientVotes[client] < m_Items);
assert(m_Votes[m_ClientVotes[client]] > 0);
m_Votes[m_ClientVotes[client]]--;
m_ClientVotes[client] = VOTE_PENDING;
m_Revoting[client] = true;
m_NumVotes--;
}
if (m_nMenuTime == MENU_TIME_FOREVER)
{
time_limit = m_nMenuTime;
}
else
{
time_limit = (int)((float)m_nMenuTime - (gpGlobals->curtime - m_fStartTime));
/* Make sure this doesn't round to zero */
if (time_limit == MENU_TIME_FOREVER)
{
time_limit = 1;
}
}
return m_pCurMenu->Display(client, time_limit, this);
}
bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu, bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
IMenuHandler *handler, IMenuHandler *handler,
unsigned int time, unsigned int time,
@@ -308,8 +173,7 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
/* Mark all clients as not voting */ /* Mark all clients as not voting */
for (int i=1; i<=gpGlobals->maxClients; i++) for (int i=1; i<=gpGlobals->maxClients; i++)
{ {
m_ClientVotes[i] = VOTE_NOT_VOTING; m_ClientVotes[i] = -2;
m_Revoting[i] = false;
} }
m_Items = menu->GetItemCount(); m_Items = menu->GetItemCount();
@@ -323,9 +187,7 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
m_Votes[i] = 0; m_Votes[i] = 0;
} }
m_Votes.resize(m_Items, 0); m_Votes.resize(m_Items, 0);
} } else {
else
{
for (unsigned int i=0; i<m_Items; i++) for (unsigned int i=0; i<m_Items; i++)
{ {
m_Votes[i] = 0; m_Votes[i] = 0;
@@ -353,8 +215,6 @@ void VoteMenuHandler::StartVoting()
m_pHandler->OnMenuVoteStart(m_pCurMenu); m_pHandler->OnMenuVoteStart(m_pCurMenu);
m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
/* By now we know how many clients were set. /* By now we know how many clients were set.
* If there are none, we should end IMMEDIATELY. * If there are none, we should end IMMEDIATELY.
*/ */
@@ -362,8 +222,6 @@ void VoteMenuHandler::StartVoting()
{ {
EndVoting(); EndVoting();
} }
m_TotalClients = m_Clients;
} }
void VoteMenuHandler::DecrementPlayerCount() void VoteMenuHandler::DecrementPlayerCount()
@@ -394,17 +252,10 @@ void VoteMenuHandler::EndVoting()
if (fVoteDelay < 1.0) if (fVoteDelay < 1.0)
{ {
g_next_vote = 0.0; g_next_vote = 0.0;
} } else {
else
{
g_next_vote = gpGlobals->curtime + fVoteDelay; g_next_vote = gpGlobals->curtime + fVoteDelay;
} }
if (m_displayTimer)
{
g_Timers.KillTimer(m_displayTimer);
}
if (m_bCancelled) if (m_bCancelled)
{ {
/* If we were cancelled, don't bother tabulating anything. /* If we were cancelled, don't bother tabulating anything.
@@ -451,7 +302,7 @@ void VoteMenuHandler::EndVoting()
/* Build the client list */ /* Build the client list */
for (int i=1; i<=gpGlobals->maxClients; i++) for (int i=1; i<=gpGlobals->maxClients; i++)
{ {
if (m_ClientVotes[i] >= VOTE_PENDING) if (m_ClientVotes[i] >= -1)
{ {
client_vote[vote.num_clients].client = i; client_vote[vote.num_clients].client = i;
client_vote[vote.num_clients].item = m_ClientVotes[i]; client_vote[vote.num_clients].item = m_ClientVotes[i];
@@ -495,7 +346,7 @@ void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display) void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
{ {
m_ClientVotes[client] = VOTE_PENDING; m_ClientVotes[client] = -1;
m_pHandler->OnMenuDisplay(menu, client, display); m_pHandler->OnMenuDisplay(menu, client, display);
} }
@@ -517,58 +368,6 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
m_ClientVotes[client] = item; m_ClientVotes[client] = item;
m_Votes[item]++; m_Votes[item]++;
m_NumVotes++; 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);
if (sm_vote_console.GetBool())
{
int target = SOURCEMOD_SERVER_LANGUAGE;
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
&target, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
Engine_LogPrintWrapper(buffer);
}
if (sm_vote_chat.GetBool() || sm_vote_client_console.GetBool())
{
int maxclients = g_Players.GetMaxClients();
for (int i=1; i<=maxclients; i++)
{
CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
assert(pPlayer);
if (pPlayer->IsInGame() && !pPlayer->IsFakeClient())
{
if (m_Revoting[client])
{
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote",
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
}
else
{
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
}
if (sm_vote_chat.GetBool())
{
g_HL2.TextMsg(i, HUD_PRINTTALK, buffer);
}
if (sm_vote_client_console.GetBool())
{
ClientConsolePrint(pPlayer->GetEdict(), buffer);
}
}
}
}
}
BuildVoteLeaders();
DrawHintProgress();
} }
m_pHandler->OnMenuSelect(menu, client, item); m_pHandler->OnMenuSelect(menu, client, item);
@@ -591,9 +390,6 @@ void VoteMenuHandler::InternalReset()
m_NumVotes = 0; m_NumVotes = 0;
m_bCancelled = false; m_bCancelled = false;
m_pHandler = NULL; m_pHandler = NULL;
m_leaderList[0] = '\0';
m_displayTimer = NULL;
m_TotalClients = 0;
} }
void VoteMenuHandler::CancelVoting() void VoteMenuHandler::CancelVoting()
@@ -615,87 +411,3 @@ bool VoteMenuHandler::IsCancelling()
{ {
return m_bCancelled; return m_bCancelled;
} }
void VoteMenuHandler::DrawHintProgress()
{
if (!sm_vote_hintbox.GetBool())
{
return;
}
static char buffer[1024];
float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
if (timeRemaining < 0)
{
timeRemaining = 0.0;
}
int iTimeRemaining = RoundFloatToInt(timeRemaining);
int maxclients = g_Players.GetMaxClients();
for (int i=1; i<=maxclients; i++)
{
if (g_Players.GetPlayerByIndex(i)->IsInGame())
{
logicore.CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count",
&i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
g_HL2.HintTextMsg(i, buffer);
}
}
}
void VoteMenuHandler::BuildVoteLeaders()
{
if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
{
return;
}
menu_vote_result_t vote;
menu_vote_result_t::menu_item_vote_t item_vote[256];
memset(&vote, 0, sizeof(vote));
/* Build the item list */
for (unsigned int i=0; i<m_Items; i++)
{
if (m_Votes[i] > 0)
{
item_vote[vote.num_items].count = m_Votes[i];
item_vote[vote.num_items].item = i;
vote.num_votes += m_Votes[i];
vote.num_items++;
}
}
vote.item_list = item_vote;
assert(vote.num_votes);
/* Sort the item list descending */
qsort(item_vote,
vote.num_items,
sizeof(menu_vote_result_t::menu_item_vote_t),
SortVoteItems);
/* Take the top 3 (if applicable) and draw them */
int len = 0;
for (unsigned int i=0; i<vote.num_items && i<3; i++)
{
int curItem = vote.item_list[i].item;
ItemDrawInfo dr;
m_pCurMenu->GetItemInfo(curItem, &dr);
len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
}
}
SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
{
DrawHintProgress();
return Pl_Continue;
}
void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
{
m_displayTimer = NULL;
}
+2 -19
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -36,7 +36,6 @@
#include <IPlayerHelpers.h> #include <IPlayerHelpers.h>
#include <sh_vector.h> #include <sh_vector.h>
#include "sm_globals.h" #include "sm_globals.h"
#include <TimerSys.h>
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
@@ -44,8 +43,7 @@ using namespace SourceMod;
class VoteMenuHandler : class VoteMenuHandler :
public IMenuHandler, public IMenuHandler,
public SMGlobalClass, public SMGlobalClass,
public IClientListener, public IClientListener
public ITimedEvent
{ {
public: //SMGlobalClass public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
@@ -63,9 +61,6 @@ public: //IMenuHandler
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason); void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style); void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr); unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
public: //ITimedEvent
ResultType OnTimer(ITimer *pTimer, void *pData);
void OnTimerEnd(ITimer *pTimer, void *pData);
public: public:
bool StartVote(IBaseMenu *menu, bool StartVote(IBaseMenu *menu,
unsigned int num_clients, unsigned int num_clients,
@@ -77,9 +72,6 @@ public:
IBaseMenu *GetCurrentMenu(); IBaseMenu *GetCurrentMenu();
bool IsCancelling(); bool IsCancelling();
unsigned int GetRemainingVoteDelay(); unsigned int GetRemainingVoteDelay();
bool IsClientInVotePool(int client);
bool GetClientVoteChoice(int client, unsigned int *pItem);
bool RedrawToClient(int client, bool revote);
private: private:
void Reset(IMenuHandler *mh); void Reset(IMenuHandler *mh);
void DecrementPlayerCount(); void DecrementPlayerCount();
@@ -90,12 +82,9 @@ private:
unsigned int time, unsigned int time,
unsigned int flags); unsigned int flags);
void StartVoting(); void StartVoting();
void DrawHintProgress();
void BuildVoteLeaders();
private: private:
IMenuHandler *m_pHandler; IMenuHandler *m_pHandler;
unsigned int m_Clients; unsigned int m_Clients;
unsigned int m_TotalClients;
unsigned int m_Items; unsigned int m_Items;
CVector<unsigned int> m_Votes; CVector<unsigned int> m_Votes;
IBaseMenu *m_pCurMenu; IBaseMenu *m_pCurMenu;
@@ -104,13 +93,7 @@ private:
unsigned int m_NumVotes; unsigned int m_NumVotes;
unsigned int m_VoteTime; unsigned int m_VoteTime;
unsigned int m_VoteFlags; unsigned int m_VoteFlags;
float m_fStartTime;
unsigned int m_nMenuTime;
int m_ClientVotes[256+1]; int m_ClientVotes[256+1];
bool m_Revoting[256+1];
char m_leaderList[1024];
ITimer *m_displayTimer;
}; };
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_ #endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
-232
View File
@@ -1,232 +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 "NextMap.h"
#include "Logger.h"
#include "HalfLife2.h"
#include "sourcemm_api.h"
#include "sm_stringutil.h"
#include "sourcehook.h"
#include "sm_srvcmds.h"
NextMapManager g_NextMap;
#if SOURCE_ENGINE != SE_DARKMESSIAH
SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *);
#else
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
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
ConCommand *changeLevelCmd = NULL;
ConVar sm_nextmap("sm_nextmap", "", FCVAR_NOTIFY);
bool g_forcedChange = false;
void NextMapManager::OnSourceModAllInitialized_Post()
{
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
#else
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
#endif
ConCommand *pCmd = FindCommand("changelevel");
if (pCmd != NULL)
{
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdChangeLevelCallback), false);
changeLevelCmd = pCmd;
}
}
void NextMapManager::OnSourceModShutdown()
{
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
#else
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
#endif
if (changeLevelCmd != NULL)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, changeLevelCmd, SH_STATIC(CmdChangeLevelCallback), false);
}
SourceHook::List<MapChangeData *>::iterator iter;
iter = m_mapHistory.begin();
while (iter != m_mapHistory.end())
{
delete (MapChangeData *)*iter;
iter = m_mapHistory.erase(iter);
}
}
const char *NextMapManager::GetNextMap()
{
return sm_nextmap.GetString();
}
bool NextMapManager::SetNextMap(const char *map)
{
if (!g_HL2.IsMapValid(map))
{
return false;
}
sm_nextmap.SetValue(map);
return true;
}
#if SOURCE_ENGINE != SE_DARKMESSIAH
void NextMapManager::HookChangeLevel(const char *map, const char *unknown)
#else
void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading)
#endif
{
if (g_forcedChange)
{
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
RETURN_META(MRES_IGNORED);
}
const char *newmap = sm_nextmap.GetString();
if (newmap[0] == 0 || !g_HL2.IsMapValid(newmap))
{
RETURN_META(MRES_IGNORED);
}
g_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");
#if SOURCE_ENGINE != SE_DARKMESSIAH
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown));
#else
RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown, video, bLongLoading));
#endif
}
void NextMapManager::OnSourceModLevelChange( const char *mapName )
{
/* Skip the first 'mapchange' when the server starts up */
if (m_tempChangeInfo.startTime != 0)
{
if (strcmp(mapName, m_tempChangeInfo.m_mapName) == 0)
{
/* The map change was as we expected */
m_mapHistory.push_back(new MapChangeData(lastMap, m_tempChangeInfo.m_changeReason, m_tempChangeInfo.startTime));
}
else
{
/* Something intercepted the mapchange */
char newReason[255];
UTIL_Format(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)
{
SourceHook::List<MapChangeData *>::iterator iter;
iter = m_mapHistory.begin();
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);
}
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);
/* Change level and skip our hook */
g_forcedChange = true;
engine->ChangeLevel(mapName, NULL);
g_forcedChange = false;
}
NextMapManager::NextMapManager()
{
m_tempChangeInfo = MapChangeData();
m_mapHistory = SourceHook::List<MapChangeData *>();
}
#if SOURCE_ENGINE == SE_DOTA
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command)
{
#else
void CmdChangeLevelCallback()
{
CCommand command;
#endif
if (command.ArgC() < 2)
{
return;
}
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");
}
}
-107
View File
@@ -1,107 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_NEXTMAP_H_
#define _INCLUDE_SOURCEMOD_NEXTMAP_H_
#include "sm_globals.h"
#include "eiface.h"
#include "sh_list.h"
#include "sm_stringutil.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);
startTime = time;
}
MapChangeData()
{
m_mapName[0] = '\0';
m_changeReason[0] = '\0';
startTime = 0;
}
char m_mapName[PLATFORM_MAX_PATH];
char m_changeReason[100];
time_t startTime;
};
#if SOURCE_ENGINE == SE_DOTA
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command);
#else
void CmdChangeLevelCallback();
#endif
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
friend void CmdChangeLevelCallback(const CCommand &command);
#else
friend void CmdChangeLevelCallback();
#endif
void OnSourceModAllInitialized_Post();
void OnSourceModShutdown();
void OnSourceModLevelChange(const char *mapName);
const char *GetNextMap();
bool SetNextMap(const char *map);
void ForceChangeLevel(const char *mapName, const char* changeReason);
#if SOURCE_ENGINE != SE_DARKMESSIAH
void HookChangeLevel(const char *map, const char *unknown);
#else
void HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading);
#endif
public:
SourceHook::List<MapChangeData *> m_mapHistory;
private:
MapChangeData m_tempChangeInfo;
char lastMap[32];
};
extern NextMapManager g_NextMap;
#endif //_INCLUDE_SOURCEMOD_NEXTMAP_H_
+186 -1089
View File
File diff suppressed because it is too large Load Diff
+7 -75
View File
@@ -41,7 +41,6 @@
#include <sh_string.h> #include <sh_string.h>
#include <sh_list.h> #include <sh_list.h>
#include <sh_vector.h> #include <sh_vector.h>
#include "ConVarManager.h"
using namespace SourceHook; using namespace SourceHook;
@@ -51,16 +50,6 @@ using namespace SourceHook;
#define MIN_API_FOR_ADMINCALLS 7 #define MIN_API_FOR_ADMINCALLS 7
union serial_t
{
uint32_t value;
struct
{
uint32_t index : 8;
uint32_t serial : 24;
} bits;
};
class CPlayer : public IGamePlayer class CPlayer : public IGamePlayer
{ {
friend class PlayerManager; friend class PlayerManager;
@@ -69,32 +58,24 @@ public:
public: public:
const char *GetName(); const char *GetName();
const char *GetIPAddress(); const char *GetIPAddress();
const char *GetAuthString(bool validated = true); const char *GetAuthString();
unsigned int GetSteamAccountID(bool validated = true);
edict_t *GetEdict(); edict_t *GetEdict();
bool IsInGame(); bool IsInGame();
bool WasCountedAsInGame(); bool WasCountedAsInGame();
bool IsConnected(); bool IsConnected();
bool IsAuthorized(); bool IsAuthorized();
bool IsFakeClient(); bool IsFakeClient();
bool IsSourceTV() const;
bool IsReplay() const;
void SetAdminId(AdminId id, bool temporary); void SetAdminId(AdminId id, bool temporary);
AdminId GetAdminId(); AdminId GetAdminId();
void Kick(const char *str); void Kick(const char *str);
bool IsInKickQueue();
IPlayerInfo *GetPlayerInfo(); IPlayerInfo *GetPlayerInfo();
unsigned int GetLanguageId(); unsigned int GetLanguageId();
void SetLanguageId(unsigned int id);
int GetUserId(); int GetUserId();
bool RunAdminCacheChecks(); bool RunAdminCacheChecks();
void NotifyPostAdminChecks(); void NotifyPostAdminChecks();
unsigned int GetSerial();
int GetIndex() const;
void PrintToConsole(const char *pMsg);
void ClearAdmin();
public: public:
void DoBasicAdminChecks(); void DoBasicAdminChecks();
bool IsInKickQueue();
void MarkAsBeingKicked(); void MarkAsBeingKicked();
int GetLifeState(); int GetLifeState();
private: private:
@@ -103,11 +84,9 @@ private:
void Disconnect(); void Disconnect();
void SetName(const char *name); void SetName(const char *name);
void DumpAdmin(bool deleting); void DumpAdmin(bool deleting);
void SetAuthString(const char *auth); void Authorize(const char *auth);
void Authorize();
void Authorize_Post(); void Authorize_Post();
void DoPostConnectAuthorization(); void DoPostConnectAuthorization();
bool IsAuthStringValidated();
private: private:
bool m_IsConnected; bool m_IsConnected;
bool m_IsInGame; bool m_IsInGame;
@@ -126,14 +105,6 @@ private:
int m_iIndex; int m_iIndex;
unsigned int m_LangId; unsigned int m_LangId;
int m_UserId; int m_UserId;
bool m_bFakeClient;
bool m_bIsSourceTV;
bool m_bIsReplay;
serial_t m_Serial;
unsigned int m_SteamAccountID;
#if SOURCE_ENGINE == SE_CSGO
QueryCvarCookie_t m_LanguageCookie;
#endif
}; };
class PlayerManager : class PlayerManager :
@@ -149,35 +120,24 @@ public: //SMGlobalClass
void OnSourceModShutdown(); void OnSourceModShutdown();
void OnSourceModLevelEnd(); void OnSourceModLevelEnd();
ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength); ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
void OnSourceModMaxPlayersChanged(int newvalue);
public: public:
CPlayer *GetPlayerByIndex(int client) const; CPlayer *GetPlayerByIndex(int client) const;
void RunAuthChecks(); void RunAuthChecks();
void ClearAdminId(AdminId id);
void ClearAllAdmins();
public: 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(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); bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
void OnClientPutInServer(edict_t *pEntity, char const *playername); void OnClientPutInServer(edict_t *pEntity, char const *playername);
void OnClientDisconnect(edict_t *pEntity); void OnClientDisconnect(edict_t *pEntity);
void OnClientDisconnect_Post(edict_t *pEntity); void OnClientDisconnect_Post(edict_t *pEntity);
#if SOURCE_ENGINE >= SE_ORANGEBOX #if defined ORANGEBOX_BUILD
void OnClientCommand(edict_t *pEntity, const CCommand &args); void OnClientCommand(edict_t *pEntity, const CCommand &args);
#else #else
void OnClientCommand(edict_t *pEntity); void OnClientCommand(edict_t *pEntity);
#endif #endif
void OnClientSettingsChanged(edict_t *pEntity); void OnClientSettingsChanged(edict_t *pEntity);
//void OnClientSettingsChanged_Pre(edict_t *pEntity); //void OnClientSettingsChanged_Pre(edict_t *pEntity);
#endif
void OnServerHibernationUpdate(bool bHibernating);
public: //IPlayerManager public: //IPlayerManager
void AddClientListener(IClientListener *listener); void AddClientListener(IClientListener *listener);
void RemoveClientListener(IClientListener *listener); void RemoveClientListener(IClientListener *listener);
@@ -192,9 +152,6 @@ public: //IPlayerManager
void RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler); void RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler); void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
void ProcessCommandTarget(cmd_target_info_t *info); void ProcessCommandTarget(cmd_target_info_t *info);
int GetClientFromSerial(unsigned int serial);
void ClearAdminId(AdminId id);
void RecheckAnyAdmins();
public: public:
inline int MaxClients() inline int MaxClients()
{ {
@@ -211,23 +168,14 @@ public:
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id); bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id); bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
const char *GetPassInfoVar(); const char *GetPassInfoVar();
void RecheckAnyAdmins();
unsigned int GetReplyTo(); unsigned int GetReplyTo();
unsigned int SetReplyTo(unsigned int reply); unsigned int SetReplyTo(unsigned int reply);
void MaxPlayersChanged(int newvalue = -1);
#if SOURCE_ENGINE == SE_CSGO
bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
#endif
private: private:
#if SOURCE_ENGINE == SE_DOTA
void OnServerActivate();
#else
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax); void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
#endif
void InvalidatePlayer(CPlayer *pPlayer);
private: private:
List<IClientListener *> m_hooks; List<IClientListener *> m_hooks;
IForward *m_clconnect; IForward *m_clconnect;
IForward *m_clconnect_post;
IForward *m_cldisconnect; IForward *m_cldisconnect;
IForward *m_cldisconnect_post; IForward *m_cldisconnect_post;
IForward *m_clputinserver; IForward *m_clputinserver;
@@ -240,30 +188,14 @@ private:
int *m_UserIdLookUp; int *m_UserIdLookUp;
int m_maxClients; int m_maxClients;
int m_PlayerCount; int m_PlayerCount;
int m_PlayersSinceActive;
bool m_FirstPass; bool m_FirstPass;
unsigned int *m_AuthQueue; unsigned int *m_AuthQueue;
String m_PassInfoVar; String m_PassInfoVar;
bool m_QueryLang; bool m_QueryLang;
bool m_bAuthstringValidation; // are we validating admins with steam before authorizing?
bool m_bIsListenServer; bool m_bIsListenServer;
int m_ListenClient; int m_ListenClient;
bool m_bIsSourceTVActive;
bool m_bIsReplayActive;
int m_SourceTVUserId;
int m_ReplayUserId;
}; };
#if SOURCE_ENGINE == SE_DOTA
void CmdMaxplayersCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void CmdMaxplayersCallback(const CCommand &command);
#else
void CmdMaxplayersCallback();
#endif
extern void ClientConsolePrint(edict_t *e, const char *fmt, ...);
extern PlayerManager g_Players; extern PlayerManager g_Players;
extern bool g_OnMapStarted; extern bool g_OnMapStarted;
extern const unsigned int *g_NumPlayersToAuth; extern const unsigned int *g_NumPlayersToAuth;
+26 -55
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -30,13 +30,13 @@
*/ */
#include "Profiler.h" #include "Profiler.h"
#include <ISourceMod.h> #include "PluginSys.h"
#include "sm_stringutil.h"
#include "Logger.h"
#if defined PLATFORM_POSIX #if defined PLATFORM_POSIX
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#endif #endif
#include <IPluginSys.h>
#include "stringutil.h"
ProfileEngine g_Profiler; ProfileEngine g_Profiler;
IProfiler *sm_profiler = &g_Profiler; IProfiler *sm_profiler = &g_Profiler;
@@ -314,74 +314,43 @@ void ProfileEngine::Clear()
void ProfileEngine::OnSourceModAllInitialized() void ProfileEngine::OnSourceModAllInitialized()
{ {
rootmenu->AddRootConsoleCommand2("profiler", "Profiler commands", this); g_RootMenu.AddRootConsoleCommand("profiler", "Profiler commands", this);
} }
void ProfileEngine::OnSourceModShutdown() void ProfileEngine::OnSourceModShutdown()
{ {
rootmenu->RemoveRootConsoleCommand("profiler", this); g_RootMenu.RemoveRootConsoleCommand("profiler", this);
} }
void ProfileEngine::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command) void ProfileEngine::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
{ {
if (command->ArgC() >= 3) if (command.ArgC() >= 3)
{ {
if (strcmp(command->Arg(2), "flush") == 0) if (strcmp(command.Arg(2), "flush") == 0)
{ {
FILE *fp; FILE *fp;
char path[256]; char path[256];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL)); g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
if ((fp = fopen(path, "wt")) == NULL) if ((fp = fopen(path, "wt")) == NULL)
{ {
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path); g_RootMenu.ConsolePrint("Failed, could not open file for writing: %s", path);
return; return;
} }
GenerateReport(fp); GenerateReport(fp);
fclose(fp); fclose(fp);
Clear();
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path); g_RootMenu.ConsolePrint("Profiler report generated as: %s\n", path);
return; return;
} }
else if (strcmp(command->Arg(2), "report") == 0)
{
FILE *fp;
char path[256];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
if ((fp = fopen(path, "wt")) == NULL)
{
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
return;
}
GenerateReport(fp);
fclose(fp);
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
return;
}
else if (strcmp(command->Arg(2), "clear") == 0)
{
Clear();
rootmenu->ConsolePrint("Profiler statistics cleared.\n");
return;
}
} }
rootmenu->ConsolePrint("Profiler commands:"); g_RootMenu.ConsolePrint("Profiler commands:");
rootmenu->DrawGenericOption("flush", "Flushes statistics to disk and starts over"); g_RootMenu.DrawGenericOption("flush", "Flushes statistics to disk and starts over");
rootmenu->DrawGenericOption("report", "Flushes statistics to disk");
rootmenu->DrawGenericOption("clear", "Clears statistics");
} }
bool ProfileEngine::GenerateReport(FILE *fp) bool ProfileEngine::GenerateReport(FILE *fp)
@@ -419,8 +388,8 @@ void ProfileEngine::WriteReport(FILE *fp, ProfileReport *report, const char *nam
ar = report->GetReport(i); ar = report->GetReport(i);
strncopy(new_name, ar->atom_name, sizeof(new_name)); strncopy(new_name, ar->atom_name, sizeof(new_name));
UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "&lt;", true); UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "&lt;");
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", "&gt;", true); UTIL_ReplaceAll(new_name, sizeof(new_name), ">", "&gt;");
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n", fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
new_name, new_name,
@@ -465,33 +434,33 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
{ {
double atom_time; double atom_time;
char full_name[256]; char full_name[256];
prof_atom_report_t *report; prof_atom_report_t **pReport, *report;
if (atom.atom_type == SP_PROF_NATIVES) if (atom.atom_type == SP_PROF_NATIVES)
{ {
smcore.strncopy(full_name, atom.name, sizeof(full_name)); strncopy(full_name, atom.name, sizeof(full_name));
} }
else else
{ {
IPlugin *pl; CPlugin *pl;
const char *file; const char *file;
file = "unknown"; file = "unknown";
if ((pl = pluginsys->FindPluginByContext(atom.ctx)) != NULL) if ((pl = g_PluginSys.GetPluginByCtx(atom.ctx)) != NULL)
{ {
file = pl->GetFilename(); file = pl->GetFilename();
} }
smcore.Format(full_name, sizeof(full_name), "%s!%s", file, atom.name); UTIL_Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
} }
atom_time = CalcAtomTime(atom); atom_time = CalcAtomTime(atom);
if (!m_ReportLookup.retrieve(full_name, &report)) if ((pReport = m_ReportLookup.retrieve(full_name)) == NULL)
{ {
report = new prof_atom_report_t; report = new prof_atom_report_t;
smcore.strncopy(report->atom_name, full_name, sizeof(report->atom_name)); strncopy(report->atom_name, full_name, sizeof(report->atom_name));
report->max_time = atom_time; report->max_time = atom_time;
report->min_time = atom_time; report->min_time = atom_time;
report->num_calls = 1; report->num_calls = 1;
@@ -502,6 +471,8 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
} }
else else
{ {
report = *pReport;
if (atom_time > report->max_time) if (atom_time > report->max_time)
{ {
report->max_time = atom_time; report->max_time = atom_time;
+8 -13
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -34,12 +34,12 @@
#include <sp_vm_api.h> #include <sp_vm_api.h>
#include <sm_platform.h> #include <sm_platform.h>
#include <sm_trie_tpl.h>
#include <sh_vector.h> #include <sh_vector.h>
#include <sh_stack.h> #include <sh_stack.h>
#include <sm_namehashset.h>
#include <stdio.h> #include <stdio.h>
#include "common_logic.h" #include "sm_globals.h"
#include <IRootConsoleMenu.h> #include "sm_srvcmds.h"
using namespace SourcePawn; using namespace SourcePawn;
using namespace SourceHook; using namespace SourceHook;
@@ -72,11 +72,6 @@ struct prof_atom_report_t
unsigned int num_calls; /* Number of invocations */ unsigned int num_calls; /* Number of invocations */
double min_time; /* Min time spent in one call, in s */ double min_time; /* Min time spent in one call, in s */
double max_time; /* Max time spent in one call, in s */ double max_time; /* Max time spent in one call, in s */
static inline bool matches(const char *name, const prof_atom_report_t *report)
{
return strcmp(report->atom_name, name) == 0;
}
}; };
class ProfileReport class ProfileReport
@@ -89,7 +84,7 @@ public:
prof_atom_report_t *GetReport(size_t i); prof_atom_report_t *GetReport(size_t i);
void Clear(); void Clear();
private: private:
NameHashSet<prof_atom_report_t *> m_ReportLookup; KTrie<prof_atom_report_t *> m_ReportLookup;
CVector<prof_atom_report_t *> m_Reports; CVector<prof_atom_report_t *> m_Reports;
}; };
@@ -108,7 +103,7 @@ public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown(); void OnSourceModShutdown();
public: //IRootConsoleCommand public: //IRootConsoleCommand
void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command); void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
public: //IProfiler public: //IProfiler
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native); void OnNativeBegin(IPluginContext *pContext, sp_native_t *native);
void OnNativeEnd() ; void OnNativeEnd() ;
@@ -131,6 +126,6 @@ private:
prof_point_t m_ProfStart; prof_point_t m_ProfStart;
}; };
extern IProfiler *sm_profiler; extern ProfileEngine g_Profiler;
#endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_ #endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -36,9 +36,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include "TextParsers.h" #include "TextParsers.h"
//#include "ShareSys.h" #include "ShareSys.h"
//#include "sm_stringutil.h" #include "sm_stringutil.h"
//#include "LibrarySys.h" #include "LibrarySys.h"
TextParsers g_TextParser; TextParsers g_TextParser;
ITextParsers *textparsers = &g_TextParser; ITextParsers *textparsers = &g_TextParser;
@@ -69,6 +69,11 @@ TextParsers::TextParsers()
g_ws_chartable[(unsigned)' '] = 1; g_ws_chartable[(unsigned)' '] = 1;
} }
void TextParsers::OnSourceModAllInitialized()
{
g_ShareSys.AddInterface(NULL, this);
}
unsigned int TextParsers::GetUTF8CharBytes(const char *stream) unsigned int TextParsers::GetUTF8CharBytes(const char *stream)
{ {
return _GetUTF8CharBytes(stream); return _GetUTF8CharBytes(stream);
@@ -169,7 +174,7 @@ SMCError TextParsers::ParseSMCFile(const char *file,
states->line = 0; states->line = 0;
states->col = 0; states->col = 0;
} }
//g_LibSys.GetPlatformError(error, sizeof(error)); g_LibSys.GetPlatformError(error, sizeof(error));
UTIL_Format(buffer, maxsize, "File could not be opened: %s", error); UTIL_Format(buffer, maxsize, "File could not be opened: %s", error);
return SMCError_StreamOpen; return SMCError_StreamOpen;
} }
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,8 +32,8 @@
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_H_ #ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_ #define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
#include "ITextParsers.h" #include <ITextParsers.h>
#include "main.h" #include "sm_globals.h"
using namespace SourceMod; using namespace SourceMod;
@@ -46,10 +46,14 @@ using namespace SourceMod;
*/ */
typedef bool (*STREAMREADER)(void *, char *, size_t, unsigned int *); typedef bool (*STREAMREADER)(void *, char *, size_t, unsigned int *);
class TextParsers : public ITextParsers class TextParsers :
public ITextParsers,
public SMGlobalClass
{ {
public: public:
TextParsers(); TextParsers();
public: //SMGlobalClass
void OnSourceModAllInitialized();
public: public:
bool ParseFile_INI(const char *file, bool ParseFile_INI(const char *file,
ITextListener_INI *ini_listener, ITextListener_INI *ini_listener,
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -28,9 +28,10 @@
* *
* Version: $Id$ * Version: $Id$
*/ */
#include <sm_platform.h>
#include "ThreadSupport.h" #include "ThreadSupport.h"
#include "common_logic.h" #include "sm_globals.h"
#include "ShareSys.h"
#if defined PLATFORM_POSIX #if defined PLATFORM_POSIX
#include "thread/PosixThreads.h" #include "thread/PosixThreads.h"
@@ -46,7 +47,6 @@ class RegThreadStuff : public SMGlobalClass
public: public:
void OnSourceModAllInitialized() void OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, g_pThreader); g_ShareSys.AddInterface(NULL, g_pThreader);
} }
} s_RegThreadStuff; } s_RegThreadStuff;
@@ -1,35 +1,41 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2013 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * 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 * the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation. * Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * 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 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
* *
* As a special exception, AlliedModders LLC gives you permission to link the * 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 * 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 * "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 * by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants * all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
*/ *
#include <sourcemod_version.h> * Version: $Id$
#include <versionlib.h> */
const char *SOURCEMOD_LOCAL_REV = SM_BUILD_LOCAL_REV; #ifndef _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
const char *SOURCEMOD_SHA = SM_BUILD_CSET; #define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
const char *SOURCEMOD_VERSION = SM_VERSION_STRING;
const char *SOURCEMOD_BUILD_TIME = __DATE__ " " __TIME__; #include <IThreader.h>
using namespace SourceMod;
extern IThreader *g_pThreader;
#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
+7 -7
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -31,10 +31,10 @@
#include <time.h> #include <time.h>
#include "TimerSys.h" #include "TimerSys.h"
#include "ForwardSys.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "frame_hooks.h" #include "frame_hooks.h"
#include "ConVarManager.h" #include "ConVarManager.h"
#include "logic_bridge.h"
#define TIMER_MIN_ACCURACY 0.1 #define TIMER_MIN_ACCURACY 0.1
@@ -180,9 +180,9 @@ TimerSystem::~TimerSystem()
void TimerSystem::OnSourceModAllInitialized() void TimerSystem::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
m_pOnGameFrame = forwardsys->CreateForward("OnGameFrame", ET_Ignore, 0, NULL); m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
m_pOnMapTimeLeftChanged = forwardsys->CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL); m_pOnMapTimeLeftChanged = g_Forwards.CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
} }
void TimerSystem::OnSourceModGameInitialized() void TimerSystem::OnSourceModGameInitialized()
@@ -198,8 +198,8 @@ void TimerSystem::OnSourceModGameInitialized()
void TimerSystem::OnSourceModShutdown() void TimerSystem::OnSourceModShutdown()
{ {
SetMapTimer(NULL); SetMapTimer(NULL);
forwardsys->ReleaseForward(m_pOnGameFrame); g_Forwards.ReleaseForward(m_pOnGameFrame);
forwardsys->ReleaseForward(m_pOnMapTimeLeftChanged); g_Forwards.ReleaseForward(m_pOnMapTimeLeftChanged);
} }
void TimerSystem::OnSourceModLevelEnd() void TimerSystem::OnSourceModLevelEnd()
+3 -3
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,11 +32,11 @@
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_ #ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_ #define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
#include "ShareSys.h"
#include <ITimerSystem.h> #include <ITimerSystem.h>
#include <sh_stack.h> #include <sh_stack.h>
#include <sh_list.h> #include <sh_list.h>
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_globals.h"
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
@@ -78,11 +78,11 @@ public: //ITimerSystem
float GetTickedTime(); float GetTickedTime();
void NotifyOfGameStart(float offset /* = 0.0f */); void NotifyOfGameStart(float offset /* = 0.0f */);
bool GetMapTimeLeft(float *pTime); bool GetMapTimeLeft(float *pTime);
IMapTimer *GetMapTimer();
public: public:
void RunFrame(); void RunFrame();
void RemoveMapChangeTimers(); void RemoveMapChangeTimers();
void GameFrame(bool simulating); void GameFrame(bool simulating);
IMapTimer *GetMapTimer();
private: private:
List<ITimer *> m_SingleTimers; List<ITimer *> m_SingleTimers;
List<ITimer *> m_LoopTimers; List<ITimer *> m_LoopTimers;
+205 -258
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet: * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -29,24 +29,20 @@
* Version: $Id$ * Version: $Id$
*/ */
#include "common_logic.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <sm_platform.h>
#include "Translator.h" #include "Translator.h"
#include <IPlayerHelpers.h> #include "Logger.h"
#include <ISourceMod.h> #include "LibrarySys.h"
#include <ILibrarySys.h> #include "sm_stringutil.h"
#include "PhraseCollection.h" #include "sourcemod.h"
#include "stringutil.h" #include "PlayerManager.h"
Translator g_Translator; Translator g_Translator;
IPhraseCollection *g_pCorePhrases = NULL; CPhraseFile *g_pCorePhrases = NULL;
unsigned int g_pCorePhraseID = 0; unsigned int g_pCorePhraseID = 0;
using namespace SourceMod;
struct trans_t struct trans_t
{ {
int stridx; int stridx;
@@ -69,10 +65,15 @@ CPhraseFile::CPhraseFile(Translator *pTranslator, const char *file)
m_LangCount = pTranslator->GetLanguageCount(); m_LangCount = pTranslator->GetLanguageCount();
m_File.assign(file); m_File.assign(file);
m_pTranslator = pTranslator; m_pTranslator = pTranslator;
m_pPhraseLookup = NULL;
} }
CPhraseFile::~CPhraseFile() CPhraseFile::~CPhraseFile()
{ {
if (m_pPhraseLookup)
{
sm_trie_destroy(m_pPhraseLookup);
}
} }
void CPhraseFile::ParseError(const char *message, ...) void CPhraseFile::ParseError(const char *message, ...)
@@ -96,16 +97,20 @@ void CPhraseFile::ParseWarning(const char *message, ...)
if (!m_FileLogged) if (!m_FileLogged)
{ {
smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str()); g_Logger.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
m_FileLogged = true; m_FileLogged = true;
} }
smcore.LogError("[SM] %s", buffer); g_Logger.LogError("[SM] %s", message);
} }
void CPhraseFile::ReparseFile() void CPhraseFile::ReparseFile()
{ {
m_PhraseLookup.clear(); if (m_pPhraseLookup)
{
sm_trie_destroy(m_pPhraseLookup);
}
m_pPhraseLookup = sm_trie_create();
m_LangCount = m_pTranslator->GetLanguageCount(); m_LangCount = m_pTranslator->GetLanguageCount();
@@ -116,19 +121,19 @@ void CPhraseFile::ReparseFile()
SMCError err; SMCError err;
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "translations/%s", m_File.c_str()); g_SourceMod.BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "translations/%s", m_File.c_str());
//backwards compatibility shim //backwards compatibility shim
/* :HACKHACK: Change .cfg/.txt and vice versa for compatibility */ /* :HACKHACK: Change .cfg/.txt and vice versa for compatibility */
if (!libsys->PathExists(path)) if (!g_LibSys.PathExists(path))
{ {
if (m_File.compare("common.cfg") == 0) if (m_File.compare("common.cfg") == 0)
{ {
UTIL_ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt", true); UTIL_ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt");
} else if (strstr(path, ".cfg")) { } else if (strstr(path, ".cfg")) {
UTIL_ReplaceAll(path, sizeof(path), ".cfg", ".txt", true); UTIL_ReplaceAll(path, sizeof(path), ".cfg", ".txt");
} else if (strstr(path, ".txt")) { } else if (strstr(path, ".txt")) {
UTIL_ReplaceAll(path, sizeof(path), ".txt", ".cfg", true); UTIL_ReplaceAll(path, sizeof(path), ".txt", ".cfg");
} }
} }
@@ -142,47 +147,8 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str(); msg = m_ParseError.c_str();
} }
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str()); g_Logger.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); g_Logger.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
}
const char *code;
for (unsigned int i = 1; i < m_LangCount; i++)
{
if (!m_pTranslator->GetLanguageInfo(i, &code, NULL))
{
continue;
}
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"translations/%s/%s",
code,
m_File.c_str());
/* Speculatively load these. */
if (!libsys->PathExists(path))
{
continue;
}
if ((err=textparsers->ParseFile_SMC(path, this, &states)) != SMCError_Okay)
{
const char *msg = textparsers->GetSMCErrorString(err);
if (!msg)
{
msg = m_ParseError.c_str();
}
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
code,
m_File.c_str());
smcore.LogError("[SM] Error (line %d, column %d): %s",
states.line,
states.col,
msg);
}
} }
} }
@@ -210,16 +176,21 @@ SMCResult CPhraseFile::ReadSMC_NewSection(const SMCStates *states, const char *n
m_ParseState = PPS_InPhrase; m_ParseState = PPS_InPhrase;
recognized = true; recognized = true;
if (!m_PhraseLookup.retrieve(name, &m_CurPhrase)) phrase_t *pPhrase;
m_CurPhrase = m_pMemory->CreateMem(sizeof(phrase_t), (void **)&pPhrase);
/* Create the reverse lookup */
if (!sm_trie_insert(m_pPhraseLookup, name, reinterpret_cast<void *>(m_CurPhrase)))
{
ParseWarning("Skipping duplicate phrase \"%s\" on line %d.", name, states->line);
/* :IDEA: prevent memory waste by seeking backwards in memtable? */
m_CurPhrase = -1;
}
else
{ {
phrase_t *pPhrase;
m_CurPhrase = m_pMemory->CreateMem(sizeof(phrase_t), (void **)&pPhrase);
m_PhraseLookup.insert(name, m_CurPhrase);
/* Initialize new phrase */ /* Initialize new phrase */
trans_t *pTrans; trans_t *pTrans;
pPhrase->fmt_count = 0; pPhrase->fmt_count = 0;
pPhrase->fmt_list = -1; pPhrase->fmt_list = -1;
@@ -229,14 +200,13 @@ SMCResult CPhraseFile::ReadSMC_NewSection(const SMCStates *states, const char *n
pPhrase->translations = 0; pPhrase->translations = 0;
pPhrase->fmt_bytes = 0; pPhrase->fmt_bytes = 0;
for (unsigned int i=0; i<m_LangCount; i++) for (unsigned int i=0; i<m_LangCount; i++)
{ {
pTrans[i].stridx = -1; pTrans[i].stridx = -1;
} }
m_LastPhraseString.assign(name);
} }
m_LastPhraseString.assign(name);
} }
else if (m_ParseState == PPS_InPhrase) else if (m_ParseState == PPS_InPhrase)
{ {
@@ -261,12 +231,15 @@ SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key
} }
phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase); phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(m_CurPhrase);
/* Duplicate format keys get silently ignored. */ if (key[0] == '#' && strcmp(key, "#format") == 0)
if (key[0] == '#'
&& strcmp(key, "#format") == 0
&& pPhrase->fmt_list == -1)
{ {
if (pPhrase->fmt_list != -1)
{
ParseWarning("Ignoring duplicated #format property on line %d", states->line);
return SMCResult_Continue;
}
if (pPhrase->translations > 0) if (pPhrase->translations > 0)
{ {
ParseWarning("#format property should come before translations on line %d, ignoring", states->line); ParseWarning("#format property should come before translations on line %d, ignoring", states->line);
@@ -474,6 +447,13 @@ SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key
} }
else else
{ {
size_t len = strlen(key);
if (len != 2)
{
ParseWarning("Ignoring translation to invalid language \"%s\" on line %d.", key, states->line);
return SMCResult_Continue;
}
unsigned int lang; unsigned int lang;
if (!m_pTranslator->GetLanguageByCode(key, &lang)) if (!m_pTranslator->GetLanguageByCode(key, &lang))
{ {
@@ -486,7 +466,7 @@ SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key
/* See how many bytes we need for this string, then allocate. /* See how many bytes we need for this string, then allocate.
* NOTE: THIS SHOULD GUARANTEE THAT WE DO NOT NEED TO NEED TO SIZE CHECK * NOTE: THIS SHOULD GUARANTEE THAT WE DO NOT NEED TO NEED TO SIZE CHECK
*/ */
size_t len = strlen(value) + pPhrase->fmt_bytes + 1; len = strlen(value) + pPhrase->fmt_bytes + 1;
char *out_buf; char *out_buf;
int out_idx; int out_idx;
@@ -620,7 +600,9 @@ SMCResult CPhraseFile::ReadSMC_LeavingSection(const SMCStates *states)
if (m_ParseState == PPS_InPhrase) if (m_ParseState == PPS_InPhrase)
{ {
if (m_CurPhrase == -1 && m_LastPhraseString.size()) if (m_CurPhrase == -1 && m_LastPhraseString.size())
m_PhraseLookup.remove(m_LastPhraseString.c_str()); {
sm_trie_delete(m_pPhraseLookup, m_LastPhraseString.c_str());
}
m_CurPhrase = -1; m_CurPhrase = -1;
m_ParseState = PPS_Phrases; m_ParseState = PPS_Phrases;
m_LastPhraseString.assign(""); m_LastPhraseString.assign("");
@@ -637,7 +619,9 @@ void CPhraseFile::ReadSMC_ParseEnd(bool halted, bool failed)
{ {
/* Check to see if we have any dangling phrases that weren't completed, and scrap them */ /* Check to see if we have any dangling phrases that weren't completed, and scrap them */
if ((halted || failed) && m_LastPhraseString.size()) if ((halted || failed) && m_LastPhraseString.size())
m_PhraseLookup.remove(m_LastPhraseString.c_str()); {
sm_trie_delete(m_pPhraseLookup, m_LastPhraseString.c_str());
}
} }
TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_id, Translation *pTrans) TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_id, Translation *pTrans)
@@ -647,11 +631,13 @@ TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_i
return Trans_BadLanguage; return Trans_BadLanguage;
} }
int address; void *object;
if (!m_PhraseLookup.retrieve(szPhrase, &address)) if (!sm_trie_retrieve(m_pPhraseLookup, szPhrase, &object))
{
return Trans_BadPhrase; return Trans_BadPhrase;
}
phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(address); phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(reinterpret_cast<int>(object));
trans_t *trans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl); trans_t *trans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl);
trans = &trans[lang_id]; trans = &trans[lang_id];
@@ -677,9 +663,10 @@ const char *CPhraseFile::GetFilename()
** MAIN TRANSLATOR CODE ** ** MAIN TRANSLATOR CODE **
**************************/ **************************/
Translator::Translator() : m_ServerLang(SOURCEMOD_LANGUAGE_ENGLISH) Translator::Translator() : m_ServerLang(LANGUAGE_ENGLISH)
{ {
m_pStringTab = new BaseStringTable(2048); m_pStringTab = new BaseStringTable(2048);
m_pLCodeLookup = sm_trie_create();
strncopy(m_InitialLang, "en", sizeof(m_InitialLang)); strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
} }
@@ -695,6 +682,8 @@ Translator::~Translator()
delete m_Languages[i]; delete m_Languages[i];
} }
sm_trie_destroy(m_pLCodeLookup);
delete m_pStringTab; delete m_pStringTab;
} }
@@ -711,13 +700,13 @@ ConfigResult Translator::OnSourceModConfigChanged(const char *key,
unsigned int index; unsigned int index;
if (!GetLanguageByCode(value, &index)) if (!GetLanguageByCode(value, &index))
{ {
smcore.Format(error, maxlength, "Language code \"%s\" is not registered", value); UTIL_Format(error, maxlength, "Language code \"%s\" is not registered", value);
return ConfigResult_Reject; return ConfigResult_Reject;
} }
m_ServerLang = index; m_ServerLang = index;
} else { } else {
smcore.strncopy(m_InitialLang, value, sizeof(m_InitialLang)); strncopy(m_InitialLang, value, sizeof(m_InitialLang));
} }
return ConfigResult_Accept; return ConfigResult_Accept;
@@ -728,50 +717,64 @@ ConfigResult Translator::OnSourceModConfigChanged(const char *key,
void Translator::OnSourceModLevelChange(const char *mapName) void Translator::OnSourceModLevelChange(const char *mapName)
{ {
RebuildLanguageDatabase(); /* Refresh language stuff */
char path[PLATFORM_MAX_PATH];
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
RebuildLanguageDatabase(path);
} }
void Translator::OnSourceModAllInitialized() void Translator::OnSourceModAllInitialized()
{ {
AddLanguage("en", "English"); AddLanguage("en", "English");
const char* lang = smcore.GetCoreConfigValue("ServerLang"); unsigned int id;
if (lang)
{
strncpy(m_InitialLang, lang, sizeof(m_InitialLang));
}
g_pCorePhrases = CreatePhraseCollection(); id = FindOrAddPhraseFile("core.phrases.txt");
g_pCorePhrases->AddPhraseFile("core.phrases"); g_pCorePhraseID = id;
g_pCorePhrases = GetFileByIndex(id);
sharesys->AddInterface(NULL, this);
}
void Translator::OnSourceModShutdown()
{
g_pCorePhrases->Destroy();
} }
bool Translator::GetLanguageByCode(const char *code, unsigned int *index) bool Translator::GetLanguageByCode(const char *code, unsigned int *index)
{ {
return m_LCodeLookup.retrieve(code, index); void *_index;
if (!sm_trie_retrieve(m_pLCodeLookup, code, &_index))
{
return false;
}
if (index)
{
*index = reinterpret_cast<unsigned int>(_index);
}
return true;
} }
bool Translator::GetLanguageByName(const char *name, unsigned int *index) bool Translator::GetLanguageByName(const char *name, unsigned int *index)
{ {
char lower[256]; CVector<Language *>::iterator iter;
size_t len = strlen(name); unsigned int id = 0;
if (len > 255) len = 255;
for (size_t i = 0; i < len; i++)
{
if (name[i] >= 'A' && name[i] <= 'Z')
lower[i] = tolower(name[i]);
else
lower[i] = name[i];
}
lower[len] = '\0';
return m_LAliases.retrieve(lower, index); for (iter=m_Languages.begin(); iter!=m_Languages.end(); iter++, id++)
{
if (strcasecmp(m_pStringTab->GetString((*iter)->m_FullName), name) == 0)
{
break;
}
}
if (iter == m_Languages.end())
{
return false;
}
if (index)
{
*index = id;
}
return true;
} }
unsigned int Translator::GetLanguageCount() unsigned int Translator::GetLanguageCount()
@@ -804,11 +807,11 @@ unsigned int Translator::FindOrAddPhraseFile(const char *phrase_file)
return idx; return idx;
} }
void Translator::RebuildLanguageDatabase() void Translator::RebuildLanguageDatabase(const char *lang_header_file)
{ {
/* Erase everything we have */ /* Erase everything we have */
m_LCodeLookup.clear(); sm_trie_destroy(m_pLCodeLookup);
m_LAliases.clear(); m_pLCodeLookup = sm_trie_create();
m_pStringTab->Reset(); m_pStringTab->Reset();
for (size_t i=0; i<m_Languages.size(); i++) for (size_t i=0; i<m_Languages.size(); i++)
@@ -818,12 +821,9 @@ void Translator::RebuildLanguageDatabase()
m_Languages.clear(); m_Languages.clear();
/* Start anew */ /* Start anew */
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
SMCError err; SMCError err;
SMCStates states; SMCStates states;
if ((err=textparsers->ParseFile_SMC(path, this, &states)) != SMCError_Okay) if ((err=textparsers->ParseFile_SMC(lang_header_file, this, &states)) != SMCError_Okay)
{ {
const char *str_err = textparsers->GetSMCErrorString(err); const char *str_err = textparsers->GetSMCErrorString(err);
if (!str_err) if (!str_err)
@@ -831,21 +831,25 @@ void Translator::RebuildLanguageDatabase()
str_err = m_CustomError.c_str(); str_err = m_CustomError.c_str();
} }
smcore.LogError("[SM] Failed to parse language header file: \"%s\"", path); g_Logger.LogError("[SM] Failed to parse language header file: \"%s\"", lang_header_file);
smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err); g_Logger.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
} }
if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang)) void *serverLang;
if (!sm_trie_retrieve(m_pLCodeLookup, m_InitialLang, &serverLang))
{ {
smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang); g_Logger.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang)); strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH; m_ServerLang = LANGUAGE_ENGLISH;
} }
m_ServerLang = reinterpret_cast<unsigned int>(serverLang);
if (!m_Languages.size()) if (!m_Languages.size())
{ {
smcore.LogError("[SM] Fatal error, no languages found! Translation will not work."); g_Logger.LogError("[SM] Fatal error, no languages found! Translation will not work.");
} }
for (size_t i=0; i<m_Files.size(); i++) for (size_t i=0; i<m_Files.size(); i++)
@@ -872,7 +876,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
if (!m_InLanguageSection) if (!m_InLanguageSection)
{ {
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name); g_Logger.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
} }
return SMCResult_Continue; return SMCResult_Continue;
@@ -889,10 +893,10 @@ SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key,
{ {
size_t len = strlen(key); size_t len = strlen(key);
if (len >= sizeof(((Language *)0)->m_code2)) if (len != 2)
{ {
smcore.LogError("[SM] Warning encountered parsing languages.cfg file."); g_Logger.LogError("[SM] Warning encountered parsing languages.cfg file.");
smcore.LogError("[SM] Invalid language code \"%s\" is too long.", key); g_Logger.LogError("[SM] Invalid language code \"%s\" is being ignored.", key);
} }
AddLanguage(key, value); AddLanguage(key, value);
@@ -902,36 +906,22 @@ SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key,
bool Translator::AddLanguage(const char *langcode, const char *description) bool Translator::AddLanguage(const char *langcode, const char *description)
{ {
char lower[256]; if (sm_trie_retrieve(m_pLCodeLookup, langcode, NULL))
size_t len = strlen(description);
if (len > 255) len = 255;
for (size_t i = 0; i < len; i++)
{ {
if (description[i] >= 'A' && description[i] <= 'Z')
lower[i] = tolower(description[i]);
else
lower[i] = description[i];
}
lower[len] = '\0';
if (m_LAliases.contains(lower))
return false; return false;
unsigned int idx;
if (!m_LCodeLookup.retrieve(langcode, &idx))
{
Language *pLanguage = new Language;
idx = m_Languages.size();
smcore.Format(pLanguage->m_code2, sizeof(pLanguage->m_code2), "%s", langcode);
pLanguage->m_CanonicalName = m_pStringTab->AddString(lower);
m_LCodeLookup.insert(langcode, idx);
m_Languages.push_back(pLanguage);
} }
m_LAliases.insert(lower, idx); Language *pLanguage = new Language;
unsigned int idx = m_Languages.size();
pLanguage->m_code2[0] = langcode[0];
pLanguage->m_code2[1] = langcode[1];
pLanguage->m_code2[2] = langcode[2];
pLanguage->m_FullName = m_pStringTab->AddString(description);
sm_trie_insert(m_pLCodeLookup, langcode, reinterpret_cast<void *>(idx));
m_Languages.push_back(pLanguage);
return true; return true;
} }
@@ -946,6 +936,61 @@ CPhraseFile *Translator::GetFileByIndex(unsigned int index)
return m_Files[index]; return m_Files[index];
} }
size_t Translator::Translate(char *buffer, size_t maxlength, void **params, const Translation *pTrans)
{
void *new_params[MAX_TRANSLATE_PARAMS];
/* Rewrite the parameter order */
for (unsigned int i=0; i<pTrans->fmt_count; i++)
{
new_params[i] = params[pTrans->fmt_order[i]];
}
return gnprintf(buffer, maxlength, pTrans->szPhrase, new_params);
}
TransError Translator::CoreTransEx(CPhraseFile *pFile,
int client,
char *buffer,
size_t maxlength,
const char *phrase,
void **params,
size_t *outlen)
{
Translation trans;
TransError err;
/* Using server lang temporarily until client lang stuff is implemented */
if ((err = pFile->GetTranslation(phrase, m_ServerLang, &trans)) != Trans_Okay)
{
return err;
}
size_t len = Translate(buffer, maxlength, params, &trans);
if (outlen)
{
*outlen = len;
}
return Trans_Okay;
}
TransError Translator::CoreTrans(int client,
char *buffer,
size_t maxlength,
const char *phrase,
void **params,
size_t *outlen)
{
if (!g_pCorePhrases)
{
return Trans_BadPhraseFile;
}
return CoreTransEx(g_pCorePhrases, client, buffer, maxlength, phrase, params, outlen);
}
unsigned int Translator::GetServerLanguage() unsigned int Translator::GetServerLanguage()
{ {
return m_ServerLang; return m_ServerLang;
@@ -953,7 +998,7 @@ unsigned int Translator::GetServerLanguage()
unsigned int Translator::GetClientLanguage(int client) unsigned int Translator::GetClientLanguage(int client)
{ {
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
return pPlayer->GetLanguageId(); return pPlayer->GetLanguageId();
} }
@@ -971,105 +1016,7 @@ bool Translator::GetLanguageInfo(unsigned int number, const char **code, const c
} }
if (name) if (name)
{ {
*name = m_pStringTab->GetString(l->m_CanonicalName); *name = m_pStringTab->GetString(l->m_FullName);
}
return true;
}
const char *Translator::GetInterfaceName()
{
return SMINTERFACE_TRANSLATOR_NAME;
}
unsigned int Translator::GetInterfaceVersion()
{
return SMINTERFACE_TRANSLATOR_VERSION;
}
IPhraseCollection *Translator::CreatePhraseCollection()
{
return new CPhraseCollection();
}
int Translator::SetGlobalTarget(int index)
{
return g_pSM->SetGlobalTarget(index);
}
int Translator::GetGlobalTarget() const
{
return g_pSM->GetGlobalTarget();
}
bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned int numparams,
size_t *pOutLength, ...)
{
va_list ap;
unsigned int i;
const char *fail_phrase;
void *params[MAX_TRANSLATE_PARAMS];
if (numparams > MAX_TRANSLATE_PARAMS)
{
assert(false);
return false;
}
va_start(ap, pOutLength);
for (i = 0; i < numparams; i++)
{
params[i] = va_arg(ap, void *);
}
va_end(ap);
if (!g_pCorePhrases->FormatString(buffer,
maxlength,
format,
params,
numparams,
pOutLength,
&fail_phrase))
{
if (fail_phrase != NULL)
{
smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase);
}
else
{
smcore.LogError("[SM] Unknown fatal error while translating a core phrase.");
}
return false;
}
return true;
}
bool Translator::FormatString(char *buffer,
size_t maxlength,
const char *format,
IPhraseCollection *pPhrases,
void **params,
unsigned int numparams,
size_t *pOutLength,
const char **pFailPhrase)
{
unsigned int arg;
arg = 0;
if (!smcore.gnprintf(buffer, maxlength, format, pPhrases, params, numparams, arg, pOutLength, pFailPhrase))
{
return false;
}
if (arg != numparams)
{
if (pFailPhrase != NULL)
{
*pFailPhrase = NULL;
}
return false;
} }
return true; return true;
+48 -49
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,13 +32,15 @@
#ifndef _INCLUDE_SOURCEMOD_TRANSLATOR_H_ #ifndef _INCLUDE_SOURCEMOD_TRANSLATOR_H_
#define _INCLUDE_SOURCEMOD_TRANSLATOR_H_ #define _INCLUDE_SOURCEMOD_TRANSLATOR_H_
#include "common_logic.h" #include "sm_trie.h"
#include <sm_stringhashmap.h>
#include <sh_string.h> #include <sh_string.h>
#include <sh_vector.h> #include <sh_vector.h>
#include "sm_globals.h"
#include "sm_memtable.h" #include "sm_memtable.h"
#include "ITextParsers.h" #include "ITextParsers.h"
#include <ITranslator.h>
#define MAX_TRANSLATE_PARAMS 32
#define CORELANG_ENGLISH 0
/* :TODO: write a templatized version of tries? */ /* :TODO: write a templatized version of tries? */
@@ -54,13 +56,29 @@ enum PhraseParseState
struct Language struct Language
{ {
char m_code2[32]; char m_code2[3];
int m_CanonicalName; int m_FullName;
}; };
class CPhraseFile : struct Translation
public ITextListener_SMC, {
public IPhraseFile const char *szPhrase; /**< Translated phrase. */
unsigned int fmt_count; /**< Number of format parameters. */
int *fmt_order; /**< Format phrase order. */
};
#define LANGUAGE_ENGLISH 0
enum TransError
{
Trans_Okay = 0,
Trans_BadLanguage = 1,
Trans_BadPhrase = 2,
Trans_BadPhraseLanguage = 3,
Trans_BadPhraseFile = 4,
};
class CPhraseFile : public ITextListener_SMC
{ {
public: public:
CPhraseFile(Translator *pTranslator, const char *file); CPhraseFile(Translator *pTranslator, const char *file);
@@ -79,7 +97,7 @@ private:
void ParseError(const char *message, ...); void ParseError(const char *message, ...);
void ParseWarning(const char *message, ...); void ParseWarning(const char *message, ...);
private: private:
StringHashMap<int> m_PhraseLookup; Trie *m_pPhraseLookup;
String m_File; String m_File;
Translator *m_pTranslator; Translator *m_pTranslator;
PhraseParseState m_ParseState; PhraseParseState m_ParseState;
@@ -94,8 +112,7 @@ private:
class Translator : class Translator :
public ITextListener_SMC, public ITextListener_SMC,
public SMGlobalClass, public SMGlobalClass
public ITranslator
{ {
public: public:
Translator(); Translator();
@@ -108,69 +125,51 @@ public: // SMGlobalClass
size_t maxlength); size_t maxlength);
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModLevelChange(const char *mapName); void OnSourceModLevelChange(const char *mapName);
void OnSourceModShutdown();
public: // ITextListener_SMC public: // ITextListener_SMC
void ReadSMC_ParseStart(); void ReadSMC_ParseStart();
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states); SMCResult ReadSMC_LeavingSection(const SMCStates *states);
public: public:
void RebuildLanguageDatabase(const char *lang_header_file);
unsigned int FindOrAddPhraseFile(const char *phrase_file); unsigned int FindOrAddPhraseFile(const char *phrase_file);
BaseStringTable *GetStringTable(); BaseStringTable *GetStringTable();
unsigned int GetLanguageCount(); unsigned int GetLanguageCount();
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
bool GetLanguageByCode(const char *code, unsigned int *index); bool GetLanguageByCode(const char *code, unsigned int *index);
bool GetLanguageByName(const char *name, unsigned int *index); bool GetLanguageByName(const char *name, unsigned int *index);
size_t Translate(char *buffer, size_t maxlength, void **params, const Translation *pTrans);
CPhraseFile *GetFileByIndex(unsigned int index); CPhraseFile *GetFileByIndex(unsigned int index);
public: //ITranslator TransError CoreTransEx(CPhraseFile *pFile,
unsigned int GetServerLanguage(); int client,
unsigned int GetClientLanguage(int client);
const char *GetInterfaceName();
unsigned int GetInterfaceVersion();
IPhraseCollection *CreatePhraseCollection();
int SetGlobalTarget(int index);
int GetGlobalTarget() const;
size_t FormatString(
char *buffer, char *buffer,
size_t maxlength, size_t maxlength,
SourcePawn::IPluginContext *pContext, const char *phrase,
const cell_t *params, void **params,
unsigned int param); size_t *outlen=NULL);
bool FormatString( TransError CoreTrans(int client,
char *buffer, char *buffer,
size_t maxlength, size_t maxlength,
const char *format, const char *phrase,
IPhraseCollection *pPhrases, void **params,
void **params, size_t *outlen=NULL);
unsigned int numparams, unsigned int GetServerLanguage();
size_t *pOutLength, unsigned int GetClientLanguage(int client);
const char **pFailPhrase);
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
void RebuildLanguageDatabase();
private: private:
bool AddLanguage(const char *langcode, const char *description); bool AddLanguage(const char *langcode, const char *description);
private: private:
CVector<Language *> m_Languages; CVector<Language *> m_Languages;
CVector<CPhraseFile *> m_Files; CVector<CPhraseFile *> m_Files;
BaseStringTable *m_pStringTab; BaseStringTable *m_pStringTab;
StringHashMap<unsigned int> m_LCodeLookup; Trie *m_pLCodeLookup;
StringHashMap<unsigned int> m_LAliases;
bool m_InLanguageSection; bool m_InLanguageSection;
String m_CustomError; String m_CustomError;
unsigned int m_ServerLang; unsigned int m_ServerLang;
char m_InitialLang[4]; char m_InitialLang[3];
}; };
/* Nice little wrapper to handle error logging and whatnot */ extern CPhraseFile *g_pCorePhrases;
bool CoreTranslate(char *buffer,
size_t maxlength,
const char *format,
unsigned int numparams,
size_t *pOutLength,
...);
extern IPhraseCollection *g_pCorePhrases;
extern unsigned int g_pCorePhraseID; extern unsigned int g_pCorePhraseID;
extern Translator g_Translator; extern Translator g_Translator;
#endif //_INCLUDE_SOURCEMOD_TRANSLATOR_H_ #endif //_INCLUDE_SOURCEMOD_TRANSLATOR_H_
File diff suppressed because it is too large Load Diff
+61 -410
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -31,35 +31,15 @@
#include "UserMessages.h" #include "UserMessages.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "logic_bridge.h"
#if SOURCE_ENGINE == SE_DOTA
#include <dota_usermessage_helpers.h>
#elif SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessage_helpers.h>
#endif
UserMessages g_UserMsgs; UserMessages g_UserMsgs;
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
#else
#if SOURCE_ENGINE >= SE_LEFT4DEAD
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
#else
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int); SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
#endif
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0); SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
#endif // ==SE_CSGO
UserMessages::UserMessages() UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
#ifndef USE_PROTOBUF_USERMESSAGES
: m_InterceptBuffer(m_pBase, 2500)
{ {
#else m_Names = sm_trie_create();
: m_InterceptBuffer(NULL)
{
#endif
m_HookCount = 0; m_HookCount = 0;
m_InExec = false; m_InExec = false;
m_InHook = false; m_InHook = false;
@@ -69,6 +49,8 @@ UserMessages::UserMessages()
UserMessages::~UserMessages() UserMessages::~UserMessages()
{ {
sm_trie_destroy(m_Names);
CStack<ListenerInfo *>::iterator iter; CStack<ListenerInfo *>::iterator iter;
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++) for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
{ {
@@ -79,46 +61,32 @@ UserMessages::~UserMessages()
void UserMessages::OnSourceModStartup(bool late) void UserMessages::OnSourceModStartup(bool late)
{ {
#ifndef USE_PROTOBUF_USERMESSAGES
/* -1 means SourceMM was unable to get the user message list */ /* -1 means SourceMM was unable to get the user message list */
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1); m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
#endif
} }
void UserMessages::OnSourceModAllInitialized() void UserMessages::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
void UserMessages::OnSourceModAllShutdown() void UserMessages::OnSourceModAllShutdown()
{ {
if (m_HookCount) if (m_HookCount)
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
#else SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
#endif
} }
m_HookCount = 0; m_HookCount = 0;
} }
int UserMessages::GetMessageIndex(const char *msg) 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
// Can split this per engine and/or game later
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
#else
int msgid; int msgid;
if (!m_Names.retrieve(msg, &msgid))
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
{ {
if (m_FallbackSearch) if (m_FallbackSearch)
{ {
@@ -130,7 +98,7 @@ int UserMessages::GetMessageIndex(const char *msg)
{ {
if (strcmp(msgbuf, msg) == 0) if (strcmp(msgbuf, msg) == 0)
{ {
m_Names.insert(msg, msgid); sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
return msgid; return msgid;
} }
msgid++; msgid++;
@@ -140,27 +108,16 @@ int UserMessages::GetMessageIndex(const char *msg)
msgid = g_SMAPI->FindUserMessage(msg); msgid = g_SMAPI->FindUserMessage(msg);
if (msgid != INVALID_MESSAGE_ID) if (msgid != INVALID_MESSAGE_ID)
m_Names.insert(msg, msgid); {
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
}
} }
return msgid; return msgid;
#endif
} }
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const 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
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
#endif
if (!pszName)
return false;
strncopy(buffer, pszName, maxlength);
return true;
#else
if (m_FallbackSearch) if (m_FallbackSearch)
{ {
int size; int size;
@@ -176,14 +133,10 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
} }
return false; return false;
#endif
} }
bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags) bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES
return NULL;
#else
bf_write *buffer; bf_write *buffer;
if (m_InExec || m_InHook) if (m_InExec || m_InHook)
@@ -211,89 +164,12 @@ bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], u
if (m_CurFlags & USERMSG_BLOCKHOOKS) if (m_CurFlags & USERMSG_BLOCKHOOKS)
{ {
#if SOURCE_ENGINE >= SE_LEFT4DEAD
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
#else
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id); buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
#endif
} else { } else {
#if SOURCE_ENGINE >= SE_LEFT4DEAD
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
#else
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id); buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
#endif
} }
return buffer; return buffer;
#endif // USE_PROTOBUF_USERMESSAGES
}
google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
{
#ifndef USE_PROTOBUF_USERMESSAGES
return NULL;
#else
protobuf::Message *buffer;
if (m_InExec || m_InHook)
{
return NULL;
}
if (msg_id < 0 || msg_id >= 255)
{
return NULL;
}
m_CurId = msg_id;
m_CellRecFilter.Initialize(players, playersNum);
m_CurFlags = flags;
if (m_CurFlags & USERMSG_INITMSG)
{
m_CellRecFilter.SetToInit(true);
}
if (m_CurFlags & USERMSG_RELIABLE)
{
m_CellRecFilter.SetToReliable(true);
}
m_InExec = true;
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
// direct message creation, return buffer "from engine". keep track
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
} else {
char messageName[32];
if (!GetMessageName(msg_id, messageName, sizeof(messageName)))
{
m_InExec = false;
return NULL;
}
protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
switch (m_FakeMetaRes)
{
case MRES_IGNORED:
case MRES_HANDLED:
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
break;
case MRES_OVERRIDE:
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
// fallthrough
case MRES_SUPERCEDE:
buffer = msg;
break;
}
OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
}
return buffer;
#endif // USE_PROTOBUF_USERMESSAGES
} }
bool UserMessages::EndMessage() bool UserMessages::EndMessage()
@@ -303,37 +179,12 @@ bool UserMessages::EndMessage()
return false; return false;
} }
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
delete m_FakeEngineBuffer;
m_FakeEngineBuffer = NULL;
} else {
OnMessageEnd_Pre();
switch (m_FakeMetaRes)
{
case MRES_IGNORED:
case MRES_HANDLED:
case MRES_OVERRIDE:
engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
delete m_FakeEngineBuffer;
m_FakeEngineBuffer = NULL;
break;
//case MRES_SUPERCEDE:
}
OnMessageEnd_Post();
}
#else
if (m_CurFlags & USERMSG_BLOCKHOOKS) if (m_CurFlags & USERMSG_BLOCKHOOKS)
{ {
ENGINE_CALL(MessageEnd)(); ENGINE_CALL(MessageEnd)();
} else { } else {
engine->MessageEnd(); engine->MessageEnd();
} }
#endif // SE_CSGO || SE_DOTA
m_InExec = false; m_InExec = false;
m_CurFlags = 0; m_CurFlags = 0;
@@ -342,60 +193,7 @@ bool UserMessages::EndMessage()
return true; return true;
} }
UserMessageType UserMessages::GetUserMessageType() const
{
#ifdef USE_PROTOBUF_USERMESSAGES
return UM_Protobuf;
#else
return UM_BitBuf;
#endif
}
bool UserMessages::HookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept)
{
#ifdef USE_PROTOBUF_USERMESSAGES
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
#else
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
#endif
}
bool UserMessages::UnhookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept)
{
#ifdef USE_PROTOBUF_USERMESSAGES
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
#else
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
#endif
}
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept) bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
{
#ifdef USE_PROTOBUF_USERMESSAGES
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
#else
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
#endif
}
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
{
#ifdef USE_PROTOBUF_USERMESSAGES
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
#else
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
#endif
}
#ifdef USE_PROTOBUF_USERMESSAGES
bool UserMessages::InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
#else
bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
#endif
{ {
if (msg_id < 0 || msg_id >= 255) if (msg_id < 0 || msg_id >= 255)
{ {
@@ -414,19 +212,13 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
pInfo->Callback = pListener; pInfo->Callback = pListener;
pInfo->IsHooked = false; pInfo->IsHooked = false;
pInfo->KillMe = false; pInfo->KillMe = false;
pInfo->IsNew = isNew;
if (!m_HookCount++) if (!m_HookCount++)
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
#else SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
#endif
} }
if (intercept) if (intercept)
@@ -439,23 +231,8 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
return true; return true;
} }
#ifdef USE_PROTOBUF_USERMESSAGES bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type) {
{
#if SOURCE_ENGINE == SE_DOTA
return g_DotaUsermessageHelpers.GetPrototype(msg_type);
#elif SOURCE_ENGINE == SE_CSGO
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
#endif
}
#endif
#ifdef USE_PROTOBUF_USERMESSAGES
bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
#else
bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
#endif
{
MsgList *pList; MsgList *pList;
MsgIter iter; MsgIter iter;
ListenerInfo *pInfo; ListenerInfo *pInfo;
@@ -470,7 +247,7 @@ bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListe
for (iter=pList->begin(); iter!=pList->end(); iter++) for (iter=pList->begin(); iter!=pList->end(); iter++)
{ {
pInfo = (*iter); pInfo = (*iter);
if (pInfo->Callback == pListener && pInfo->IsNew == isNew) if (pInfo->Callback == pListener)
{ {
if (pInfo->IsHooked) if (pInfo->IsHooked)
{ {
@@ -495,81 +272,14 @@ void UserMessages::_DecRefCounter()
{ {
if (--m_HookCount == 0) if (--m_HookCount == 0)
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
#else SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true);
#endif
} }
} }
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
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
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
if (m_FakeMetaRes == MRES_SUPERCEDE)
{
int size = msg.ByteSize();
uint8 *data = (uint8 *)stackalloc(size);
msg.SerializePartialToArray(data, size);
m_InterceptBuffer->ParsePartialFromArray(data, size);
}
else
{
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
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
OnMessageEnd_Pre();
if (m_FakeMetaRes == MRES_SUPERCEDE)
RETURN_META(MRES_SUPERCEDE);
RETURN_META(MRES_IGNORED);
}
void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
{
OnMessageEnd_Post();
RETURN_META(MRES_IGNORED);
}
#endif
#ifdef USE_PROTOBUF_USERMESSAGES
#define UM_RETURN_META_VALUE(res, val) \
m_FakeMetaRes = res; \
return val;
#define UM_RETURN_META(res) \
m_FakeMetaRes = res; \
return;
#else
#define UM_RETURN_META_VALUE(res, val) \
RETURN_META_VALUE(res, val)
#define UM_RETURN_META(res) \
RETURN_META(res)
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
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)
#else
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type) bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
#endif
{ {
bool is_intercept_empty = m_msgIntercepts[msg_type].empty(); bool is_intercept_empty = m_msgIntercepts[msg_type].empty();
bool is_hook_empty = m_msgHooks[msg_type].empty(); bool is_hook_empty = m_msgHooks[msg_type].empty();
@@ -578,7 +288,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS))) || (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
{ {
m_InHook = false; m_InHook = false;
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
m_CurId = msg_type; m_CurId = msg_type;
@@ -588,73 +298,42 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
if (!is_intercept_empty) if (!is_intercept_empty)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES
if (m_InterceptBuffer)
delete m_InterceptBuffer;
m_InterceptBuffer = GetMessagePrototype(msg_type)->New();
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
#else
m_InterceptBuffer.Reset(); m_InterceptBuffer.Reset();
UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer); RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
#endif
} }
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
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)
#else
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type) bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
#endif
{ {
if (!m_InHook) if (!m_InHook)
{ {
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
#ifdef USE_PROTOBUF_USERMESSAGES
if (m_FakeMetaRes == MRES_SUPERCEDE)
m_OrigBuffer = m_InterceptBuffer;
else
m_OrigBuffer = m_FakeEngineBuffer;
#else
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *); m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
#endif
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
void UserMessages::OnMessageEnd_Post() void UserMessages::OnMessageEnd_Post()
{ {
if (!m_InHook) if (!m_InHook || m_BlockEndPost)
{ {
UM_RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
MsgList *pList; MsgList *pList;
MsgIter iter; MsgIter iter;
ListenerInfo *pInfo; ListenerInfo *pInfo;
m_InHook = false;
pList = &m_msgIntercepts[m_CurId]; pList = &m_msgIntercepts[m_CurId];
for (iter=pList->begin(); iter!=pList->end(); ) for (iter=pList->begin(); iter!=pList->end(); )
{ {
pInfo = (*iter); pInfo = (*iter);
if (m_BlockEndPost && !pInfo->IsNew)
{
continue;
}
pInfo->IsHooked = true; pInfo->IsHooked = true;
pInfo->Callback->OnUserMessageSent(m_CurId); pInfo->Callback->OnUserMessageSent(m_CurId);
if (pInfo->IsNew)
{
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
}
if (pInfo->KillMe) if (pInfo->KillMe)
{ {
@@ -668,20 +347,14 @@ void UserMessages::OnMessageEnd_Post()
iter++; iter++;
} }
m_InHook = false;
pList = &m_msgHooks[m_CurId]; pList = &m_msgHooks[m_CurId];
for (iter=pList->begin(); iter!=pList->end(); ) for (iter=pList->begin(); iter!=pList->end(); )
{ {
pInfo = (*iter); pInfo = (*iter);
if (m_BlockEndPost && !pInfo->IsNew)
{
continue;
}
pInfo->IsHooked = true; pInfo->IsHooked = true;
pInfo->Callback->OnUserMessageSent(m_CurId); pInfo->Callback->OnUserMessageSent(m_CurId);
if (pInfo->IsNew)
{
pInfo->Callback->OnPostUserMessage(m_CurId, !m_BlockEndPost);
}
if (pInfo->KillMe) if (pInfo->KillMe)
{ {
@@ -700,7 +373,7 @@ void UserMessages::OnMessageEnd_Pre()
{ {
if (!m_InHook) if (!m_InHook)
{ {
UM_RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
MsgList *pList; MsgList *pList;
@@ -716,11 +389,7 @@ void UserMessages::OnMessageEnd_Pre()
{ {
pInfo = (*iter); pInfo = (*iter);
pInfo->IsHooked = true; pInfo->IsHooked = true;
#ifdef USE_PROTOBUF_USERMESSAGES
res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
#else
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter); res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
#endif
intercepted = true; intercepted = true;
@@ -766,61 +435,43 @@ void UserMessages::OnMessageEnd_Pre()
iter++; iter++;
} }
if (!handled && intercepted) if (handled)
{
goto supercede;
}
if (intercepted)
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
#else
bf_write *engine_bfw; bf_write *engine_bfw;
#if SOURCE_ENGINE >= SE_LEFT4DEAD
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
#else
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId); engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
#endif
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten()); m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten()); engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
ENGINE_CALL(MessageEnd)(); ENGINE_CALL(MessageEnd)();
#endif // SE_CSGO || SE_DOTA
} }
pList = &m_msgHooks[m_CurId];
for (iter=pList->begin(); iter!=pList->end(); )
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA pInfo = (*iter);
int size = m_OrigBuffer->ByteSize(); pInfo->IsHooked = true;
uint8 *data = (uint8 *)stackalloc(size); pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
m_OrigBuffer->SerializePartialToArray(data, size);
protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New(); if (pInfo->KillMe)
pTempMsg->ParsePartialFromArray(data, size);
#else
bf_write *pTempMsg = m_OrigBuffer;
#endif
pList = &m_msgHooks[m_CurId];
for (iter=pList->begin(); iter!=pList->end(); )
{ {
pInfo = (*iter); iter = pList->erase(iter);
pInfo->IsHooked = true; m_FreeListeners.push(pInfo);
pInfo->Callback->OnUserMessage(m_CurId, pTempMsg, m_CurRecFilter); _DecRefCounter();
continue;
if (pInfo->KillMe)
{
iter = pList->erase(iter);
m_FreeListeners.push(pInfo);
_DecRefCounter();
continue;
}
pInfo->IsHooked = false;
iter++;
} }
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA pInfo->IsHooked = false;
delete pTempMsg; iter++;
#endif
} }
UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED); RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
supercede: supercede:
m_InHook = false;
m_BlockEndPost = true; m_BlockEndPost = true;
UM_RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
+8 -70
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,44 +32,22 @@
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_ #ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_ #define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
#include "ShareSys.h"
#include <IUserMessages.h> #include <IUserMessages.h>
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <sm_stringhashmap.h> #include "sm_trie.h"
#include "sm_stringutil.h"
#include "CellRecipientFilter.h" #include "CellRecipientFilter.h"
#include "sm_globals.h"
#include <sh_list.h>
#include <sh_stack.h>
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#define USE_PROTOBUF_USERMESSAGES
#endif
#ifdef USE_PROTOBUF_USERMESSAGES
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include <netmessages.pb.h>
using namespace google;
#else
#include <bitbuf.h>
#endif
#define INVALID_MESSAGE_ID -1 #define INVALID_MESSAGE_ID -1
struct ListenerInfo struct ListenerInfo
{ {
#ifdef USE_PROTOBUF_USERMESSAGES IUserMessageListener *Callback;
IProtobufUserMessageListener *Callback;
#else
IBitBufUserMessageListener *Callback;
#endif
bool IsHooked; bool IsHooked;
bool KillMe; bool KillMe;
bool IsNew;
}; };
typedef List<ListenerInfo *> MsgList; typedef List<ListenerInfo *> MsgList;
@@ -91,70 +69,30 @@ public: //IUserMessages
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const; bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false); bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false); bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
bf_write *StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags); bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
google::protobuf::Message *StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
bool EndMessage(); bool EndMessage();
bool HookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept=false);
bool UnhookUserMessage2(int msg_id,
IUserMessageListener *pListener,
bool intercept=false);
UserMessageType GetUserMessageType() const;
public: public:
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
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
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
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
#else
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type); bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type);
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type); bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type);
#endif
void OnMessageEnd_Pre(); void OnMessageEnd_Pre();
void OnMessageEnd_Post(); void OnMessageEnd_Post();
private: private:
#ifdef USE_PROTOBUF_USERMESSAGES
const protobuf::Message *GetMessagePrototype(int msg_type);
bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
#else
bool InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
#endif
void _DecRefCounter(); void _DecRefCounter();
private: private:
List<ListenerInfo *> m_msgHooks[255]; List<ListenerInfo *> m_msgHooks[255];
List<ListenerInfo *> m_msgIntercepts[255]; List<ListenerInfo *> m_msgIntercepts[255];
CStack<ListenerInfo *> m_FreeListeners; CStack<ListenerInfo *> m_FreeListeners;
IRecipientFilter *m_CurRecFilter;
#ifndef USE_PROTOBUF_USERMESSAGES
unsigned char m_pBase[2500]; unsigned char m_pBase[2500];
IRecipientFilter *m_CurRecFilter;
bf_write m_InterceptBuffer; bf_write m_InterceptBuffer;
bf_write *m_OrigBuffer; bf_write *m_OrigBuffer;
bf_read m_ReadBuffer; bf_read m_ReadBuffer;
#else
// The engine used to provide this. Now we track it.
protobuf::Message *m_OrigBuffer;
protobuf::Message *m_FakeEngineBuffer;
META_RES m_FakeMetaRes;
protobuf::Message *m_InterceptBuffer;
#endif
size_t m_HookCount; size_t m_HookCount;
bool m_InHook; bool m_InHook;
bool m_BlockEndPost; bool m_BlockEndPost;
#ifndef USE_PROTOBUF_USERMESSAGES
bool m_FallbackSearch; bool m_FallbackSearch;
StringHashMap<int> m_Names; Trie *m_Names;
#endif
CellRecipientFilter m_CellRecFilter; CellRecipientFilter m_CellRecFilter;
bool m_InExec; bool m_InExec;
int m_CurFlags; int m_CurFlags;
+23 -37
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -35,13 +35,9 @@
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "compat_wrappers.h"
#if SOURCE_ENGINE >= SE_ORANGEBOX #if defined ORANGEBOX_BUILD
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *); SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
#else
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
#endif #endif
using namespace SourceHook; using namespace SourceHook;
@@ -54,55 +50,29 @@ struct ConCommandInfo
}; };
List<ConCommandInfo *> tracked_bases; List<ConCommandInfo *> tracked_bases;
IConCommandLinkListener *IConCommandLinkListener::head = NULL;
ConCommandBase *FindConCommandBase(const char *name); ConCommandBase *FindConCommandBase(const char *name);
class ConCommandCleaner : public SMGlobalClass class ConCommandCleaner : public SMGlobalClass
{ {
public: public:
#if defined ORANGEBOX_BUILD
void OnSourceModAllInitialized() void OnSourceModAllInitialized()
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_ADD_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
SH_ADD_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
#else
SH_ADD_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
#endif
} }
void OnSourceModShutdown() void OnSourceModShutdown()
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_REMOVE_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false); }
SH_REMOVE_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
#else
SH_REMOVE_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
#endif #endif
}
void LinkConCommandBase(ConCommandBase *pBase)
{
IConCommandLinkListener *listener = IConCommandLinkListener::head;
while (listener)
{
listener->OnLinkConCommand(pBase);
listener = listener->next;
}
}
void UnlinkConCommandBase(ConCommandBase *pBase) void UnlinkConCommandBase(ConCommandBase *pBase)
{ {
ConCommandInfo *pInfo; ConCommandInfo *pInfo;
List<ConCommandInfo *>::iterator iter = tracked_bases.begin(); List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
IConCommandLinkListener *listener = IConCommandLinkListener::head;
while (listener)
{
listener->OnUnlinkConCommand(pBase);
listener = listener->next;
}
if (pBase) if (pBase)
{ {
while (iter != tracked_bases.end()) while (iter != tracked_bases.end())
@@ -125,7 +95,7 @@ public:
while (iter != tracked_bases.end()) while (iter != tracked_bases.end())
{ {
/* This is just god-awful! */ /* This is just god-awful! */
if (FindCommandBase((*iter)->name) != (*iter)->pBase) if (FindConCommandBase((*iter)->name) != (*iter)->pBase)
{ {
pInfo = (*iter); pInfo = (*iter);
iter = tracked_bases.erase(iter); iter = tracked_bases.erase(iter);
@@ -173,6 +143,22 @@ public:
} }
} s_ConCmdTracker; } s_ConCmdTracker;
ConCommandBase *FindConCommandBase(const char *name)
{
const ConCommandBase *pBase = icvar->GetCommands();
while (pBase != NULL)
{
if (strcmp(pBase->GetName(), name) == 0)
{
return const_cast<ConCommandBase *>(pBase);
}
pBase = pBase->GetNext();
}
return NULL;
}
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me) void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
{ {
s_ConCmdTracker.AddTarget(pBase, me); s_ConCmdTracker.AddTarget(pBase, me);
+2 -23
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -38,30 +38,9 @@ public:
virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0; virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0;
}; };
ConCommandBase *FindConCommandBase(const char *name);
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me); void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me); void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase); void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
class IConCommandLinkListener
{
friend class ConCommandCleaner;
static IConCommandLinkListener *head;
IConCommandLinkListener *next;
public:
IConCommandLinkListener()
{
next = head;
head = this;
}
virtual void OnLinkConCommand(ConCommandBase *pBase)
{
}
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
{
}
};
#endif //_INCLUDE_CONCMD_TRACKER_H_ #endif //_INCLUDE_CONCMD_TRACKER_H_
File diff suppressed because it is too large Load Diff
-718
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
+1 -1
View File
@@ -24,7 +24,7 @@
#ifdef _WIN32 #ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE #define FORCEINLINE_CVAR FORCEINLINE
#elif defined _LINUX || defined __APPLE__ #elif _LINUX
#define FORCEINLINE_CVAR inline #define FORCEINLINE_CVAR inline
#else #else
#error "implement me" #error "implement me"
File diff suppressed because it is too large Load Diff
+5 -64
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -30,79 +30,20 @@
*/ */
#include "frame_hooks.h" #include "frame_hooks.h"
#include "TimerSys.h" #include "TimerSys.h"
#include "Database.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "MenuStyle_Valve.h" #include "MenuStyle_Valve.h"
#include "MenuStyle_Radio.h" #include "MenuStyle_Radio.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "CoreConfig.h"
#include <sm_queue.h>
#include <IThreader.h>
#include "sourcemod.h"
static IMutex *frame_mutex; float g_LastMenuTime = 0.0f;
static Queue<FrameAction> *frame_queue; float g_LastAuthCheck = 0.0f;
static Queue<FrameAction> *frame_actions;
static float g_LastMenuTime = 0.0f;
static float g_LastAuthCheck = 0.0f;
bool g_PendingInternalPush = false;
class FrameActionInit : public SMGlobalClass
{
public:
void OnSourceModAllInitialized()
{
frame_queue = new Queue<FrameAction>();
frame_actions = new Queue<FrameAction>();
frame_mutex = g_pThreader->MakeMutex();
}
void OnSourceModShutdown()
{
delete frame_queue;
delete frame_actions;
frame_mutex->DestroyThis();
}
} s_FrameActionInit;
void AddFrameAction(const FrameAction & action)
{
frame_mutex->Lock();
frame_queue->push(action);
frame_mutex->Unlock();
}
void RunFrameHooks(bool simulating) void RunFrameHooks(bool simulating)
{ {
/* It's okay if this check races. */
if (frame_queue->size())
{
Queue<FrameAction> *temp;
/* Very quick lock to move queue/actions back and forth */
frame_mutex->Lock();
temp = frame_queue;
frame_queue = frame_actions;
frame_actions = temp;
frame_mutex->Unlock();
/* The server will now be adding to the other queue, so we can process events. */
while (!frame_actions->empty())
{
FrameAction &item = frame_actions->first();
frame_actions->pop();
item.action(item.data);
}
}
/* Frame based hooks */ /* Frame based hooks */
g_DBMan.RunFrame();
g_HL2.ProcessFakeCliCmdQueue(); g_HL2.ProcessFakeCliCmdQueue();
g_HL2.ProcessDelayedKicks();
if (g_PendingInternalPush)
{
SM_InternalCmdTrigger();
}
g_SourceMod.ProcessGameFrameHooks(simulating); g_SourceMod.ProcessGameFrameHooks(simulating);
float curtime = *g_pUniversalTime; float curtime = *g_pUniversalTime;
+1 -17
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,22 +32,6 @@
#ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ #ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
#define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ #define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
#include <ISourceMod.h>
using namespace SourceMod;
struct FrameAction
{
FrameAction(FRAMEACTION a, void *d) : data(d), action(a)
{
}
void *data;
FRAMEACTION action;
};
extern bool g_PendingInternalPush;
void AddFrameAction(const FrameAction & action);
void RunFrameHooks(bool simulating); void RunFrameHooks(bool simulating);
#endif //_INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ #endif //_INCLUDE_SOURCEMOD_FRAME_HOOKS_H_
-81
View File
@@ -1,81 +0,0 @@
# 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'
]
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-']
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',
'Profiler.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',
]
if builder.target_platform == 'windows':
binary.sources += ['thread/WinThreads.cpp']
else:
binary.sources += ['thread/PosixThreads.cpp']
SM.binaries += [builder.Add(binary)]
File diff suppressed because it is too large Load Diff
-108
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)
-612
View File
@@ -1,612 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2011 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 "MemoryUtils.h"
#ifdef PLATFORM_LINUX
#include <fcntl.h>
#include <link.h>
#include <sys/mman.h>
#define PAGE_SIZE 4096
#define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
#endif
#ifdef PLATFORM_APPLE
#include <AvailabilityMacros.h>
#include <mach/task.h>
#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;
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;
}
#endif
}
MemoryUtils::~MemoryUtils()
{
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
for (size_t i = 0; i < m_SymTables.size(); i++)
{
delete m_SymTables[i];
}
m_SymTables.clear();
#endif
}
void MemoryUtils::OnSourceModAllInitialized()
{
sharesys->AddInterface(NULL, this);
}
void *MemoryUtils::FindPattern(const void *libPtr, const char *pattern, size_t len)
{
DynLibInfo lib;
bool found;
char *ptr, *end;
memset(&lib, 0, sizeof(DynLibInfo));
if (!GetLibraryInfo(libPtr, lib))
{
return NULL;
}
ptr = reinterpret_cast<char *>(lib.baseAddress);
end = ptr + lib.memorySize - len;
while (ptr < end)
{
found = true;
for (register size_t i = 0; i < len; i++)
{
if (pattern[i] != '\x2A' && pattern[i] != ptr[i])
{
found = false;
break;
}
}
if (found)
return ptr;
ptr++;
}
return NULL;
}
void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
{
#ifdef PLATFORM_WINDOWS
return GetProcAddress((HMODULE)handle, symbol);
#elif defined PLATFORM_LINUX
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;
const char *shstrtab, *strtab;
uint16_t section_count;
uint32_t symbol_count;
LibSymbolTable *libtable;
SymbolTable *table;
Symbol *symbol_entry;
dlmap = (struct link_map *)handle;
symtab_hdr = NULL;
strtab_hdr = NULL;
table = NULL;
/* See if we already have a symbol table for this library */
for (size_t i = 0; i < m_SymTables.size(); i++)
{
libtable = m_SymTables[i];
if (libtable->lib_base == dlmap->l_addr)
{
table = &libtable->table;
break;
}
}
/* If we don't have a symbol table for this library, then create one */
if (table == NULL)
{
libtable = new LibSymbolTable();
libtable->table.Initialize();
libtable->lib_base = dlmap->l_addr;
libtable->last_pos = 0;
table = &libtable->table;
m_SymTables.push_back(libtable);
}
/* See if the symbol is already cached in our table */
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
if (symbol_entry != NULL)
{
return symbol_entry->address;
}
/* If symbol isn't in our table, then we have open the actual library */
dlfile = open(dlmap->l_name, O_RDONLY);
if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)
{
close(dlfile);
return NULL;
}
/* Map library file into memory */
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
map_base = (uintptr_t)file_hdr;
if (file_hdr == MAP_FAILED)
{
close(dlfile);
return NULL;
}
close(dlfile);
if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF)
{
munmap(file_hdr, dlstat.st_size);
return NULL;
}
sections = (Elf32_Shdr *)(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];
shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);
/* 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];
const char *section_name = shstrtab + hdr.sh_name;
if (strcmp(section_name, ".symtab") == 0)
{
symtab_hdr = &hdr;
}
else if (strcmp(section_name, ".strtab") == 0)
{
strtab_hdr = &hdr;
}
}
/* Uh oh, we don't have a symbol table or a string table */
if (symtab_hdr == NULL || strtab_hdr == NULL)
{
munmap(file_hdr, dlstat.st_size);
return NULL;
}
symtab = (Elf32_Sym *)(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);
const char *sym_name = strtab + sym.st_name;
Symbol *cur_sym;
/* Skip symbols that are undefined or do not refer to functions or objects */
if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT))
{
continue;
}
/* Caching symbols as we go along */
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlmap->l_addr + sym.st_value));
if (strcmp(symbol, sym_name) == 0)
{
symbol_entry = cur_sym;
libtable->last_pos = ++i;
break;
}
}
munmap(file_hdr, dlstat.st_size);
return symbol_entry ? symbol_entry->address : NULL;
#elif defined PLATFORM_APPLE
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;
const char *strtab;
uint32_t loadcmd_count;
uint32_t symbol_count;
LibSymbolTable *libtable;
SymbolTable *table;
Symbol *symbol_entry;
dlbase = 0;
image_count = m_ImageList->infoArrayCount;
linkedit_hdr = NULL;
symtab_hdr = NULL;
table = NULL;
/* Loop through mach-o images in process.
* We can skip index 0 since that is just the executable.
*/
for (uint32_t i = 1; i < image_count; i++)
{
const struct dyld_image_info &info = m_ImageList->infoArray[i];
/* "Load" each one until we get a matching handle */
void *h = dlopen(info.imageFilePath, RTLD_NOLOAD);
if (h == handle)
{
dlbase = (uintptr_t)info.imageLoadAddress;
dlclose(h);
break;
}
dlclose(h);
}
if (!dlbase)
{
/* Uh oh, we couldn't find a matching handle */
return NULL;
}
/* See if we already have a symbol table for this library */
for (size_t i = 0; i < m_SymTables.size(); i++)
{
libtable = m_SymTables[i];
if (libtable->lib_base == dlbase)
{
table = &libtable->table;
break;
}
}
/* If we don't have a symbol table for this library, then create one */
if (table == NULL)
{
libtable = new LibSymbolTable();
libtable->table.Initialize();
libtable->lib_base = dlbase;
libtable->last_pos = 0;
table = &libtable->table;
m_SymTables.push_back(libtable);
}
/* See if the symbol is already cached in our table */
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
if (symbol_entry != NULL)
{
return symbol_entry->address;
}
/* 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));
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)
{
struct segment_command *seg = (struct segment_command *)loadcmds;
if (strcmp(seg->segname, "__LINKEDIT") == 0)
{
linkedit_hdr = seg;
if (symtab_hdr)
{
break;
}
}
}
else if (loadcmds->cmd == LC_SYMTAB)
{
symtab_hdr = (struct symtab_command *)loadcmds;
if (linkedit_hdr)
{
break;
}
}
/* Load commands are not of a fixed size which is why we add the size */
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
}
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
{
/* Uh oh, no symbol table */
return NULL;
}
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
symtab = (struct nlist *)(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];
/* Ignore the prepended underscore on all symbols, so +1 here */
const char *sym_name = strtab + sym.n_un.n_strx + 1;
Symbol *cur_sym;
/* Skip symbols that are undefined */
if (sym.n_sect == NO_SECT)
{
continue;
}
/* Caching symbols as we go along */
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlbase + sym.n_value));
if (strcmp(symbol, sym_name) == 0)
{
symbol_entry = cur_sym;
libtable->last_pos = ++i;
break;
}
}
return symbol_entry ? symbol_entry->address : NULL;
#endif
}
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
{
uintptr_t baseAddr;
if (libPtr == NULL)
{
return false;
}
#ifdef PLATFORM_WINDOWS
MEMORY_BASIC_INFORMATION info;
IMAGE_DOS_HEADER *dos;
IMAGE_NT_HEADERS *pe;
IMAGE_FILE_HEADER *file;
IMAGE_OPTIONAL_HEADER *opt;
if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
{
return false;
}
baseAddr = reinterpret_cast<uintptr_t>(info.AllocationBase);
/* All this is for our insane sanity checks :o */
dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr);
pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew);
file = &pe->FileHeader;
opt = &pe->OptionalHeader;
/* Check PE magic and signature */
if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
{
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)
{
return false;
}
/* For our purposes, this must be a dynamic library */
if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
{
return false;
}
/* Finally, we can do this */
lib.memorySize = opt->SizeOfImage;
#elif defined PLATFORM_LINUX
Dl_info info;
Elf32_Ehdr *file;
Elf32_Phdr *phdr;
uint16_t phdrCount;
if (!dladdr(libPtr, &info))
{
return false;
}
if (!info.dli_fbase || !info.dli_fname)
{
return false;
}
/* This is for our insane sanity checks :o */
baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase);
file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
/* Check ELF magic */
if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
{
return false;
}
/* Check ELF version */
if (file->e_ident[EI_VERSION] != EV_CURRENT)
{
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)
{
return false;
}
/* For our purposes, this must be a dynamic library/shared object */
if (file->e_type != ET_DYN)
{
return false;
}
phdrCount = file->e_phnum;
phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
for (uint16_t i = 0; i < phdrCount; i++)
{
Elf32_Phdr &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))
{
/* From glibc, elf/dl-load.c:
* c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1)
* & ~(GLRO(dl_pagesize) - 1));
*
* In glibc, the segment file size is aligned up to the nearest page size and
* added to the virtual address of the segment. We just want the size here.
*/
lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz);
break;
}
}
#elif defined PLATFORM_APPLE
Dl_info info;
struct mach_header *file;
struct segment_command *seg;
uint32_t cmd_count;
if (!dladdr(libPtr, &info))
{
return false;
}
if (!info.dli_fbase || !info.dli_fname)
{
return false;
}
/* This is for our insane sanity checks :o */
baseAddr = (uintptr_t)info.dli_fbase;
file = (struct mach_header *)baseAddr;
/* Check Mach-O magic */
if (file->magic != MH_MAGIC)
{
return false;
}
/* Check architecture (32-bit/x86) */
if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL)
{
return false;
}
/* For our purposes, this must be a dynamic library */
if (file->filetype != MH_DYLIB)
{
return false;
}
cmd_count = file->ncmds;
seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header));
/* Add up memory sizes of mapped segments */
for (uint32_t i = 0; i < cmd_count; i++)
{
if (seg->cmd == LC_SEGMENT)
{
lib.memorySize += seg->vmsize;
}
seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize);
}
#endif
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
return true;
}
-399
View File
@@ -1,399 +0,0 @@
// MersenneTwister.h
// Mersenne Twister random number generator -- a C++ class MTRand
// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
// Richard J. Wagner v1.0 15 May 2003 [email protected]
// The Mersenne Twister is an algorithm for generating random numbers. It
// was designed with consideration of the flaws in various other generators.
// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
// are far greater. The generator is also fast; it avoids multiplication and
// division, and it benefits from caches and pipelines. For more information
// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
// Reference
// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
// Copyright (C) 2000 - 2003, Richard J. Wagner
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The names of its contributors may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The original code included the following notice:
//
// When you use this, send an email to: [email protected]
// with an appropriate reference to your work.
//
// It would be nice to CC: [email protected] and [email protected]
// when you write.
#ifndef MERSENNETWISTER_H
#define MERSENNETWISTER_H
// Not thread safe (unless auto-initialization is avoided and each thread has
// its own MTRand object)
#include <limits.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
class MTRand {
// Data
public:
typedef unsigned long uint32; // unsigned integer type, at least 32 bits
enum { N = 624 }; // length of state vector
enum { SAVE = N + 1 }; // length of array for save()
protected:
enum { M = 397 }; // period parameter
uint32 state[N]; // internal state
uint32 *pNext; // next value to get from state
int left; // number of values left before reload needed
//Methods
public:
MTRand( const uint32& oneSeed ); // initialize with a simple uint32
MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
MTRand(); // auto-initialize with /dev/urandom or time() and clock()
// Do NOT use for CRYPTOGRAPHY without securely hashing several returned
// values together, otherwise the generator state can be learned after
// reading 624 consecutive values.
// Access to 32-bit random numbers
double rand(); // real number in [0,1]
double rand( const double& n ); // real number in [0,n]
double randExc(); // real number in [0,1)
double randExc( const double& n ); // real number in [0,n)
double randDblExc(); // real number in (0,1)
double randDblExc( const double& n ); // real number in (0,n)
uint32 randInt(); // integer in [0,2^32-1]
uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
double operator()() { return rand(); } // same as rand()
// Access to 53-bit random numbers (capacity of IEEE double precision)
double rand53(); // real number in [0,1)
// Access to nonuniform random number distributions
double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
// Re-seeding functions with same behavior as initializers
void seed( const uint32 oneSeed );
void seed( uint32 *const bigSeed, const uint32 seedLength = N );
void seed();
// Saving and loading generator state
void save( uint32* saveArray ) const; // to array of size SAVE
void load( uint32 *const loadArray ); // from such array
protected:
void initialize( const uint32 oneSeed );
void reload();
uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
uint32 mixBits( const uint32& u, const uint32& v ) const
{ return hiBit(u) | loBits(v); }
uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
{ return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
static uint32 hash( time_t t, clock_t c );
};
inline MTRand::MTRand( const uint32& oneSeed )
{ seed(oneSeed); }
inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
{ seed(bigSeed,seedLength); }
inline MTRand::MTRand()
{ seed(); }
inline double MTRand::rand()
{ return double(randInt()) * (1.0/4294967295.0); }
inline double MTRand::rand( const double& n )
{ return rand() * n; }
inline double MTRand::randExc()
{ return double(randInt()) * (1.0/4294967296.0); }
inline double MTRand::randExc( const double& n )
{ return randExc() * n; }
inline double MTRand::randDblExc()
{ return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
inline double MTRand::randDblExc( const double& n )
{ return randDblExc() * n; }
inline double MTRand::rand53()
{
uint32 a = randInt() >> 5, b = randInt() >> 6;
return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
}
inline double MTRand::randNorm( const double& mean, const double& variance )
{
// Return a real number from a normal (Gaussian) distribution with given
// mean and variance by Box-Muller method
double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
return mean + r * cos(phi);
}
inline MTRand::uint32 MTRand::randInt()
{
// Pull a 32-bit integer from the generator state
// Every other access function simply transforms the numbers extracted here
if( left == 0 ) reload();
--left;
register uint32 s1;
s1 = *pNext++;
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9d2c5680UL;
s1 ^= (s1 << 15) & 0xefc60000UL;
return ( s1 ^ (s1 >> 18) );
}
inline MTRand::uint32 MTRand::randInt( const uint32& n )
{
// Find which bits are used in n
// Optimized by Magnus Jonsson ([email protected])
uint32 used = n;
used |= used >> 1;
used |= used >> 2;
used |= used >> 4;
used |= used >> 8;
used |= used >> 16;
// Draw numbers until one is found in [0,n]
uint32 i;
do
i = randInt() & used; // toss unused bits to shorten search
while( i > n );
return i;
}
inline void MTRand::seed( const uint32 oneSeed )
{
// Seed the generator with a simple uint32
initialize(oneSeed);
reload();
}
inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
{
// Seed the generator with an array of uint32's
// There are 2^19937-1 possible initial states. This function allows
// all of those to be accessed by providing at least 19937 bits (with a
// default seed length of N = 624 uint32's). Any bits above the lower 32
// in each element are discarded.
// Just call seed() if you want to get array from /dev/urandom
initialize(19650218UL);
register int i = 1;
register uint32 j = 0;
register int k = ( N > seedLength ? N : seedLength );
for( ; k; --k )
{
state[i] =
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
state[i] &= 0xffffffffUL;
++i; ++j;
if( i >= N ) { state[0] = state[N-1]; i = 1; }
if( j >= seedLength ) j = 0;
}
for( k = N - 1; k; --k )
{
state[i] =
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
state[i] -= i;
state[i] &= 0xffffffffUL;
++i;
if( i >= N ) { state[0] = state[N-1]; i = 1; }
}
state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
reload();
}
inline void MTRand::seed()
{
// Seed the generator with an array from /dev/urandom if available
// Otherwise use a hash of time() and clock() values
// First try getting an array from /dev/urandom
FILE* urandom = fopen( "/dev/urandom", "rb" );
if( urandom )
{
uint32 bigSeed[N];
register uint32 *s = bigSeed;
register int i = N;
register bool success = true;
while( success && i-- )
success = fread( s++, sizeof(uint32), 1, urandom );
fclose(urandom);
if( success ) { seed( bigSeed, N ); return; }
}
// Was not successful, so use time() and clock() instead
seed( hash( time(NULL), clock() ) );
}
inline void MTRand::initialize( const uint32 seed )
{
// Initialize generator state with seed
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
// In previous versions, most significant bits (MSBs) of the seed affect
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
register uint32 *s = state;
register uint32 *r = state;
register int i = 1;
*s++ = seed & 0xffffffffUL;
for( ; i < N; ++i )
{
*s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
r++;
}
}
inline void MTRand::reload()
{
// Generate N new values in state
// Made clearer and faster by Matthew Bellew ([email protected])
register uint32 *p = state;
register int i;
for( i = N - M; i--; ++p )
*p = twist( p[M], p[0], p[1] );
for( i = M; --i; ++p )
*p = twist( p[M-N], p[0], p[1] );
*p = twist( p[M-N], p[0], state[0] );
left = N, pNext = state;
}
inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
{
// Get a uint32 from t and c
// Better than uint32(x) in case x is floating point in [0,1]
// Based on code by Lawrence Kirby ([email protected])
static uint32 differ = 0; // guarantee time-based seeds will change
uint32 h1 = 0;
unsigned char *p = (unsigned char *) &t;
for( size_t i = 0; i < sizeof(t); ++i )
{
h1 *= UCHAR_MAX + 2U;
h1 += p[i];
}
uint32 h2 = 0;
p = (unsigned char *) &c;
for( size_t j = 0; j < sizeof(c); ++j )
{
h2 *= UCHAR_MAX + 2U;
h2 += p[j];
}
return ( h1 + differ++ ) ^ h2;
}
inline void MTRand::save( uint32* saveArray ) const
{
register uint32 *sa = saveArray;
register const uint32 *s = state;
register int i = N;
for( ; i--; *sa++ = *s++ ) {}
*sa = left;
}
inline void MTRand::load( uint32 *const loadArray )
{
register uint32 *s = state;
register uint32 *la = loadArray;
register int i = N;
for( ; i--; *s++ = *la++ ) {}
left = *la;
pNext = &state[N-left];
}
#endif // MERSENNETWISTER_H
// Change log:
//
// v0.1 - First release on 15 May 2000
// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
// - Translated from C to C++
// - Made completely ANSI compliant
// - Designed convenient interface for initialization, seeding, and
// obtaining numbers in default or user-defined ranges
// - Added automatic seeding from /dev/urandom or time() and clock()
// - Provided functions for saving and loading generator state
//
// v0.2 - Fixed bug which reloaded generator one step too late
//
// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
//
// v0.4 - Removed trailing newline in saved generator format to be consistent
// with output format of built-in types
//
// v0.5 - Improved portability by replacing static const int's with enum's and
// clarifying return values in seed(); suggested by Eric Heimburg
// - Removed MAXINT constant; use 0xffffffffUL instead
//
// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
// - Changed integer [0,n] generator to give better uniformity
//
// v0.7 - Fixed operator precedence ambiguity in reload()
// - Added access for real numbers in (0,1) and (0,n)
//
// v0.8 - Included time.h header to properly support time_t and clock_t
//
// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
// - Allowed for seeding with arrays of any length
// - Added access for real numbers in [0,1) with 53-bit resolution
// - Added access for real numbers from normal (Gaussian) distributions
// - Increased overall speed by optimizing twist()
// - Doubled speed of integer [0,n] generation
// - Fixed out-of-range number generation on 64-bit machines
// - Improved portability by substituting literal constants for long enum's
// - Changed license from GNU LGPL to BSD
-98
View File
@@ -1,98 +0,0 @@
/**
* 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$
*/
#ifndef _include_sourcemod_native_h_
#define _include_sourcemod_native_h_
#include <IShareSys.h>
#include <IHandleSys.h>
#include <am-string.h>
#include <am-utility.h>
#include <am-refcounting.h>
#include "common_logic.h"
struct FakeNative
{
FakeNative(const char *name, IPluginFunction *fun)
: name(name),
ctx(fun->GetParentContext()),
call(fun),
gate(NULL)
{
}
~FakeNative();
ke::AString name;
IPluginContext *ctx;
IPluginFunction *call;
SPVM_NATIVE_FUNC gate;
};
struct Native : public ke::Refcounted<Native>
{
Native(CNativeOwner *owner, const sp_nativeinfo_t *native)
: owner(owner),
native(native),
fake(NULL)
{
}
Native(CNativeOwner *owner, FakeNative *fake)
: owner(owner),
native(NULL),
fake(fake)
{
}
CNativeOwner *owner;
const sp_nativeinfo_t *native;
ke::AutoPtr<FakeNative> fake;
SPVM_NATIVE_FUNC func() const
{
if (native)
return native->func;
return fake->gate;
}
const char *name() const
{
if (native)
return native->name;
return fake->name.chars();
}
static inline bool matches(const char *name, const ke::Ref<Native> &entry)
{
return strcmp(name, entry->name()) == 0;
}
};
#endif // _include_sourcemod_native_h_
-360
View File
@@ -1,360 +0,0 @@
/**
* 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;
}

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