Compare commits

..
Author SHA1 Message Date
Nicholas Hastings 7ecdfae3ed Removed tag sourcemod-1.5.3 2014-03-22 17:08:18 -04:00
Nicholas Hastings af6350176d Fix compile error in DisplayAskConnectBox stock (bug 5984). 2014-03-22 17:06:37 -04:00
Nicholas Hastings ca2e8e4675 Backed out changeset: 9b092b739653. 2014-03-22 17:07:19 -04:00
Nicholas Hastings 50ace321d1 Bumping version. 2014-03-22 16:02:59 -04:00
Nicholas Hastings d3d700cfdc Added tag sourcemod-1.5.3 for changeset 27bf76b007d2 2014-03-22 16:02:19 -04:00
Nicholas Hastings d3277ce11a Update versioning for 1.5.3 release. 2014-03-22 15:32:11 -04:00
Nicholas Hastings 9f40261c69 Updated changelog for version 1.5.3. 2014-03-22 15:31:12 -04:00
Nicholas Hastings 3b4e73cdd7 Improve logical entity support in SDKHooks natives (bug 6069, r=asherkin). 2014-03-21 22:09:15 -04:00
Nicholas Hastings ccca0a91eb Fix Alien Swarm EntityListeners gamedata for SDKHooks (bug 6059). 2014-03-21 13:10:44 -04:00
Nicholas Hastings fa8bf950ac Fix missing compile.exe and unecessary compile.sh in Windows package (bug 6047, r=asherkin). 2014-03-21 12:30:47 -04:00
FlaminSarge eee2108efb Add support for passwords to DisplayAskConnectBox stock (bug 5984, r=psychonic). 2014-03-21 12:14:08 -04:00
Nicholas Hastings 406b72e0a6 Record inline function debug info in PDB files (r=asherkin). 2014-03-21 12:04:41 -04:00
Nicholas Hastings 6c658b4f8e Add default infinite value for TF2_AddCondition duration (nobug, r=asherkin). 2014-03-21 12:03:49 -04:00
Nicholas Hastings 8a51bc6dbf Add hack to not throw error on FEBC not found if not attempted to be found (nobug, r=asherkin). 2014-03-21 12:03:19 -04:00
Kyle Sanderson 3fffcdb931 Remove unfinished ConVar queries on client disconnect (bug 6003, r=psychonic). 2014-02-27 19:55:13 -07:00
Kyle Sanderson 5630fa67fc Fix FakeClientCommandEx always leaking memory (bug 5678, r=psychonic). 2014-03-08 19:50:55 -07:00
Kyle Sanderson 1a87eeead0 Fix Anti-Flood resolution of gametime (bug 5394, r=psychonic). 2014-02-27 20:49:19 -07:00
Peace-Maker d1ac171e72 Update GoldenEye: Source gamedata. 2014-03-17 10:01:17 -04:00
Peace-Maker c6899a86f1 Fix crash in SDKHooks Reload post-hook (irc, r=psychonic).
--HG--
extra : rebase_source : ae38cb50949e0be8f0f754832ee829adebc5a525
2014-01-27 10:09:03 -05:00
Ruben Gonzalez a2e2355101 Update CS:GO gamedata 2014-03-10 18:56:48 -04:00
Nicholas Hastings 7ca786168f Fix TE_* natives operating on incorrect data for some tempents (bug 6072, r=fyren). 2014-03-08 19:46:49 -05:00
Nicholas Hastings d1ec331ada Update CPlayer::Kick for hl2sdk-csgo IClient changes.
--HG--
extra : rebase_source : d592d29e58a6834201053f91d23a53d9a723c75b
2014-03-06 21:33:18 -05:00
Scott Ehlert 37658183bc Fix upload step for builds. 2014-03-05 15:37:40 -06:00
Nicholas Hastings aef08d1f19 Define NETWORK_VARS_ENABLED for SDKs that require it.
--HG--
extra : rebase_source : 6eec50055697d4c78c812c71f6ae923a558b233f
2014-02-10 21:04:01 -05:00
Nicholas Hastings b83e8e6c29 Add GiveAmmo gamedata for more games.
--HG--
extra : rebase_source : 3ec36c4060d5dc33ac327f49b81d51cfa4052e92
2014-02-10 11:46:10 -05:00
Peace-Maker f328aecc62 Add GiveAmmo native to SDKTools (bug 6039, r=psychonic).
--HG--
extra : rebase_source : 5cae34d7db2f4b395010fce344c4efcb2f29e88f
2014-02-10 10:49:19 -05:00
Nicholas Hastings 4620f4cf7a Update SDKHooks CTakeDamageInfoHack for SDK updates.
--HG--
extra : rebase_source : 31d12bdfef5a9eeca20c0c492ca3f0629953d758
2014-02-28 15:03:53 -05:00
Ruben Gonzalez 80e3198b7b Update gamedata for CS:GO 2014-02-27 22:17:29 -05:00
Ruben Gonzalez 064aa83991 Fix not returning a valid weaponID for cz75a (irc, r=KyleS) 2014-02-13 13:19:31 -05:00
Peace-Maker d359e5eef3 Fix CS:S GroundEntChanged SDKHooks Windows gamedata. 2014-02-13 11:37:06 -05:00
Scott Ehlert 0425527b83 Make symstore.pl die if it fails to open a symbol directory (no bug, r=dvander). 2014-02-13 02:01:02 -06:00
Scott Ehlert 4f3399ae91 Fix ___strlcat_chk symbol error on OS X 10.8 and earlier (bug 6046, r=dvander). 2014-02-13 02:05:16 -06:00
Dr!fter 9223c714b3 Fix possible crash when unloading cstrike extension. (irc, r=KyleS) 2014-02-12 23:59:57 -05:00
Dr!fter c546e59c80 Fix CS_GetWeaponPrice returning incorrect value for M4A1 in CS:GO (bug 6045, r=KyleS) 2014-02-12 19:46:47 -05:00
Asher Baker fe2383e061 Package plugin_settings.cfg (r=dvander). 2014-02-11 20:56:14 +00:00
Nicholas Hastings cc9c5e227d Fix build. 2014-02-10 10:06:21 -05:00
FlaminSarge 53f53c64fc Update TFCond and customkill enum values (bug 6012, r=psychonic). 2014-01-27 10:15:17 -05:00
Nicholas Hastings cd58e16d9c Remove over-aggressive error handling of Addresses gamedata (bug 6044, r=asherkin). 2014-02-10 10:02:29 -05:00
Nicholas Hastings df6ca9b246 Remove over-aggressive error handling of Addresses gamedata (bug 6044, r=asherkin). 2014-02-10 09:43:10 -05:00
Scott Ehlert defa74660b Use == instead of is operator for checking string equality in AMBuild scripts (bug 6043, r=dvander). 2014-02-09 22:53:51 -06:00
Peace-Maker 3b9962f05a Fix param order in AddToTopMenu function doc (bug 6035, r=psychonic).
--HG--
extra : amend_source : dd2964c4e39d6273f50f617d11cec211992e8619
2014-02-09 19:38:41 -05:00
Scott Ehlert 6151a39b7f Remove GLIBC 2.7 depedency from Webternet extension (no bug, r=dvander). 2014-02-09 15:20:30 -06:00
Ruben Gonzalez eb0d2efa48 Fix typo in sdktools error. 2014-02-08 22:16:25 -05:00
Nicholas Hastings fb4ad7ae81 Fix CS:GO EntInfosFinder gamedata. 2014-02-08 12:22:02 -05:00
Nicholas Hastings 5916709430 Fix SDKHooks load issue and reliance on gEntList ptr on CS:GO and Dota 2 on Windows. 2014-02-07 22:11:31 -05:00
Nicholas Hastings 6e40168f79 Fix logical entity support for Dota 2 and CS:GO on Windows. 2014-02-07 20:44:52 -05:00
Nicholas Hastings f457362f18 Update CS:GO SDKTools gamedata. 2014-02-07 13:07:30 -05:00
Ruben Gonzalez f801ce9542 Update CStrike extension and gamedata on windows for latest CS:GO update (irc, r= psychonic) 2014-02-08 20:52:45 -05:00
Ruben Gonzalez cb489af757 Increase max sig length (irc, r=psychonic) 2014-02-08 20:51:59 -05:00
Kyle Sanderson dd4a02bf1f Remove unmanaged forwards from lookup list on Release (bug 6025, r=psychonic). 2014-02-08 14:53:27 -07:00
Nicholas Hastings 95de3a64d8 Update CS:GO SDKHooks gamedata. 2014-02-03 08:56:33 -05:00
David Anderson d3144079e9 Backed out changeset d144486e4921 2014-02-02 01:36:46 -08:00
David Anderson fc331ad4e0 Trigger build. 2014-02-02 01:27:34 -08:00
David Anderson 269c4c56ee Trigger build. 2014-02-01 17:35:36 -08:00
David Anderson 965aaeb543 Trigger build 2014-02-01 17:31:10 -08:00
David Anderson 69c00d69dc Trigger build. 2014-02-01 17:26:37 -08:00
David Anderson ec5968d5aa Disable console colors when configuring. 2014-02-01 17:21:09 -08:00
David Anderson 80bfd9557e Trigger build. 2014-02-01 17:07:40 -08:00
Scott Ehlert b52489f723 Triggering build. 2014-02-01 04:30:52 -06:00
Scott Ehlert bada4c82eb Fix freeing non-heap object warning from GCC (r=ann). 2014-02-01 03:30:46 -06:00
Scott Ehlert 5e3419836c Fix Linux build (r=dvander). 2014-02-01 03:07:14 -06:00
Michael McKoy e1f91a768c Fix overoptimization of nomination counts in Mapchooser (bug 5359, r=kyles). 2014-01-30 19:13:24 -07:00
David Anderson 467d796d7a Disable blade on 1.5. 2014-01-23 20:01:53 -08:00
David Anderson b92ad41d6d Disable dota on 1.5. 2014-01-23 20:00:26 -08:00
David Anderson 010da757da Fix build. 2014-01-23 19:37:21 -08:00
David Anderson 1030c9b1b3 Merge AMBuild2 upgrade from sourcemod-1.6 to sourcemod-1.5. 2014-01-22 22:40:57 -08:00
Peace-Maker de8157302d Rename SortFunc2D parameters to match documentation (bug 6014, r=kyles). 2014-01-22 21:29:42 -07:00
Scott Ehlert 4d1893df4d Triggering build for OS X 10.9 VM. 2014-01-22 00:46:34 -06:00
Kyle Sanderson a2baac7f5e Fix being able to nominate same map multiple times (bug 5109, r=psychonic) 2014-01-17 23:21:52 -05:00
Kyle Sanderson ac4a381295 Add any tag to WritePackCell and ReadPackCell natives (bug 6001, r=asherkin) 2014-01-17 23:19:13 -05:00
Peace-Maker 9831316aff Added SQL_SetCharset native to (re)set charset even after reconnect (bug 5786, r=psychonic). 2013-07-18 10:27:12 -04:00
Dr!fter 7ec2f45708 Update CS:GO CSWeaponDrop signature 2013-11-21 19:26:45 -05:00
Nicholas Hastings 3fd3f99c89 Updaee CS:GO gamedata. 2013-11-16 10:19:20 -05:00
Nicholas Hastings 520a5b1bea Fix incorrect return and inability to block in TF2 OnCrit forward (r=FlaminSarge, VoiDeD). 2013-11-09 19:33:06 -05:00
Nicholas Hastings 1afc603bdf Updated CS:GO gamedata. 2013-11-06 22:48:07 -05:00
Nicholas Hastings d8907b332d Fix build. 2013-11-01 09:58:07 -04:00
FlaminSarge 27b6a190f0 Add support for tracking player conditions >= 64. (bug 5565, bug 5976, r=asherkin)
--HG--
extra : amend_source : 4b997f630583070f3e91c4d71fbb9a295d77735e
2013-08-12 01:11:11 +01:00
Nicholas Hastings de9ff287a1 Bumping version. 2013-10-29 22:00:32 -04:00
Nicholas Hastings 32fb29582e Added tag sourcemod-1.5.2 for changeset 238c41726d73 2013-10-29 22:00:03 -04:00
Nicholas Hastings b635dace11 Update versioning for 1.5.2 release. 2013-10-29 20:21:20 -04:00
Nicholas Hastings d990f956f9 Updated changelog for version 1.5.2. 2013-10-29 20:20:35 -04:00
Nicholas Hastings 955f1e0d3a Updated TF2 enums. 2013-10-29 20:08:18 -04:00
Nicholas Hastings b4cd559186 Fix GetEngineVersion ret values for MM:S 1.9.x on orangebox (bug 5967, r=asherkin). 2013-10-29 19:00:21 -04:00
Nicholas Hastings 46e89891e1 Have SDKTools use IServerTools to get ent facts where available (bug 5968, r=asherkin). 2013-10-29 18:59:36 -04:00
Nicholas Hastings 080e2563c3 Updated TF2 ext Burn call with new parameter. 2013-10-29 18:59:12 -04:00
Nicholas Hastings e1e0c33f2c Updated TF2 gamedata. 2013-10-29 18:59:00 -04:00
Kyle Sanderson 0160d3cc71 Fix regression in SDKTools SetClientListening hook refcounting (bug 5956, r=fyren). 2013-10-24 13:20:42 -04:00
Dr!fter 81f0d82c67 Update CS:GO sdktools gamedata 2013-10-23 22:28:11 -04:00
Scott Ehlert b5276b435a Trigger build. 2013-10-21 03:20:17 -05:00
Nicholas Hastings 16aecfb404 Update CTakeDamageInfo var names from sdk update. 2013-10-06 10:57:38 -04:00
Nicholas Hastings 7054ef56f6 Added missing change from cset e9e163571fde. 2013-10-03 10:48:58 -04:00
Nicholas Hastings bfae78d1ec Updated gamedata for CS:GO Get/SetClientContribution score.
--HG--
extra : rebase_source : fee683e74786f060f670ea6a7c98bd6645c07da5
2013-10-03 10:43:20 -04:00
Nicholas Hastings c82f2b4659 Ported new TF2 critical hit detection logic from sm-central (bug 5894).
--HG--
extra : rebase_source : 687edebc87d34924fdb7c70924a2910389dedd47
2013-10-03 10:44:53 -04:00
Dr!fter 46d71790be Fix Team Score Offset's for linux on CS:GO 2013-09-26 21:00:58 -04:00
Nicholas Hastings 647811f930 Updated HL2DM gamedata. 2013-09-18 21:50:44 -04:00
Kyle Sanderson 7ca80d1c7c Update CS:S gamedata 2013-09-16 21:23:20 -04:00
Nicholas Hastings 8823bab3f3 Fix some format string misuse with map names.
--HG--
extra : rebase_source : 9dc894bfde14718cb96833f6076fae4261f06f5a
2013-09-13 13:47:55 -04:00
Nicholas Hastings b9d5b59bd1 Increase mapname buffer size in nextmap to accomodate longer map names.
--HG--
extra : rebase_source : fef22cc353663630ed54d3f07d4b243b01e84b44
2013-09-13 13:47:55 -04:00
Dr!fter 7fc892d38b Update gamedata for CS:GO update 2013-09-12 21:56:36 -04:00
Asher Baker 09040231a0 Updated plugin blacklist. 2013-09-11 06:18:45 +01:00
Nicholas Hastings 16541a5668 Bumping version. 2013-09-10 16:27:52 -04:00
Nicholas Hastings e1b3b14311 Added tag sourcemod-1.5.1 for changeset 5574bfe07731 2013-09-10 16:27:24 -04:00
Nicholas Hastings 300632db86 Update versioning for 1.5.1 release. 2013-09-10 14:59:41 -04:00
Nicholas Hastings d1776dd641 Updated changelog for version 1.5.1. 2013-09-10 14:58:42 -04:00
Drifter 22cee6a2dd Add CS_UpdateClientModel native to cstrike extension (bug 5905, r=psychonic). 2013-09-10 13:08:14 -04:00
Nicholas Hastings a2194df273 Fix attempted triggers from gagged users displaying in chat (bug 5918, r=asherkin). 2013-09-10 09:52:37 -04:00
Nicholas Hastings 27e20996dd Initialize DamageCustom var in SDKHooks CTakeDamageInfoHack (nobug, r=asherkin). 2013-09-09 18:41:54 -04:00
Kyle Sanderson b5f16142e5 Fix incorrect assignment in SDKHook_TakeDamage + cleanup (bug 5911, r=psychonic). 2013-09-06 18:37:13 -04:00
Peace-Maker 23f1f9e148 Added missing DispatchKeyValues and SDKHooks gamedata for HL2CTF (bug 5114, r=psychonic). 2013-09-05 22:31:44 -04:00
Nicholas Hastings 990f99af5a Reserved slot fixes for OB games when SourceTV or Replay are enabled (bug 5499, r=drifter). 2013-08-30 14:15:02 -04:00
Nicholas Hastings 6ca9d86e8f Make sm_mapvote_runoffpercent cvar work as advertised (bug 5890, r=asherkin). 2013-08-30 14:14:59 -04:00
Nicholas Hastings fae8b4d49a Fix translator system not loading languages with long identifier (bug 5888, r=dvander). 2013-08-28 13:18:55 -04:00
Nicholas Hastings 7f2d9dd8eb Updated TF2 Regenerate signature. 2013-08-27 23:32:56 -04:00
Nicholas Hastings 8ae1b3e1e7 Updated TF2 AddCond signature. 2013-08-27 21:08:37 -04:00
Nicholas Hastings c77c853c02 Updated plugin blacklist. 2013-08-26 10:31:25 -04:00
Nicholas Hastings 2b0daba573 Bumping version. 2013-08-25 19:45:28 -04:00
Nicholas Hastings ba4aa4d37f Added tag sourcemod-1.5.0 for changeset 78a1f1b1c6fa 2013-08-25 19:44:52 -04:00
Nicholas Hastings e3f31af5d3 Update versioning for 1.5.0 release. 2013-08-25 17:38:09 -04:00
Nicholas Hastings bc0bf4e270 Updated changelog for version 1.5.0. 2013-08-25 16:59:14 -04:00
Nicholas Hastings 60c5ad6324 Synced changelog.txt from releases/sourcemod-1.4. 2013-08-25 12:16:54 -04:00
Nicholas Hastings e996a00675 Add missing MarkNativeAsOptional calls for cstrike.inc (r=me). 2013-08-25 11:01:55 -04:00
Kyle Sanderson 0be3f0afed Fix broken translating in some plugins and natives (bug 5612, r=psychonic). 2013-08-25 10:15:35 -04:00
Kyle Sanderson 86bdfa2205 Fixed potential deadlock in HandleSystem::TryAndFreeSomeHandles (bug 5665, r=dvander). 2013-08-25 09:59:53 -04:00
Nicholas Hastings 56c87e927f Fix cmd listener callback return behavior to match func doc (bug 5882, r=asherkin). 2013-08-24 23:56:39 -04:00
Nicholas Hastings be54443918 Replace hardcoded "/ff" check in basetriggers (bug 5863, r=drifter). 2013-08-24 21:59:52 -04:00
Nicholas Hastings 676ea8b29c Don't call SayCommand forwards for chat triggers (bug 5863, r=asherkin). 2013-08-24 21:59:52 -04:00
Nicholas Hastings d77ff38428 Fixed regression causing public triggers to no longer display (bug 5863, r=drifter). 2013-08-24 21:59:52 -04:00
Nicholas Hastings d3256ef339 Removed unused var m_bTriggerWasSilent from core ChatTriggers (bug 5863, r=asherkin). 2013-08-24 21:59:52 -04:00
Nicholas Hastings 3d11742f91 Add missing GetFunctionCount check in ChatTriggers::OnSayCommand_Pre (bug 5864, r=kyles). 2013-08-23 18:48:06 -04:00
Peace-Maker a2aa5d1cda Fixed crash in OnSayCommand_Post with console chat, pass console chat (bug 5864, r=kyles). 2013-08-23 07:31:04 -04:00
Nicholas Hastings 8860e18026 Backed out changeset: 6118b70b1103 (bug 5864). 2013-08-23 07:31:56 -04:00
Nicholas Hastings 7dba540b97 Fixed crash in OnSayCommand_Post with console chat, pass console chat (bug 5864, r=voided);
--HG--
extra : rebase_source : 3090e700ea04a1b2cc6a92c727e3bb58df69500d
2013-08-22 21:45:42 -04:00
Nicholas Hastings 0dd9a5b842 Changed from RemoveEdict to using the Kill input for TF2_RemoveWeapon (r=voided).
--HG--
extra : rebase_source : 1bc5d8aa9aa6be4022b3e1e730ff06de3e428f8e
2013-08-22 21:45:40 -04:00
Nicholas Hastings e6c3565544 Fixed SDKHooks thinking a hook type was supported when gamedata missing (r=voided).
--HG--
extra : rebase_source : 8e89e780c12309a3a772f1edfadc9c4541318b48
2013-08-22 21:45:19 -04:00
Kyle Sanderson 8cacba922a Fix weapon ID checks (bug 5872, r=Dr!fter) 2013-08-21 10:56:04 -04:00
Nicholas Hastings 767396d4ee Fixed GuessSDKVersion return value when using MM:S versions < 1.10 (r=me). 2013-08-16 11:47:35 -04:00
Nicholas Hastings 07a51a0d4e Fixed char * constant conversion warning in cstrike ext. 2013-08-15 18:43:14 -04:00
Drifter 9f042625d0 Fix CS:GO GetWeaponPrice and OnGetWeaponPrice using outdated method (r=psychonic). 2013-08-15 14:40:30 -04:00
Dr!fter fc29f4249a Update some more CS:GO gamedata 2013-08-15 17:04:33 -04:00
Nicholas Hastings 5ca5ecee85 Fixed chat trigger crash regression on ep1 (bug 5394, r=asherkin). 2013-08-15 10:21:04 -04:00
Nicholas Hastings c79d547492 Update BuyCommand detour in CStrike extension with new param on CS:GO. 2013-08-14 17:08:02 -04:00
Nicholas Hastings f079773195 Update GivePlayerItem for new params in CS:GO. 2013-08-14 17:07:27 -04:00
Dr!fter e6ead8b5aa Update some more CS:GO gamedata 2013-08-14 16:40:58 -04:00
Nicholas Hastings 9eba6402eb Updated some CS:GO gamedata. 2013-08-14 14:20:57 -04:00
Nicholas Hastings f95be3b10c Fixed typo in Nuclear Dawn gamedata backcompat fix. 2013-08-14 13:14:59 -04:00
Nicholas Hastings 2220cc961e Added compat shim to load on Nuclear Dawn with MM:S < 1.9.3. (bug 5813, r=me). 2013-08-14 12:55:55 -04:00
Nicholas Hastings cfc6b2fee9 Added gamedata and extension loading compat shims for Nuclear Dawn (bug 5813, r=asherkin). 2013-08-14 11:56:34 -04:00
Nicholas Hastings d188859fc5 Readded another missing hunk from 394499aa9d33 merge. 2013-08-14 12:10:31 -04:00
Kyle Sanderson 96a8003448 Added global pre and post forwards for client chat (bug 5394, r=psychonic). 2013-08-05 11:46:29 -04:00
Nicholas Hastings 696f702204 Fixed a path not using updated mapcycle file detection (bug 5719). 2013-08-05 11:36:59 -04:00
Nicholas Hastings 8b26ce73c2 Triggering build. 2013-08-05 08:36:34 -04:00
GoD-Tony ee5f488aa2 Added ISDKHooks interface with entity listeners (bug 5602, r=psychonic). 2013-08-04 10:03:40 -04:00
Nicholas Hastings 3a5cf80e2b Fixed build. 2013-08-03 20:22:01 -04:00
Nicholas Hastings 3e4f7af96a Readded missing hunk from 394499aa9d33 merge for ep2v extension loading backcompat. 2013-08-03 19:10:23 -04:00
Erik Minekus a1a483fa27 Numerous code documentation fixups (bug 5720, r=psychonic).
--HG--
extra : rebase_source : 864171c29442accaef2a051e37dfd25c2ee1566c
2013-08-01 09:26:34 -04:00
Asher Baker b32f8a4803 Disable SteamAuthstringValidation config option by default (bug 5791, r=psychonic). 2013-08-01 14:33:06 +01:00
Nicholas Hastings 96ee6dbf8a Check all possible mapcycle paths on newer orangebox games (bug 5719, r=asherkin). 2013-07-31 22:57:50 -04:00
Drifter ac07cf95e1 Added CS_IsValidWeaponID native and validity checks to other natives (bug 5566, r=psychonic). 2013-07-31 22:11:15 -04:00
Drifter 8f51e33167 Fixed incorrect return for some weapons in CS_GetWeaponPrice (bug 5562, r=psychonic). 2013-07-31 22:08:23 -04:00
Kyle Sanderson 8366f371ad Fixed crash in SDKHooks when throwing bad ent type error on logical ent (r=psychonic). 2013-07-31 22:03:59 -04:00
Nicholas Hastings 9b44dfea11 Build against MM:S 1.10.
--HG--
extra : rebase_source : 3ae670b671c8bbc964affa77ccf3f2c9191c7f90
2013-07-31 18:42:15 -04:00
Nicholas Hastings 7ede8e0924 Split TF2, DoD:S, HL2:DM, and ND to separate binaries (bug 5813, r=asherkin).
--HG--
extra : rebase_source : 89a3d9703bbb0f5c3225ce8f5da85ce1fabafeaa
2013-07-21 11:53:56 -04:00
Dr!fter 9fe2d9c1cf Update WeaponIDToAlias Sig for CS:GO 2013-07-26 14:42:36 -04:00
Kyle Sanderson 1836ec9d45 Fixed handle misuse in clientprefs plugin (bug 5805, r=psychonic). 2013-07-20 15:17:43 -04:00
Kyle Sanderson 380d7adc09 Make compile.sh set working dir to own dir (bug 5710, r=psychonic). 2013-07-18 19:40:42 -04:00
Kyle Sanderson 4109d0df39 Fixed accidental assignment in each of SDKTools and sp compiler (bug 5745, r=psychonic). 2013-07-18 15:50:50 -04:00
systematicmania 9cab1e3ab7 Fixed clients not being marked as in kick queue in some cases (bug 5746, r=psychonic). 2013-07-18 11:38:04 -04:00
Kyle Sanderson e9d8bfcdfc Throw error instead of crash when calling SetTeamScore between maps (bug 5718, r=psychonic). 2013-07-18 11:38:04 -04:00
Peace-Maker f134602991 Fixed typo in too-many-params native error message (r=psychonic). 2013-07-17 08:09:10 -04:00
Nicholas Hastings b493532ee1 Updated DoD:S gamedata. 2013-07-16 20:45:02 -04:00
Dr!fter 84dec75fb8 Fix SDKHooks gamedata for Half-Life 2 and DOD:S 2013-07-10 20:46:13 -04:00
Dr!fter b1094f87c6 Update TF2 Reload Offset 2013-07-10 20:33:28 -04:00
Dr!fter 284b4bfe20 Update GroundEndChanged for CS:S and CS:GO 2013-07-10 19:56:43 -04:00
Dr!fter b46537ddd5 Update TF2 ForceRespawn offset 2013-07-10 19:14:06 -04:00
Dr!fter c9446c4d7d Update TF2 Gamedata 2013-07-10 18:53:12 -04:00
Nicholas Hastings d4610ab340 Updated L4D2 IServer gamedata for Windows. 2013-07-08 16:13:47 -04:00
Nicholas Hastings 0016b8ef2f Fix tier0/vstdlib lookup in core for recent L4D2 changes. 2013-07-06 12:02:42 -04:00
Nicholas Hastings 72e08f7e44 Define POSIX when compiling for any build on linux/mac. 2013-07-06 12:02:01 -04:00
Nicholas Hastings b06cfa5414 Updated L4D2 gamedata. 2013-07-05 14:30:20 -04:00
Nicholas Hastings a7742cae3d Triggering build for L4D2 sdk update. 2013-07-04 16:45:31 -04:00
Nicholas Hastings 8a78285659 Fixed build. 2013-07-04 11:29:18 -04:00
Ryan Stecker 6847c8eec0 Fixed ReadMapList not seeing maps in all valveFS paths (bug 5715, r=asherkin). 2013-07-03 23:23:05 -04:00
Nicholas Hastings 66790254ac Updated ambuild script for new l4d2 library names. 2013-06-30 10:45:19 -04:00
Ryan Stecker 86b8a0b16a Updated TF2 CalcCriticalMelee Windows byte signature.
--HG--
extra : rebase_source : 7ecde66470b85425c9836fbf61b6d042264a210e
2013-06-13 21:37:05 -04:00
Asher Baker 25fced78e8 File upload support for webternet (r=psychonic). 2013-05-16 14:49:03 +01:00
Dr!fter 22d11160ba Update Remove Disguise sig 2013-05-13 19:07:13 -04:00
Nicholas Hastings 8d65b3e94e Don't omit frame pointer on msvc builds. 2013-05-13 14:19:17 -04:00
Nicholas Hastings 5518544ecd Fixed CS:S CommitSuicide offset. 2013-05-03 15:29:20 -04:00
Nicholas Hastings af3523bd2d Backed out changeset: d1a5f4fe8f61. 2013-05-02 15:31:36 -04:00
Nicholas Hastings 8646cca538 Backed out changeset: 1bdf91c47e13. 2013-05-02 15:31:25 -04:00
Nicholas Hastings c7cea1b40b Backed out changeset: a4fe868541d6. 2013-05-02 15:31:13 -04:00
Nicholas Hastings 58914f71bd Backed out changeset: 3e8245271fd8. 2013-04-30 15:38:50 -04:00
Nicholas Hastings 3841e98c4f Updated TF2 gamedata. 2013-04-29 21:20:11 -04:00
Nicholas Hastings acd025dba2 Merge. 2013-04-16 13:25:22 -04:00
Nicholas Hastings 78c2206628 Updated CS:S gamedata. 2013-04-16 12:19:45 -04:00
Brian Simon 5c47bf8803 Added more alternative names for TFClass_Heavy (bug 5338, r=asherkin). 2013-04-11 03:07:50 +01:00
Kyle Sanderson 8e78ee6f57 Remove debug printout from PerformGravity (bug 5679, r=asherkin). 2013-04-11 03:03:29 +01:00
Asher Baker a2da4cc868 Only split DWARF data out for non-explicit-debug builds (bug 5683, r=dvander). 2013-04-11 00:34:52 +01:00
Asher Baker 00e44ad3c3 Fixed JIT conflicts with SELinux (bug 5581, r=dvander). 2013-04-11 00:33:12 +01:00
Nicholas Hastings 29ba84fc5c Allow localizaton of more base plugin strings (bug 5120, r=asherkin). 2013-04-08 08:00:13 -04:00
Nicholas Hastings 283f1f012d Allow localization of name-reserved kick message (bug 5146, r=asherkin). 2013-04-08 08:00:13 -04:00
Nicholas Hastings fff17f8043 Updated HL2DM gamedata. 2013-04-03 12:26:08 -04:00
Nicholas Hastings 847eaf38f9 Updated DoD:S gamedata. 2013-03-29 15:45:16 -04:00
Drifter 1d59a329eb Update gamedata for CS:GO update 2013-03-21 20:00:29 -04:00
Nicholas Hastings 5689888682 Fixed IsMapValid passing blank string to engine's IsMapValid which crashes some games. 2013-03-21 01:22:08 -04:00
Nicholas Hastings a01768525a Backed out changeset: f38675c67f64 (bug 5484). 2013-03-20 07:08:49 -04:00
Kyle Sanderson e3d2ddf278 Fix a number of issues with cloned handles (bug 5240, r=asherkin). 2013-03-17 22:05:33 +00:00
Kyle Sanderson b3e48b0ad7 Check for cloned handles when dumping (bug 5245, r=asherkin). 2013-03-17 21:58:56 +00:00
Nicholas Hastings 6d528b5c55 Merge. 2013-03-18 20:39:41 -04:00
Peace-Maker 22daf26e3e Fixed possible rte in basetriggers for !ingame clients (bug 5191, r=psychonic). 2013-03-18 20:11:50 -04:00
Michael McKoy 73061969da Fixed mapchooser interaction with CS:GO winlimits (bug 5484, r=psychonic). 2013-03-18 20:10:31 -04:00
Kyle Sanderson 4653530095 Fixed check against uninitialized string in extension loader (bug 5546, r=psychonic). 2013-03-18 20:03:17 -04:00
Peace-Maker ef5faaaa4a Fixed double print when sending psay to self (bug 5649, r=psychonic). 2013-03-18 19:58:18 -04:00
GoD-Tony f52ea98eb4 Added logged error when PlayerRunCommand offset lookup fails (bug 5535, r=psychonic). 2013-03-18 19:53:30 -04:00
Asher Baker d315d4bf53 Backport some clientprefs crash fixes from 1.6. 2013-03-18 18:54:00 +00:00
Kyle Sanderson eaef2a46fb Change extension unload order to avoid exposing finalisation window (bug 5556, r=asherkin). 2013-03-18 18:06:55 +00:00
Nicholas Hastings b0304a89a6 Fixed errors with SendConVarValue on CS:GO (bug 5638, r=asherkin). 2013-03-18 11:47:55 -04:00
Asher Baker a4790f0358 Generate debugging information during compilation (bug 5227, r=ds). 2013-03-17 21:00:28 +00:00
Scott Ehlert d3d5cd8181 Added --no-mysql option to configure script to make MySQL optional (bug 5661, r+a=dvander). 2013-03-17 04:09:44 -05:00
Peace-Maker 64be2bc5a0 Increased map name buffer sizes in mapchooser (bug 5609, r=psychonic). 2013-03-16 23:17:22 -04:00
Kyle Sanderson 30e476c35e Added GetSteamAccountID function to IPlayerHelpers and native for sp (bug 5548, r=asherkin). 2013-03-16 23:12:40 -04:00
Nicholas Hastings 88af208cdd Add DPT_Int64 type to netprop dumps (bug 5655, r=asherkin). 2013-03-16 22:57:57 -04:00
Scott Ehlert b64751c1af Made BreakpadSymbols script compatbile with Python 2.6 and above (bug 5660, r=asherkin). 2013-03-16 22:55:59 -04:00
FlaminSarge 2e158a72e2 Exposed third parameter of TF2's AddCond in TF2_AddCondition (bug 5641, r=psychonic). 2013-03-16 18:05:22 -04:00
Nicholas Hastings c8fb05dd4b Fixed some engine builds failing. 2013-03-16 14:11:56 -04:00
Nicholas Hastings 860af1e6cb Add GetPlayerResourceEntity to SDKTools; deprecate old, broken TF2-specific impl (bug 5491, r=asherkin). 2013-03-16 13:50:36 -04:00
Nicholas Hastings 5c1cadb64e Move UserMessages::m_pBase to only engines without protobuf msgs (r=asherkin). 2013-03-16 13:42:11 -04:00
Nicholas Hastings bfb97a4207 Added repeated field handing to PbSet* natives (bug 5633, r=asherkin). 2013-03-16 13:31:56 -04:00
Nicholas Hastings 7e26691b99 Added repeated field handling to PbRead* natives. Deprecate PbReadRepeated* (bug 5633, r=asherkin). 2013-03-16 13:31:35 -04:00
FlaminSarge ca469a218a Updated TF2 TFCond defines (bug 5642, r=psychonic). 2013-03-16 13:30:00 -04:00
Scott Ehlert 6052ddaa64 Triggering a build. 2013-03-14 00:07:11 -05:00
Scott Ehlert 0ddc675472 Added --sdks option to configure script to specify which SDKs to build againt (bug 5630, r+a=dvander).
Valid arguments are "all", "present", or a comma delimited list of engine names.

The "all" option will try to build against all supported SDKs. (This is the default.)
The "present" option will only attempt to build against SDKs that exist on the system.

Examples:

configure.py --sdks=css,csgo,ep2v
configure.py --sdks=l4d
configure.py -s present
2013-03-13 22:02:40 -05:00
Asher Baker 9412f687cb Fixed issues with COMMAND_FILTER_NO_BOTS and @bots multi-target. (r=fennec) 2013-03-10 03:24:03 +00:00
Asher Baker 0e865c0618 Allow access to unvalidated authstrings (bug 5587, r=psychonic). 2013-03-07 00:58:17 +00:00
Nicholas Hastings 462b5213d7 Fixed SDKHooks GetMaxHealth callback being passed incorrect parameters. 2013-03-02 13:42:07 -05:00
Scott Ehlert f52e84730f Triggering a build. 2013-03-02 11:56:31 -06:00
Asher Baker b8873efa0d Error on access to nested datamap props (bug 5446, r=psychonic). 2012-09-03 20:26:39 +01:00
Scott Ehlert 4132b9bd21 Added L4D and L4D2 gamedata for SDK Hooks on Mac OS X (bug 5628, r=psychonic). 2013-02-25 20:45:11 -06:00
Kyle Sanderson c0caa9f158 Removed call to getchar() in debug build of compiler (bug 5626, r=ds). 2013-02-25 18:02:10 -06:00
Nicholas Hastings 7346b0c081 Added support for "fuzzy" map names in L4D and later (bug 5599, r=asherkin). 2013-02-14 19:28:12 -05:00
Nicholas Hastings 6a361e3045 Updated CS:GO gamedata. 2013-02-13 22:25:15 -05:00
Nicholas Hastings 61d7519ef5 More, hopefully final CS:GO/protobuf usermessage fixups (bug 5588). 2013-02-11 15:11:04 -05:00
Ruben Gonzalez 3e1a78703e Fix CS_WeaponIDToAlias param missing CSWeaponID tag (bug 5460) 2013-02-11 11:17:46 -05:00
Nicholas Hastings bb195a9b2d Added missing smn_protobuf.cpp to core msvc10 project (NPOTB). 2013-02-11 09:39:23 -05:00
Nicholas Hastings 6f095a064c Removed intentional invalid steamid crash in SDK Hooks. 2013-02-11 09:39:23 -05:00
Nicholas Hastings eb334f5fe2 Fixed typo in Fortress Forever gamedat.a 2013-02-11 09:39:23 -05:00
1195 changed files with 126752 additions and 213696 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
+28
View File
@@ -0,0 +1,28 @@
# Binaries
\.dll$
\.dylib$
\.exe$
\.so$
# Files generated by Visual Studio
\.aps$
\.ipch$
\.ncb$
\.opensdf$
\.sdf$
\.suo$
\.user$
# Build directories
/CrazyDebug.*
/Debug.*
/Release.*
# Files generated by Mac OS X Finder
(^|/)\.DS_Store$
# Files generated by Windows Explorer
(^|/)[dD]esktop\.ini$
(^|/)[tT]humbs\.db$
syntax: glob
build/*
+11
View File
@@ -0,0 +1,11 @@
54539fa4e51f98d7841c853c1370dff6ccd3cdf2 sourcemod-1.0.0
e6ef5ecdf8d75740ca2685a709bf321f8873bc3b sourcemod-1.1.0
e877885fac80be71822641f7a9122cebc9812521 sourcemod-1.1.1
b3ffa8a4511c4eadaf533fc790aa6b14f7f0c6ea sourcemod-1.1.2
3a73bbf60f34befa9b66be03fa5974b394bb3411 sourcemod-1.2.0
78a1f1b1c6fa86fd7691c70ebf48a9fb3dfb3c11 sourcemod-1.5.0
5574bfe07731b7dba171c1300f6022319d2dbc89 sourcemod-1.5.1
238c41726d73d9f0d65005ff43c1ab86adb0e163 sourcemod-1.5.2
27bf76b007d2360a9cfc7af9e14d1c9a6bddcc64 sourcemod-1.5.3
27bf76b007d2360a9cfc7af9e14d1c9a6bddcc64 sourcemod-1.5.3
0000000000000000000000000000000000000000 sourcemod-1.5.3
-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
+192 -228
View File
@@ -3,12 +3,16 @@ import os, sys
class SDK(object):
def __init__(self, sdk, ext, aDef, name, platform, dir):
self.folder = 'hl2sdk-' + dir
if dir == 'ep1':
folder = 'hl2sdk'
else:
folder = 'hl2sdk-' + dir
self.envvar = sdk
self.ext = ext
self.code = aDef
self.define = name
self.platform = platform
self.folder = folder # Default folder name.
self.name = dir
self.path = None # Actual path
@@ -17,26 +21,27 @@ 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'),
'ep1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'ep1'),
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'ob'),
'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'),
'nd': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nd'),
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '13', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '15', 'ALIENSWARM', WinOnly, 'swarm'),
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '14', 'ALIENSWARM', WinOnly, 'swarm'),
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '19', 'CSGO', WinLinuxMac, 'csgo'),
'dota': SDK('HL2SDKDOTA', '2.dota', '20', 'DOTA', WinLinuxMac, 'dota'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '16', 'PORTAL2', [], 'portal2'),
'blade': SDK('HL2SDKBLADE', '2.blade', '17', 'BLADE', WinLinux, 'blade'),
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '18', 'INSURGENCY', WinLinuxMac, 'insurgency'),
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '13', 'CONTAGION', WinOnly, 'contagion'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '18', 'CSGO', WinLinuxMac, 'csgo'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '15', 'PORTAL2', [], 'portal2'),
# These engines are only supported on SourceMod 1.6.
# 'blade': SDK('HL2SDKBLADE', '2.blade', '16', 'BLADE', WinLinux, 'blade'),
# 'dota': SDK('HL2SDKDOTA', '2.dota', '19', 'DOTA', WinOnly, 'dota'),
# 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '17', 'INSURGENCY', WinLinuxMac, 'insurgency'),
# 'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, '2013'),
}
def ResolveEnvPath(env, folder):
@@ -44,22 +49,17 @@ def ResolveEnvPath(env, folder):
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)
else:
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 = {}
@@ -72,17 +72,6 @@ class SMConfig(object):
self.smx_files = {}
self.versionlib = None
def use_auto_versioning(self):
if builder.backend != 'amb2':
return False
return not getattr(builder.options, 'disable_auto_versioning', False)
@property
def tag(self):
if builder.options.debug == '1':
return 'Debug'
return 'Release'
def detectProductVersion(self):
builder.AddConfigureFile('product.version')
@@ -105,54 +94,40 @@ class SMConfig(object):
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):
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
if sdk_path is None:
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)
sdk.path = 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')
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
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)
raise Exception('Could not find a source copy of Metamod:Source')
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):
for i in range(7):
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
if self.mysql_root:
break
if not 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()
cfg = builder.DetectCompilers()
cxx = cfg.cxx
if cxx.like('gcc'):
cxx.defines += [
if cxx.behavior == 'gcc':
cfg.defines += [
'stricmp=strcasecmp',
'_stricmp=strcasecmp',
'_snprintf=snprintf',
@@ -160,42 +135,35 @@ class SMConfig(object):
'HAVE_STDINT_H',
'GNUC',
]
cxx.cflags += [
cfg.cflags += [
'-pipe',
'-fno-strict-aliasing',
'-Wall',
'-Werror',
'-Wno-uninitialized',
'-Wno-unused',
'-Wno-switch',
'-Wno-array-bounds',
'-msse',
'-m32',
]
cxx.cxxflags += [
'-std=c++11',
]
have_gcc = cxx.vendor == 'gcc'
have_clang = cxx.vendor == 'clang'
if have_clang or (have_gcc and cxx.version >= '4'):
cxx.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.version >= '4.6'):
cxx.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if have_gcc and cxx.version >= '4.8':
cxx.cflags += ['-Wno-unused-result']
if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
have_gcc = cxx.name == 'gcc'
have_clang = cxx.name == 'clang'
if have_clang or (have_gcc and cxx.majorVersion >= 4):
cfg.cflags += ['-fvisibility=hidden']
cfg.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.minorVersion >= 6):
cfg.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.minorVersion >= 7) or (have_clang and cxx.majorVersion >= 3):
cfg.cxxflags += ['-Wno-delete-non-virtual-dtor']
cxx.linkflags += ['-m32']
cxx.cxxflags += [
if have_gcc:
cfg.cflags += ['-Wno-parentheses']
elif have_clang:
cfg.cflags += ['-Wno-logical-op-parentheses']
cfg.linkflags += ['-m32']
cfg.cxxflags += [
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
@@ -203,30 +171,28 @@ class SMConfig(object):
]
if have_gcc:
cxx.cflags += ['-mfpmath=sse']
elif cxx.vendor == 'msvc':
cfg.cflags += ['-mfpmath=sse']
elif cxx.name == 'msvc':
if builder.options.debug == '1':
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
cfg.cflags += ['/MTd']
cfg.linkflags += ['/NODEFAULTLIB:libcmt']
else:
cxx.cflags += ['/MT']
cxx.defines += [
cfg.cflags += ['/MT']
cfg.defines += [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
'_ITERATOR_DEBUG_LEVEL=0',
]
if cxx.version < 1800:
cxx.defines += 'strtoull=_strtoui64'
cxx.cflags += [
cfg.cflags += [
'/W3',
]
cxx.cxxflags += [
cfg.cxxflags += [
'/EHsc',
'/GR-',
'/TP',
]
cxx.linkflags += [
cfg.linkflags += [
'/MACHINE:X86',
'/SUBSYSTEM:WINDOWS',
'kernel32.lib',
@@ -245,83 +211,96 @@ class SMConfig(object):
# Optimization
if builder.options.opt == '1':
cxx.defines += ['NDEBUG']
if cxx.like('gcc'):
cxx.cflags += ['-O3']
elif cxx.like('msvc'):
cxx.cflags += ['/Ox', '/Zo']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
cfg.defines += ['NDEBUG']
if cxx.behavior == 'gcc':
cfg.cflags += ['-O3']
elif cxx.behavior == 'msvc':
cfg.cflags += ['/Ox']
cfg.linkflags += ['/OPT:ICF', '/OPT:REF']
# Debugging
if builder.options.debug == '1':
cxx.defines += ['DEBUG', '_DEBUG']
if cxx.like('msvc'):
cxx.cflags += ['/Od', '/RTC1']
cfg.defines += ['DEBUG', '_DEBUG']
if cxx.behavior == 'msvc':
cfg.cflags += ['/Od', '/RTC1']
if int(cxx.version) >= 1600:
cfg.cflags += ['/d2Zi+']
# This needs to be after our optimization flags which could otherwise disable it.
if cxx.vendor == 'msvc':
if cxx.name == 'msvc':
# Don't omit the frame pointer.
cxx.cflags += ['/Oy-']
cfg.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']
cfg.defines += ['_LINUX', 'POSIX']
if cxx.name == 'gcc':
cfg.linkflags += ['-static-libgcc']
elif cxx.name == 'clang':
cfg.linkflags += ['-lgcc_eh']
elif builder.target_platform == 'mac':
cxx.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [
cfg.defines += ['OSX', '_OSX', 'POSIX']
cfg.cflags += ['-mmacosx-version-min=10.5']
cfg.linkflags += [
'-mmacosx-version-min=10.5',
'-arch', 'i386',
'-lstdc++',
'-stdlib=libstdc++',
]
cxx.cxxflags += ['-stdlib=libstdc++']
cfg.cxxflags += ['-stdlib=libstdc++']
elif builder.target_platform == 'windows':
cxx.defines += ['WIN32', '_WINDOWS']
cfg.defines += ['WIN32', '_WINDOWS']
# Finish up.
cxx.defines += [
cfg.defines += [
'SOURCEMOD_BUILD',
'SM_GENERATED_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')]
cfg.includes += [os.path.join(builder.buildPath, 'includes')]
cfg.includes += [os.path.join(builder.sourcePath, 'versionlib')]
def AddVersioning(self, binary):
def LibraryBuilder(self, compiler, name):
binary = compiler.Library(name)
if builder.target_platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'SM_GENERATED_BUILD',
'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
binary.compiler.postlink += [
'-compatibility_version', '1.0.0',
'-current_version', self.productVersion
]
binary.compiler.linkflags += [self.versionlib]
binary.compiler.sourcedeps += SM.generated_headers
return binary
def ProgramBuilder(self, compiler, name):
binary = compiler.Program(name)
if builder.target_platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'SM_GENERATED_BUILD',
'RC_COMPILE',
]
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)
compiler = context.compiler.clone()
return self.LibraryBuilder(compiler, name)
def Program(self, context, name):
binary = context.compiler.Program(name)
return self.AddVersioning(binary)
compiler = context.compiler.clone()
return self.ProgramBuilder(compiler, name)
def ConfigureForExtension(self, context, compiler):
def ExtCompiler(self, context):
compiler = context.compiler.clone()
compiler.cxxincludes += [
os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sdk'),
@@ -332,15 +311,10 @@ class SMConfig(object):
]
return compiler
def ExtLibrary(self, context, name):
binary = context.compiler.Library(name)
self.ConfigureForExtension(context, binary.compiler)
return self.AddVersioning(binary)
def HL2Compiler(self, context, sdk):
compiler = self.ExtCompiler(context)
def ConfigureForHL2(self, binary, sdk):
compiler = binary.compiler
if sdk.name == 'episode1':
if sdk.name == 'ep1':
mms_path = os.path.join(self.mms_root, 'core-legacy')
else:
mms_path = os.path.join(self.mms_root, 'core')
@@ -352,7 +326,6 @@ class SMConfig(object):
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines
paths = [
['public'],
['public', 'engine'],
@@ -361,7 +334,7 @@ class SMConfig(object):
['public', 'tier0'],
['public', 'tier1']
]
if sdk.name == 'episode1' or sdk.name == 'darkm':
if sdk.name == 'ep1' or sdk.name == 'darkm':
paths.append(['public', 'dlls'])
paths.append(['game_shared'])
else:
@@ -372,48 +345,55 @@ class SMConfig(object):
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name == 'sdk2013' and compiler.like('gcc'):
if sdk.name == '2013' and compiler.cxx.behavior == '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 ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
if compiler.cc.behavior == '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 sdk.name in ['css', 'hl2dm', 'dods', '2013', 'tf2', 'l4d2']:
if builder.target_platform in ['linux', 'mac']:
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
if sdk.name == 'csgo' and builder.target_platform == 'linux':
compiler.linkflags += ['-lstdc++']
compiler.defines += ['NO_MALLOC_OVERRIDE']
for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
return compiler
def ExtLibrary(self, context, name):
compiler = self.ExtCompiler(context)
return self.LibraryBuilder(compiler, name)
def HL2Library(self, context, name, sdk):
compiler = self.HL2Compiler(context, sdk)
if builder.target_platform == 'linux':
if sdk.name == 'episode1':
if sdk.name == 'ep1':
lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name == 'sdk2013':
elif sdk.name == '2013':
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':
if sdk.name == '2013':
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':
if sdk.name == '2013':
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
@@ -427,19 +407,19 @@ class SMConfig(object):
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
self.AddVersioning(binary)
binary = self.LibraryBuilder(compiler, name)
dynamic_libs = []
if builder.target_platform == 'linux':
compiler.linkflags[0:0] = ['-lm']
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'nucleardawn', 'l4d2']:
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', '2013', 'l4d2']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
elif sdk.name in ['l4d', 'nd', 'blade', 'insurgency', 'csgo']:
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac':
compiler.linkflags.append('-liconv')
binary.compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
@@ -447,7 +427,7 @@ class SMConfig(object):
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))
binary.compiler.linkflags.append(binary.Dep(lib_path))
for library in dynamic_libs:
source_path = os.path.join(lib_folder, library)
@@ -460,67 +440,51 @@ class SMConfig(object):
return link
linker = make_linker(source_path, output_path)
compiler.linkflags[0:0] = [compiler.Dep(library, linker)]
binary.compiler.linkflags[0:0] = [binary.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 }
)
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 += [
builder.RunBuildScripts(
[
'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',
'plugins/AMBuilder',
'tools/buildbot/PackageScript',
]
builder.RunBuildScripts(BuildScripts, { 'SM': SM })
],
{
'SM': SM
}
)
if builder.options.breakpad_dump:
builder.RunScript('tools/buildbot/BreakpadSymbols', { 'SM': SM })
+5
View File
@@ -0,0 +1,5 @@
CONFIGURE YOUR IDENTITY FOR MERCURIAL!
IF YOU ARE A DEVELOPER WITH PUSH ACCESS, DO IT NOW KPLZTHX.
http://wiki.alliedmods.net/Mercurial_Tutorial#Identity
-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
-265
View File
@@ -1,270 +1,5 @@
SourceMod Changelog
SourceMod 1.7.2 [2015-05-30]
URL: http://wiki.alliedmods.net/SourceMod_1.7.2_Release_Notes
User Changes:
- Updated game compatibility for the latest CS:GO updates.
- Fixed potential crash when using SDKTools GameRules_* natives. (PR 330) (yed).
- Fixed regression in v1.7.0 causing admin-sql-threaded plugin to not properly load admins. (bug 6365) (PR 342).
- Fixed leak in plugin heap memory that could lead to "Not enough space on the heap" error. (bug 6370).
----------------------------------------------------------
SourceMod 1.7.1 [2015-04-18]
URL: http://wiki.alliedmods.net/SourceMod_1.7.1_Release_Notes
User Changes:
- Updated game compatibility for CS:GO, TF2, Dota 2, Insurgency, and Fortress Forever.
- Fixed regression causing crash in games that do not support radio menus (PR 286) (Peace-Maker).
- Fixed sm_rename not working on some games, including CS:S and CS:GO (PR 313).
- Fixed some core.cfg values being ignored on start (PR 322).
- Fixed crash when plugins close a menu handle during menu draw (PR 268)
Developer Changes:
- Added tagged TF2_SetClientTeam to provide symmetry to TF2_GetClientTeam (PR 267) (Wliu).
- Added block parameter to FindValueInArray native (PR 213) (splewis).
- Added explicit return types to forwards missing them to avoid future compatibility issues (PR 294).
- Added new SetClientName native to reliably change a player's name on any game (PR 313).
- Fixed tag mismatch warning when using SQLite_UseDatabase (bug 6310) (PR 262) (VoiDeD).
- Fixed not actually being able to block CS_OnCSWeaponDrop (bug 6334) (PR 316).
- Fixed DirExists to throw an error when passed empty string (PR 315).
- Fixed ReadUint16 on File methodmap throwing "not bound" error (PR 265).
- Fixed various include docs (PR 288) (PR 290) (PR 295).
- Fixed issues with declaring variable on same line after array (SP PR 7) (Peace-Maker).
- Fixed debug info for multidimensional strings not being written to smx (SP PR 8) (Peace-Maker).
- Fixed issues with nesting methodmap calls (bug 6329) (SP PR 11) (SP PR 13).
- Improved diagnostic given when function prototype doesn't match an existing definition (PR 291) (VoiDeD).
----------------------------------------------------------
SourceMod 1.7.0 [2015-02-04]
URL: http://wiki.alliedmods.net/SourceMod_1.7.0_Release_Notes
User Changes:
- Updated game compatibility for TF2, CS:GO, and Dota 2.
- Fixed regression in SM 1.6.3 causing load failure on games older than Orangebox. (PR 237)
- Rewrote internal Steam auth ID handling (PR 147, PR 153, PR 155, PR 162, PR 204, PR 210, PR 222, PR 246).
--- admins.cfg now supports Steam2, Steam3, and SteamID 64 formats for the Steam auth provider.
--- admins-simple.ini now supports Steam3 auth IDs in addition to Steam2 IDs.
--- Command targeting now supports both Steam3 auth IDs in addition to Steam2 IDs.
- Added default timeout for MySQL connections to avoid hangs. (PR 248).
- SDKTools' gamerules gamedata is now far less likely to break on updates (PR 220).
- Fixed crash with sm_dump_admcache on Windows (PR 163).
- Fixed SDKHooks causing crash on player join/leave or plugin load/unload if gamedata missing (PR 236).
- Changed default sm_trigger_show ConVar value to 0 / disabled.
Developer Changes:
- Added new SourcePawn Transitional Syntax!
--- New methodmap-based APIs have been added for many existing functions and handle types.
--- New work-in-progress API doc page.
- Added Blocked hook type to SDKHooks (PR 119) (VoiDeD).
- Added OnTakeDamage_Alive hook type to SDKHooks (PR 149).
- Many more File natives now support Valve FS (PR 120, PR 169, PR 178).
- Added SetFilePermissions native (PR 43) (hlstriker).
- Added API for iterating StringMaps (formerly "tries").
- Added natives for accessing command line parameters (PR 164) (VoiDeD).
- Exposed engine Message_DetermineMulticastRecipients as GetClientsInRange native. (PR 234).
- CloseHandle (or delete) on INVALID_HANDLE is now a no-op, instead of an error (PR 74).
- GetClientAuthString is now deprecated. Use GetClientAuthId instead.
- Added OnCoreMapEnd to extension interface (PR 127).
- Fixed IThreader threads leaking if they're not joined. (bug 3460, PR 241).
- TFHoliday updates no longer require a plugin recompile (PR 217).
- Fixed FindFlagChar returning false when passing AdminFlag_Custom6 (bug 6248, PR 203).
- Added support for (entity) CLASSPTR and EDICT Prop_Data fields with GetEntPropEnt and SetEntPropEnt (PR 83).
- Doubled maximum handle count per plugin to 32,768 (PR 215), (Thordin).
- Added support for custom default values with GetEvent* natives, rather than using ""/0 for unset fields (PR 157) (VoiDeD).
- Removed old profiler, and added new, pluggable profiler (with hooks to VProf) (PR 54).
- Added command to dump profiler output (PR 128) (VoiDeD).
- Fixed ICommandLine and related features being reported as unavailable on Dark Messiah.
- Fixed OnPlayerRunCommand forward in SDKTools being unavailable on Dark Messiah.
- SourceMod now uses some C++11 and has newer compiler requirements.
- Added --disable-auto-versioning option to ambuild configure script.
----------------------------------------------------------
SourceMod 1.6.3 [2014-11-25]
URL: http://wiki.alliedmods.net/SourceMod_1.6.3_Release_Notes
User Changes:
- Updated game support for TF2, CS:GO, No More Room in Hell, Insurgency, PVK2 and Fistful of Frags.
- Made changes to make TF2, CSS, DoDS, HL2DM, and SDK 2013 mods less likely to break on game update (PR 174, PR 192).
- Added support for longer key names in languages.cfg (to fix Portuguese) (bug 6282, PR 208).
Developer Changes:
- Updated TF2 player condition and holiday enums (Ross "Powerlord" Bemrose) (PR 183, PR 181).
- Add support for TF2 player conditions >= 96 for condition functions/forwards (PR 205).
----------------------------------------------------------
SourceMod 1.6.2 [2014-09-20]
URL: http://wiki.alliedmods.net/SourceMod_1.6.2_Release_Notes
User Changes:
- Updated game support for TF2, CS:GO, No More Room in Hell and Fistful of Frags.
- Added compatibility shim to force Steam player auth strings to be in "Steam2" rendered format (PR 136).
- Fixed possible performance regression in DBI handling.
Developer Changes:
- Added new GetClientAuthId native to retrieve player auth strings in desired format (PR 159).
- Updated TF2 weapon and player condition enums (FlaminSarge).
----------------------------------------------------------
SourceMod 1.6.1 [2014-08-17]
URL: http://wiki.alliedmods.net/SourceMod_1.6.1_Release_Notes
User Changes:
- Updated game support for CS:GO and Fistful of Frags.
- Added support for Romanian language.
- Re-added languages.cfg, missing from 1.6.0, causing all clients to use server language.
- Fixed a regression in version 1.6.0 that caused certain SDKHooks usage patterns to cause a server crash (PR 107).
- Improved error reporting in basebans plugin when banreasons.txt is missing (PR 115).
- Fixed incorrect logged gravity value for sm_gravity command (Ryan "VoiDeD" Stecker) (PR 116).
- Fixed a regression in version 1.6.0 causing SDKHook_ReloadPost hooks to not fire in plugins (Peace-Maker) (PR 96).
- Added workaround for game bug in TF2_RemoveWeaponSlot to avoid wearable entities left on map (Ryan "VoiDeD" Stecker) (bug 6206, PR 121).
- Removed DisableJIT option from core.cfg. (It was never meant for normal use.)
Developer Changes:
- Added new TF2_RemoveWearable native (Ryan "VoiDeD" Stecker, WildCard65) (PR 114).
- Added new functions for interacting with and playing scripted game sounds (Ross "Powerlord" Bemrose) (bug 5942, PR 65).
- Added new StringToKeyValues natives (Ryan "VoiDeD" Stecker) (PR 74).
----------------------------------------------------------
SourceMod 1.6.0 [2014-07-03]
URL: http://wiki.alliedmods.net/SourceMod_1.6.0_Release_Notes
User Changes:
- Added support for Dota 2 (bug 5656, bug 6068).
- Added support for Source SDK 2013 mods (bug 5917).
- Added support for Insurgency (bug 5951).
- Added support for Contagion (bug 6007).
- Added support for Blade Symphony (bug 5949).
- Updated support for some mods that moved to SDK 2013 - No More Room In Hell, Fistful of Frags, Empires, Synergy.
- Updated gamedata and other support for TF2, DoD:S, HL2:DM, CS:S, CS:GO, Left 4 Dead, and Nuclear Dawn.
- Added support for customizing ban reasons in basebans.sp (bug 5762) (Matthias "House" Kollek).
- Added support for searching all gameinfo search paths when seeking mapcycle file (bug 5839).
- Added sm_reload_translations command (bug 5750).
- Added support for single-file gamedata custom overrides (bug 5386) (Ondrej "RavuAlHemio" Hošek).
- Re-enabled SteamAuthstringValidation config option by default (bug 5791, PR 20).
- Fixed plugins not reaching ext dep lists, making dependent plugin not unload on ext unload (bug 5851) (Peace-Maker).
- Added printing of SendProp flags to netprop dumps (bug 6082).
- Removed support for obsolete plugin_settings.cfg (bug 5605).
- Fixed topmenu sorting not getting refreshed after reloading sorting config (bug 6032) (Peace-Maker).
- Fixed error log filename date sometimes being incorrect (bug 5761) (Matheus "M28" Valadares).
- Dump handle information when a plugin is forcefully unloaded. (bug 5666).
- Fixed sm_cancelvote not resetting rtv state. (bug 5808) (Peace-Maker).
- Fixed Mapchooser dying on single map rotation servers (bug 5179).
- Fixed various problems with unloading ClientPrefs and SourceMod (bug 5874).
- Fixed "sm version" command reporting incorrect compile time in many cases (bug 6078) (SystematicMania).
- Clear default database driver reference if backing extension is unloaded (bug 5934) (Peace-Maker).
- Moved funcommands material and sound definitions to gamedata for easier cross-game support (bug 6085).
- Implement a watchdog timer for scripts that take too long to execute (bug 5837).
- Use Linux game data for offsets and signatures/symbols on OS X if Mac-specific data is not available (bug 6056).
Developer Changes:
- Added an API for off-thread SQL transactions. (bug 3775, PR 26).
- Added string literal concatenation using ellipses "..." (bug 4261, PR 5) (Peace-Maker).
- Added support for nested datatables. (bug 5446).
- Added PbRemoveRepeatedFieldValue native (bug 6066).
- Added support for getting/setting protobuf enum values with PbGetInt, PbSetInt, and PbAddInt natives.
- Removed deprecated PbReadRepeated natives that existed briefly in 1.5.0-dev prerelease versions.
- Added RequestFrame native for one-off next-frame actions (bug 5965).
- Added CS_DMG_HEADSHOT define for CS:S and CS:GO (PR 7) (Bara20).
- Added CS_SLOT_KNIFE define for CS:S and CS:GO (bug 6131).
- Updated TF_WEAPON enum (PR 37) (FlaminSarge).
- Added TFHoliday_AprilFools to TFHoliday enum (bug 6092) (Ross "Powerlord" Bemrose).
- Added new TF2_IsHolidayActive native to TF2 Ext (bug 6095) (Ross "Powerlord" Bemrose).
- Switch TF2 extension to hook CTFGameRules::IsHolidayActive for holiday forward (bug 6137, PR 42).
- Added GetPlayerJingleFile native. (bug 5690) (FlaminSarge).
- Added PrepSDKCall_SetAddress and Address support to PrepSDKCall_SetFromConf (bug 5261).
- Added ability to disable TopMenu Title Caching (bug 6034) (Peace-Maker).
- Added DisplayTopMenuCategory native (bug 6033) (Peace-Maker).
- Added support for Valve search paths to GetFileSize native (bug 5931).
- Fixed invalid entities sometimes passed to OnEntityCreated and OnEntityDestroyed (bug 6119).
- Fixed inconsistencies with OnClientDisconnected foward calls (bug 5988, PR 16).
- Changed OnClientSayCommand to now pass non-silent chat triggers onward (bug 5926) (SystematicMania).
- Changed OnClientSayCommand forwards to strip quotes from chat (bug 5986) (SystematicMania).
- Fixed FindStringIndex native not returning INVALID_STRING_INDEX when string not found (bug 6144, PR 40).
- Fixed GroundEntChanged hooks not being called (bug 6050) (Peace-Maker).
- Fixed INetChannelInfo natives to no longer require clients to be ingame (bug 5775) (SystematicMania).
- Fixed replace param being respected inconsistently in SetTrieArray (bug 6113).
- Fixed crash creating a timer when there are no handles available. (bug 5317) (Peace-Maker).
- Fixed crash in ReconnectClient and InactivateClient natives when IServer ptr is null (bug 6122).
- Fixed StoreFromAddress and LoadFromAddress continuing with bad values, usually crashing after error (bug 6080).
- Fixed compiler bug with multidimensional array variable release (bug 6100).
- Changed float comparison operators to return false for NaN (bug 6107).
- Added support in spcomp for sp/inc files > 32767 lines (bug 5959).
- Fixed FindFlagChar returning '?' for Admin_Custom6.
- Fixed AllPluginsLoaded activities happening before SM is loaded.
- Deduplicated a number of files used by extensions by moving them to the public directory (bug 5341).
- Removed 'state' keyword from compiler (bug 4572) (Ryan "VoiDeD" Stecker).
- Removed LogMessageEx definition from logging.inc because it never existed (bug 5897) (Peace-Maker).
- Removed native override API (bug 5852).
- Call OnLibraryAdded for all available libraries (bug 5925, PR 4).
- Made IGameConfig::GetMemSig return value clearer (bug 6081).
- Switched StringToInt(Ex) from using strtol to strtoul internally (bug 5939).
- Added an spcomp option to print #included files (bug 5997).
- Recompiled Regex extension libpcre against v8.32, enabling utf8, unicode props, and jit (bug 5593).
- Optimized native calls if statically bound (bug 5842).
Internal Changes:
- Now using new AlliedModders Template Library (AMTL) in many places, https://github.com/alliedmodders/amtl
- Ported buildscripts to new AMBuild2 platform, https://github.com/alliedmodders/ambuild
- Moved much logic from core to logic binary to reduce file sizes and compile times (bug 5606, bug 5607, bug 5680, bug 5953, PR 12, PR 13).
- Refactored the JIT to use a newer, simpler macro assembler. (bug 5827).
- Added sourcepawn interpreter (bug 5902).
- Added support for compiling spcomp with emscripten.
- Rewrite IThreader implementation around new synchronization primitives (bug 5862).
- Rewrite DBManager to use the new synchronization primitives (bug 5870).
- Overhauled internals of ClientPrefs extension for improved stability (bug 5538).
- Changed ShareSys to store C++ native lists more optimally (bug 5852).
- Simplified NativeEntry state (bug 5852).
- Changed NativeEntry to use Refcounted to manage (bug 5852).
- Switched Translator and GameConfigs to hash tables (bug 5878).
- Switched numerous subsystems from KTrie to AMTL NameHashSet (bug 5884).
- Refactored Trie natives to use AMTL HashMap instead of KTrie (bug 5892).
- Removed usages of memtables from many subsystems (bug 5899).
- Changed EventHook name storage to use AMTL AString (bug 6188).
- Replaced SH List usages in game extensions with AMTL variants (PR 23).
- Replaced SourceHook list usages in clientprefs with AMTL (PR 25).
- Changed floating-point operations to use SSE when available (bug 5841).
- Moved tracker related opcodes entirely to C++.
- Statically align the stack at function boundaries (bug 5842).
- Removed InfoVars, reassigned DAT from EBP to ESI to preserve C++ stacktraces in JIT code (5844).
- Fixed dereferencing potential null pointer in CPlugin::GetProperty (bug 5725).
- Fixed memory corruption when parsing natives. (bug 5840).
- Fixed some memory errors (bug 5904).
- Fixed unaligned memory access in spcomp.
- Move versioning to a static library to improve trivial build speed (bug 5997).
- Added many missing handle security checks (bug 5595).
- Made GetEntityClassname get and cache m_iClassname offset from worldspawn for ents not having it in datadesc (bug 5654).
- Cache m_iEFlags offset for datamaps dump instead of getting for each ent (bug 5657).
- Fixed mismatched delete [] on thunks in JIT CompData dtor (bug 5639).
- Fixed various memory issues. (bug 5766).
- Added reference counting and use it for CGameConfig and IDatabase (bug 5876).
- Added atomic reference counting and port DBI (bug 5876).
- Replaced usages of deprecated Sourcehook Add/Remove macros (bug 5631).
- Fixed SDKHooks hook ent validation missing first datatable name (bug 5881).
- Fixed case where bots leave server without disconnect notice (hibernation) (PR 20).
- Changed FindConVar to utilize convar cache for improved performance (PR 27) (VoiDeD).
- Gave define value (of 1) to PLATFORM defs to match the same-name defs in some SDKs (PR 10).
- Wrapped ClientPrintf into IGamePlayer (bug 6021).
- Consolidated FileExists usage in logic bin (bug 5931).
- Removed hardcoded paths to tier0/vstdlib in ICommandLine lookup.
- Use updated IServerTools iface on TF2 for getting tempent list and FindEntityByClassname (PR 33).
- Added early exit in entity output detour if entity has no classname to prevent crash.
- Updated SDKTools entity output functions to use core's GetEntityClassname instead of own (PR 39).
- Consolidated SDKTools entity factory lookups.
- Changed SDKTools PlayerRunCmd to a global vtable hook to improve performance (bug 6051).
- Changed SDKHooks to use global vtable hooks to improve performance (bug 6070).
- Added client validation checks to EmitSound SoundsHooks (bug 5873).
- Added missing meta results to some pre-hooks in SDKHooks.
- Replaced magic numbers for sm_show_activity with named constants (PR 14).
----------------------------------------------------------
SourceMod 1.5.3 [2014-03-22]
URL: http://wiki.alliedmods.net/SourceMod_1.5.3_Release_Notes
-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"
}
+2 -2
View File
@@ -105,8 +105,8 @@ sm_timeleft_interval 0
// 1 (Enabled)
// --
// Requires: basetriggers.smx
// Default: 0
sm_trigger_show 0
// Default: 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).
+1 -9
View File
@@ -114,7 +114,7 @@
* 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"
"SteamAuthstringValidation" "no"
/**
* Enables or disables whether SourceMod blocks known or potentially malicious plugins from loading.
@@ -125,12 +125,4 @@
* "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"
}
+36
View File
@@ -0,0 +1,36 @@
/**
* 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:
* "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"
{
}
}
}
-8
View File
@@ -14,12 +14,6 @@ except:
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',
@@ -31,6 +25,4 @@ run.options.add_option('-s', '--sdks', default='all', dest='sdks',
'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.options.add_option('--disable-auto-versioning', action='store_true', dest='disable_auto_versioning',
default=False, help='Disable the auto versioning script')
run.Configure()
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,6 +30,7 @@
*/
#include "ADTFactory.h"
#include "sm_globals.h"
#include "ShareSys.h"
ADTFactory g_AdtFactory;
@@ -56,30 +57,32 @@ IBasicTrie *ADTFactory::CreateBasicTrie()
BaseTrie::BaseTrie()
{
m_pTrie = sm_trie_create();
}
BaseTrie::~BaseTrie()
{
sm_trie_destroy(m_pTrie);
}
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)
{
return map_.retrieve(key, value);
return sm_trie_retrieve(m_pTrie, key, value);
}
bool BaseTrie::Delete(const char *key)
{
return map_.remove(key);
return sm_trie_delete(m_pTrie, key);
}
void BaseTrie::Clear()
{
map_.clear();
sm_trie_clear(m_pTrie);
}
void BaseTrie::Destroy()
@@ -89,5 +92,5 @@ void BaseTrie::Destroy()
bool BaseTrie::Replace(const char *key, void *value)
{
return map_.replace(key, value);
return sm_trie_replace(m_pTrie, key, value);
}
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -33,8 +33,8 @@
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
#include <IADTFactory.h>
#include "common_logic.h"
#include <sm_stringhashmap.h>
#include "sm_globals.h"
#include "sm_trie.h"
using namespace SourceMod;
@@ -50,7 +50,7 @@ public:
virtual void Clear();
virtual void Destroy();
private:
StringHashMap<void *> map_;
Trie *m_pTrie;
};
class ADTFactory :
+67 -61
View File
@@ -1,65 +1,25 @@
# 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',
'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_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',
'vprof_tool.cpp',
'smn_commandline.cpp',
]
for sdk_name in SM.sdks:
sdk = SM.sdks[sdk_name]
binary_name = 'sourcemod.' + sdk.ext
binary = SM.HL2Config(project, binary_name, sdk)
binary = SM.HL2Library(builder, binary_name, sdk)
compiler = binary.compiler
if sdk.name == 'csgo':
# Protobuf 2.3 headers have some signed/unsigned compares. I believe that it's fixed in later versions, but Valve.
if compiler.cxx.behavior == 'gcc':
compiler.cflags += ['-Wno-sign-compare']
compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
os.path.join(sdk.path, 'common', 'protobuf-2.3.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.6.1', 'src'),
os.path.join(sdk.path, 'common', 'protobuf-2.4.1', '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')
@@ -74,22 +34,69 @@ for sdk_name in SM.sdks:
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')
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs2010', 'libprotobuf.lib')
else:
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs2010', 'libprotobuf.lib')
compiler.linkflags.insert(0, binary.Dep(lib_path))
binary.sources += [
'AdminCache.cpp',
'MenuStyle_Valve.cpp',
'logic_bridge.cpp',
'smn_entities.cpp',
'sm_stringutil.cpp',
'MenuVoting.cpp',
'smn_events.cpp',
'smn_menus.cpp',
'sm_trie.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',
'NativeInvoker.cpp',
'smn_database.cpp',
'ForwardSys.cpp',
'Database.cpp',
'DebugReporter.cpp',
'ShareSys.cpp',
'PluginSys.cpp',
'HandleSys.cpp',
'NativeOwner.cpp',
'ExtensionSys.cpp',
'smn_fakenatives.cpp',
'smn_filesystem.cpp',
'ADTFactory.cpp',
'PluginInfoDatabase.cpp',
]
if sdk.name in ['csgo', 'dota']:
binary.sources += ['smn_protobuf.cpp']
@@ -106,7 +113,6 @@ for sdk_name in SM.sdks:
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'),
@@ -114,5 +120,5 @@ for sdk_name in SM.sdks:
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessage_helpers.cpp'),
]
SM.binaries += builder.Add(project)
SM.binaries += [builder.Add(binary)]
File diff suppressed because it is too large Load Diff
+208 -227
View File
@@ -1,227 +1,208 @@
/**
* 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_ADMINCACHE_H_
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
#include "common_logic.h"
#include <IAdminSystem.h>
#include "sm_memtable.h"
#include <sm_trie.h>
#include <sh_list.h>
#include <sh_string.h>
#include <IForwardSys.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
using namespace SourceHook;
#define GRP_MAGIC_SET 0xDEADFADE
#define GRP_MAGIC_UNSET 0xFACEFACE
#define USR_MAGIC_SET 0xDEADFACE
#define USR_MAGIC_UNSET 0xFADEDEAD
typedef StringHashMap<OverrideRule> OverrideMap;
struct AdminGroup
{
uint32_t magic; /* Magic flag, for memory validation (ugh) */
unsigned int immunity_level; /* Immunity level */
/* Immune from target table (-1 = nonexistent)
* [0] = number of entries
* [1...N] = immune targets
*/
int immune_table;
OverrideMap *pCmdTable; /* Command override table (can be NULL) */
OverrideMap *pCmdGrpTable; /* Command group override table (can be NULL) */
int next_grp; /* Next group in the chain */
int prev_grp; /* Previous group in the chain */
int nameidx; /* Name */
FlagBits addflags; /* Additive flags */
};
struct AuthMethod
{
String name;
StringHashMap<AdminId> identities;
AuthMethod(const char *name)
: name(name)
{
}
static inline bool matches(const char *name, const AuthMethod *method)
{
return strcmp(name, method->name.c_str()) == 0;
}
};
struct UserAuth
{
unsigned int index; /* Index into auth table */
int identidx; /* Index into the string table */
};
struct AdminUser
{
uint32_t magic; /* Magic flag, for memory validation */
FlagBits flags; /* Flags */
FlagBits eflags; /* Effective flags */
int nameidx; /* Name index */
int password; /* Password index */
unsigned int grp_count; /* Number of groups */
unsigned int grp_size; /* Size of groups table */
int grp_table; /* Group table itself */
int next_user; /* Next user in the list */
int prev_user; /* Previous user in the list */
UserAuth auth; /* Auth method for this user */
unsigned int immunity_level; /* Immunity level */
unsigned int serialchange; /* Serial # for changes */
};
class AdminCache :
public IAdminSystem,
public SMGlobalClass
{
public:
AdminCache();
~AdminCache();
public: //SMGlobalClass
void OnSourceModStartup(bool late);
void OnSourceModAllInitialized();
void OnSourceModLevelChange(const char *mapName);
void OnSourceModShutdown();
void OnSourceModPluginsLoaded();
public: //IAdminSystem
/** Command cache stuff */
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
void UnsetCommandOverride(const char *cmd, OverrideType type);
/** Group cache stuff */
GroupId AddGroup(const char *group_name);
GroupId FindGroupByName(const char *group_name);
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
bool GetGroupAddFlag(GroupId id, AdminFlag flag);
FlagBits GetGroupAddFlags(GroupId id);
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
void InvalidateGroup(GroupId id);
void AddGroupImmunity(GroupId id, GroupId other_id);
unsigned int GetGroupImmunityCount(GroupId id);
GroupId GetGroupImmunity(GroupId id, unsigned int number);
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
void DumpAdminCache(AdminCachePart part, bool rebuild);
void AddAdminListener(IAdminListener *pListener);
void RemoveAdminListener(IAdminListener *pListener);
/** User stuff */
void RegisterAuthIdentType(const char *name);
AdminId CreateAdmin(const char *name);
const char *GetAdminName(AdminId id);
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
FlagBits GetAdminFlags(AdminId id, AccessMode mode);
bool AdminInheritGroup(AdminId id, GroupId gid);
unsigned int GetAdminGroupCount(AdminId id);
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
void SetAdminPassword(AdminId id, const char *password);
const char *GetAdminPassword(AdminId id);
AdminId FindAdminByIdentity(const char *auth, const char *identity);
bool InvalidateAdmin(AdminId id);
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
bool CheckAdminFlags(AdminId id, FlagBits bits);
bool CanAdminTarget(AdminId id, AdminId target);
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
bool FindFlag(const char *str, AdminFlag *pFlag);
bool FindFlag(char c, AdminFlag *pAdmFlag);
FlagBits ReadFlagString(const char *flags, const char **end);
size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen);
unsigned int GetAdminSerialChange(AdminId id);
bool CanAdminUseCommand(int client, const char *cmd);
const char *GetGroupName(GroupId gid);
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
unsigned int GetGroupImmunityLevel(GroupId gid);
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
unsigned int GetAdminImmunityLevel(AdminId id);
bool CheckAccess(int client,
const char *cmd,
FlagBits flags,
bool override_only);
bool FindFlagChar(AdminFlag flag, char *c);
bool IsValidAdmin(AdminId id);
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags);
public:
bool DumpCache(const char *filename);
AdminGroup *GetGroup(GroupId gid);
AdminUser *GetUser(AdminId id);
const char *GetString(int idx);
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
private:
void _UnsetCommandOverride(const char *cmd);
void _UnsetCommandGroupOverride(const char *group);
void InvalidateGroupCache();
void InvalidateAdminCache(bool unlink_admins);
void DumpCommandOverrideCache(OverrideType type);
AuthMethod *GetMethodByIndex(unsigned int index);
bool GetMethodIndex(const char *name, unsigned int *_index);
const char *GetMethodName(unsigned int index);
void NameFlag(const char *str, AdminFlag flag);
bool GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen);
public:
typedef StringHashMap<FlagBits> FlagMap;
BaseStringTable *m_pStrings;
BaseMemTable *m_pMemory;
FlagMap m_CmdOverrides;
FlagMap m_CmdGrpOverrides;
int m_FirstGroup;
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_
/**
* 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_ADMINCACHE_H_
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
#include "sm_memtable.h"
#include <sm_trie.h>
#include <sh_list.h>
#include <sh_string.h>
#include <IAdminSystem.h>
#include "sm_globals.h"
#include <IForwardSys.h>
using namespace SourceHook;
#define GRP_MAGIC_SET 0xDEADFADE
#define GRP_MAGIC_UNSET 0xFACEFACE
#define USR_MAGIC_SET 0xDEADFACE
#define USR_MAGIC_UNSET 0xFADEDEAD
struct AdminGroup
{
uint32_t magic; /* Magic flag, for memory validation (ugh) */
unsigned int immunity_level; /* Immunity level */
/* Immune from target table (-1 = nonexistent)
* [0] = number of entries
* [1...N] = immune targets
*/
int immune_table;
Trie *pCmdTable; /* Command override table (can be NULL) */
Trie *pCmdGrpTable; /* Command group override table (can be NULL) */
int next_grp; /* Next group in the chain */
int prev_grp; /* Previous group in the chain */
int nameidx; /* Name */
FlagBits addflags; /* Additive flags */
};
struct AuthMethod
{
String name;
Trie *table;
};
struct UserAuth
{
unsigned int index; /* Index into auth table */
int identidx; /* Index into the string table */
};
struct AdminUser
{
uint32_t magic; /* Magic flag, for memory validation */
FlagBits flags; /* Flags */
FlagBits eflags; /* Effective flags */
int nameidx; /* Name index */
int password; /* Password index */
unsigned int grp_count; /* Number of groups */
unsigned int grp_size; /* Size of groups table */
int grp_table; /* Group table itself */
int next_user; /* Next user in the list */
int prev_user; /* Previous user in the list */
UserAuth auth; /* Auth method for this user */
unsigned int immunity_level; /* Immunity level */
unsigned int serialchange; /* Serial # for changes */
};
class AdminCache :
public IAdminSystem,
public SMGlobalClass
{
public:
AdminCache();
~AdminCache();
public: //SMGlobalClass
void OnSourceModStartup(bool late);
void OnSourceModAllInitialized();
void OnSourceModLevelChange(const char *mapName);
void OnSourceModShutdown();
void OnSourceModPluginsLoaded();
public: //IAdminSystem
/** Command cache stuff */
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
void UnsetCommandOverride(const char *cmd, OverrideType type);
/** Group cache stuff */
GroupId AddGroup(const char *group_name);
GroupId FindGroupByName(const char *group_name);
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
bool GetGroupAddFlag(GroupId id, AdminFlag flag);
FlagBits GetGroupAddFlags(GroupId id);
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
void InvalidateGroup(GroupId id);
void AddGroupImmunity(GroupId id, GroupId other_id);
unsigned int GetGroupImmunityCount(GroupId id);
GroupId GetGroupImmunity(GroupId id, unsigned int number);
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
void DumpAdminCache(AdminCachePart part, bool rebuild);
void AddAdminListener(IAdminListener *pListener);
void RemoveAdminListener(IAdminListener *pListener);
/** User stuff */
void RegisterAuthIdentType(const char *name);
AdminId CreateAdmin(const char *name);
const char *GetAdminName(AdminId id);
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
FlagBits GetAdminFlags(AdminId id, AccessMode mode);
bool AdminInheritGroup(AdminId id, GroupId gid);
unsigned int GetAdminGroupCount(AdminId id);
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
void SetAdminPassword(AdminId id, const char *password);
const char *GetAdminPassword(AdminId id);
AdminId FindAdminByIdentity(const char *auth, const char *identity);
bool InvalidateAdmin(AdminId id);
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
bool CheckAdminFlags(AdminId id, FlagBits bits);
bool CanAdminTarget(AdminId id, AdminId target);
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
bool FindFlag(const char *str, AdminFlag *pFlag);
bool FindFlag(char c, AdminFlag *pAdmFlag);
FlagBits ReadFlagString(const char *flags, const char **end);
size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen);
unsigned int GetAdminSerialChange(AdminId id);
bool CanAdminUseCommand(int client, const char *cmd);
const char *GetGroupName(GroupId gid);
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
unsigned int GetGroupImmunityLevel(GroupId gid);
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
unsigned int GetAdminImmunityLevel(AdminId id);
bool CheckAccess(int client,
const char *cmd,
FlagBits flags,
bool override_only);
bool FindFlagChar(AdminFlag flag, char *c);
public:
bool IsValidAdmin(AdminId id);
void DumpCache(FILE *fp);
AdminGroup *GetGroup(GroupId gid);
AdminUser *GetUser(AdminId id);
const char *GetString(int idx);
private:
void _UnsetCommandOverride(const char *cmd);
void _UnsetCommandGroupOverride(const char *group);
void InvalidateGroupCache();
void InvalidateAdminCache(bool unlink_admins);
void DumpCommandOverrideCache(OverrideType type);
Trie *GetMethodByIndex(unsigned int index);
bool GetMethodIndex(const char *name, unsigned int *_index);
const char *GetMethodName(unsigned int index);
void NameFlag(const char *str, AdminFlag flag);
public:
BaseStringTable *m_pStrings;
BaseMemTable *m_pMemory;
Trie *m_pCmdOverrides;
Trie *m_pCmdGrpOverrides;
int m_FirstGroup;
int m_LastGroup;
int m_FreeGroupList;
Trie *m_pGroups;
List<IAdminListener *> m_hooks;
List<AuthMethod> m_AuthMethods;
Trie *m_pAuthTables;
IForward *m_pCacheFwd;
int m_FirstUser;
int m_LastUser;
int m_FreeUserList;
bool m_InvalidatingAdmins;
bool m_destroying;
Trie *m_pLevelNames;
};
extern AdminCache g_Admins;
#endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
+10 -84
View File
@@ -76,12 +76,9 @@ void CDataPack::ResetSize()
size_t CDataPack::CreateMemory(size_t size, void **addr)
{
CheckSize(sizeof(char) + sizeof(size_t) + size);
CheckSize(sizeof(size_t) + size);
size_t pos = m_curptr - m_pBase;
*(char *)m_curptr = Raw;
m_curptr += sizeof(char);
*(size_t *)m_curptr = size;
m_curptr += sizeof(size_t);
@@ -91,17 +88,14 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
}
m_curptr += size;
m_size += sizeof(char) + sizeof(size_t) + size;
m_size += sizeof(size_t) + size;
return pos;
}
void CDataPack::PackCell(cell_t cell)
{
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
*(char *)m_curptr = Cell;
m_curptr += sizeof(char);
CheckSize(sizeof(size_t) + sizeof(cell_t));
*(size_t *)m_curptr = sizeof(cell_t);
m_curptr += sizeof(size_t);
@@ -109,15 +103,12 @@ void CDataPack::PackCell(cell_t cell)
*(cell_t *)m_curptr = cell;
m_curptr += sizeof(cell_t);
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
m_size += sizeof(size_t) + sizeof(cell_t);
}
void CDataPack::PackFloat(float val)
{
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float));
*(char *)m_curptr = Float;
m_curptr += sizeof(char);
CheckSize(sizeof(size_t) + sizeof(float));
*(size_t *)m_curptr = sizeof(float);
m_curptr += sizeof(size_t);
@@ -125,18 +116,15 @@ void CDataPack::PackFloat(float val)
*(float *)m_curptr = val;
m_curptr += sizeof(float);
m_size += sizeof(char) + sizeof(size_t) + sizeof(float);
m_size += sizeof(size_t) + sizeof(float);
}
void CDataPack::PackString(const char *string)
{
size_t len = strlen(string);
size_t maxsize = sizeof(char) + sizeof(size_t) + len + 1;
size_t maxsize = sizeof(size_t) + len + 1;
CheckSize(maxsize);
*(char *)m_curptr = String;
m_curptr += sizeof(char);
// Pack the string length first for buffer overrun checking.
*(size_t *)m_curptr = len;
m_curptr += sizeof(size_t);
@@ -172,16 +160,10 @@ bool CDataPack::SetPosition(size_t pos) const
cell_t CDataPack::ReadCell() const
{
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
if (!IsReadable(sizeof(size_t) + sizeof(cell_t)))
{
return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Cell)
{
return 0;
}
m_curptr += sizeof(char);
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
{
return 0;
@@ -196,16 +178,10 @@ cell_t CDataPack::ReadCell() const
float CDataPack::ReadFloat() const
{
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float)))
if (!IsReadable(sizeof(size_t) + sizeof(float)))
{
return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Float)
{
return 0;
}
m_curptr += sizeof(char);
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
{
return 0;
@@ -225,15 +201,10 @@ bool CDataPack::IsReadable(size_t bytes) const
const char *CDataPack::ReadString(size_t *len) const
{
if (!IsReadable(sizeof(char) + sizeof(size_t)))
if (!IsReadable(sizeof(size_t)))
{
return NULL;
}
if (*reinterpret_cast<char *>(m_curptr) != String)
{
return NULL;
}
m_curptr += sizeof(char);
size_t real_len = *(size_t *)m_curptr;
@@ -266,11 +237,6 @@ void *CDataPack::ReadMemory(size_t *size) const
{
return NULL;
}
if (*reinterpret_cast<char *>(m_curptr) != Raw)
{
return NULL;
}
m_curptr += sizeof(char);
size_t bytecount = *(size_t *)m_curptr;
m_curptr += sizeof(size_t);
@@ -291,43 +257,3 @@ void *CDataPack::ReadMemory(size_t *size) const
return ptr;
}
void CDataPack::PackFunction(cell_t function)
{
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t));
*(char *)m_curptr = Function;
m_curptr += sizeof(char);
*(size_t *)m_curptr = sizeof(cell_t);
m_curptr += sizeof(size_t);
*(cell_t *)m_curptr = function;
m_curptr += sizeof(cell_t);
m_size += sizeof(char) + sizeof(size_t) + sizeof(cell_t);
}
cell_t CDataPack::ReadFunction() const
{
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(cell_t)))
{
return 0;
}
if (*reinterpret_cast<char *>(m_curptr) != Function)
{
return 0;
}
m_curptr += sizeof(char);
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
{
return 0;
}
m_curptr += sizeof(size_t);
cell_t val = *reinterpret_cast<cell_t *>(m_curptr);
m_curptr += sizeof(cell_t);
return val;
}
-10
View File
@@ -51,14 +51,12 @@ public: //IDataReader
const char *ReadString(size_t *len) const;
void *GetMemory() const;
void *ReadMemory(size_t *size) const;
cell_t ReadFunction() const;
public: //IDataPack
void ResetSize();
void PackCell(cell_t cell);
void PackFloat(float val);
void PackString(const char *string);
size_t CreateMemory(size_t size, void **addr);
void PackFunction(cell_t function);
public:
void Initialize();
private:
@@ -68,14 +66,6 @@ private:
mutable char *m_curptr;
size_t m_capacity;
size_t m_size;
enum DataPackType {
Raw,
Cell,
Float,
String,
Function
};
};
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
+2 -20
View File
@@ -44,11 +44,7 @@ public: //IRecipientFilter
bool IsReliable() const;
bool IsInitMessage() const;
int GetRecipientCount() const;
#if SOURCE_ENGINE == SE_DOTA
CEntityIndex GetRecipientIndex(int slot) const;
#else
int GetRecipientIndex(int slot) const;
#endif
public:
void Initialize(const cell_t *ptr, size_t count);
void SetToReliable(bool isreliable);
@@ -83,27 +79,13 @@ inline int CellRecipientFilter::GetRecipientCount() const
return m_Size;
}
#if SOURCE_ENGINE == SE_DOTA
inline CEntityIndex CellRecipientFilter::GetRecipientIndex(int slot) const
#else
inline int CellRecipientFilter::GetRecipientIndex(int slot) const
#endif
{
int ret;
if ((slot < 0) || (slot >= GetRecipientCount()))
{
ret = -1;
return -1;
}
else
{
ret = static_cast<int>(m_Players[slot]);
}
#if SOURCE_ENGINE == SE_DOTA
return CEntityIndex(ret);
#else
return ret;
#endif
return static_cast<int>(m_Players[slot]);
}
inline void CellRecipientFilter::SetToInit(bool isinitmsg)
+84 -121
View File
@@ -36,35 +36,37 @@
#include "PlayerManager.h"
#include "HalfLife2.h"
#include "logic_bridge.h"
#include "sourcemod.h"
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
/* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
* While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
* can technically be compiled against any MM:S version after 1.4.2.
*/
#if SOURCE_ENGINE >= SE_ORANGEBOX
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
# 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
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
#if SH_IMPL_VERSION >= 5
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate0<void>);
#elif SH_IMPL_VERSION == 4
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
#elif SH_IMPL_VERSION == 3
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
#endif //SH_IMPL_VERSION
#endif //SE_ORANGEBOX
ChatTriggers g_ChatTriggers;
bool g_bSupressSilentFails = false;
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL)
m_ReplyTo(SM_REPLY_CONSOLE)
{
m_PubTrigger = sm_strdup("!");
m_PrivTrigger = sm_strdup("/");
m_PubTriggerSize = 1;
m_PrivTriggerSize = 1;
m_bIsChatTrigger = false;
m_bPluginIgnored = true;
m_bPluginIgnored = false;
#if SOURCE_ENGINE == SE_EPISODEONE
m_bIsINS = false;
#endif
@@ -76,8 +78,6 @@ ChatTriggers::~ChatTriggers()
m_PubTrigger = NULL;
delete [] m_PrivTrigger;
m_PrivTrigger = NULL;
delete [] m_ArgSBackup;
m_ArgSBackup = NULL;
}
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
@@ -111,10 +111,10 @@ ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
void ChatTriggers::OnSourceModAllInitialized()
{
m_pShouldFloodBlock = forwardsys->CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
m_pDidFloodBlock = forwardsys->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);
m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
m_pOnClientSayCmd = g_Forwards.CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String);
m_pOnClientSayCmd_Post = g_Forwards.CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
}
void ChatTriggers::OnSourceModAllInitialized_Post()
@@ -129,13 +129,13 @@ void ChatTriggers::OnSourceModGameInitialized()
if (m_pSayCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
}
if (m_pSayTeamCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
}
#if SOURCE_ENGINE == SE_EPISODEONE
@@ -165,8 +165,8 @@ 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);
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 (m_pSayTeamCmd)
@@ -189,16 +189,13 @@ void ChatTriggers::OnSourceModShutdown()
}
#endif
forwardsys->ReleaseForward(m_pShouldFloodBlock);
forwardsys->ReleaseForward(m_pDidFloodBlock);
forwardsys->ReleaseForward(m_pOnClientSayCmd);
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post);
g_Forwards.ReleaseForward(m_pShouldFloodBlock);
g_Forwards.ReleaseForward(m_pDidFloodBlock);
g_Forwards.ReleaseForward(m_pOnClientSayCmd);
g_Forwards.ReleaseForward(m_pOnClientSayCmd_Post);
}
#if SOURCE_ENGINE == SE_DOTA
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{
#else
@@ -209,10 +206,10 @@ void ChatTriggers::OnSayCommand_Pre()
int client = g_ConCmds.GetCommandClient();
m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
m_bPluginIgnored = true;
m_bPluginIgnored = false;
const char *args = command.ArgS();
if (!args)
{
RETURN_META(MRES_IGNORED);
@@ -221,73 +218,17 @@ void ChatTriggers::OnSayCommand_Pre()
/* 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';
}
}
m_ArgSBackup = command.ArgS();
/* The server console cannot do this */
if (client == 0)
{
if (CallOnClientSayCommand(client) >= Pl_Handled)
cell_t res = CallOnClientSayCommand(client);
if (res >= Pl_Handled)
{
m_bPluginIgnored = (res >= Pl_Stop);
RETURN_META(MRES_SUPERCEDE);
}
RETURN_META(MRES_IGNORED);
}
@@ -318,26 +259,41 @@ void ChatTriggers::OnSayCommand_Pre()
RETURN_META(MRES_SUPERCEDE);
}
/* Handle quoted string sets */
bool is_quoted = false;
if (args[0] == '"')
{
args++;
is_quoted = true;
}
#if SOURCE_ENGINE == SE_EPISODEONE
if (m_bIsINS && strcmp(m_Arg0Backup, "say2") == 0 && strlen(args) >= 4)
{
args += 4;
}
#endif
bool is_trigger = false;
bool is_silent = false;
/* 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;
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_silent = true;
args = &m_ArgSBackup[m_PrivTriggerSize];
args = &args[m_PrivTriggerSize];
}
/**
* Test if this is actually a command!
*/
if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args))
if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
{
m_bIsChatTrigger = true;
@@ -347,12 +303,15 @@ void ChatTriggers::OnSayCommand_Pre()
m_bWillProcessInPost = true;
}
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
cell_t res = CallOnClientSayCommand(client);
if (res >= Pl_Handled)
{
m_bPluginIgnored = (res >= Pl_Stop);
RETURN_META(MRES_SUPERCEDE);
}
if (CallOnClientSayCommand(client) >= Pl_Handled)
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID)))
{
RETURN_META(MRES_SUPERCEDE);
}
@@ -361,9 +320,7 @@ void ChatTriggers::OnSayCommand_Pre()
RETURN_META(MRES_IGNORED);
}
#if SOURCE_ENGINE == SE_DOTA
void ChatTriggers::OnSayCommand_Post(const CCommandContext &context, const CCommand &command)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Post(const CCommand &command)
#else
void ChatTriggers::OnSayCommand_Post()
@@ -375,19 +332,19 @@ void ChatTriggers::OnSayCommand_Post()
{
/* Reset this for re-entrancy */
m_bWillProcessInPost = false;
/* Execute the cached command */
unsigned int old = SetReplyTo(SM_REPLY_CHAT);
#if SOURCE_ENGINE == SE_DOTA
engine->ClientCommand(client, "%s", m_ToExecute);
#else
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
#endif
SetReplyTo(old);
}
if (!m_bPluginIgnored && m_pOnClientSayCmd_Post->GetFunctionCount() != 0)
if (m_bPluginIgnored)
{
m_bPluginIgnored = false;
}
else if (!m_bWasFloodedMessage && !m_bIsChatTrigger && m_pOnClientSayCmd_Post->GetFunctionCount() != 0)
{
m_pOnClientSayCmd_Post->PushCell(client);
m_pOnClientSayCmd_Post->PushString(m_Arg0Backup);
m_pOnClientSayCmd_Post->PushString(m_ArgSBackup);
@@ -398,7 +355,7 @@ void ChatTriggers::OnSayCommand_Post()
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. */
char cmd_buf[64];
@@ -440,12 +397,12 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
{
return false;
}
prepended = true;
}
/* See if we need to do extra string manipulation */
if (prepended)
if (is_quoted || prepended)
{
size_t len;
@@ -456,6 +413,15 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
} else {
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 {
strncopy(m_ToExecute, args, sizeof(m_ToExecute));
}
@@ -466,16 +432,13 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
cell_t ChatTriggers::CallOnClientSayCommand(int client)
{
cell_t res = Pl_Continue;
if (m_pOnClientSayCmd->GetFunctionCount() != 0)
if (!m_bIsChatTrigger && 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;
}
+3 -6
View File
@@ -54,10 +54,7 @@ public: //SMGlobalClass
char *error,
size_t maxlength);
private: //ConCommand
#if SOURCE_ENGINE == SE_DOTA
void OnSayCommand_Pre(const CCommandContext &, const CCommand &command);
void OnSayCommand_Post(const CCommandContext &, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void OnSayCommand_Pre(const CCommand &command);
void OnSayCommand_Post(const CCommand &command);
#else
@@ -70,7 +67,7 @@ public:
bool IsChatTrigger();
bool WasFloodedMessage();
private:
bool PreProcessTrigger(edict_t *pEdict, const char *args);
bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
bool ClientIsFlooding(int client);
cell_t CallOnClientSayCommand(int client);
private:
@@ -92,7 +89,7 @@ private:
unsigned int m_ReplyTo;
char m_ToExecute[300];
const char *m_Arg0Backup;
char *m_ArgSBackup;
const char *m_ArgSBackup;
IForward *m_pShouldFloodBlock;
IForward *m_pDidFloodBlock;
IForward *m_pOnClientSayCmd;
+487 -201
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -31,19 +31,16 @@
#include "ConCmdManager.h"
#include "sm_srvcmds.h"
#include "AdminCache.h"
#include "sm_stringutil.h"
#include "PlayerManager.h"
#include "HalfLife2.h"
#include "ChatTriggers.h"
#include "logic_bridge.h"
using namespace ke;
ConCmdManager g_ConCmds;
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#else
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
@@ -51,30 +48,40 @@ ConCmdManager g_ConCmds;
SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
typedef ke::LinkedList<CmdHook *> PluginHookList;
void RegisterInPlugin(CmdHook *hook);
ConCmdManager::ConCmdManager()
struct PlCmdInfo
{
ConCmdInfo *pInfo;
CmdHook *pHook;
CmdType type;
};
typedef List<PlCmdInfo> CmdList;
void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info);
ConCmdManager::ConCmdManager() : m_Strings(1024)
{
m_pCmds = sm_trie_create();
m_pCmdGrps = sm_trie_create();
m_CmdClient = 0;
}
ConCmdManager::~ConCmdManager()
{
sm_trie_destroy(m_pCmds);
sm_trie_destroy(m_pCmdGrps);
}
void ConCmdManager::OnSourceModAllInitialized()
{
scripts->AddPluginsListener(this);
g_PluginSys.AddPluginsListener(this);
g_RootMenu.AddRootConsoleCommand("cmds", "List console commands", this);
SH_ADD_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &ConCmdManager::SetCommandClient), false);
SH_ADD_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &ConCmdManager::SetCommandClient, false);
}
void ConCmdManager::OnSourceModShutdown()
{
scripts->RemovePluginsListener(this);
/* All commands should already be removed by the time we're done */
SH_REMOVE_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &ConCmdManager::SetCommandClient), false);
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &ConCmdManager::SetCommandClient, false);
g_RootMenu.RemoveRootConsoleCommand("cmds", this);
}
@@ -83,68 +90,122 @@ void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
/* Whoa, first get its information struct */
ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(name, &pInfo))
return;
CmdHookList::iterator iter = pInfo->hooks.begin();
while (iter != pInfo->hooks.end())
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
{
CmdHook *hook = *iter;
IPluginContext *pContext = hook->pf->GetParentContext();
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
// The list is guaranteed to exist.
PluginHookList *list;
pPlugin->GetProperty("CommandList", (void **)&list, false);
for (PluginHookList::iterator hiter = list->begin(); hiter != list->end(); hiter++)
{
if (*hiter == hook)
{
list->erase(hiter);
break;
}
}
if (hook->admin)
hook->admin->group->hooks.remove(hook);
iter = pInfo->hooks.erase(iter);
delete hook;
return;
}
RemoveConCmds(pInfo->srvhooks);
RemoveConCmds(pInfo->conhooks);
RemoveConCmd(pInfo, name, is_read_safe, false);
}
void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist)
{
PluginHookList *pList;
if (!plugin->GetProperty("CommandList", (void **)&pList, true))
return;
List<CmdHook *>::iterator iter = cmdlist.begin();
PluginHookList::iterator iter = pList->begin();
while (iter != pList->end())
while (iter != cmdlist.end())
{
CmdHook *hook = *iter;
CmdHook *pHook = (*iter);
IPluginContext *pContext = pHook->pf->GetParentContext();
IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
CmdList *pList = NULL;
//gaben
if (!pPlugin->GetProperty("CommandList", (void **)&pList, false) || !pList)
{
continue;
}
hook->info->hooks.remove(hook);
if (hook->admin)
hook->admin->group->hooks.remove(hook);
CmdList::iterator p_iter = pList->begin();
while (p_iter != pList->end())
{
PlCmdInfo &cmd = (*p_iter);
if (cmd.pHook == pHook)
{
p_iter = pList->erase(p_iter);
}
else
{
p_iter++;
}
}
if (hook->info->hooks.empty())
RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true, true);
iter = pList->erase(iter);
delete hook;
delete pHook->pAdmin;
delete pHook;
iter = cmdlist.erase(iter);
}
delete pList;
}
#if SOURCE_ENGINE == SE_DOTA
void CommandCallback(const CCommandContext &context, const CCommand &command)
void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
List<CmdHook *>::iterator iter = cmdlist.begin();
CmdHook *pHook;
while (iter != cmdlist.end())
{
pHook = (*iter);
if (pHook->pf->GetParentContext() == pContext)
{
delete pHook->pAdmin;
delete pHook;
iter = cmdlist.erase(iter);
}
else
{
iter++;
}
}
}
void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
{
CmdList *pList;
List<ConCmdInfo *> removed;
if (plugin->GetProperty("CommandList", (void **)&pList, true))
{
IPluginContext *pContext = plugin->GetBaseContext();
CmdList::iterator iter;
/* First pass!
* Only bother if there's an actual command list on this plugin...
*/
for (iter=pList->begin();
iter!=pList->end();
iter++)
{
PlCmdInfo &cmd = (*iter);
ConCmdInfo *pInfo = cmd.pInfo;
/* Has this chain already been fully cleaned/removed? */
if (removed.find(pInfo) != removed.end())
{
continue;
}
/* Remove any hooks from us on this command */
RemoveConCmds(pInfo->conhooks, pContext);
RemoveConCmds(pInfo->srvhooks, pContext);
/* See if there are still hooks */
if (pInfo->srvhooks.size())
{
continue;
}
if (pInfo->conhooks.size())
{
continue;
}
/* Remove the command, it should be safe now */
RemoveConCmd(pInfo, pInfo->pCmd->GetName(), true, true);
removed.push_back(pInfo);
}
delete pList;
}
}
#if SOURCE_ENGINE >= SE_ORANGEBOX
void CommandCallback(const CCommand &command)
{
#else
@@ -168,7 +229,7 @@ void ConCmdManager::SetCommandClient(int client)
ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
{
ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(name, &pInfo))
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
return NULL;
return pInfo;
}
@@ -200,34 +261,44 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
}
cell_t result = type;
for (CmdHookList::iterator iter = pInfo->hooks.begin(); iter != pInfo->hooks.end(); iter++)
cell_t tempres = result;
List<CmdHook *>::iterator iter;
CmdHook *pHook;
for (iter=pInfo->conhooks.begin();
iter!=pInfo->conhooks.end();
iter++)
{
CmdHook *hook = *iter;
if (hook->type == CmdHook::Server || !hook->pf->IsRunnable())
continue;
if (hook->admin && !CheckAccess(client, cmd, hook->admin))
pHook = (*iter);
if (!pHook->pf->IsRunnable())
{
if (result < Pl_Handled)
result = Pl_Handled;
continue;
}
hook->pf->PushCell(client);
hook->pf->PushCell(args);
cell_t tempres = result;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
if (pHook->pAdmin && !CheckAccess(client, cmd, pHook->pAdmin))
{
if (result < Pl_Handled)
{
result = Pl_Handled;
}
continue;
}
pHook->pf->PushCell(client);
pHook->pf->PushCell(args);
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
{
if (tempres > result)
{
result = tempres;
}
if (result == Pl_Stop)
{
break;
}
}
}
return (ResultType)result;
type = (ResultType)result;
return type;
}
void ConCmdManager::InternalDispatch(const CCommand &command)
@@ -238,7 +309,9 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
{
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer || !pPlayer->IsConnected())
{
return;
}
}
/**
@@ -270,78 +343,198 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
* "nicer" when we expose explicit say hooks.
*/
if (g_ChatTriggers.WasFloodedMessage())
{
return;
}
cell_t result = Pl_Continue;
int args = command.ArgC() - 1;
// On a listen server, sometimes the server host's client index can be set
// as 0. So index 1 is passed to the command callback to correct this
// potential problem.
int realClient = (!engine->IsDedicatedServer() && client == 0)
? g_Players.ListenClient()
: client;
int dedicatedClient = engine->IsDedicatedServer() ? 0 : g_Players.ListenClient();
List<CmdHook *>::iterator iter;
CmdHook *pHook;
for (CmdHookList::iterator iter = pInfo->hooks.begin(); iter != pInfo->hooks.end(); iter++)
/* Execute server-only commands if viable */
if (client == 0 && pInfo->srvhooks.size())
{
CmdHook *hook = *iter;
if (!hook->pf->IsRunnable())
continue;
if (hook->type == CmdHook::Server)
cell_t tempres = result;
for (iter=pInfo->srvhooks.begin();
iter!=pInfo->srvhooks.end();
iter++)
{
// Don't execute unless we're in the server console.
if (realClient != dedicatedClient)
pHook = (*iter);
if (!pHook->pf->IsRunnable())
{
continue;
} else {
// Check admin rights if needed. realClient isn't needed since we
// should bypass admin checks if client == 0 anyway.
if (client && hook->admin && !CheckAccess(client, cmd, hook->admin))
}
pHook->pf->PushCell(args);
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
{
if (tempres > result)
{
result = tempres;
}
if (result == Pl_Stop)
{
break;
}
}
}
/* Check if there's an early stop */
if (result >= Pl_Stop)
{
if (!pInfo->sourceMod)
{
RETURN_META(MRES_SUPERCEDE);
}
return;
}
}
/* Execute console commands */
if (pInfo->conhooks.size())
{
cell_t tempres = result;
for (iter=pInfo->conhooks.begin();
iter!=pInfo->conhooks.end();
iter++)
{
pHook = (*iter);
if (!pHook->pf->IsRunnable())
{
continue;
}
if (client
&& pHook->pAdmin
&& !CheckAccess(client, cmd, pHook->pAdmin))
{
if (result < Pl_Handled)
{
result = Pl_Handled;
}
continue;
}
// Client hooks get a client argument.
hook->pf->PushCell(realClient);
}
/* On a listen server, sometimes the server host's client index can be set as 0.
* So index 1 is passed to the command callback to correct this potential problem.
*/
if (!engine->IsDedicatedServer())
{
client = g_Players.ListenClient();
}
hook->pf->PushCell(args);
pHook->pf->PushCell(client);
pHook->pf->PushCell(args);
cell_t tempres = result;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
{
if (tempres > result)
result = tempres;
if (result == Pl_Stop)
break;
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
{
if (tempres > result)
{
result = tempres;
}
if (result == Pl_Stop)
{
break;
}
}
}
}
if (result >= Pl_Handled)
{
if (!pInfo->sourceMod)
{
RETURN_META(MRES_SUPERCEDE);
}
return;
}
}
bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
bool ConCmdManager::CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags)
{
if (adminsys->CheckClientCommandAccess(client, cmd, pAdmin->eflags))
if (cmdflags == 0 || client == 0)
{
return true;
}
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer)
/* If running listen server, then client 1 is the server host and should have 'root' access */
if (client == 1 && !engine->IsDedicatedServer())
{
return true;
}
CPlayer *player = g_Players.GetPlayerByIndex(client);
if (!player
|| player->GetEdict() == NULL
|| player->IsFakeClient())
{
return false;
}
return CheckAdminCommandAccess(player->GetAdminId(), cmd, cmdflags);
}
bool ConCmdManager::CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits cmdflags)
{
if (adm != INVALID_ADMIN_ID)
{
FlagBits bits = g_Admins.GetAdminFlags(adm, Access_Effective);
/* root knows all, WHOA */
if ((bits & ADMFLAG_ROOT) == ADMFLAG_ROOT)
{
return true;
}
/* Check for overrides
* :TODO: is it worth optimizing this?
*/
unsigned int groups = g_Admins.GetAdminGroupCount(adm);
GroupId gid;
OverrideRule rule;
bool override = false;
for (unsigned int i=0; i<groups; i++)
{
gid = g_Admins.GetAdminGroup(adm, i, NULL);
/* First get group-level override */
override = g_Admins.GetGroupCommandOverride(gid, cmd, Override_CommandGroup, &rule);
/* Now get the specific command override */
if (g_Admins.GetGroupCommandOverride(gid, cmd, Override_Command, &rule))
{
override = true;
}
if (override)
{
if (rule == Command_Allow)
{
return true;
}
else if (rule == Command_Deny)
{
return false;
}
}
}
/* See if our other flags match */
if ((bits & cmdflags) == cmdflags)
{
return true;
}
}
return false;
}
bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
{
if (CheckClientCommandAccess(client, cmd, pAdmin->eflags))
{
return true;
}
edict_t *pEdict = PEntityOfEntIndex(client);
/* If we got here, the command failed... */
char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
@@ -354,7 +547,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
{
char fullbuffer[192];
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer);
pPlayer->PrintToConsole(fullbuffer);
engine->ClientPrintf(pEdict, fullbuffer);
}
else if (replyto == SM_REPLY_CHAT)
{
@@ -376,41 +569,72 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo)
return false;
GroupMap::Insert i = m_CmdGrps.findForAdd(group);
if (!i.found())
{
if (!m_CmdGrps.add(i, group))
return false;
i->value = new CommandGroup();
return false;
}
Ref<CommandGroup> cmdgroup = i->value;
CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description);
pHook->admin = new AdminCmdInfo(cmdgroup, adminflags);
CmdHook *pHook = new CmdHook();
AdminCmdInfo *pAdmin = new AdminCmdInfo();
pHook->pf = pFunction;
if (description && description[0])
{
pHook->helptext.assign(description);
}
pHook->pAdmin = pAdmin;
void *object;
int grpid;
if (!sm_trie_retrieve(m_pCmdGrps, group, (void **)&object))
{
grpid = m_Strings.AddString(group);
sm_trie_insert(m_pCmdGrps, group, (void *)grpid);
}
else
{
grpid = (int)object;
}
pAdmin->cmdGrpId = grpid;
pAdmin->flags = adminflags;
/* First get the command group override, if any */
bool override = adminsys->GetCommandOverride(group,
bool override = g_Admins.GetCommandOverride(group,
Override_CommandGroup,
&(pHook->admin->eflags));
&(pAdmin->eflags));
/* Next get the command override, if any */
if (adminsys->GetCommandOverride(name,
if (g_Admins.GetCommandOverride(name,
Override_Command,
&(pHook->admin->eflags)))
&(pAdmin->eflags)))
{
override = true;
}
/* Assign normal flags if there were no overrides */
if (!override)
pHook->admin->eflags = pHook->admin->flags;
pInfo->eflags = pHook->admin->eflags;
{
pAdmin->eflags = pAdmin->flags;
}
/* Finally, add the hook */
pInfo->conhooks.push_back(pHook);
pInfo->admin = *(pHook->pAdmin);
/* Now add to the plugin */
CmdList *pList;
IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new CmdList();
pPlugin->SetProperty("CommandList", pList);
}
PlCmdInfo info;
info.pInfo = pInfo;
info.type = Cmd_Admin;
info.pHook = pHook;
AddToPlCmdList(pList, info);
cmdgroup->hooks.append(pHook);
pInfo->hooks.append(pHook);
RegisterInPlugin(pHook);
return true;
}
@@ -423,42 +647,63 @@ bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo)
{
return false;
}
CmdHook *pHook = new CmdHook(CmdHook::Server, pInfo, pFunction, description);
CmdHook *pHook = new CmdHook();
pHook->pf = pFunction;
if (description && description[0])
{
pHook->helptext.assign(description);
}
pInfo->srvhooks.push_back(pHook);
/* Add to the plugin */
CmdList *pList;
IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new CmdList();
pPlugin->SetProperty("CommandList", pList);
}
PlCmdInfo info;
info.pInfo = pInfo;
info.type = Cmd_Server;
info.pHook = pHook;
AddToPlCmdList(pList, info);
pInfo->hooks.append(pHook);
RegisterInPlugin(pHook);
return true;
}
void RegisterInPlugin(CmdHook *hook)
void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info)
{
PluginHookList *pList;
CmdList::iterator iter = pList->begin();
bool inserted = false;
const char *orig = NULL;
IPlugin *pPlugin = scripts->FindPluginByContext(hook->pf->GetParentContext());
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new PluginHookList();
pPlugin->SetProperty("CommandList", pList);
}
const char *orig = hook->info->pCmd->GetName();
orig = info.pInfo->pCmd->GetName();
/* Insert this into the help list, SORTED alphabetically. */
PluginHookList::iterator iter = pList->begin();
while (iter != pList->end())
{
const char *cmd = (*iter)->info->pCmd->GetName();
PlCmdInfo &obj = (*iter);
const char *cmd = obj.pInfo->pCmd->GetName();
if (strcmp(orig, cmd) < 0)
{
pList->insertBefore(iter, hook);
return;
pList->insert(iter, info);
inserted = true;
break;
}
iter++;
}
pList->append(hook);
if (!inserted)
{
pList->push_back(info);
}
}
void ConCmdManager::AddToCmdList(ConCmdInfo *info)
@@ -493,40 +738,64 @@ void ConCmdManager::AddToCmdList(ConCmdInfo *info)
void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove)
{
ConCmdInfo *pInfo;
if (type == Override_Command)
{
ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(cmd, &pInfo))
return;
for (CmdHookList::iterator iter = pInfo->hooks.begin(); iter != pInfo->hooks.end(); iter++)
if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
{
if (!iter->admin)
continue;
return;
}
if (!remove)
iter->admin->eflags = bits;
else
iter->admin->eflags = iter->admin->flags;
pInfo->eflags = iter->admin->eflags;
List<CmdHook *>::iterator iter;
CmdHook *pHook;
for (iter=pInfo->conhooks.begin(); iter!=pInfo->conhooks.end(); iter++)
{
pHook = (*iter);
if (pHook->pAdmin)
{
if (!remove)
{
pHook->pAdmin->eflags = bits;
} else {
pHook->pAdmin->eflags = pHook->pAdmin->flags;
}
pInfo->admin = *(pHook->pAdmin);
}
}
}
else if (type == Override_CommandGroup)
{
GroupMap::Result r = m_CmdGrps.find(cmd);
if (!r.found())
return;
Ref<CommandGroup> group(r->value);
for (PluginHookList::iterator iter = group->hooks.begin(); iter != group->hooks.end(); iter++)
void *object;
if (!sm_trie_retrieve(m_pCmdGrps, cmd, &object))
{
CmdHook *hook = *iter;
if (remove)
hook->admin->eflags = bits;
else
hook->admin->eflags = hook->admin->flags;
hook->info->eflags = hook->admin->eflags;
return;
}
int grpid = (int)object;
/* This is bad :( loop through all commands */
List<ConCmdInfo *>::iterator iter;
CmdHook *pHook;
for (iter=m_CmdList.begin(); iter!=m_CmdList.end(); iter++)
{
pInfo = (*iter);
for (List<CmdHook *>::iterator citer=pInfo->conhooks.begin();
citer!=pInfo->conhooks.end();
citer++)
{
pHook = (*citer);
if (pHook->pAdmin && pHook->pAdmin->cmdGrpId == grpid)
{
if (remove)
{
pHook->pAdmin->eflags = bits;
} else {
pHook->pAdmin->eflags = pHook->pAdmin->flags;
}
pInfo->admin = *(pHook->pAdmin);
}
}
}
}
}
@@ -534,7 +803,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_read_safe, bool untrack)
{
/* Remove from the trie */
m_Cmds.remove(name);
sm_trie_delete(m_pCmds, name);
/* Remove console-specific information
* This should always be true as of right now
@@ -557,7 +826,7 @@ void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_rea
if (is_read_safe)
{
/* Remove the external hook */
SH_REMOVE_HOOK(ConCommand, Dispatch, info->pCmd, SH_STATIC(CommandCallback), false);
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, info->pCmd, CommandCallback, false);
}
if (untrack)
{
@@ -575,26 +844,33 @@ void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_rea
bool ConCmdManager::LookForSourceModCommand(const char *cmd)
{
ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(cmd, &pInfo))
return false;
return pInfo->sourceMod && !pInfo->hooks.empty();
if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
{
return false;
}
return pInfo->sourceMod && (pInfo->conhooks.size() > 0);
}
bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
{
ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(cmd, &pInfo))
return false;
*pFlags = pInfo->eflags;
if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
{
return false;
}
*pFlags = pInfo->admin.eflags;
return true;
}
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
{
ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(name, &pInfo))
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
{
ConCmdList::iterator item = FindInList(name);
if (item != m_CmdList.end())
@@ -621,12 +897,12 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
else
{
TrackConCommandBase(pCmd, this);
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CommandCallback), false);
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CommandCallback, false);
}
pInfo->pCmd = pCmd;
m_Cmds.insert(name, pInfo);
sm_trie_insert(m_pCmds, name, pInfo);
AddToCmdList(pInfo);
}
@@ -639,7 +915,7 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
{
const char *text = command.Arg(2);
IPlugin *pPlugin = scripts->FindPluginByConsoleArg(text);
CPlugin *pPlugin = g_PluginSys.FindPluginByConsoleArg(text);
if (!pPlugin)
{
@@ -650,36 +926,46 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo();
const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename();
PluginHookList *pList;
CmdList *pList;
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
return;
}
if (pList->empty())
if (!pList->size())
{
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
return;
}
CmdList::iterator iter;
const char *type = NULL;
const char *name;
const char *help;
g_RootMenu.ConsolePrint("[SM] Listing commands for: %s", plname);
g_RootMenu.ConsolePrint("[SM] Listing %d commands for: %s", pList->size(), plname);
g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
for (PluginHookList::iterator iter = pList->begin(); iter != pList->end(); iter++)
for (iter=pList->begin();
iter!=pList->end();
iter++)
{
CmdHook *hook = *iter;
if (hook->type == CmdHook::Server)
PlCmdInfo &cmd = (*iter);
if (cmd.type == Cmd_Server)
{
type = "server";
else
type = hook->info->eflags == 0 ? "console" : "admin";
name = hook->info->pCmd->GetName();
if (hook->helptext.length())
help = hook->helptext.chars();
}
else if (cmd.type == Cmd_Admin)
{
type = (cmd.pInfo->admin.eflags == 0)?"console":"admin";
}
name = cmd.pInfo->pCmd->GetName();
if (cmd.pHook->helptext.size())
{
help = cmd.pHook->helptext.c_str();
}
else
help = hook->info->pCmd->GetHelpText();
{
help = cmd.pInfo->pCmd->GetHelpText();
}
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
}
+30 -46
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,77 +34,60 @@
#include "sm_globals.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_string.h>
#include <IRootConsoleMenu.h>
#include <IAdminSystem.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;
struct CmdHook;
struct ConCmdInfo;
struct CommandGroup : public ke::Refcounted<CommandGroup>
enum CmdType
{
ke::LinkedList<CmdHook *> hooks;
Cmd_Server,
Cmd_Admin,
};
struct AdminCmdInfo
{
AdminCmdInfo(const ke::Ref<CommandGroup> &group, FlagBits flags)
: group(group),
flags(flags),
eflags(0)
AdminCmdInfo()
{
cmdGrpId = -1;
flags = 0;
eflags = 0;
}
ke::Ref<CommandGroup> group;
int cmdGrpId; /* index into cmdgroup string table */
FlagBits flags; /* default flags */
FlagBits eflags; /* effective flags */
};
struct CmdHook : public ke::InlineListNode<CmdHook>
struct CmdHook
{
enum Type {
Server,
Client
};
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description)
: type(type),
info(cmd),
pf(fun),
helptext(description)
CmdHook()
{
pf = NULL;
pAdmin = NULL;
}
Type type;
ConCmdInfo *info;
IPluginFunction *pf; /* function hook */
ke::AString helptext; /* help text */
ke::AutoPtr<AdminCmdInfo> admin; /* admin requirements, if any */
IPluginFunction *pf; /* function hook */
String helptext; /* help text */
AdminCmdInfo *pAdmin; /* admin requirements, if any */
};
typedef ke::InlineList<CmdHook> CmdHookList;
struct ConCmdInfo
{
ConCmdInfo()
{
sourceMod = false;
pCmd = NULL;
eflags = 0;
}
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
ConCommand *pCmd; /**< Pointer to the command itself */
CmdHookList hooks; /**< Hook list */
FlagBits eflags; /**< Effective admin flags */
List<CmdHook *> srvhooks; /**< Hooks as a server command */
List<CmdHook *> conhooks; /**< Hooks as a console command */
AdminCmdInfo admin; /**< Admin info, if any */
};
typedef List<ConCmdInfo *> ConCmdList;
@@ -115,9 +98,7 @@ class ConCmdManager :
public IPluginsListener,
public IConCommandTracker
{
#if SOURCE_ENGINE == SE_DOTA
friend void CommandCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
friend void CommandCallback(const CCommand &command);
#else
friend void CommandCallback();
@@ -146,6 +127,8 @@ public:
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool LookForSourceModCommand(const char *cmd);
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits flags);
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
private:
void InternalDispatch(const CCommand &command);
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
@@ -153,6 +136,8 @@ private:
void SetCommandClient(int client);
void AddToCmdList(ConCmdInfo *info);
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);
// Case insensitive
@@ -170,12 +155,11 @@ public:
return m_CmdList;
}
private:
typedef StringHashMap<ke::Ref<CommandGroup> > GroupMap;
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
GroupMap m_CmdGrps; /* command group map */
Trie *m_pCmds; /* command lookup */
Trie *m_pCmdGrps; /* command group lookup */
ConCmdList m_CmdList; /* command list */
int m_CmdClient; /* current client */
BaseStringTable m_Strings; /* string table */
};
extern ConCmdManager g_ConCmds;
+56 -83
View File
@@ -29,31 +29,34 @@
#include "ConVarManager.h"
#include "HalfLife2.h"
#include "PluginSys.h"
#include "ForwardSys.h"
#include "HandleSys.h"
#include "sm_srvcmds.h"
#include "sm_stringutil.h"
#include <sh_vector.h>
#include <sm_namehashset.h>
#include "logic_bridge.h"
#include <sm_trie_tpl.h>
ConVarManager g_ConVarManager;
#if SOURCE_ENGINE <= SE_DARKMESSIAH
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
#endif
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
#else
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *);
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
#endif
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
#elif SOURCE_ENGINE != SE_DARKMESSIAH
#if SOURCE_ENGINE != SE_DARKMESSIAH
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
#endif
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
typedef List<const ConVar *> ConVarList;
NameHashSet<ConVarInfo *> convar_cache;
KTrie<ConVarInfo *> convar_cache;
class ConVarReentrancyGuard
{
@@ -107,7 +110,7 @@ void ConVarManager::OnSourceModStartup(bool late)
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
/* 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()
@@ -118,20 +121,16 @@ void ConVarManager::OnSourceModAllInitialized()
#if SOURCE_ENGINE == SE_EPISODEONE
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;
}
#endif
g_Players.AddClientListener(this);
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
#else
SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
#endif
SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
scripts->AddPluginsListener(this);
g_PluginSys.AddPluginsListener(this);
/* Add the 'convars' option to the 'sm' console command */
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
@@ -149,10 +148,10 @@ void ConVarManager::OnSourceModShutdown()
iter = m_ConVars.erase(iter);
handlesys->FreeHandle(pInfo->handle, &sec);
g_HandleSys.FreeHandle(pInfo->handle, &sec);
if (pInfo->pChangeForward != NULL)
{
forwardsys->ReleaseForward(pInfo->pChangeForward);
g_Forwards.ReleaseForward(pInfo->pChangeForward);
}
if (pInfo->sourceMod)
{
@@ -184,33 +183,27 @@ void ConVarManager::OnSourceModShutdown()
/* Unhook things */
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;
}
else if (m_bIsVSPQueryHooked)
{
#if SOURCE_ENGINE != SE_DOTA
SH_REMOVE_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
#endif
SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsVSPQueryHooked = false;
}
#endif
g_Players.RemoveClientListener(this);
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
#else
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
#endif
SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
/* Remove the 'convars' option from the 'sm' console command */
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
scripts->RemovePluginsListener(this);
g_PluginSys.RemovePluginsListener(this);
/* Remove the 'ConVar' handle type */
handlesys->RemoveType(m_ConVarType, g_pCoreIdent);
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
}
/**
@@ -240,15 +233,24 @@ void ConVarManager::OnSourceModVSPReceived()
}
#endif
#if SOURCE_ENGINE != SE_DARKMESSIAH && SOURCE_ENGINE != SE_DOTA
SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
#if SOURCE_ENGINE != SE_DARKMESSIAH
SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsVSPQueryHooked = true;
#endif
}
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)
@@ -267,7 +269,7 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
convar_cache.remove(name);
/* 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())
{
IPlugin *pl = pl_iter->GetPlugin();
@@ -283,7 +285,7 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
}
/* Free resources */
handlesys->FreeHandle(pInfo->handle, &sec);
g_HandleSys.FreeHandle(pInfo->handle, &sec);
delete pInfo;
}
@@ -298,19 +300,14 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
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();)
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++)
{
ConVarQuery &query = (*iter);
if (query.pCallback->GetParentRuntime() == pRuntime)
if (query.pCallback->GetParentRuntime() == plugin->GetRuntime())
{
iter = m_ConVarQueries.erase(iter);
continue;
m_ConVarQueries.erase(iter);
}
++iter;
}
}
@@ -356,7 +353,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
}
/* Get plugin object */
IPlugin *plugin = scripts->FindPluginByConsoleArg(arg);
CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
if (!plugin)
{
@@ -437,7 +434,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
pInfo->pVar = pConVar;
/* 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)
{
delete pInfo;
@@ -468,7 +465,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
pInfo->pChangeForward = NULL;
/* 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)
{
delete pInfo;
@@ -497,13 +494,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
ConVarInfo *pInfo;
Handle_t hndl;
/* Check convar cache to find out if we already have a handle */
if (convar_cache_lookup(name, &pInfo))
{
return pInfo->handle;
}
/* Couldn't find it in cache, so search for it */
/* Search for convar */
pConVar = icvar->FindVar(name);
/* If it doesn't exist, then return an invalid handle */
@@ -512,6 +503,12 @@ Handle_t ConVarManager::FindConVar(const char *name)
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 */
pInfo = new ConVarInfo();
pInfo->sourceMod = false;
@@ -519,7 +516,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
pInfo->pVar = pConVar;
/* 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)
{
delete pInfo;
@@ -577,7 +574,7 @@ void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction
/* If forward does not exist, create it */
if (!pForward)
{
pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
pInfo->pChangeForward = pForward;
}
@@ -617,7 +614,7 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
!ConVarReentrancyGuard::IsCvarInChain(pConVar))
{
/* Free this forward */
forwardsys->ReleaseForward(pForward);
g_Forwards.ReleaseForward(pForward);
pInfo->pChangeForward = NULL;
}
}
@@ -631,28 +628,19 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
/* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
if (m_bIsDLLQueryHooked)
{
#if SOURCE_ENGINE == SE_DOTA
cookie = engine->StartQueryCvarValue(CEntityIndex(IndexOfEdict(pPlayer)), name);
#else
cookie = engine->StartQueryCvarValue(pPlayer, name);
#endif
}
#if SOURCE_ENGINE != SE_DOTA
else if (m_bIsVSPQueryHooked)
{
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
}
#endif
else
{
return InvalidQueryCvarCookie;
}
if (pCallback != NULL)
{
ConVarQuery query = { cookie, pCallback, (cell_t) hndl, IndexOfEdict(pPlayer) };
m_ConVarQueries.push_back(query);
}
ConVarQuery query = {cookie, pCallback, (cell_t)hndl, IndexOfEdict(pPlayer)};
m_ConVarQueries.push_back(query);
#endif
return cookie;
@@ -665,7 +653,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
bool inserted = false;
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 */
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
@@ -750,19 +738,8 @@ bool ConVarManager::IsQueryingSupported()
}
#if SOURCE_ENGINE != SE_DARKMESSIAH
#if SOURCE_ENGINE == SE_DOTA
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
#else
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
#endif // SE_DOTA
{
#if SOURCE_ENGINE == SE_CSGO
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
{
return;
}
#endif
IPluginFunction *pCallback = NULL;
cell_t value = 0;
List<ConVarQuery>::iterator iter;
@@ -783,11 +760,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
cell_t ret;
pCallback->PushCell(cookie);
#if SOURCE_ENGINE == SE_DOTA
pCallback->PushCell(player.Get());
#else
pCallback->PushCell(IndexOfEdict(pPlayer));
#endif
pCallback->PushCell(result);
pCallback->PushString(cvarName);
@@ -813,7 +786,7 @@ HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
ConVarInfo *pInfo;
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;
}
+2 -10
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -67,11 +67,6 @@ struct ConVarInfo
IChangeableForward *pChangeForward; /**< Forward associated with convar */
ConVar *pVar; /**< The actual convar */
List<IConVarChangeListener *> changeListeners;
static inline bool matches(const char *name, const ConVarInfo *info)
{
return strcmp(name, info->pVar->GetName()) == 0;
}
};
/**
@@ -165,10 +160,7 @@ private:
/**
* 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
#if SOURCE_ENGINE != SE_DARKMESSIAH
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue);
#endif
+46 -38
View File
@@ -49,8 +49,7 @@
#include "ConCmdManager.h"
#include "HalfLife2.h"
#include "ConCommandBaseIterator.h"
#include "logic_bridge.h"
#include <am-utility.h>
#include "ShareSys.h"
#if defined PLATFORM_POSIX
# include <dlfcn.h>
@@ -60,9 +59,7 @@
#endif
#if SH_IMPL_VERSION >= 5
# if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
# elif SOURCE_ENGINE >= SE_ORANGEBOX
# if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
# else
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
@@ -134,9 +131,7 @@ class GenericCommandHooker : public IConCommandLinkListener
}
}
# if SOURCE_ENGINE == SE_DOTA
void Dispatch(const CCommandContext &context, const CCommand& args)
# elif SOURCE_ENGINE >= SE_ORANGEBOX
# if SOURCE_ENGINE >= SE_ORANGEBOX
void Dispatch(const CCommand& args)
# else
void Dispatch()
@@ -195,7 +190,7 @@ class GenericCommandHooker : public IConCommandLinkListener
size_t index;
if (!FindVtable(vtable, index))
{
logger->LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
return;
}
@@ -219,7 +214,7 @@ public:
if (dispatch.thisptroffs < 0)
{
logger->LogError("Command filter could not determine ConCommand layout");
g_Logger.LogError("Command filter could not determine ConCommand layout");
return false;
}
@@ -228,7 +223,7 @@ public:
if (!vtables.size())
{
logger->LogError("Command filter could not find any cvars!");
g_Logger.LogError("Command filter could not find any cvars!");
return false;
}
@@ -579,21 +574,23 @@ ConsoleDetours::ConsoleDetours() : status(FeatureStatus_Unknown)
void ConsoleDetours::OnSourceModAllInitialized()
{
m_pForward = forwardsys->CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
m_pForward = g_Forwards.CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
sharesys->AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
g_ShareSys.AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
}
void ConsoleDetours::OnSourceModShutdown()
{
for (StringHashMap<IChangeableForward *>::iterator iter = m_Listeners.iter();
!iter.empty();
iter.next())
List<Listener*>::iterator iter = m_Listeners.begin();
while (iter != m_Listeners.end())
{
forwardsys->ReleaseForward(iter->value);
Listener *listener = (*iter);
g_Forwards.ReleaseForward(listener->forward);
delete listener;
iter = m_Listeners.erase(iter);
}
forwardsys->ReleaseForward(m_pForward);
g_Forwards.ReleaseForward(m_pForward);
s_GenericHooker.Disable();
}
@@ -622,15 +619,22 @@ bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
}
else
{
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
IChangeableForward *forward;
if (!m_Listeners.retrieve(str, &forward))
const char *str = UTIL_ToLowerCase(command);
Listener *listener;
Listener **plistener = m_CmdLookup.retrieve(str);
if (plistener == NULL)
{
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
m_Listeners.insert(str, forward);
listener = new Listener;
listener->forward = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
m_CmdLookup.insert(str, listener);
}
forward->AddFunction(fun);
else
{
listener = *plistener;
}
listener->forward->AddFunction(fun);
delete [] str;
}
return true;
@@ -644,11 +648,14 @@ bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
}
else
{
ke::AutoArray<char> str(UTIL_ToLowerCase(command));
IChangeableForward *forward;
if (!m_Listeners.retrieve(str, &forward))
const char *str = UTIL_ToLowerCase(command);
Listener *listener;
Listener **plistener = m_CmdLookup.retrieve(str);
delete [] str;
if (plistener == NULL)
return false;
return forward->RemoveFunction(fun);
listener = *plistener;
return listener->forward->RemoveFunction(fun);
}
}
@@ -684,17 +691,18 @@ cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
if (result >= Pl_Handled)
return result;
IChangeableForward *forward;
if (!m_Listeners.retrieve(name, &forward))
Listener **plistener = m_CmdLookup.retrieve(name);
if (plistener == NULL)
return result;
if (forward->GetFunctionCount() == 0)
Listener *listener = *plistener;
if (listener->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);
listener->forward->PushCell(client);
listener->forward->PushString(name);
listener->forward->PushCell(args.ArgC() - 1);
listener->forward->Execute(&result2, NULL);
if (result2 > result)
result = result2;
@@ -723,10 +731,10 @@ cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
/* 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);
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
dummy_hook_set = true;
pBase->Dispatch();
SH_REMOVE_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false);
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
}
else
{
+8 -3
View File
@@ -33,8 +33,8 @@
#include "sm_globals.h"
#include "sourcemm_api.h"
#include <IForwardSys.h>
#include <sm_stringhashmap.h>
#include "ForwardSys.h"
#include <sm_trie_tpl.h>
class ConsoleDetours :
public SMGlobalClass,
@@ -43,6 +43,10 @@ class ConsoleDetours :
friend class PlayerManager;
friend class GenericCommandHooker;
struct Listener
{
IChangeableForward *forward;
};
public:
ConsoleDetours();
public: //SMGlobalClass
@@ -69,7 +73,8 @@ public:
private:
FeatureStatus status;
IChangeableForward *m_pForward;
StringHashMap<IChangeableForward *> m_Listeners;
KTrie<Listener*> m_CmdLookup;
List<Listener*> m_Listeners;
};
extern ConsoleDetours g_ConsoleDetours;
+36 -36
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,12 +34,13 @@
#include "sourcemod.h"
#include "sourcemm_api.h"
#include "sm_srvcmds.h"
#include <sourcemod_version.h>
#include "sm_stringutil.h"
#include "LibrarySys.h"
#include "Logger.h"
#include "PluginSys.h"
#include "ForwardSys.h"
#include "frame_hooks.h"
#include "logic_bridge.h"
#include <sourcemod_version.h>
#ifdef PLATFORM_WINDOWS
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
@@ -60,10 +61,7 @@ ConVar *g_ServerCfgFile = NULL;
void CheckAndFinalizeConfigs();
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
void Hook_ExecDispatchPre(const CCommandContext &context, const CCommand &cmd)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
void Hook_ExecDispatchPre(const CCommand &cmd)
#elif SOURCE_ENGINE == SE_DARKMESSIAH
@@ -91,9 +89,7 @@ void Hook_ExecDispatchPre()
}
}
#if SOURCE_ENGINE == SE_DOTA
void Hook_ExecDispatchPost(const CCommandContext &context, const CCommand &cmd)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void Hook_ExecDispatchPost(const CCommand &cmd)
#else
void Hook_ExecDispatchPost()
@@ -118,12 +114,12 @@ void CheckAndFinalizeConfigs()
void CoreConfig::OnSourceModAllInitialized()
{
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
g_pOnServerCfg = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
g_pOnConfigsExecuted = g_Forwards.CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
g_pOnAutoConfigsBuffered = g_Forwards.CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
}
CoreConfig::CoreConfig()
CoreConfig::CoreConfig() : m_Strings(512)
{
}
@@ -134,14 +130,14 @@ CoreConfig::~CoreConfig()
void CoreConfig::OnSourceModShutdown()
{
g_RootMenu.RemoveRootConsoleCommand("config", this);
forwardsys->ReleaseForward(g_pOnServerCfg);
forwardsys->ReleaseForward(g_pOnConfigsExecuted);
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered);
g_Forwards.ReleaseForward(g_pOnServerCfg);
g_Forwards.ReleaseForward(g_pOnConfigsExecuted);
g_Forwards.ReleaseForward(g_pOnAutoConfigsBuffered);
if (g_pExecPtr != NULL)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false);
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true);
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
g_pExecPtr = NULL;
}
}
@@ -166,8 +162,8 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName)
g_pExecPtr = FindCommand("exec");
if (g_pExecPtr != NULL)
{
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false);
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true);
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
}
else
{
@@ -256,13 +252,14 @@ void CoreConfig::Initialize()
/* Reset cached key values */
m_KeyValues.clear();
m_Strings.Reset();
/* Parse config file */
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
{
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
const char *error = textparsers->GetSMCErrorString(err);
logger->LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
}
}
@@ -274,7 +271,7 @@ SMCResult CoreConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key,
if (err == ConfigResult_Reject)
{
/* This is a fatal error */
logger->LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
}
return SMCResult_Continue;
@@ -295,18 +292,19 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
pBase = pBase->m_pGlobalClassNext;
}
ke::AString vstr(value);
m_KeyValues.replace(option, ke::Move(vstr));
m_KeyValues.replace(option, m_Strings.AddString(value));
return ConfigResult_Ignore;
}
const char *CoreConfig::GetCoreConfigValue(const char *key)
{
StringHashMap<ke::AString>::Result r = m_KeyValues.find(key);
if (!r.found())
int *pKey = m_KeyValues.retrieve(key);
if (pKey == NULL)
{
return NULL;
return r->value.chars();
}
return m_Strings.GetString(*pKey);
}
bool SM_AreConfigsExecuted()
@@ -323,7 +321,7 @@ inline bool IsPathSepChar(char c)
#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;
@@ -469,7 +467,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
}
else
{
logger->LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
return can_create;
}
}
@@ -502,10 +500,10 @@ void SM_DoSingleExecFwds(IPluginContext *ctx)
void SM_ConfigsExecuted_Plugin(unsigned int serial)
{
IPluginIterator *iter = scripts->GetPluginIterator();
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
while (iter->MorePlugins())
{
IPlugin *plugin = iter->GetPlugin();
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
if (plugin->GetSerial() == serial)
{
SM_DoSingleExecFwds(plugin->GetBaseContext());
@@ -518,7 +516,7 @@ void SM_ConfigsExecuted_Plugin(unsigned int serial)
void SM_ExecuteForPlugin(IPluginContext *ctx)
{
SMPlugin *plugin = scripts->FindPluginByContext(ctx->GetContext());
CPlugin *plugin = (CPlugin *)g_PluginSys.GetPluginByCtx(ctx->GetContext());
unsigned int num = plugin->GetConfigCount();
if (!num)
@@ -547,17 +545,19 @@ void SM_ExecuteAllConfigs()
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
AutoPluginList plugins(scripts);
for (size_t i = 0; i < plugins->size(); i++)
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
while (iter->MorePlugins())
{
SMPlugin *plugin = plugins->at(i);
CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
unsigned int num = plugin->GetConfigCount();
bool can_create = true;
for (unsigned int i=0; i<num; i++)
{
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
}
iter->NextPlugin();
}
iter->Release();
g_bGotServerStart = true;
CheckAndFinalizeConfigs();
+5 -4
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -35,8 +35,8 @@
#include "sm_globals.h"
#include <ITextParsers.h>
#include <IRootConsoleMenu.h>
#include <am-string.h>
#include <sm_stringhashmap.h>
#include <sm_trie_tpl.h>
#include "sm_memtable.h"
using namespace SourceMod;
@@ -68,7 +68,8 @@ private:
*/
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
private:
StringHashMap<ke::AString> m_KeyValues;
BaseStringTable m_Strings;
KTrie<int> m_KeyValues;
};
extern bool SM_AreConfigsExecuted();
+89 -105
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,10 +30,12 @@
*/
#include "Database.h"
#include "ISourceMod.h"
#include "HandleSys.h"
#include "ShareSys.h"
#include "sourcemod.h"
#include "sm_stringutil.h"
#include "Logger.h"
#include "ExtensionSys.h"
#include "PluginSys.h"
#include <stdlib.h>
#include <IThreader.h>
@@ -45,18 +47,10 @@ DBManager g_DBMan;
static bool s_OneTimeThreaderErrorMsg = false;
DBManager::DBManager()
: m_Terminate(false),
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()
{
HandleAccess sec;
@@ -70,11 +64,13 @@ void DBManager::OnSourceModAllInitialized()
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_pSM->AddGameFrameHook(&FrameHook);
}
void DBManager::OnSourceModLevelChange(const char *mapName)
@@ -86,23 +82,26 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
* This way the thread's search won't be searching through a
* potentially empty/corrupt list, which would be very bad.
*/
ke::AutoLock lock(&m_ConfigLock);
m_pConfigLock->Lock();
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
{
logger->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)
{
const char *txt = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Line %d: %s", states.line, txt);
g_Logger.LogError("[SM] Line %d: %s", states.line, txt);
}
}
m_pConfigLock->Unlock();
}
void DBManager::OnSourceModShutdown()
{
g_pSM->RemoveGameFrameHook(&FrameHook);
KillWorkerThread();
g_PluginSys.RemovePluginsListener(this);
m_pConfigLock->DestroyThis();
m_pThinkLock->DestroyThis();
m_pQueueLock->DestroyThis();
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
ClearConfigs();
@@ -271,7 +270,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
*pdr = NULL;
}
*pdb = NULL;
g_pSM->Format(error, maxlength, "Configuration \"%s\" not found", name);
UTIL_Format(error, maxlength, "Configuration \"%s\" not found", name);
return false;
}
@@ -308,7 +307,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
}
*pdb = NULL;
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname);
UTIL_Format(error, maxlength, "Driver \"%s\" not found", dname);
return false;
}
@@ -353,12 +352,6 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
}
}
/* 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.
* Whatever happens therein is up to the db op!
*/
@@ -490,7 +483,7 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
}
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);
if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size)
@@ -511,17 +504,12 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
void DBManager::KillWorkerThread()
{
if (m_Worker)
if (m_pWorker)
{
{
ke::AutoLock lock(&m_QueueEvent);
m_Terminate = true;
m_QueueEvent.Notify();
}
m_Worker->Join();
m_Worker = NULL;
m_pWorker->Stop(false);
g_pThreader->DestroyWorker(m_pWorker);
m_pWorker = NULL;
s_OneTimeThreaderErrorMsg = false;
m_Terminate = false;
}
}
@@ -534,106 +522,99 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
return false;
}
if (!m_Worker)
if (!m_pWorker)
{
m_Worker = new ke::Thread(this, "SM SQL Worker");
if (!m_Worker->Succeeded())
m_pWorker = g_pThreader->MakeWorker(this, true);
if (!m_pWorker)
{
if (!s_OneTimeThreaderErrorMsg)
{
logger->LogError("[SM] Unable to create db threader (error unknown)");
g_Logger.LogError("[SM] Unable to create db threader (error unknown)");
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;
}
}
/* Add to the queue */
{
ke::AutoLock lock(&m_QueueEvent);
m_pQueueLock->Lock();
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio);
queue.push(op);
m_QueueEvent.Notify();
m_pQueueLock->Unlock();
}
/* Make the thread */
m_pWorker->MakeThread(this);
return true;
}
void DBManager::Run()
void DBManager::OnWorkerStart(IThreadWorker *pWorker)
{
// Initialize DB threadsafety.
for (size_t i=0; i < m_drivers.size(); i++)
m_drSafety.clear();
for (size_t i=0; i<m_drivers.size(); i++)
{
if (m_drivers[i]->IsThreadSafe())
{
m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety());
else
} else {
m_drSafety.push_back(false);
}
}
}
// Run actual worker thread logic.
ThreadMain();
// Shutdown DB threadsafety.
void DBManager::OnWorkerStop(IThreadWorker *pWorker)
{
for (size_t i=0; i<m_drivers.size(); i++)
{
if (m_drSafety[i])
{
m_drivers[i]->ShutdownThreadSafety();
}
}
m_drSafety.clear();
}
void DBManager::ThreadMain()
void DBManager::RunThread(IThreadHandle *pThread)
{
ke::AutoLock lock(&m_QueueEvent);
IDBThreadOperation *op = NULL;
while (true) {
// 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,
// we process all operations we can before checking to terminate.
// There's no risk of starvation since the main thread blocks on us
// terminating.
while (true)
/* Get something from the queue */
{
m_pQueueLock->Lock();
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
if (!queue.empty())
{
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
if (queue.empty())
break;
IDBThreadOperation *op = queue.first();
op = queue.first();
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
}
}
if (m_Terminate)
return;
// Release the lock and wait for a signal.
m_QueueEvent.Wait();
m_pQueueLock->Unlock();
}
/* 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()
@@ -645,16 +626,19 @@ void DBManager::RunFrame()
}
/* Dump one thing per-frame so the server stays sane. */
IDBThreadOperation *op;
{
ke::AutoLock lock(&m_ThinkLock);
op = m_ThinkQueue.first();
m_ThinkQueue.pop();
}
m_pThinkLock->Lock();
IDBThreadOperation *op = m_ThinkQueue.first();
m_ThinkQueue.pop();
m_pThinkLock->Unlock();
op->RunThinkPart();
op->Destroy();
}
void DBManager::OnTerminate(IThreadHandle *pThread, bool cancel)
{
/* Do nothing */
}
void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
{
s_pAddBlock = pToken;
@@ -730,12 +714,12 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
void DBManager::LockConfig()
{
m_ConfigLock.Lock();
m_pConfigLock->Lock();
}
void DBManager::UnlockConfig()
{
m_ConfigLock.Unlock();
m_pConfigLock->Unlock();
}
const char *DBManager::GetDefaultDriverName()
+17 -14
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -33,15 +33,15 @@
#define _INCLUDE_DATABASE_MANAGER_H_
#include <IDBDriver.h>
#include "common_logic.h"
#include "sm_globals.h"
#include <sh_vector.h>
#include <sh_string.h>
#include <sh_list.h>
#include <ITextParsers.h>
#include "sm_memtable.h"
#include <IThreader.h>
#include <IPluginSys.h>
#include <am-thread-utils.h>
#include "sm_simple_prioqueue.h"
#include "PluginSys.h"
using namespace SourceHook;
@@ -65,8 +65,9 @@ class DBManager :
public SMGlobalClass,
public IHandleTypeDispatch,
public ITextListener_SMC,
public IPluginsListener,
public ke::IRunnable
public IThread,
public IThreadWorkerCallbacks,
public IPluginsListener
{
public:
DBManager();
@@ -97,9 +98,12 @@ public: //ITextListener_SMC
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
void ReadSMC_ParseEnd(bool halted, bool failed);
public: //ke::IRunnable
void Run();
void ThreadMain();
public: //IThread
void RunThread(IThreadHandle *pThread);
void OnTerminate(IThreadHandle *pThread, bool cancel);
public: //IThreadWorkerCallbacks
void OnWorkerStart(IThreadWorker *pWorker);
void OnWorkerStop(IThreadWorker *pWorker);
public: //IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public:
@@ -125,11 +129,10 @@ private:
PrioQueue<IDBThreadOperation *> m_OpQueue;
Queue<IDBThreadOperation *> m_ThinkQueue;
CVector<bool> m_drSafety; /* which drivers are safe? */
ke::AutoPtr<ke::Thread> m_Worker;
ke::ConditionVariable m_QueueEvent;
ke::Mutex m_ConfigLock;
ke::Mutex m_ThinkLock;
bool m_Terminate;
IThreadWorker *m_pWorker; /* Worker thread object */
IMutex *m_pConfigLock; /* Configuration lock */
IMutex *m_pQueueLock; /* Queue safety lock */
IMutex *m_pThinkLock; /* Think-queue lock */
List<ConfDbInfo *> m_confs;
HandleType_t m_DriverType;
@@ -29,10 +29,10 @@
* Version: $Id$
*/
#include <IPluginSys.h>
#include <stdarg.h>
#include "DebugReporter.h"
#include "Logger.h"
#include "PluginSys.h"
#include "sm_stringutil.h"
DebugReport g_DbgReporter;
@@ -47,7 +47,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
char buffer[512];
va_start(ap, msg);
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
va_end(ap);
g_Logger.LogMessage("[SM] %s", buffer);
@@ -65,9 +65,9 @@ void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, c
void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap)
{
char buffer[512];
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
const char *error = g_pSourcePawn2->GetErrorString(err);
if (error)
@@ -99,10 +99,10 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
char buffer[512];
va_start(ap, message);
smcore.FormatArgs(buffer, sizeof(buffer), message, ap);
UTIL_FormatArgs(buffer, sizeof(buffer), message, 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);
if (error)
@@ -135,7 +135,7 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
{
const char *lastname;
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename();
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
int n_err = error->GetErrorCode();
if (n_err != SP_ERROR_NATIVE)
@@ -180,7 +180,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
int DebugReport::_GetPluginIndex(IPluginContext *ctx)
{
int id = 1;
IPluginIterator *iter = pluginsys->GetPluginIterator();
IPluginIterator *iter = g_PluginSys.GetPluginIterator();
for (; iter->MorePlugins(); iter->NextPlugin(), id++)
{
@@ -196,6 +196,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. */
return pluginsys->GetPluginCount() + 1;
return g_PluginSys.GetPluginCount() + 1;
}
@@ -33,7 +33,7 @@
#define _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
#include "sp_vm_api.h"
#include "common_logic.h"
#include "sm_globals.h"
class DebugReport :
public SMGlobalClass,
+39 -29
View File
@@ -30,8 +30,10 @@
*/
#include "EventManager.h"
#include "ForwardSys.h"
#include "HandleSys.h"
#include "PluginSys.h"
#include "sm_stringutil.h"
#include "logic_bridge.h"
EventManager g_EventManager;
@@ -56,10 +58,14 @@ public:
EventManager::EventManager() : m_EventType(0)
{
/* Create an event lookup trie */
m_EventHooks = sm_trie_create();
}
EventManager::~EventManager()
{
sm_trie_destroy(m_EventHooks);
/* Free memory used by EventInfo structs if any */
CStack<EventInfo *>::iterator iter;
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
@@ -73,8 +79,8 @@ EventManager::~EventManager()
void EventManager::OnSourceModAllInitialized()
{
/* Add a hook for IGameEventManager2::FireEvent() */
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(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, false);
SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
HandleAccess sec;
@@ -84,17 +90,17 @@ void EventManager::OnSourceModAllInitialized()
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
/* 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()
{
/* Remove hook for IGameEventManager2::FireEvent() */
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(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, false);
SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
/* Remove the 'GameEvent' handle type */
handlesys->RemoveType(m_EventType, g_pCoreIdent);
g_HandleSys.RemoveType(m_EventType, g_pCoreIdent);
/* Remove ourselves as listener for events */
gameevents->RemoveListener(this);
@@ -132,12 +138,12 @@ void EventManager::OnPluginUnloaded(IPlugin *plugin)
{
if (pHook->pPreHook)
{
forwardsys->ReleaseForward(pHook->pPreHook);
g_Forwards.ReleaseForward(pHook->pPreHook);
}
if (pHook->pPostHook)
{
forwardsys->ReleaseForward(pHook->pPostHook);
g_Forwards.ReleaseForward(pHook->pPostHook);
}
delete pHook;
@@ -155,7 +161,7 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
}
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
#if SOURCE_ENGINE >= SE_LEFT4DEAD
int EventManager::GetEventDebugID()
{
return EVENT_DEBUG_ID_INIT;
@@ -178,10 +184,10 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
}
/* If a hook structure does not exist... */
if (!m_EventHooks.retrieve(name, &pHook))
if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
{
EventHookList *pHookList;
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext());
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Check plugin for an existing EventHook list */
if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
@@ -196,12 +202,12 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
if (mode == EventHookMode_Pre)
{
/* 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 */
pHook->pPreHook->AddFunction(pFunction);
} else {
/* 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? */
pHook->postCopy = (mode == EventHookMode_Post);
/* Add to forward list */
@@ -209,14 +215,14 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
}
/* Cache the name for post hooks */
pHook->name = name;
pHook->name = sm_strdup(name);
/* Increase reference count */
pHook->refCount++;
/* Add hook structure to hook lists */
pHookList->push_back(pHook);
m_EventHooks.insert(name, pHook);
sm_trie_insert(m_EventHooks, name, pHook);
return EventHookErr_Okay;
}
@@ -228,7 +234,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
/* Create pre hook forward if necessary */
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 */
@@ -237,7 +243,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
/* Create post hook forward if necessary */
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 */
@@ -262,7 +268,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
IChangeableForward **pEventForward;
/* 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;
}
@@ -284,7 +290,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
/* If forward's list contains 0 functions now, free it */
if ((*pEventForward)->GetFunctionCount() == 0)
{
forwardsys->ReleaseForward(*pEventForward);
g_Forwards.ReleaseForward(*pEventForward);
*pEventForward = NULL;
}
@@ -294,7 +300,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
/* If reference count is now 0, free hook structure */
EventHookList *pHookList;
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext());
IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Get plugin's event hook list */
if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
@@ -312,7 +318,10 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
pHookList->remove(pHook);
/* Delete entry in trie */
m_EventHooks.remove(name);
sm_trie_delete(m_EventHooks, name);
/* Free the cached name */
delete pHook->name;
/* And finally free structure memory */
delete pHook;
@@ -388,7 +397,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
name = pEvent->GetName();
if (m_EventHooks.retrieve(name, &pHook))
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
{
/* 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.
@@ -402,7 +411,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
{
EventInfo info(pEvent, NULL);
HandleSecurity sec(NULL, g_pCoreIdent);
Handle_t hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
info.bDontBroadcast = bDontBroadcast;
@@ -415,7 +424,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
broadcast = info.bDontBroadcast;
handlesys->FreeHandle(hndl, &sec);
g_HandleSys.FreeHandle(hndl, &sec);
}
if (pHook->postCopy)
@@ -467,14 +476,14 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
info.bDontBroadcast = bDontBroadcast;
info.pEvent = m_EventCopies.front();
info.pOwner = NULL;
hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
pForward->PushCell(hndl);
} else {
pForward->PushCell(BAD_HANDLE);
}
pForward->PushString(pHook->name.chars());
pForward->PushString(pHook->name);
pForward->PushCell(bDontBroadcast);
pForward->Execute(NULL);
@@ -482,7 +491,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{
/* Free handle */
HandleSecurity sec(NULL, g_pCoreIdent);
handlesys->FreeHandle(hndl, &sec);
g_HandleSys.FreeHandle(hndl, &sec);
/* Free event structure */
gameevents->FreeEvent(info.pEvent);
@@ -495,7 +504,8 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{
assert(pHook->pPostHook == NULL);
assert(pHook->pPreHook == NULL);
m_EventHooks.remove(pHook->name.chars());
sm_trie_delete(m_EventHooks, pHook->name);
delete pHook->name;
delete pHook;
}
}
+5 -10
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -34,7 +34,7 @@
#include "sm_globals.h"
#include "sourcemm_api.h"
#include <sm_namehashset.h>
#include "sm_trie.h"
#include <sh_list.h>
#include <sh_stack.h>
#include <IHandleSys.h>
@@ -69,12 +69,7 @@ struct EventHook
IChangeableForward *pPostHook;
bool postCopy;
unsigned int refCount;
ke::AString name;
static inline bool matches(const char *name, const EventHook *hook)
{
return strcmp(name, hook->name.chars()) == 0;
}
char *name;
};
enum EventHookMode
@@ -110,7 +105,7 @@ public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin);
public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent);
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
#if SOURCE_ENGINE >= SE_LEFT4DEAD
int GetEventDebugID();
#endif
public:
@@ -132,7 +127,7 @@ private: // IGameEventManager2 hooks
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
private:
HandleType_t m_EventType;
NameHashSet<EventHook *> m_EventHooks;
Trie *m_EventHooks;
CStack<EventInfo *> m_FreeEvents;
CStack<EventHook *> m_EventStack;
CStack<IGameEvent *> m_EventCopies;
@@ -31,11 +31,13 @@
#include <stdlib.h>
#include "ExtensionSys.h"
#include <ILibrarySys.h>
#include <ISourceMod.h>
#include "common_logic.h"
#include "PluginSys.h"
#include <am-utility.h>
#include "LibrarySys.h"
#include "ShareSys.h"
#include "Logger.h"
#include "sourcemm_api.h"
#include "sm_srvcmds.h"
#include "sm_stringutil.h"
#include "PlayerManager.h"
CExtensionManager g_Extensions;
IdentityType_t g_ExtType;
@@ -49,7 +51,7 @@ void CExtension::Initialize(const char *filename, const char *path)
m_File.assign(filename);
m_Path.assign(path);
char real_name[PLATFORM_MAX_PATH];
libsys->GetFileFromPath(real_name, sizeof(real_name), m_Path.c_str());
g_LibSys.GetFileFromPath(real_name, sizeof(real_name), m_Path.c_str());
m_RealFile.assign(real_name);
}
@@ -59,6 +61,42 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena
m_pAPI = pAPI;
}
#if defined METAMOD_PLAPI_VERSION
#if SOURCE_ENGINE == SE_LEFT4DEAD
#define GAMEFIX "2.l4d"
#elif SOURCE_ENGINE == SE_LEFT4DEAD2
#define GAMEFIX "2.l4d2"
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
#define GAMEFIX "2.nd"
#elif SOURCE_ENGINE == SE_ALIENSWARM
#define GAMEFIX "2.swarm"
#elif SOURCE_ENGINE == SE_ORANGEBOX
#define GAMEFIX "2.ep2"
#elif SOURCE_ENGINE == SE_BLOODYGOODTIME
#define GAMEFIX "2.bgt"
#elif SOURCE_ENGINE == SE_EYE
#define GAMEFIX "2.eye"
#elif SOURCE_ENGINE == SE_CSS
#define GAMEFIX "2.css"
#elif SOURCE_ENGINE == SE_HL2DM
#define GAMEFIX "2.hl2dm"
#elif SOURCE_ENGINE == SE_DODS
#define GAMEFIX "2.dods"
#elif SOURCE_ENGINE == SE_TF2
#define GAMEFIX "2.tf2"
#elif SOURCE_ENGINE == SE_DARKMESSIAH
#define GAMEFIX "2.darkm"
#elif SOURCE_ENGINE == SE_PORTAL2
#define GAMEFIX "2.portal2"
#elif SOURCE_ENGINE == SE_CSGO
#define GAMEFIX "2.csgo"
#else
#define GAMEFIX "2.ep1"
#endif //(SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2)
#else //METAMOD_PLAPI_VERSION
#define GAMEFIX "1.ep1"
#endif //METAMOD_PLAPI_VERSION
CLocalExtension::CLocalExtension(const char *filename)
{
m_PlId = 0;
@@ -73,62 +111,54 @@ CLocalExtension::CLocalExtension(const char *filename)
}
/* Zeroth, see if there is an engine specific build in the new place. */
g_pSM->BuildPath(Path_SM,
g_SourceMod.BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.%s." PLATFORM_LIB_EXT,
filename,
smcore.gamesuffix);
"extensions/%s." GAMEFIX "." PLATFORM_LIB_EXT,
filename);
if (libsys->IsPathFile(path))
if (g_LibSys.IsPathFile(path))
{
goto found;
}
#if SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
if (strcmp(smcore.gamesuffix, "2.tf2") == 0
|| strcmp(smcore.gamesuffix, "2.dods") == 0
|| strcmp(smcore.gamesuffix, "2.hl2dm") == 0
)
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
g_SourceMod.BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
if (libsys->IsPathFile(path))
{
goto found;
}
}
else if (strcmp(smcore.gamesuffix, "2.nd") == 0)
if (g_LibSys.IsPathFile(path))
{
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
if (libsys->IsPathFile(path))
{
goto found;
}
goto found;
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
g_SourceMod.BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
if (g_LibSys.IsPathFile(path))
{
goto found;
}
#endif
/* First see if there is an engine specific build! */
g_pSM->BuildPath(Path_SM,
g_SourceMod.BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/auto.%s/%s." PLATFORM_LIB_EXT,
filename,
smcore.gamesuffix);
"extensions/auto." GAMEFIX "/%s." PLATFORM_LIB_EXT,
filename);
/* Try the "normal" version */
if (!libsys->IsPathFile(path))
if (!g_LibSys.IsPathFile(path))
{
normal:
g_pSM->BuildPath(Path_SM,
g_SourceMod.BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s." PLATFORM_LIB_EXT,
@@ -158,7 +188,7 @@ bool CRemoteExtension::Load(char *error, size_t maxlength)
bool CLocalExtension::Load(char *error, size_t maxlength)
{
m_pLib = libsys->OpenLibrary(m_Path.c_str(), error, maxlength);
m_pLib = g_LibSys.OpenLibrary(m_Path.c_str(), error, maxlength);
if (m_pLib == NULL)
{
@@ -190,10 +220,24 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
/* Load as MM:S */
if (m_pAPI->IsMetamodExtension())
{
bool ok;
m_PlId = smcore.LoadMMSPlugin(m_Path.c_str(), &ok, error, maxlength);
bool already;
m_PlId = g_pMMPlugins->Load(m_Path.c_str(), g_PLID, already, error, maxlength);
if (!m_PlId || !ok)
// Check the plugin didn't refuse load
Pl_Status status;
#ifndef METAMOD_PLAPI_VERSION
const char *file;
PluginId source;
#endif
if (!m_PlId || (
#ifndef METAMOD_PLAPI_VERSION
g_pMMPlugins->Query(m_PlId, file, status, source)
#else
g_pMMPlugins->Query(m_PlId, NULL, &status, NULL)
#endif
&& status < Pl_Paused))
{
m_pLib->CloseLibrary();
m_pLib = NULL;
@@ -208,7 +252,8 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
{
if (m_PlId)
{
smcore.UnloadMMSPlugin(m_PlId);
char dummy[255];
g_pMMPlugins->Unload(m_PlId, true, dummy, sizeof(dummy));
m_PlId = 0;
}
}
@@ -229,7 +274,8 @@ void CLocalExtension::Unload()
{
if (m_pAPI != NULL && m_PlId)
{
smcore.UnloadMMSPlugin(m_PlId);
char temp_buffer[255];
g_pMMPlugins->Unload(m_PlId, true, temp_buffer, sizeof(temp_buffer));
m_PlId = 0;
}
@@ -292,7 +338,7 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
bool CExtension::Load(char *error, size_t maxlength)
{
CreateIdentity();
if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, maxlength, !smcore.IsMapLoading()))
if (!m_pAPI->OnExtensionLoad(this, &g_ShareSys, error, maxlength, !g_SourceMod.IsMapLoading()))
{
DestroyIdentity();
return false;
@@ -300,7 +346,7 @@ bool CExtension::Load(char *error, size_t maxlength)
else
{
/* Check if we're past load time */
if (!smcore.IsMapLoading())
if (!g_SourceMod.IsMapLoading())
{
m_pAPI->OnExtensionsAllLoaded();
}
@@ -343,7 +389,7 @@ void CExtension::MarkAllLoaded()
void CExtension::AddPlugin(CPlugin *pPlugin)
{
/* Unfortunately we have to do this :( */
if (m_Dependents.find(pPlugin) == m_Dependents.end())
if (m_Dependents.find(pPlugin) != m_Dependents.end())
{
m_Dependents.push_back(pPlugin);
}
@@ -510,15 +556,14 @@ void CExtension::AddLibrary(const char *library)
void CExtensionManager::OnSourceModAllInitialized()
{
g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
pluginsys->AddPluginsListener(this);
rootmenu->AddRootConsoleCommand("exts", "Manage extensions", this);
g_PluginSys.AddPluginsListener(this);
g_RootMenu.AddRootConsoleCommand("exts", "Manage extensions", this);
g_ShareSys.AddInterface(NULL, this);
}
void CExtensionManager::OnSourceModShutdown()
{
rootmenu->RemoveRootConsoleCommand("exts", this);
pluginsys->RemovePluginsListener(this);
g_RootMenu.RemoveRootConsoleCommand("exts", this);
g_ShareSys.DestroyIdentType(g_ExtType);
}
@@ -536,11 +581,13 @@ void CExtensionManager::TryAutoload()
{
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "extensions");
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "extensions");
ke::AutoPtr<IDirectory> pDir(libsys->OpenDirectory(path));
IDirectory *pDir = g_LibSys.OpenDirectory(path);
if (!pDir)
{
return;
}
const char *lfile;
size_t len;
@@ -567,7 +614,7 @@ void CExtensionManager::TryAutoload()
}
char file[PLATFORM_MAX_PATH];
len = smcore.Format(file, sizeof(file), "%s", lfile);
len = UTIL_Format(file, sizeof(file), "%s", lfile);
strcpy(&file[len - 9], ".ext");
LoadAutoExtension(file);
@@ -579,11 +626,11 @@ void CExtensionManager::TryAutoload()
IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOnMissing)
{
/* Remove platform extension if it's there. Compat hack. */
const char *ext = libsys->GetFileExtension(path);
const char *ext = g_LibSys.GetFileExtension(path);
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{
char path2[PLATFORM_MAX_PATH];
smcore.Format(path2, sizeof(path2), "%s", path);
UTIL_Format(path2, sizeof(path2), "%s", path);
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadAutoExtension(path2, bErrorOnMissing);
}
@@ -604,11 +651,11 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
if (!p->Load(error, sizeof(error)) || !p->IsLoaded())
{
if (bErrorOnMissing || libsys->IsPathFile(p->GetPath()))
if (bErrorOnMissing || g_LibSys.IsPathFile(p->GetPath()))
{
logger->LogError("[SM] Unable to load extension \"%s\": %s", path, error);
g_Logger.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
}
p->SetError(error);
}
@@ -622,7 +669,7 @@ IExtension *CExtensionManager::FindExtensionByFile(const char *file)
/* Chomp off the path */
char lookup[PLATFORM_MAX_PATH];
libsys->GetFileFromPath(lookup, sizeof(lookup), file);
g_LibSys.GetFileFromPath(lookup, sizeof(lookup), file);
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
{
@@ -671,11 +718,11 @@ IExtension *CExtensionManager::FindExtensionByName(const char *ext)
IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size_t maxlength)
{
/* Remove platform extension if it's there. Compat hack. */
const char *ext = libsys->GetFileExtension(file);
const char *ext = g_LibSys.GetFileExtension(file);
if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{
char path2[PLATFORM_MAX_PATH];
smcore.Format(path2, sizeof(path2), "%s", file);
UTIL_Format(path2, sizeof(path2), "%s", file);
path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadExtension(path2, error, maxlength);
}
@@ -737,11 +784,11 @@ void CExtensionManager::AddInterface(IExtension *pOwner, SMInterface *pInterface
pExt->AddInterface(pInterface);
}
void CExtensionManager::BindChildPlugin(IExtension *pParent, SMPlugin *pPlugin)
void CExtensionManager::BindChildPlugin( IExtension *pParent, CPlugin *pPlugin )
{
CExtension *pExt = (CExtension *)pParent;
pExt->AddPlugin(static_cast<CPlugin *>(pPlugin));
pExt->AddPlugin(pPlugin);
}
void CExtensionManager::OnPluginDestroyed(IPlugin *plugin)
@@ -750,7 +797,7 @@ void CExtensionManager::OnPluginDestroyed(IPlugin *plugin)
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
{
(*iter)->DropRefsTo(static_cast<CPlugin *>(plugin));
(*iter)->DropRefsTo((CPlugin *)plugin);
}
}
@@ -778,21 +825,25 @@ CExtension *CExtensionManager::FindByOrder(unsigned int num)
bool CExtensionManager::UnloadExtension(IExtension *_pExt)
{
if (!_pExt)
{
return false;
}
CExtension *pExt = (CExtension *)_pExt;
if (m_Libs.find(pExt) == m_Libs.end())
{
return false;
}
/* Tell it to unload */
if (pExt->IsLoaded())
pExt->GetAPI()->OnExtensionUnload();
/* Tell it to unload */
if (pExt->IsLoaded())
{
IExtensionInterface *pAPI = pExt->GetAPI();
pAPI->OnExtensionUnload();
}
// Remove us from internal lists. Note that because we do this, it's
// possible that our extension could be added back if another plugin
// tries to load during this process. If we ever find this to happen,
// we can just block plugin loading.
/* First remove us from internal lists */
g_ShareSys.RemoveInterfaces(_pExt);
m_Libs.remove(pExt);
@@ -806,7 +857,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
while (p_iter != pExt->m_Dependents.end())
{
/* We have to manually unlink ourselves here, since we're no longer being managed */
scripts->UnloadPlugin((*p_iter));
g_PluginSys.UnloadPlugin((*p_iter));
p_iter = pExt->m_Dependents.erase(p_iter);
}
@@ -815,7 +866,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
s_iter != pExt->m_Libraries.end();
s_iter++)
{
scripts->OnLibraryAction((*s_iter).c_str(), LibraryAction_Removed);
g_PluginSys.OnLibraryAction((*s_iter).c_str(), LibraryAction_Removed);
}
/* Notify and/or unload all dependencies */
@@ -826,9 +877,13 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
{
pDep = (*c_iter);
if ((pAPI=pDep->GetAPI()) == NULL)
{
continue;
}
if (pDep == pExt)
{
continue;
}
/* Now, get its dependency list */
bool dropped = false;
List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin();
@@ -857,9 +912,13 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
while (i_iter != pDep->m_ChildDeps.end())
{
if ((*i_iter).owner == pExt)
{
i_iter = pDep->m_ChildDeps.erase(i_iter);
}
else
{
i_iter++;
}
}
}
@@ -878,11 +937,6 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
}
}
// Everything has been informed that we're unloading, so give the
// extension one last notification.
if (pExt->IsLoaded() && pExt->GetAPI()->GetExtensionVersion() >= 7)
pExt->GetAPI()->OnDependenciesDropped();
pExt->Unload();
delete pExt;
@@ -930,10 +984,10 @@ void CExtensionManager::AddDependency(IExtension *pSource, const char *file, boo
void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
{
int argcount = smcore.Argc(command);
int argcount = command.ArgC();
if (argcount >= 3)
{
const char *cmd = smcore.Arg(command, 2);
const char *cmd = command.Arg(2);
if (strcmp(cmd, "list") == 0)
{
List<CExtension *>::iterator iter;
@@ -943,17 +997,17 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{
case 1:
{
rootmenu->ConsolePrint("[SM] Displaying 1 extension:");
g_RootMenu.ConsolePrint("[SM] Displaying 1 extension:");
break;
}
case 0:
{
rootmenu->ConsolePrint("[SM] No extensions are loaded.");
g_RootMenu.ConsolePrint("[SM] No extensions are loaded.");
break;
}
default:
{
rootmenu->ConsolePrint("[SM] Displaying %d extensions:", m_Libs.size());
g_RootMenu.ConsolePrint("[SM] Displaying %d extensions:", m_Libs.size());
break;
}
}
@@ -965,7 +1019,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
char error[255];
if (!pExt->IsRunning(error, sizeof(error)))
{
rootmenu->ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), error);
g_RootMenu.ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), error);
}
else
{
@@ -973,10 +1027,10 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
const char *name = pAPI->GetExtensionName();
const char *version = pAPI->GetExtensionVerString();
const char *descr = pAPI->GetExtensionDescription();
rootmenu->ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr);
g_RootMenu.ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr);
}
} else {
rootmenu->ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
g_RootMenu.ConsolePrint("[%02d] <FAILED> file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str());
}
}
return;
@@ -985,29 +1039,29 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{
if (argcount < 4)
{
rootmenu->ConsolePrint("[SM] Usage: sm exts load <file>");
g_RootMenu.ConsolePrint("[SM] Usage: sm exts load <file>");
return;
}
const char *filename = smcore.Arg(command, 3);
const char *filename = command.Arg(3);
char path[PLATFORM_MAX_PATH];
char error[256];
smcore.Format(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
UTIL_Format(path, sizeof(path), "%s%s%s", filename, !strstr(filename, ".ext") ? ".ext" : "",
!strstr(filename, "." PLATFORM_LIB_EXT) ? "." PLATFORM_LIB_EXT : "");
if (FindExtensionByFile(path) != NULL)
{
rootmenu->ConsolePrint("[SM] Extension %s is already loaded.", path);
g_RootMenu.ConsolePrint("[SM] Extension %s is already loaded.", path);
return;
}
if (LoadExtension(path, error, sizeof(error)))
{
rootmenu->ConsolePrint("[SM] Loaded extension %s successfully.", path);
g_RootMenu.ConsolePrint("[SM] Loaded extension %s successfully.", path);
} else
{
rootmenu->ConsolePrint("[SM] Extension %s failed to load: %s", path, error);
g_RootMenu.ConsolePrint("[SM] Extension %s failed to load: %s", path, error);
}
return;
@@ -1016,27 +1070,27 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{
if (argcount < 4)
{
rootmenu->ConsolePrint("[SM] Usage: sm exts info <#>");
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
return;
}
const char *sId = smcore.Arg(command, 3);
const char *sId = command.Arg(3);
unsigned int id = atoi(sId);
if (id <= 0)
{
rootmenu->ConsolePrint("[SM] Usage: sm exts info <#>");
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
return;
}
if (m_Libs.size() == 0)
{
rootmenu->ConsolePrint("[SM] No extensions are loaded.");
g_RootMenu.ConsolePrint("[SM] No extensions are loaded.");
return;
}
if (id > m_Libs.size())
{
rootmenu->ConsolePrint("[SM] No extension was found with id %d.", id);
g_RootMenu.ConsolePrint("[SM] No extension was found with id %d.", id);
return;
}
@@ -1054,44 +1108,44 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
/* This should never happen */
if (!pExt)
{
rootmenu->ConsolePrint("[SM] No extension was found with id %d.", id);
g_RootMenu.ConsolePrint("[SM] No extension was found with id %d.", id);
return;
}
if (!pExt->IsLoaded())
{
rootmenu->ConsolePrint(" File: %s", pExt->GetFilename());
rootmenu->ConsolePrint(" Loaded: No (%s)", pExt->m_Error.c_str());
g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename());
g_RootMenu.ConsolePrint(" Loaded: No (%s)", pExt->m_Error.c_str());
}
else
{
char error[255];
if (!pExt->IsRunning(error, sizeof(error)))
{
rootmenu->ConsolePrint(" File: %s", pExt->GetFilename());
rootmenu->ConsolePrint(" Loaded: Yes");
rootmenu->ConsolePrint(" Running: No (%s)", error);
g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename());
g_RootMenu.ConsolePrint(" Loaded: Yes");
g_RootMenu.ConsolePrint(" Running: No (%s)", error);
}
else
{
IExtensionInterface *pAPI = pExt->GetAPI();
rootmenu->ConsolePrint(" File: %s", pExt->GetFilename());
rootmenu->ConsolePrint(" Loaded: Yes (version %s)", pAPI->GetExtensionVerString());
rootmenu->ConsolePrint(" Name: %s (%s)", pAPI->GetExtensionName(), pAPI->GetExtensionDescription());
rootmenu->ConsolePrint(" Author: %s (%s)", pAPI->GetExtensionAuthor(), pAPI->GetExtensionURL());
rootmenu->ConsolePrint(" Binary info: API version %d (compiled %s)", pAPI->GetExtensionVersion(), pAPI->GetExtensionDateString());
g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename());
g_RootMenu.ConsolePrint(" Loaded: Yes (version %s)", pAPI->GetExtensionVerString());
g_RootMenu.ConsolePrint(" Name: %s (%s)", pAPI->GetExtensionName(), pAPI->GetExtensionDescription());
g_RootMenu.ConsolePrint(" Author: %s (%s)", pAPI->GetExtensionAuthor(), pAPI->GetExtensionURL());
g_RootMenu.ConsolePrint(" Binary info: API version %d (compiled %s)", pAPI->GetExtensionVersion(), pAPI->GetExtensionDateString());
if (pExt->IsExternal())
{
rootmenu->ConsolePrint(" Method: Loaded by Metamod:Source, attached to SourceMod");
g_RootMenu.ConsolePrint(" Method: Loaded by Metamod:Source, attached to SourceMod");
}
else if (pAPI->IsMetamodExtension())
{
rootmenu->ConsolePrint(" Method: Loaded by SourceMod, attached to Metamod:Source");
g_RootMenu.ConsolePrint(" Method: Loaded by SourceMod, attached to Metamod:Source");
}
else
{
rootmenu->ConsolePrint(" Method: Loaded by SourceMod");
g_RootMenu.ConsolePrint(" Method: Loaded by SourceMod");
}
}
}
@@ -1101,33 +1155,33 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{
if (argcount < 4)
{
rootmenu->ConsolePrint("[SM] Usage: sm exts unload <#> [code]");
g_RootMenu.ConsolePrint("[SM] Usage: sm exts unload <#> [code]");
return;
}
const char *arg = smcore.Arg(command, 3);
const char *arg = command.Arg(3);
unsigned int num = atoi(arg);
CExtension *pExt = FindByOrder(num);
if (!pExt)
{
rootmenu->ConsolePrint("[SM] Extension number %d was not found.", num);
g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
return;
}
if (argcount > 4 && pExt->unload_code)
{
const char *unload = smcore.Arg(command, 4);
const char *unload = command.Arg(4);
if (pExt->unload_code == (unsigned)atoi(unload))
{
char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
}
else
{
rootmenu->ConsolePrint("[SM] Please try again, the correct unload code is \"%d\"", pExt->unload_code);
g_RootMenu.ConsolePrint("[SM] Please try again, the correct unload code is \"%d\"", pExt->unload_code);
}
return;
}
@@ -1138,7 +1192,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename);
g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
return;
}
else
@@ -1146,7 +1200,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
List<CPlugin *> plugins;
if (pExt->m_ChildDeps.size())
{
rootmenu->ConsolePrint("[SM] Unloading %s will unload the following extensions: ", pExt->GetFilename());
g_RootMenu.ConsolePrint("[SM] Unloading %s will unload the following extensions: ", pExt->GetFilename());
List<CExtension *>::iterator iter;
CExtension *pOther;
/* Get list of all extensions */
@@ -1171,7 +1225,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
/* Will our dependent care? */
if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface))
{
rootmenu->ConsolePrint(" -> %s", pExt->GetFilename());
g_RootMenu.ConsolePrint(" -> %s", pExt->GetFilename());
/* Add to plugin unload list */
List<CPlugin *>::iterator p_iter;
for (p_iter=pOther->m_Dependents.begin();
@@ -1189,7 +1243,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
}
if (pExt->m_Dependents.size())
{
rootmenu->ConsolePrint("[SM] Unloading %s will unload the following plugins: ", pExt->GetFilename());
g_RootMenu.ConsolePrint("[SM] Unloading %s will unload the following plugins: ", pExt->GetFilename());
List<CPlugin *>::iterator iter;
CPlugin *pPlugin;
for (iter = pExt->m_Dependents.begin(); iter != pExt->m_Dependents.end(); iter++)
@@ -1203,13 +1257,13 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
for (iter = plugins.begin(); iter != plugins.end(); iter++)
{
pPlugin = (*iter);
rootmenu->ConsolePrint(" -> %s", pPlugin->GetFilename());
g_RootMenu.ConsolePrint(" -> %s", pPlugin->GetFilename());
}
}
srand(static_cast<int>(time(NULL)));
pExt->unload_code = (rand() % 877) + 123; //123 to 999
rootmenu->ConsolePrint("[SM] To verify unloading %s, please use the following: ", pExt->GetFilename());
rootmenu->ConsolePrint("[SM] sm exts unload %d %d", num, pExt->unload_code);
g_RootMenu.ConsolePrint("[SM] To verify unloading %s, please use the following: ", pExt->GetFilename());
g_RootMenu.ConsolePrint("[SM] sm exts unload %d %d", num, pExt->unload_code);
return;
}
@@ -1218,17 +1272,17 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{
if (argcount < 4)
{
rootmenu->ConsolePrint("[SM] Usage: sm exts reload <#>");
g_RootMenu.ConsolePrint("[SM] Usage: sm exts reload <#>");
return;
}
const char *arg = smcore.Arg(command, 3);
const char *arg = command.Arg(3);
unsigned int num = atoi(arg);
CExtension *pExt = FindByOrder(num);
if (!pExt)
{
rootmenu->ConsolePrint("[SM] Extension number %d was not found.", num);
g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
return;
}
@@ -1241,18 +1295,18 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
if (pExt->Reload(error, sizeof(error)))
{
rootmenu->ConsolePrint("[SM] Extension %s is now reloaded.", filename);
g_RootMenu.ConsolePrint("[SM] Extension %s is now reloaded.", filename);
}
else
{
rootmenu->ConsolePrint("[SM] Extension %s failed to reload: %s", filename, error);
g_RootMenu.ConsolePrint("[SM] Extension %s failed to reload: %s", filename, error);
}
return;
}
else
{
rootmenu->ConsolePrint("[SM] Extension %s is not loaded.", pExt->GetFilename());
g_RootMenu.ConsolePrint("[SM] Extension %s is not loaded.", pExt->GetFilename());
return;
}
@@ -1260,12 +1314,100 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
}
}
rootmenu->ConsolePrint("SourceMod Extensions Menu:");
rootmenu->DrawGenericOption("info", "Extra extension information");
rootmenu->DrawGenericOption("list", "List extensions");
rootmenu->DrawGenericOption("load", "Load an extension");
rootmenu->DrawGenericOption("reload", "Reload an extension");
rootmenu->DrawGenericOption("unload", "Unload an extension");
g_RootMenu.ConsolePrint("SourceMod Extensions Menu:");
g_RootMenu.DrawGenericOption("info", "Extra extension information");
g_RootMenu.DrawGenericOption("list", "List extensions");
g_RootMenu.DrawGenericOption("load", "Load an extension");
g_RootMenu.DrawGenericOption("reload", "Reload an extension");
g_RootMenu.DrawGenericOption("unload", "Unload an extension");
}
void CExtensionManager::ListExtensionsToClient(CPlayer *player, const CCommand &args)
{
char buffer[256];
int numExtensions = m_Libs.size();
edict_t *edict = player->GetEdict();
unsigned int id = 0;
unsigned int start = 0;
if (!numExtensions)
{
ClientConsolePrint(edict, "[SM] No extensions found.");
return;
}
if (args.ArgC() > 2)
{
start = atoi(args.Arg(2));
}
CExtension *ext;
SourceHook::List<CExtension *>::iterator iter;
for (iter = m_Libs.begin();
iter != m_Libs.end();
iter++)
{
ext = (*iter);
char error[255];
if (!ext->IsRunning(error, sizeof(error)))
{
continue;
}
id++;
if (id < start)
{
continue;
}
if (id - start > 10)
{
break;
}
IExtensionInterface *api = ext->GetAPI();
const char *name = api->GetExtensionName();
const char *version = api->GetExtensionVerString();
const char *author = api->GetExtensionAuthor();
const char *description = api->GetExtensionDescription();
size_t len = UTIL_Format(buffer, sizeof(buffer), " \"%s\"", name);
if (version != NULL && IS_STR_FILLED(version))
{
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", version);
}
if (author != NULL && IS_STR_FILLED(author))
{
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", author);
}
if (description != NULL && IS_STR_FILLED(description))
{
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, ": %s", description);
}
ClientConsolePrint(edict, "%s", buffer);
}
while (iter != m_Libs.end())
{
char error[255];
if ((*iter)->IsRunning(error, sizeof(error)))
{
break;
}
}
if (iter != m_Libs.end())
{
ClientConsolePrint(edict, "To see more, type \"sm exts %d\"", id);
}
}
CExtension *CExtensionManager::GetExtensionFromIdent(IdentityToken_t *ptr)
@@ -1290,7 +1432,7 @@ void CExtensionManager::AddLibrary(IExtension *pSource, const char *library)
{
CExtension *pExt = (CExtension *)pSource;
pExt->AddLibrary(library);
scripts->OnLibraryAction(library, LibraryAction_Added);
g_PluginSys.OnLibraryAction(library, LibraryAction_Added);
}
bool CExtensionManager::LibraryExists(const char *library)
@@ -1360,37 +1502,6 @@ void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount,
}
}
void CExtensionManager::CallOnCoreMapEnd()
{
IExtensionInterface *pAPI;
List<CExtension *>::iterator iter;
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
{
if ((pAPI = (*iter)->GetAPI()) == NULL)
{
continue;
}
if (pAPI->GetExtensionVersion() > 7)
{
pAPI->OnCoreMapEnd();
}
}
}
const CVector<IExtension *> *CExtensionManager::ListExtensions()
{
CVector<IExtension *> *list = new CVector<IExtension *>();
for (List<CExtension *>::iterator iter = m_Libs.begin(); iter != m_Libs.end(); iter++)
list->push_back(*iter);
return list;
}
void CExtensionManager::FreeExtensionList(const CVector<IExtension *> *list)
{
delete const_cast<CVector<IExtension *> *>(list);
}
bool CLocalExtension::IsSameFile(const char *file)
{
/* Only care about the shortened name. */
@@ -36,11 +36,14 @@
#include <ILibrarySys.h>
#include <sh_list.h>
#include <sh_string.h>
#include "common_logic.h"
#include <sm_trie_tpl.h>
#include "sm_globals.h"
#include "ShareSys.h"
#include <ISmmAPI.h>
#include <IPluginSys.h>
#include <IRootConsoleMenu.h>
#include "PluginSys.h"
#include "NativeOwner.h"
#include "ShareSys.h"
class CPlayer;
@@ -117,7 +120,7 @@ public:
bool IsExternal();
bool IsSameFile(const char *file);
private:
int m_PlId;
PluginId m_PlId;
ILibrary *m_pLib;
};
@@ -135,7 +138,7 @@ public:
};
class CExtensionManager :
public IExtensionSys,
public IExtensionManager,
public SMGlobalClass,
public IPluginsListener,
public IRootConsoleCommand
@@ -166,17 +169,16 @@ public:
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true);
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
void AddInterface(IExtension *pOwner, SMInterface *pInterface);
void BindChildPlugin(IExtension *pParent, SMPlugin *pPlugin);
void BindChildPlugin(IExtension *pParent, CPlugin *pPlugin);
void MarkAllLoaded();
void AddDependency(IExtension *pSource, const char *file, bool required, bool autoload);
void TryAutoload();
void AddLibrary(IExtension *pSource, const char *library);
bool LibraryExists(const char *library);
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
void CallOnCoreMapEnd();
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
const CVector<IExtension *> *ListExtensions();
void FreeExtensionList(const CVector<IExtension *> *list);
public:
void ListExtensionsToClient(CPlayer *player, const CCommand &args);
public:
CExtension *GetExtensionFromIdent(IdentityToken_t *ptr);
void Shutdown();
@@ -33,8 +33,9 @@
#include <stdarg.h>
#include <string.h>
#include "ForwardSys.h"
#include "PluginSys.h"
#include "ShareSys.h"
#include "DebugReporter.h"
#include "common_logic.h"
CForwardManager g_Forwards;
@@ -62,8 +63,8 @@ CForwardManager::~CForwardManager()
void CForwardManager::OnSourceModAllInitialized()
{
scripts->AddPluginsListener(this);
sharesys->AddInterface(NULL, this);
g_PluginSys.AddPluginsListener(this);
g_ShareSys.AddInterface(NULL, this);
}
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
@@ -78,7 +79,7 @@ IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned
if (fwd)
{
scripts->AddFunctionsToForward(name, fwd);
g_PluginSys.AddFunctionsToForward(name, fwd);
m_managed.push_back(fwd);
}
@@ -210,23 +211,7 @@ CForward *CForwardManager::ForwardMake()
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
{
if(paused)
return;
/* Attach any globally managed forwards */
List<CForward *>::iterator iter;
CForward *fwd;
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
{
fwd = (*iter);
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
// Only add functions, if they aren't registered yet!
if (pFunc && !fwd->IsFunctionRegistered(pFunc))
{
fwd->AddFunction(pFunc);
}
}
/* No longer used */
}
/*************************************
@@ -699,7 +684,7 @@ bool CForward::RemoveFunction(IPluginFunction *func)
lst = &m_paused;
}
for (iter=lst->begin(); iter!=lst->end(); iter++)
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
{
if ((*iter) == func)
{
@@ -757,28 +742,6 @@ bool CForward::AddFunction(IPluginFunction *func)
return true;
}
bool CForward::IsFunctionRegistered(IPluginFunction *func)
{
FuncIter iter;
List<IPluginFunction *> *lst;
if (func->IsRunnable())
{
lst = &m_functions;
} else {
lst = &m_paused;
}
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
{
if ((*iter) == func)
{
return true;
}
}
return false;
}
const char *CForward::GetForwardName()
{
return m_name;
+25 -3
View File
@@ -34,10 +34,10 @@
#include <IForwardSys.h>
#include <IPluginSys.h>
#include "common_logic.h"
#include "sm_globals.h"
#include <sh_list.h>
#include <sh_stack.h>
#include "ISourceMod.h"
#include "sourcemod.h"
using namespace SourceHook;
@@ -46,6 +46,29 @@ typedef List<IPluginFunction *>::iterator FuncIter;
/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
#define FORWARDS_NAME_MAX 64
struct ByrefInfo
{
unsigned int cells;
cell_t *orig_addr;
int flags;
int sz_flags;
};
struct FwdParamInfo
{
cell_t val;
ByrefInfo byref;
ParamType pushedas;
};
class SourceMod::IForwardFilter
{
public:
virtual void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
{
}
};
class FuncIteratorGuard
{
bool triggered;
@@ -118,7 +141,6 @@ public:
unsigned int num_params,
const ParamType *types,
va_list ap);
bool IsFunctionRegistered(IPluginFunction *func);
private:
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags);
void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags);
+172 -201
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -42,24 +42,21 @@
#include "logic_bridge.h"
#include <tier0/mem.h>
#if SOURCE_ENGINE == SE_DOTA
#include <game/shared/protobuf/usermessages.pb.h>
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessages.pb.h>
#endif
typedef ICommandLine *(*FakeGetCommandLine)();
#if defined _WIN32
#define TIER0_NAME "tier0.dll"
#define VSTDLIB_NAME "vstdlib.dll"
#elif defined __APPLE__
#define TIER0_NAME "libtier0.dylib"
#define VSTDLIB_NAME "libvstdlib.dylib"
#if defined _WIN32
#define TIER0_NAME "tier0.dll"
#define VSTDLIB_NAME "vstdlib.dll"
#elif defined __APPLE__
#define TIER0_NAME "libtier0.dylib"
#define VSTDLIB_NAME "libvstdlib.dylib"
#elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_LEFT4DEAD2
#define TIER0_NAME "libtier0_srv.so"
#define VSTDLIB_NAME "libvstdlib_srv.so"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
@@ -68,7 +65,7 @@ typedef ICommandLine *(*FakeGetCommandLine)();
#else
#define TIER0_NAME "tier0_i486.so"
#define VSTDLIB_NAME "vstdlib_i486.so"
#endif
#endif
#endif
CHalfLife2 g_HL2;
@@ -92,20 +89,51 @@ static CEntInfo *EntInfoArray()
return NULL;
}
namespace SourceHook
{
template<>
int HashFunction<datamap_t *>(datamap_t * const &k)
{
return reinterpret_cast<int>(k);
}
template<>
int Compare<datamap_t *>(datamap_t * const &k1, datamap_t * const &k2)
{
return (k1-k2);
}
}
CHalfLife2::CHalfLife2()
{
m_Maps.init();
m_pGetCommandLine = NULL;
m_pClasses = sm_trie_create();
}
CHalfLife2::~CHalfLife2()
{
for (NameHashSet<DataTableInfo *>::iterator iter = m_Classes.iter(); !iter.empty(); iter.next())
delete *iter;
sm_trie_destroy(m_pClasses);
for (DataTableMap::iterator iter = m_Maps.iter(); !iter.empty(); iter.next())
delete iter->value;
List<DataTableInfo *>::iterator iter;
DataTableInfo *pInfo;
for (iter=m_Tables.begin(); iter!=m_Tables.end(); iter++)
{
pInfo = (*iter);
delete pInfo;
}
m_Tables.clear();
THash<datamap_t *, DataMapTrie>::iterator h_iter;
for (h_iter=m_Maps.begin(); h_iter!=m_Maps.end(); h_iter++)
{
if (h_iter->val.trie)
{
sm_trie_destroy(h_iter->val.trie);
h_iter->val.trie = NULL;
}
}
m_Maps.clear();
}
#if SOURCE_ENGINE != SE_DARKMESSIAH
@@ -142,7 +170,7 @@ void CHalfLife2::OnSourceModAllInitialized()
m_HinTextMsg = g_UserMsgs.GetMessageIndex("HintText");
m_SayTextMsg = g_UserMsgs.GetMessageIndex("SayText");
m_VGUIMenu = g_UserMsgs.GetMessageIndex("VGUIMenu");
sharesys->AddInterface(NULL, this);
g_ShareSys.AddInterface(NULL, this);
}
void CHalfLife2::OnSourceModAllInitialized_Post()
@@ -153,18 +181,6 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
void CHalfLife2::InitLogicalEntData()
{
#if SOURCE_ENGINE == SE_TF2 \
|| SOURCE_ENGINE == SE_DODS \
|| SOURCE_ENGINE == SE_HL2DM \
|| SOURCE_ENGINE == SE_CSS \
|| SOURCE_ENGINE == SE_SDK2013
if (g_SMAPI->GetServerFactory(false)("VSERVERTOOLS003", nullptr))
{
g_EntList = servertools->GetEntityList();
}
#endif
char *addr = NULL;
/*
@@ -174,24 +190,21 @@ void CHalfLife2::InitLogicalEntData()
* If symbols aren't present (Windows or stripped Linux/Mac),
* attempt find via LevelShutdown + offset
*/
if (!g_EntList)
if (g_pGameConf->GetMemSig("gEntList", (void **)&addr))
{
if (g_pGameConf->GetMemSig("gEntList", (void **) &addr))
#if !defined PLATFORM_WINDOWS
if (!addr)
{
#if !defined PLATFORM_WINDOWS
if (!addr)
{
// Key exists so notify if lookup fails, but try other method.
logger->LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
}
else
{
#endif
g_EntList = reinterpret_cast<void *>(addr);
#if !defined PLATFORM_WINDOWS
}
#endif
// Key exists so notify if lookup fails, but try other method.
g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
}
else
{
#endif
g_EntList = reinterpret_cast<void *>(addr);
#if !defined PLATFORM_WINDOWS
}
#endif
}
if (!g_EntList)
@@ -201,7 +214,7 @@ void CHalfLife2::InitLogicalEntData()
int offset;
if (!g_pGameConf->GetOffset("gEntList", &offset))
{
logger->LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
return;
}
@@ -213,7 +226,7 @@ void CHalfLife2::InitLogicalEntData()
// If we have g_EntList from either of the above methods, make sure we can get the offset from it to EntInfo as well
if (g_EntList && !g_pGameConf->GetOffset("EntInfo", &entInfoOffset))
{
logger->LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
g_EntList = NULL;
return;
}
@@ -226,48 +239,58 @@ void CHalfLife2::InitLogicalEntData()
if (!g_EntList && !g_pEntInfoList)
{
logger->LogError("Failed lookup of gEntList - Reverting to networkable entities only");
g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only");
return;
}
}
void CHalfLife2::InitCommandLine()
{
char path[PLATFORM_MAX_PATH];
char error[256];
#if SOURCE_ENGINE != SE_DARKMESSIAH
if (!is_original_engine)
{
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(TIER0_NAME, error, sizeof(error)));
if (lib == NULL)
{
logger->LogError("Could not load %s: %s", TIER0_NAME, error);
return;
}
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine_Tier0");
/* '_Tier0' dropped on Alien Swarm version */
if (m_pGetCommandLine == NULL)
{
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
}
}
else
#endif
{
ke::AutoPtr<ILibrary> lib(g_LibSys.OpenLibrary(VSTDLIB_NAME, error, sizeof(error)));
if (lib == NULL)
{
logger->LogError("Could not load %s: %s", VSTDLIB_NAME, error);
return;
}
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
}
if (m_pGetCommandLine == NULL)
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "../bin/" TIER0_NAME);
if (!g_LibSys.IsPathFile(path))
{
logger->LogError("Could not locate any command line functionality");
g_Logger.LogError("Could not find path for: " TIER0_NAME);
return;
}
ILibrary *lib = g_LibSys.OpenLibrary(path, error, sizeof(error));
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine_Tier0");
/* '_Tier0' dropped on Alien Swarm version */
if (m_pGetCommandLine == NULL)
{
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
}
if (m_pGetCommandLine == NULL)
{
/* We probably have a Ship engine. */
lib->CloseLibrary();
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "../bin/" VSTDLIB_NAME);
if (!g_LibSys.IsPathFile(path))
{
g_Logger.LogError("Could not find path for: " VSTDLIB_NAME);
return;
}
if ((lib = g_LibSys.OpenLibrary(path, error, sizeof(error))) == NULL)
{
g_Logger.LogError("Could not load %s: %s", path, error);
return;
}
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
if (m_pGetCommandLine == NULL)
{
g_Logger.LogError("Could not locate any command line functionality");
}
lib->CloseLibrary();
}
}
@@ -289,11 +312,7 @@ bool CHalfLife2::IsOriginalEngine()
#if SOURCE_ENGINE != SE_DARKMESSIAH
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
{
#if SOURCE_ENGINE == SE_DOTA
return engine->GetChangeAccessor( IndexOfEdict((const edict_t *)this) );
#else
return engine->GetChangeAccessor( (const edict_t *)this );
#endif
}
#endif
@@ -332,11 +351,16 @@ bool UTIL_FindInSendTable(SendTable *pTable,
return false;
}
bool UTIL_FindDataMapInfo(datamap_t *pMap, const char *name, sm_datatable_info_t *pDataTable)
typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name, bool *isNested)
{
if (isNested)
{
*isNested = false;
}
while (pMap)
{
for (int i = 0; i < pMap->dataNumFields; ++i)
for (int i=0; i<pMap->dataNumFields; i++)
{
if (pMap->dataDesc[i].fieldName == NULL)
{
@@ -344,23 +368,32 @@ bool UTIL_FindDataMapInfo(datamap_t *pMap, const char *name, sm_datatable_info_t
}
if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
{
pDataTable->prop = &(pMap->dataDesc[i]);
pDataTable->actual_offset = GetTypeDescOffs(pDataTable->prop);
return true;
return &(pMap->dataDesc[i]);
}
if (pMap->dataDesc[i].td == NULL || !UTIL_FindDataMapInfo(pMap->dataDesc[i].td, name, pDataTable))
if (pMap->dataDesc[i].td)
{
continue;
if (isNested)
{
*isNested = (UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL) != NULL);
if (*isNested)
{
return NULL;
} else {
continue;
}
} else { // Use the old behaviour, we dont want to spring this on extensions - even if they're doing bad things.
typedescription_t *_td;
if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL)) != NULL)
{
return _td;
}
}
}
pDataTable->actual_offset += GetTypeDescOffs(&(pMap->dataDesc[i]));
return true;
}
pMap = pMap->baseMap;
}
return false;
return NULL;
}
ServerClass *CHalfLife2::FindServerClass(const char *classname)
@@ -368,7 +401,9 @@ ServerClass *CHalfLife2::FindServerClass(const char *classname)
DataTableInfo *pInfo = _FindServerClass(classname);
if (!pInfo)
{
return NULL;
}
return pInfo->sc;
}
@@ -376,21 +411,26 @@ ServerClass *CHalfLife2::FindServerClass(const char *classname)
DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
{
DataTableInfo *pInfo = NULL;
if (!m_Classes.retrieve(classname, &pInfo))
if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
{
ServerClass *sc = gamedll->GetAllServerClasses();
while (sc)
{
if (strcmp(classname, sc->GetName()) == 0)
{
pInfo = new DataTableInfo(sc);
m_Classes.insert(classname, pInfo);
pInfo = new DataTableInfo;
pInfo->sc = sc;
sm_trie_insert(m_pClasses, classname, pInfo);
m_Tables.push_back(pInfo);
break;
}
sc = sc->m_pNext;
}
if (!pInfo)
{
return NULL;
}
}
return pInfo;
@@ -399,13 +439,14 @@ DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
bool CHalfLife2::FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info)
{
DataTableInfo *pInfo;
sm_sendprop_info_t *prop;
if ((pInfo = _FindServerClass(classname)) == NULL)
{
return false;
}
if (!pInfo->lookup.retrieve(offset, info))
if ((prop = pInfo->lookup.retrieve(offset)) == NULL)
{
sm_sendprop_info_t temp_info;
@@ -417,6 +458,10 @@ bool CHalfLife2::FindSendPropInfo(const char *classname, const char *offset, sm_
pInfo->lookup.insert(offset, temp_info);
*info = temp_info;
}
else
{
*info = *prop;
}
return true;
}
@@ -435,32 +480,27 @@ SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
{
sm_datatable_info_t dt_info;
if (!(this->FindDataMapInfo(pMap, offset, &dt_info)))
{
return NULL;
}
return dt_info.prop;
return this->FindInDataMap(pMap, offset, NULL);
}
bool CHalfLife2::FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable)
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested)
{
DataTableMap::Insert i = m_Maps.findForAdd(pMap);
if (!i.found())
m_Maps.add(i, pMap, new DataMapCache());
typedescription_t *td = NULL;
DataMapTrie &val = m_Maps[pMap];
DataMapCache *cache = i->value;
if (!cache->retrieve(offset, pDataTable))
if (!val.trie)
{
if (!UTIL_FindDataMapInfo(pMap, offset, pDataTable))
return false;
cache->insert(offset, *pDataTable);
val.trie = sm_trie_create();
}
if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
{
if ((td = UTIL_FindInDataMap(pMap, offset, isNested)) != NULL)
{
sm_trie_insert(val.trie, offset, td);
}
}
return true;
return td;
}
void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
@@ -486,7 +526,7 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
{
#ifndef USE_PROTOBUF_USERMESSAGES
#if SOURCE_ENGINE != SE_CSGO
bf_write *pBitBuf = NULL;
#endif
cell_t players[] = {client};
@@ -501,17 +541,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
char buffer[192];
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_SayText *pMsg;
if ((pMsg = (CUserMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_client(0);
pMsg->set_text(buffer);
pMsg->set_chat(false);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_SayText *pMsg;
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
@@ -538,16 +568,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
}
}
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_TextMsg *pMsg;
if ((pMsg = (CUserMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_dest(dest);
pMsg->add_param(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_TextMsg *pMsg;
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
@@ -580,15 +601,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
{
cell_t players[] = {client};
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_HintText *pMsg;
if ((pMsg = (CUserMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_message(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
@@ -618,15 +631,7 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
{
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_HintText *pMsg;
if ((pMsg = (CUserMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_message(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
{
@@ -661,13 +666,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
int count = 0;
cell_t players[] = {client};
#if SOURCE_ENGINE == SE_DOTA
CUserMsg_VGUIMenu *pMsg;
if ((pMsg = (CUserMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_VGUIMenu *pMsg;
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
{
@@ -692,18 +691,7 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
SubKey = data->GetFirstSubKey();
}
#if SOURCE_ENGINE == SE_DOTA
pMsg->set_name(name);
pMsg->set_show(show);
while (SubKey)
{
CUserMsg_VGUIMenu_Keys *key = pMsg->add_keys();
key->set_name(SubKey->GetName());
key->set_value(SubKey->GetString());
SubKey = SubKey->GetNextKey();
}
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
pMsg->set_name(name);
pMsg->set_show(show);
@@ -759,11 +747,7 @@ void CHalfLife2::ProcessFakeCliCmdQueue()
if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
{
CPlayer *pPlayer = g_Players.GetPlayerByIndex(pFake->client);
#if SOURCE_ENGINE == SE_DOTA
engine->ClientCommand(pPlayer->GetIndex(), "%s", pFake->cmd.c_str());
#else
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
#endif
}
m_CmdQueue.pop();
@@ -1185,22 +1169,9 @@ const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity)
static int offset = -1;
if (offset == -1)
{
CBaseEntity *pGetterEnt = ReferenceToEntity(0);
if (pGetterEnt == NULL)
{
// If we don't have a world entity yet, we'll have to rely on the given entity
pGetterEnt = pEntity;
}
datamap_t *pMap = GetDataMap(pGetterEnt);
sm_datatable_info_t info;
if (!FindDataMapInfo(pMap, "m_iClassname", &info))
{
return NULL;
}
offset = info.actual_offset;
datamap_t *pMap = GetDataMap(pEntity);
typedescription_t *pDesc = FindInDataMap(pMap, "m_iClassname");
offset = GetTypeDescOffs(pDesc);
}
return *(const char **)(((unsigned char *)pEntity) + offset);
+12 -37
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -35,10 +35,8 @@
#include <sh_list.h>
#include <sh_string.h>
#include <sh_tinyhash.h>
#include <am-utility.h>
#include <am-hashmap.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
#include <sm_trie_tpl.h>
#include "sm_trie.h"
#include "sm_globals.h"
#include "sm_queue.h"
#include <IGameHelpers.h>
@@ -61,38 +59,16 @@ using namespace SourceMod;
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;
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)
{
return strcmp(name, info.prop->fieldName) == 0;
}
DataMapTrie() : trie(NULL) {}
Trie *trie;
};
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
struct DelayedFakeCliCmd
{
String cmd;
@@ -123,7 +99,7 @@ public:
int m_SerialNumber;
CEntInfo *m_pPrev;
CEntInfo *m_pNext;
#if (SOURCE_ENGINE >= SE_PORTAL2) && (SOURCE_ENGINE != SE_DOTA)
#if SOURCE_ENGINE >= SE_PORTAL2
string_t m_iName;
string_t m_iClassName;
#endif
@@ -147,7 +123,7 @@ public: //IGameHelpers
datamap_t *GetDataMap(CBaseEntity *pEntity);
ServerClass *FindServerClass(const char *classname);
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable);
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested);
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
bool TextMsg(int client, int dest, const char *msg);
bool HintTextMsg(int client, const char *msg);
@@ -193,10 +169,9 @@ private:
void InitLogicalEntData();
void InitCommandLine();
private:
typedef ke::HashMap<datamap_t *, DataMapCache *, ke::PointerPolicy<datamap_t> > DataTableMap;
NameHashSet<DataTableInfo *> m_Classes;
DataTableMap m_Maps;
Trie *m_pClasses;
List<DataTableInfo *> m_Tables;
THash<datamap_t *, DataMapTrie> m_Maps;
int m_MsgTextMsg;
int m_HinTextMsg;
int m_SayTextMsg;
+80 -108
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,12 +30,13 @@
*/
#include "HandleSys.h"
#include "ShareSys.h"
#include "PluginSys.h"
#include "ExtensionSys.h"
#include "Logger.h"
#include <assert.h>
#include <string.h>
#include "common_logic.h"
#include "ShareSys.h"
#include "ExtensionSys.h"
#include "PluginSys.h"
#include "sm_stringutil.h"
HandleSystem g_HandleSys;
@@ -59,6 +60,9 @@ HandleSystem::HandleSystem()
m_Types = new QHandleType[HANDLESYS_TYPEARRAY_SIZE];
memset(m_Types, 0, sizeof(QHandleType) * HANDLESYS_TYPEARRAY_SIZE);
m_TypeLookup = sm_trie_create();
m_strtab = new BaseStringTable(512);
m_TypeTail = 0;
}
@@ -66,6 +70,8 @@ HandleSystem::~HandleSystem()
{
delete [] m_Handles;
delete [] m_Types;
sm_trie_destroy(m_TypeLookup);
delete m_strtab;
}
@@ -139,10 +145,12 @@ HandleType_t HandleSystem::CreateType(const char *name,
if (name && name[0] != '\0')
{
if (m_TypeLookup.contains(name))
if (sm_trie_retrieve(m_TypeLookup, name, NULL))
{
if (err)
{
*err = HandleError_Parameter;
}
return 0;
}
}
@@ -204,8 +212,10 @@ HandleType_t HandleSystem::CreateType(const char *name,
pType->dispatch = dispatch;
if (name && name[0] != '\0')
{
pType->name = new ke::AString(name);
m_TypeLookup.insert(name, pType);
pType->nameIdx = m_strtab->AddString(name);
sm_trie_insert(m_TypeLookup, name, (void *)pType);
} else {
pType->nameIdx = -1;
}
pType->opened = 0;
@@ -233,14 +243,21 @@ HandleType_t HandleSystem::CreateType(const char *name,
return index;
}
bool HandleSystem::FindHandleType(const char *name, HandleType_t *aResult)
bool HandleSystem::FindHandleType(const char *name, HandleType_t *type)
{
QHandleType *type;
if (!m_TypeLookup.retrieve(name, &type))
return false;
QHandleType *_type;
if (aResult)
*aResult = type - m_Types;
if (!sm_trie_retrieve(m_TypeLookup, name, (void **)&_type))
{
return false;
}
unsigned int offset = _type - m_Types;
if (type)
{
*type = offset;
}
return true;
}
@@ -643,13 +660,13 @@ void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigne
HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
{
if (pHandle->is_destroying)
{
/* Someone tried to free this recursively.
* We'll just ignore this safely.
*/
return HandleError_None;
}
if (pHandle->is_destroying)
{
/* Someone tried to free this recursively.
* We'll just ignore this safely.
*/
return HandleError_None;
}
QHandleType *pType = &m_Types[pHandle->type];
@@ -674,9 +691,9 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
/* Type should be the same but do this anyway... */
pType = &m_Types[pMaster->type];
pMaster->is_destroying = true;
if (pMaster->object)
{
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
if (pMaster->object)
{
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
}
ReleasePrimHandle(master);
}
@@ -691,9 +708,9 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
if (--pHandle->refcount == 0)
{
pHandle->is_destroying = true;
if (pHandle->object)
{
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
if (pHandle->object)
{
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
}
ReleasePrimHandle(index);
} else {
@@ -897,6 +914,10 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
m_Types[++m_FreeTypes].freeID = type;
}
/* Invalidate the type now */
IHandleTypeDispatch *dispatch = pType->dispatch;
pType->dispatch = NULL;
/* Make sure nothing is using this type. */
if (pType->opened)
{
@@ -918,12 +939,14 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
}
}
/* Invalidate the type now */
pType->dispatch = NULL;
/* Remove it from the type cache. */
if (pType->name)
m_TypeLookup.remove(pType->name->chars());
if (pType->nameIdx != -1)
{
const char *typeName;
typeName = m_strtab->GetString(pType->nameIdx);
sm_trie_delete(m_TypeLookup, typeName);
}
return true;
}
@@ -957,8 +980,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
}
#define HANDLE_LOG_VERY_BAD(message, ...) \
logger->LogFatal(message, ##__VA_ARGS__); \
logger->LogError(message, ##__VA_ARGS__);
g_Logger.LogFatal(message, ##__VA_ARGS__); \
g_Logger.LogError(message, ##__VA_ARGS__);
bool HandleSystem::TryAndFreeSomeHandles()
{
@@ -1005,63 +1028,10 @@ bool HandleSystem::TryAndFreeSomeHandles()
HANDLE_LOG_VERY_BAD("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
HANDLE_LOG_VERY_BAD("[SM] Unloading plugin to free %d handles.", highest_handle_count);
HANDLE_LOG_VERY_BAD("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
HANDLE_LOG_VERY_BAD("--------------------------------------------------------------------------");
const IdentityToken_t *pIdentity = highest_owner->GetIdentity();
unsigned int total = 0, highest_index = 0, total_size = 0, size;
unsigned int * pCount = new unsigned int[HANDLESYS_TYPEARRAY_SIZE+1];
memset(pCount, 0, ((HANDLESYS_TYPEARRAY_SIZE + 1) * sizeof(unsigned int)));
for (unsigned int i = 1; i <= m_HandleTail; ++i)
{
const QHandle &Handle = m_Handles[i];
if (Handle.set != HandleSet_Used || Handle.owner != pIdentity)
{
continue;
}
++pCount[Handle.type];
++total;
if (Handle.type >= highest_index)
{
highest_index = ((Handle.type) + 1);
}
if (Handle.clone != 0)
{
continue;
}
if (m_Types[Handle.type].dispatch->GetHandleApproxSize(Handle.type, Handle.object, &size))
{
total_size += size;
}
}
const char * pTypeName = NULL;
for (unsigned int i = 0; i < highest_index; ++i)
{
if (pCount[i] == 0)
{
continue; /* We may have gaps, it's fine. */
}
if (m_Types[i].name)
pTypeName = m_Types[i].name->chars();
else
pTypeName = "ANON";
HANDLE_LOG_VERY_BAD("Type\t%-20.20s|\tCount\t%u", pTypeName, pCount[i]);
}
HANDLE_LOG_VERY_BAD("-- Approximately %d bytes of memory are in use by (%u) Handles.\n", total_size, total);
delete [] pCount;
highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak");
return scripts->UnloadPlugin(highest_owner);
return g_PluginSys.UnloadPlugin(highest_owner);
}
void HandleSystem::Dump(HANDLE_REPORTER rep)
@@ -1086,20 +1056,20 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
{
owner = "CORE";
}
else if (pOwner == scripts->GetIdentity())
else if (pOwner == g_PluginSys.GetIdentity())
{
owner = "PLUGINSYS";
}
else
{
IExtension *ext = g_Extensions.GetExtensionFromIdent(pOwner);
CExtension *ext = g_Extensions.GetExtensionFromIdent(pOwner);
if (ext)
{
owner = ext->GetFilename();
}
else
{
SMPlugin *pPlugin = scripts->FindPluginByIdentity(pOwner);
CPlugin *pPlugin = g_PluginSys.GetPluginFromIdentity(pOwner);
if (pPlugin)
{
owner = pPlugin->GetFilename();
@@ -1116,24 +1086,26 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
unsigned int size = 0;
unsigned int parentIdx;
bool bresult;
if (pType->name)
type = pType->name->chars();
if ((parentIdx = m_Handles[i].clone) != 0)
if (pType->nameIdx != -1)
{
if (m_Handles[parentIdx].refcount > 0)
{
size = 0;
bresult = true;
}
else
{
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[parentIdx].type, m_Handles[parentIdx].object, &size);
}
type = m_strtab->GetString(pType->nameIdx);
}
else
{
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size);
if ((parentIdx = m_Handles[i].clone) != 0)
{
if (m_Handles[parentIdx].refcount > 0)
{
size = 0;
bresult = true;
}
else
{
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[parentIdx].type, m_Handles[parentIdx].object, &size);
}
}
else
{
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size);
}
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
@@ -1144,7 +1116,7 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
else
{
char buffer[32];
smcore.Format(buffer, sizeof(buffer), "%d", size);
UTIL_Format(buffer, sizeof(buffer), "%d", size);
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
total_size += size;
}
+9 -12
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,11 +34,12 @@
#include <IHandleSys.h>
#include <stdio.h>
#include <sm_namehashset.h>
#include <am-string.h>
#include "common_logic.h"
#include "sm_globals.h"
#include "sm_trie.h"
#include "sourcemod.h"
#include "sm_memtable.h"
#define HANDLESYS_MAX_HANDLES (1<<15)
#define HANDLESYS_MAX_HANDLES (1<<14)
#define HANDLESYS_MAX_TYPES (1<<9)
#define HANDLESYS_MAX_SUBTYPES 0xF
#define HANDLESYS_SUBTYPE_MASK 0xF
@@ -103,12 +104,7 @@ struct QHandleType
TypeAccess typeSec;
HandleAccess hndlSec;
unsigned int opened;
ke::AutoPtr<ke::AString> name;
static inline bool matches(const char *key, const QHandleType *type)
{
return type->name && type->name->compare(key) == 0;
}
int nameIdx;
};
typedef void (HANDLE_REPORTER)(const char *str, ...);
@@ -221,12 +217,13 @@ protected:
private:
QHandle *m_Handles;
QHandleType *m_Types;
NameHashSet<QHandleType *> m_TypeLookup;
Trie *m_TypeLookup;
unsigned int m_TypeTail;
unsigned int m_FreeTypes;
unsigned int m_HandleTail;
unsigned int m_FreeHandles;
unsigned int m_HSerial;
BaseStringTable *m_strtab;
};
extern HandleSystem g_HandleSys;
+511 -25
View File
@@ -36,35 +36,521 @@
#include "Logger.h"
#include "LibrarySys.h"
#include "TimerSys.h"
#include "logic_bridge.h"
#include <sourcemod_version.h>
Logger g_Logger;
/**
* :TODO: This should be creating the log folder if it doesn't exist
*/
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{
if (strcasecmp(key, "Logging") == 0)
{
bool state;
if (strcasecmp(value, "on") == 0)
{
state = true;
} else if (strcasecmp(value, "off") == 0) {
state = false;
} else {
UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
return ConfigResult_Reject;
}
if (source == ConfigSource_Console)
{
state ? EnableLogging() : DisableLogging();
} else {
m_InitialState = state;
}
return ConfigResult_Accept;
} else if (strcasecmp(key, "LogMode") == 0) {
if (strcasecmp(value, "daily") == 0)
{
m_Mode = LoggingMode_Daily;
} else if (strcasecmp(value, "map") == 0) {
m_Mode = LoggingMode_PerMap;
} else if (strcasecmp(value, "game") == 0) {
m_Mode = LoggingMode_Game;
} else {
UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]");
return ConfigResult_Reject;
}
return ConfigResult_Accept;
}
return ConfigResult_Ignore;
}
void Logger::OnSourceModStartup(bool late)
{
InitLogger(m_Mode);
}
void Logger::OnSourceModAllShutdown()
{
CloseLogger();
}
void Logger::OnSourceModLevelChange(const char *mapName)
{
MapChange(mapName);
}
void Logger::_NewMapFile()
{
if (!m_Active)
{
return;
}
/* Append "Log file closed" to previous log file */
_CloseFile();
char _filename[256];
int i = 0;
time_t t;
GetAdjustedTime(&t);
tm *curtime = localtime(&t);
while (true)
{
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
FILE *fp = fopen(_filename, "r");
if (!fp)
{
break;
}
fclose(fp);
i++;
}
m_NrmFileName.assign(_filename);
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
if (!fp)
{
char error[255];
g_LibSys.GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return;
} else {
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
fclose(fp);
}
}
void Logger::_CloseFile()
{
if (!m_Active)
{
return;
}
FILE *fp = NULL;
if (!m_NrmFileName.empty())
{
fp = fopen(m_NrmFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogMessage("Log file closed.");
fclose(fp);
}
m_NrmFileName.clear();
}
if (!m_ErrMapStart)
{
return;
}
fp = fopen(m_ErrFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogError("Error log file session closed.");
fclose(fp);
}
m_ErrFileName.clear();
}
void Logger::InitLogger(LoggingMode mode)
{
m_Mode = mode;
m_Active = m_InitialState;
time_t t;
GetAdjustedTime(&t);
tm *curtime = localtime(&t);
m_CurDay = curtime->tm_mday;
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);
m_ErrFileName.assign(_filename);
switch (m_Mode)
{
case LoggingMode_PerMap:
{
if (!m_Active)
{
m_DelayedStart = true;
}
break;
}
case LoggingMode_Daily:
{
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_DailyPrintHdr = true;
break;
}
default:
{
/* do nothing... */
break;
}
}
}
void Logger::CloseLogger()
{
_CloseFile();
}
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
{
if (!m_Active)
{
return;
}
va_list ap;
va_start(ap, msg);
LogToOpenFileEx(fp, msg, 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)
{
if (!m_Active)
{
return;
}
static ConVar *sv_logecho = icvar->FindVar("sv_logecho");
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);
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, ...)
{
if (!m_Active)
{
return;
}
if (m_Mode == LoggingMode_Game)
{
va_list ap;
va_start(ap, vafmt);
_PrintToGameLog(vafmt, ap);
va_end(ap);
return;
}
if (m_DelayedStart)
{
m_DelayedStart = false;
_NewMapFile();
}
time_t t;
GetAdjustedTime(&t);
tm *curtime = localtime(&t);
FILE *fp = NULL;
if (m_Mode == LoggingMode_PerMap)
{
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
_NewMapFile();
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
goto print_error;
}
}
} else {
if (m_CurDay != curtime->tm_mday)
{
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);
m_NrmFileName.assign(_filename);
m_CurDay = curtime->tm_mday;
m_DailyPrintHdr = true;
}
fp = fopen(m_NrmFileName.c_str(), "a+");
}
if (fp)
{
if (m_DailyPrintHdr)
{
char date[32];
m_DailyPrintHdr = false;
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
}
va_list ap;
va_start(ap, vafmt);
LogToOpenFileEx(fp, vafmt, ap);
va_end(ap);
fclose(fp);
} else {
goto print_error;
}
return;
print_error:
char error[255];
g_LibSys.GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
}
void Logger::LogError(const char *vafmt, ...)
{
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)
{
return;
}
time_t t;
GetAdjustedTime(&t);
tm *curtime = localtime(&t);
if (curtime->tm_mday != m_CurDay)
{
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);
m_ErrFileName.assign(_filename);
m_CurDay = curtime->tm_mday;
m_ErrMapStart = false;
}
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
if (fp)
{
if (!m_ErrMapStart)
{
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod error session started\n", date);
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrMapStart = true;
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
}
else
{
char error[255];
g_LibSys.GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return;
}
}
void Logger::MapChange(const char *mapname)
{
m_CurMapName.assign(mapname);
switch (m_Mode)
{
case LoggingMode_Daily:
{
LogMessage("-------- Mapchange to %s --------", mapname);
break;
}
case LoggingMode_PerMap:
{
_NewMapFile();
break;
}
default:
{
/* Do nothing... */
break;
}
}
if (m_ErrMapStart)
{
LogError("Error log file session closed.");
}
m_ErrMapStart = false;
}
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
{
char msg[3072];
size_t len;
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
msg[len++] = '\n';
msg[len] = '\0';
Engine_LogPrintWrapper(msg);
}
const char *Logger::GetLogFileName(LogType type) const
{
switch (type)
{
case LogType_Normal:
{
return m_NrmFileName.c_str();
}
case LogType_Error:
{
return m_ErrFileName.c_str();
}
default:
{
return "";
}
}
}
LoggingMode Logger::GetLoggingMode() const
{
return m_Mode;
}
void Logger::EnableLogging()
{
if (m_Active)
{
return;
}
m_Active = true;
LogMessage("[SM] Logging enabled manually by user.");
}
void Logger::DisableLogging()
{
if (!m_Active)
{
return;
}
LogMessage("[SM] Logging disabled manually by user.");
m_Active = false;
}
void Logger::LogFatal(const char *msg, ...)
{
/* :TODO: make this print all pretty-like
* In fact, the pretty log printing function should be abstracted.
* It's already implemented twice which is bad.
*/
va_list ap;
char path[PLATFORM_MAX_PATH];
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
FILE *fp = fopen(path, "at");
if (fp)
{
m_Active = true;
va_start(ap, msg);
LogToOpenFileEx(fp, msg, ap);
va_end(ap);
m_Active = false;
fclose(fp);
}
}
bool g_in_game_log_hook = false;
static LoggerCore g_LoggerCore;
SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *);
static void HookLogPrint(const char *message)
{
g_in_game_log_hook = true;
bool stopped = logicore.OnLogPrint(message);
g_in_game_log_hook = false;
if (stopped)
RETURN_META(MRES_SUPERCEDE);
}
void LoggerCore::OnSourceModStartup(bool late)
{
SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
}
void LoggerCore::OnSourceModAllShutdown()
{
SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false);
}
void Engine_LogPrintWrapper(const char *msg)
{
if (g_in_game_log_hook)
+61 -1
View File
@@ -38,13 +38,73 @@
using namespace SourceHook;
class LoggerCore : public SMGlobalClass
enum LogType
{
LogType_Normal,
LogType_Error
};
enum LoggingMode
{
LoggingMode_Daily,
LoggingMode_PerMap,
LoggingMode_Game
};
class Logger : public SMGlobalClass
{
public:
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
m_InitialState(true)
{
}
public: //SMGlobalClass
ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength);
void OnSourceModStartup(bool late);
void OnSourceModAllShutdown();
void OnSourceModLevelChange(const char *mapName);
public:
void InitLogger(LoggingMode mode);
void CloseLogger();
void EnableLogging();
void DisableLogging();
void LogMessage(const char *msg, ...);
void LogError(const char *msg, ...);
void LogErrorEx(const char *msg, va_list ap);
void LogFatal(const char *msg, ...);
void LogToOpenFile(FILE *fp, const char *msg, ...);
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);
const char *GetLogFileName(LogType type) const;
LoggingMode GetLoggingMode() const;
private:
void _CloseFile();
void _NewMapFile();
void _PrintToGameLog(const char *fmt, va_list ap);
private:
String m_NrmFileName;
String m_ErrFileName;
String m_CurMapName;
LoggingMode m_Mode;
int m_CurDay;
bool m_ErrMapStart;
bool m_Active;
bool m_DelayedStart;
bool m_DailyPrintHdr;
bool m_InitialState;
};
void Engine_LogPrintWrapper(const char *msg);
extern bool g_in_game_log_hook;
extern Logger g_Logger;
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
+12 -10
View File
@@ -38,6 +38,8 @@
#include "sourcemm_api.h"
#include "PlayerManager.h"
#include "MenuStyle_Valve.h"
#include "ShareSys.h"
#include "HandleSys.h"
#include "sourcemm_api.h"
#include "logic_bridge.h"
@@ -54,24 +56,24 @@ MenuManager::MenuManager()
void MenuManager::OnSourceModAllInitialized()
{
sharesys->AddInterface(NULL, this);
g_ShareSys.AddInterface(NULL, this);
HandleAccess access;
handlesys->InitAccessDefaults(NULL, &access);
g_HandleSys.InitAccessDefaults(NULL, &access);
/* Deny cloning to menus */
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 */
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()
{
handlesys->RemoveType(m_MenuType, g_pCoreIdent);
handlesys->RemoveType(m_StyleType, g_pCoreIdent);
g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
}
void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
@@ -110,7 +112,7 @@ Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
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)
@@ -120,7 +122,7 @@ Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
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)
@@ -130,7 +132,7 @@ HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
sec.pIdentity = g_pCoreIdent;
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)
@@ -140,7 +142,7 @@ HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
sec.pIdentity = 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)
+1
View File
@@ -37,6 +37,7 @@
#include <sh_stack.h>
#include <sh_list.h>
#include <sh_string.h>
#include "sm_memtable.h"
#include "sm_globals.h"
using namespace SourceMod;
+46 -25
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,12 +34,11 @@
#include "MenuStyle_Base.h"
#include "PlayerManager.h"
#include "MenuManager.h"
#include "HandleSys.h"
#include "CellRecipientFilter.h"
#if defined MENU_DEBUG
#include "Logger.h"
#endif
#include "logic_bridge.h"
#include "AutoHandleRooter.h"
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
{
@@ -338,7 +337,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
#endif
0,
PITCH_NORM,
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2
0,
#endif
&pos);
@@ -604,7 +603,7 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
}
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_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
{
@@ -627,74 +626,94 @@ Handle_t CBaseMenu::GetHandle()
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
{
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
&& m_items.length() >= m_pStyle->GetMaxPageItems())
&& m_items.size() >= m_pStyle->GetMaxPageItems())
{
return false;
}
CItem item;
item.info = info;
item.infoString = m_Strings.AddString(info);
if (draw.display)
item.display = new ke::AString(draw.display);
{
item.displayString = m_Strings.AddString(draw.display);
}
item.style = draw.style;
m_items.append(ke::Move(item));
m_items.push_back(item);
return true;
}
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
{
if (m_Pagination == (unsigned)MENU_NO_PAGINATION &&
m_items.length() >= m_pStyle->GetMaxPageItems())
if (m_Pagination == (unsigned)MENU_NO_PAGINATION
&& m_items.size() >= m_pStyle->GetMaxPageItems())
{
return false;
}
if (position >= m_items.length())
if (position >= m_items.size())
{
return false;
}
CItem item;
item.info = info;
item.infoString = m_Strings.AddString(info);
if (draw.display)
item.display = new ke::AString(draw.display);
{
item.displayString = m_Strings.AddString(draw.display);
}
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;
}
bool CBaseMenu::RemoveItem(unsigned int position)
{
if (position >= m_items.length())
if (position >= m_items.size())
{
return false;
}
m_items.erase(m_items.iterAt(position));
if (m_items.size() == 0)
{
m_Strings.Reset();
}
m_items.remove(position);
return true;
}
void CBaseMenu::RemoveAllItems()
{
m_items.clear();
m_Strings.Reset();
}
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
{
if (position >= m_items.length())
if (position >= m_items.size())
{
return NULL;
}
if (draw)
{
draw->display = m_items[position].display->chars();
draw->display = m_Strings.GetString(m_items[position].displayString);
draw->style = m_items[position].style;
}
return m_items[position].info.chars();
return m_Strings.GetString(m_items[position].infoString);
}
unsigned int CBaseMenu::GetItemCount()
{
return m_items.length();
return m_items.size();
}
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
@@ -727,12 +746,12 @@ IMenuStyle *CBaseMenu::GetDrawStyle()
void CBaseMenu::SetDefaultTitle(const char *message)
{
m_Title = message;
m_Title.assign(message);
}
const char *CBaseMenu::GetDefaultTitle()
{
return m_Title.chars();
return m_Title.c_str();
}
void CBaseMenu::Cancel()
@@ -799,7 +818,7 @@ void CBaseMenu::InternalDelete()
m_hHandle = BAD_HANDLE;
m_bDeleting = true;
handlesys->FreeHandle(hndl, &sec);
g_HandleSys.FreeHandle(hndl, &sec);
}
m_pHandler->OnMenuDestroy(this);
@@ -824,5 +843,7 @@ IMenuHandler *CBaseMenu::GetHandler()
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));
}
+12 -27
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,45 +34,29 @@
#include <IMenuManager.h>
#include <IPlayerHelpers.h>
#include <am-string.h>
#include <am-vector.h>
#include <sh_string.h>
#include <sh_vector.h>
#include "sm_memtable.h"
#include "sm_fastlink.h"
using namespace SourceMod;
using namespace SourceHook;
class CItem
{
public:
CItem()
{
infoString = -1;
displayString = -1;
style = 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:
ke::AString info;
ke::AutoPtr<ke::AString> display;
int infoString;
int displayString;
unsigned int style;
unsigned int access;
private:
CItem(const CItem &other) KE_DELETE;
CItem &operator =(const CItem &other) KE_DELETE;
};
class CBaseMenuPlayer
@@ -155,10 +139,11 @@ public:
private:
void InternalDelete();
protected:
ke::AString m_Title;
String m_Title;
IMenuStyle *m_pStyle;
BaseStringTable m_Strings;
unsigned int m_Pagination;
ke::Vector<CItem> m_items;
CVector<CItem> m_items;
bool m_bShouldDelete;
bool m_bCancelling;
IdentityToken_t *m_pOwner;
+13 -17
View File
@@ -83,10 +83,6 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
}
g_bRadioInit = true;
// Always register the style. Use IsSupported() to check for validity before use.
g_Menus.AddStyle(this);
const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
if (!msg || msg[0] == '\0')
{
@@ -122,6 +118,7 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
}
}
g_Menus.AddStyle(this);
g_Menus.SetDefaultStyle(this);
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
@@ -141,11 +138,7 @@ void CRadioStyle::OnSourceModShutdown()
bool CRadioStyle::IsSupported()
{
#if SOURCE_ENGINE == SE_DOTA
return false;
#else
return (g_ShowMenuId != -1);
#endif
}
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
@@ -176,7 +169,6 @@ void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFi
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
#endif
{
#if SOURCE_ENGINE != SE_DOTA
int count = pFilter->GetRecipientCount();
#ifdef USE_PROTOBUF_USERMESSAGES
@@ -194,7 +186,6 @@ void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFil
{
g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
}
#endif
}
void CRadioStyle::OnUserMessageSent(int msg_id)
@@ -264,6 +255,15 @@ CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
return display;
}
IMenuPanel *CRadioStyle::MakeRadioDisplay(const char *str, int keys)
{
CRadioDisplay *pPanel = MakeRadioDisplay(NULL);
pPanel->DirectSet(str, keys);
return pPanel;
}
void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
{
m_FreeDisplays.push(display);
@@ -330,12 +330,11 @@ void CRadioDisplay::Reset()
keys = 0;
}
bool CRadioDisplay::DirectSet(const char *str)
void CRadioDisplay::DirectSet(const char *str, int keymap)
{
m_Title.clear();
m_BufferText.assign(str);
return true;
keys = keymap;
}
unsigned int CRadioDisplay::GetCurrentKey()
@@ -474,8 +473,7 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
void CRadioMenuPlayer::Radio_Refresh()
{
#if SOURCE_ENGINE != SE_DOTA
cell_t players[1] = { (cell_t)m_index };
cell_t players[1] = {m_index};
char *ptr = display_pkt;
char save = 0;
size_t len = display_len;
@@ -528,7 +526,6 @@ void CRadioMenuPlayer::Radio_Refresh()
#endif
display_last_refresh = gpGlobals->curtime;
#endif // !DOTA
}
int CRadioDisplay::GetAmountRemaining()
@@ -596,7 +593,6 @@ bool CRadioMenu::DisplayAtItem(int client,
return false;
}
AutoHandleRooter ahr(this->GetHandle());
return g_RadioMenuStyle.DoClientMenu(client,
this,
start_item,
+3 -3
View File
@@ -41,8 +41,6 @@
#include "sm_fastlink.h"
#include <sh_stack.h>
#include <compat_wrappers.h>
#include "logic/common_logic.h"
#include "AutoHandleRooter.h"
using namespace SourceMod;
@@ -103,6 +101,7 @@ public:
CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL);
void FreeRadioDisplay(CRadioDisplay *display);
CRadioMenuPlayer *GetRadioMenuPlayer(int client);
IMenuPanel *MakeRadioDisplay(const char *str, int keys);
private:
CRadioMenuPlayer *m_players;
CStack<CRadioDisplay *> m_FreeDisplays;
@@ -130,7 +129,8 @@ public: //IMenuPanel
bool SetCurrentKey(unsigned int key);
int GetAmountRemaining();
unsigned int GetApproxMemUsage();
bool DirectSet(const char *str);
public:
void DirectSet(const char *str, int keymap);
private:
String m_BufferText;
String m_Title;
+2 -7
View File
@@ -65,20 +65,16 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom
void ValveMenuStyle::OnSourceModAllInitialized()
{
#if SOURCE_ENGINE != SE_DOTA
g_Players.AddClientListener(this);
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
#endif
}
void ValveMenuStyle::OnSourceModShutdown()
{
#if SOURCE_ENGINE != SE_DOTA
SH_RELEASE_CALLCLASS(g_pSPHCC);
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false);
SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
g_Players.RemoveClientListener(this);
#endif
}
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
@@ -408,7 +404,6 @@ bool CValveMenu::DisplayAtItem(int client,
return false;
}
AutoHandleRooter ahr(this->GetHandle());
return g_ValveMenuStyle.DoClientMenu(client, this, start_item, alt_handler ? alt_handler : m_pHandler, time);
}
-4
View File
@@ -39,8 +39,6 @@
#include "KeyValues.h"
#include "sm_fastlink.h"
#include <compat_wrappers.h>
#include "logic/common_logic.h"
#include "AutoHandleRooter.h"
using namespace SourceMod;
@@ -77,7 +75,6 @@ public: //IMenuStyle
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
unsigned int GetMaxPageItems();
unsigned int GetApproxMemUsage();
bool IsSupported() { return true; }
private:
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
private:
@@ -108,7 +105,6 @@ public:
bool SetCurrentKey(unsigned int key);
int GetAmountRemaining();
unsigned int GetApproxMemUsage();
bool DirectSet(const char *str) { return false; }
private:
KeyValues *m_pKv;
unsigned int m_NextPos;
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourcePawn
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
@@ -54,7 +54,7 @@ unsigned int NativeInterface::GetInterfaceVersion()
void NativeInterface::OnSourceModAllInitialized()
{
sharesys->AddInterface(NULL, &g_NInvoke);
g_ShareSys.AddInterface(NULL, &g_NInvoke);
}
IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes)
@@ -69,15 +69,30 @@ INativeInvoker *NativeInterface::CreateInvoker()
bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
{
ke::Ref<Native> entry = g_ShareSys.FindNative(name);
if (!entry)
NativeEntry *entry;
entry = g_ShareSys.FindNative(name);
if (entry == NULL)
{
return false;
}
if (!entry->owner)
native = NULL;
if (entry->replacement.owner != NULL)
{
native = entry->replacement.func;
}
else if (entry->owner != NULL)
{
native = entry->func;
}
if (native == NULL)
{
return false;
}
native_ = entry->func();
context_ = pContext;
this->pContext = pContext;
m_curparam = 0;
m_errorstate = SP_ERROR_NONE;
@@ -169,13 +184,15 @@ int NativeInvoker::_PushString(const char *string, int sz_flags, int cp_flags, s
void NativeInvoker::Cancel()
{
if (context_ == NULL)
if (pContext == NULL)
{
return;
}
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
context_ = NULL;
native_ = NULL;
pContext = NULL;
native = NULL;
}
int NativeInvoker::SetError(int err)
@@ -188,8 +205,10 @@ int NativeInvoker::Invoke(cell_t *result)
{
int err = SP_ERROR_NONE;
if (context_ == NULL)
if (pContext == NULL)
{
return SP_ERROR_INVALID_NATIVE;
}
if (m_errorstate != SP_ERROR_NONE)
{
@@ -206,7 +225,7 @@ int NativeInvoker::Invoke(cell_t *result)
}
//This is for re-entrancy!
IPluginContext *ctx = context_;
IPluginContext *ctx = pContext;
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
cell_t *temp_params = &_temp_params[1];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
@@ -220,7 +239,7 @@ int NativeInvoker::Invoke(cell_t *result)
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
}
m_curparam = 0;
context_ = NULL;
pContext = NULL;
/* Initialize 0th parameter */
_temp_params[0] = numparams;
@@ -305,7 +324,7 @@ int NativeInvoker::Invoke(cell_t *result)
/* Make the call if we can */
if (err == SP_ERROR_NONE)
{
*result = native_(ctx, _temp_params);
*result = native(ctx, _temp_params);
if (ctx->GetLastNativeError() != SP_ERROR_NONE)
{
docopies = false;
@@ -32,12 +32,8 @@
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#include <sp_vm_api.h>
#include "sm_globals.h"
#include <INativeInvoker.h>
#include "common_logic.h"
using namespace SourceMod;
using namespace SourcePawn;
struct ParamInfo
{
@@ -75,8 +71,8 @@ private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
IPluginContext *context_;
SPVM_NATIVE_FUNC native_;
IPluginContext *pContext;
SPVM_NATIVE_FUNC native;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
+144
View File
@@ -0,0 +1,144 @@
#include "NativeOwner.h"
#include "ShareSys.h"
#include "PluginSys.h"
CNativeOwner::CNativeOwner() : m_nMarkSerial(0)
{
}
void CNativeOwner::SetMarkSerial(unsigned int serial)
{
m_nMarkSerial = serial;
}
unsigned int CNativeOwner::GetMarkSerial()
{
return m_nMarkSerial;
}
void CNativeOwner::AddDependent(CPlugin *pPlugin)
{
m_Dependents.push_back(pPlugin);
}
void CNativeOwner::AddWeakRef(const WeakNative & ref)
{
m_WeakRefs.push_back(ref);
}
void CNativeOwner::AddNatives(const sp_nativeinfo_t *natives)
{
NativeEntry *pEntry;
for (unsigned int i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
{
if ((pEntry = g_ShareSys.AddNativeToCache(this, &natives[i])) == NULL)
{
continue;
}
m_Natives.push_back(pEntry);
}
}
void CNativeOwner::PropogateMarkSerial(unsigned int serial)
{
CNativeOwner *pOwner;
List<CPlugin *>::iterator iter;
for (iter = m_Dependents.begin();
iter != m_Dependents.end();
iter++)
{
pOwner = (*iter);
pOwner->SetMarkSerial(serial);
}
}
void CNativeOwner::UnbindWeakRef(const WeakNative & ref)
{
sp_native_t *native;
IPluginContext *pContext;
pContext = ref.pl->GetBaseContext();
if ((pContext->GetNativeByIndex(ref.idx, &native)) == SP_ERROR_NONE)
{
/* If there is no reference, the native must be unbound */
if (ref.entry == NULL)
{
native->status = SP_NATIVE_UNBOUND;
native->pfn = NULL;
}
/* If we've cached a reference, it's a core native we can
* rebind back to its original (this was a replacement).
*/
else
{
native->pfn = ref.entry->func;
}
}
}
void CNativeOwner::DropEverything()
{
NativeEntry *pEntry;
List<WeakNative>::iterator iter;
List<NativeEntry *>::iterator ntv_iter;
/* Unbind and remove all weak references to us */
iter = m_WeakRefs.begin();
while (iter != m_WeakRefs.end())
{
UnbindWeakRef((*iter));
iter = m_WeakRefs.erase(iter);
}
/* Unmark our replacement natives */
ntv_iter = m_ReplacedNatives.begin();
while (ntv_iter != m_ReplacedNatives.end())
{
pEntry = (*ntv_iter);
pEntry->replacement.func = NULL;
pEntry->replacement.owner = NULL;
ntv_iter = m_ReplacedNatives.erase(ntv_iter);
}
/* Strip all of our natives from the cache */
ntv_iter = m_Natives.begin();
while (ntv_iter != m_Natives.end())
{
g_ShareSys.ClearNativeFromCache(this, (*ntv_iter)->name);
ntv_iter = m_Natives.erase(ntv_iter);
}
}
void CNativeOwner::DropWeakRefsTo(CPlugin *pPlugin)
{
List<WeakNative>::iterator iter;
iter = m_WeakRefs.begin();
while (iter != m_WeakRefs.end())
{
WeakNative & ref = (*iter);
if (ref.pl == pPlugin)
{
iter = m_WeakRefs.erase(iter);
}
else
{
iter++;
}
}
}
void CNativeOwner::DropRefsTo(CPlugin *pPlugin)
{
m_Dependents.remove(pPlugin);
DropWeakRefsTo(pPlugin);
}
void CNativeOwner::AddReplacedNative(NativeEntry *pEntry)
{
m_ReplacedNatives.push_back(pEntry);
}
+59
View File
@@ -0,0 +1,59 @@
#ifndef _INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
#include <sp_vm_types.h>
#include <sh_list.h>
class CPlugin;
struct NativeEntry;
struct WeakNative
{
WeakNative(CPlugin *plugin, uint32_t index) :
pl(plugin), idx(index), entry(NULL)
{
pl = plugin;
idx = index;
}
WeakNative(CPlugin *plugin, uint32_t index, NativeEntry *pEntry) :
pl(plugin), idx(index), entry(pEntry)
{
pl = plugin;
idx = index;
}
CPlugin *pl;
uint32_t idx;
NativeEntry *entry;
};
using namespace SourceHook;
class CNativeOwner
{
public:
CNativeOwner();
public:
virtual void DropEverything();
public:
void AddNatives(const sp_nativeinfo_t *info);
public:
void SetMarkSerial(unsigned int serial);
unsigned int GetMarkSerial();
void PropogateMarkSerial(unsigned int serial);
public:
void AddDependent(CPlugin *pPlugin);
void AddWeakRef(const WeakNative & ref);
void DropRefsTo(CPlugin *pPlugin);
void AddReplacedNative(NativeEntry *pEntry);
private:
void DropWeakRefsTo(CPlugin *pPlugin);
void UnbindWeakRef(const WeakNative & ref);
protected:
List<CPlugin *> m_Dependents;
unsigned int m_nMarkSerial;
List<WeakNative> m_WeakRefs;
List<NativeEntry *> m_Natives;
List<NativeEntry *> m_ReplacedNatives;
};
#endif //_INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
+8 -14
View File
@@ -36,7 +36,6 @@
#include "sm_stringutil.h"
#include "sourcehook.h"
#include "sm_srvcmds.h"
#include "logic_bridge.h"
NextMapManager g_NextMap;
@@ -46,9 +45,7 @@ SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, co
SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool);
#endif
#if SOURCE_ENGINE == SE_DOTA
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
@@ -72,13 +69,13 @@ 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);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
#endif
ConCommand *pCmd = FindCommand("changelevel");
if (pCmd != NULL)
{
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdChangeLevelCallback), false);
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdChangeLevelCallback, false);
changeLevelCmd = pCmd;
}
}
@@ -88,12 +85,12 @@ 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);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, ChangeLevel, engine, this, &NextMapManager::HookChangeLevel, false);
#endif
if (changeLevelCmd != NULL)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, changeLevelCmd, SH_STATIC(CmdChangeLevelCallback), false);
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, changeLevelCmd, CmdChangeLevelCallback, false);
}
SourceHook::List<MapChangeData *>::iterator iter;
@@ -131,7 +128,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
{
if (g_forcedChange)
{
logger->LogMessage("[SM] Changed map to \"%s\"", map);
g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
RETURN_META(MRES_IGNORED);
}
@@ -142,7 +139,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
RETURN_META(MRES_IGNORED);
}
logger->LogMessage("[SM] Changed map to \"%s\"", newmap);
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");
@@ -208,10 +205,7 @@ NextMapManager::NextMapManager()
m_mapHistory = SourceHook::List<MapChangeData *>();
}
#if SOURCE_ENGINE == SE_DOTA
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command)
{
#else
+2 -6
View File
@@ -58,9 +58,7 @@ struct MapChangeData
time_t startTime;
};
#if SOURCE_ENGINE == SE_DOTA
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command);
#else
void CmdChangeLevelCallback();
@@ -71,9 +69,7 @@ class NextMapManager : public SMGlobalClass
public:
NextMapManager();
#if SOURCE_ENGINE == SE_DOTA
friend void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
friend void CmdChangeLevelCallback(const CCommand &command);
#else
friend void CmdChangeLevelCallback();
+158 -680
View File
File diff suppressed because it is too large Load Diff
+7 -42
View File
@@ -41,11 +41,8 @@
#include <sh_string.h>
#include <sh_list.h>
#include <sh_vector.h>
#include <am-string.h>
#include "ConVarManager.h"
#include <steam/steamclientpublic.h>
using namespace SourceHook;
#define PLAYER_LIFE_UNKNOWN 0
@@ -74,10 +71,6 @@ public:
const char *GetIPAddress();
const char *GetAuthString(bool validated = true);
unsigned int GetSteamAccountID(bool validated = true);
const CSteamID &GetSteamId(bool validated = true);
uint64_t GetSteamId64(bool validated = true) { return GetSteamId(validated).ConvertToUint64(); }
const char *GetSteam2Id(bool validated = true);
const char *GetSteam3Id(bool validated = true);
edict_t *GetEdict();
bool IsInGame();
bool WasCountedAsInGame();
@@ -97,9 +90,6 @@ public:
bool RunAdminCacheChecks();
void NotifyPostAdminChecks();
unsigned int GetSerial();
int GetIndex() const;
void PrintToConsole(const char *pMsg);
void ClearAdmin();
public:
void DoBasicAdminChecks();
void MarkAsBeingKicked();
@@ -110,7 +100,7 @@ private:
void Disconnect();
void SetName(const char *name);
void DumpAdmin(bool deleting);
void UpdateAuthIds();
void SetAuthString(const char *auth);
void Authorize();
void Authorize_Post();
void DoPostConnectAuthorization();
@@ -123,9 +113,7 @@ private:
String m_Name;
String m_Ip;
String m_IpNoPort;
ke::AString m_AuthID;
ke::AString m_Steam2Id;
ke::AString m_Steam3Id;
String m_AuthID;
AdminId m_Admin;
bool m_TempAdmin;
edict_t *m_pEdict;
@@ -139,10 +127,7 @@ private:
bool m_bIsSourceTV;
bool m_bIsReplay;
serial_t m_Serial;
CSteamID m_SteamId;
#if SOURCE_ENGINE == SE_CSGO
QueryCvarCookie_t m_LanguageCookie;
#endif
unsigned int m_SteamAccountID;
};
class PlayerManager :
@@ -162,17 +147,9 @@ public: //SMGlobalClass
public:
CPlayer *GetPlayerByIndex(int client) const;
void RunAuthChecks();
void ClearAdminId(AdminId id);
void ClearAllAdmins();
public:
#if SOURCE_ENGINE == SE_DOTA
bool OnClientConnect(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
bool OnClientConnect_Post(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
void OnClientPutInServer(CEntityIndex index, char const *playername);
void OnClientDisconnect(CEntityIndex index, int reason);
void OnClientDisconnect_Post(CEntityIndex index, int reason);
void OnClientCommand(CEntityIndex index, const CCommand &args);
void OnClientSettingsChanged(CEntityIndex index);
//void OnClientSettingsChanged_Pre(CEntityIndex client);
#else
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
void OnClientPutInServer(edict_t *pEntity, char const *playername);
@@ -185,8 +162,6 @@ public:
#endif
void OnClientSettingsChanged(edict_t *pEntity);
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
#endif
void OnServerHibernationUpdate(bool bHibernating);
public: //IPlayerManager
void AddClientListener(IClientListener *listener);
void RemoveClientListener(IClientListener *listener);
@@ -202,8 +177,6 @@ public: //IPlayerManager
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
void ProcessCommandTarget(cmd_target_info_t *info);
int GetClientFromSerial(unsigned int serial);
void ClearAdminId(AdminId id);
void RecheckAnyAdmins();
public:
inline int MaxClients()
{
@@ -220,18 +193,12 @@ public:
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
const char *GetPassInfoVar();
void RecheckAnyAdmins();
unsigned int GetReplyTo();
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:
#if SOURCE_ENGINE == SE_DOTA
void OnServerActivate();
#else
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
#endif
void InvalidatePlayer(CPlayer *pPlayer);
private:
List<IClientListener *> m_hooks;
@@ -263,9 +230,7 @@ private:
int m_ReplayUserId;
};
#if SOURCE_ENGINE == SE_DOTA
void CmdMaxplayersCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdMaxplayersCallback(const CCommand &command);
#else
void CmdMaxplayersCallback();
+349
View File
@@ -0,0 +1,349 @@
/**
* 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 <stdarg.h>
#include <string.h>
#include "PluginInfoDatabase.h"
#include "PluginSys.h"
void PluginSettings::Init()
{
name = -1;
pause_val = false;
type_val = PluginType_MapUpdated;
optarray = -1;
opts_num = 0;
opts_size = 0;
blockload_val = false;
}
/**
* :TODO: write the logger, make these errors log instead of being static
* NOTE: once we do that, we will have to change some code to ignore sections
*/
CPluginInfoDatabase::CPluginInfoDatabase()
{
m_strtab = NULL;
m_infodb_count = 0;
m_infodb_size = 0;
m_infodb = -1;
}
CPluginInfoDatabase::~CPluginInfoDatabase()
{
delete m_strtab;
}
void CPluginInfoDatabase::ReadSMC_ParseStart()
{
/* Create or reset our string table */
if (m_strtab)
{
m_strtab->Reset();
} else {
m_strtab = new BaseStringTable(1024);
}
/* Set our internal states to the beginning */
in_plugins = false;
cur_plugin = -1;
in_options = false;
m_infodb_size = 0;
m_infodb_count = 0;
m_infodb = -1;
}
SMCResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
{
char buffer[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
m_errmsg = m_strtab->AddString(buffer);
return SMCResult_HaltFail;
}
unsigned int CPluginInfoDatabase::GetSettingsNum()
{
return m_infodb_count;
}
PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
{
BaseMemTable *memtab = m_strtab->GetMemTable();
int *table = (int *)memtab->GetAddress(m_infodb);
if (!table || index >= m_infodb_count)
{
return NULL;
}
PluginSettings *plugin = (PluginSettings *)memtab->GetAddress(table[index]);
const char *name = m_strtab->GetString(plugin->name);
if (!name)
{
return NULL;
}
if (!g_PluginSys.TestAliasMatch(name, filename))
{
return NULL;
}
return plugin;
}
void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
{
PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
if (!table)
{
*key = NULL;
*val = NULL;
return;
}
if (opt_num >= settings->opts_num)
{
*key = NULL;
*val = NULL;
return;
}
*key = m_strtab->GetString(table[opt_num].key);
*val = m_strtab->GetString(table[opt_num].val);
}
SMCResult CPluginInfoDatabase::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{
if (cur_plugin != -1)
{
PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
if (!in_options)
{
if (strcmp(key, "pause") == 0)
{
if (strcasecmp(value, "yes") == 0)
{
plugin->pause_val = true;
}
else
{
plugin->pause_val = false;
}
}
else if (strcmp(key, "lifetime") == 0)
{
if (strcasecmp(value, "private") == 0)
{
plugin->type_val = PluginType_Private;
}
else if (strcasecmp(value, "mapsync") == 0)
{
plugin->type_val = PluginType_MapUpdated;
}
else if (strcasecmp(value, "maponly") == 0)
{
plugin->type_val = PluginType_MapOnly;
}
else if (strcasecmp(value, "global") == 0)
{
plugin->type_val = PluginType_Global;
}
else
{
return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
}
}
else if (strcmp(key, "blockload") == 0)
{
plugin->blockload_val = true;
}
else
{
return MakeError("Unknown property key: \"%s\"", key);
}
}
else
{
/* Cache every option, valid or not */
int keyidx = m_strtab->AddString(key);
int validx = m_strtab->AddString(value);
PluginOpts *table;
BaseMemTable *memtab = m_strtab->GetMemTable();
plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
if (plugin->opts_num + 1 > plugin->opts_size)
{
unsigned int oldsize = plugin->opts_size;
if (oldsize == 0)
{
//right now we don't have many
plugin->opts_size = 2;
}
else
{
plugin->opts_size *= 2;
}
int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
/* in case it resized */
plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
if (plugin->optarray != -1)
{
void *oldtable = memtab->GetAddress(plugin->optarray);
memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
}
plugin->optarray = newidx;
}
else
{
table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
}
PluginOpts *opt = &table[plugin->opts_num++];
opt->key = keyidx;
opt->val = validx;
}
}
else if (in_plugins)
{
return MakeError("Unknown property key: \"%s\"", key);
}
else
{
/* Ignore anything we don't know about! */
}
return SMCResult_Continue;
}
SMCResult CPluginInfoDatabase::ReadSMC_LeavingSection(const SMCStates *states)
{
if (in_plugins)
{
if (cur_plugin != -1)
{
if (in_options)
{
in_options = false;
}
else
{
/* If the plugin is ending, add it to the table */
BaseMemTable *memtab = m_strtab->GetMemTable();
int *table;
if (m_infodb_count + 1 > m_infodb_size)
{
unsigned int oldsize = m_infodb_size;
if (!m_infodb_size)
{
m_infodb_size = 8;
}
else
{
m_infodb_size *= 2;
}
int newidx = memtab->CreateMem(m_infodb_size * sizeof(int), (void **)&table);
if (m_infodb != -1)
{
void *oldtable = (int *)memtab->GetAddress(m_infodb);
memcpy(table, oldtable, oldsize * sizeof(int));
}
m_infodb = newidx;
}
else
{
table = (int *)memtab->GetAddress(m_infodb);
}
/* Assign to table and scrap the current plugin */
table[m_infodb_count++] = cur_plugin;
cur_plugin = -1;
}
}
else
{
in_plugins = false;
}
}
return SMCResult_Continue;
}
SMCResult CPluginInfoDatabase::ReadSMC_NewSection(const SMCStates *states, const char *name)
{
if (!in_plugins)
{
/* If we're not in the main Plugins section, and we don't get it for the name, error out */
if (strcmp(name, "Plugins") != 0)
{
return MakeError("Unknown root section: \"%s\"", name);
}
else
{
/* Otherwise set our states */
in_plugins = true;
cur_plugin = -1;
in_options = false;
}
}
else
{
if (cur_plugin == -1)
{
/* If we get a plugin node and we don't have a current plugin, create a new one */
PluginSettings *plugin;
int i_name = m_strtab->AddString(name);
cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
plugin->Init();
plugin->name = i_name;
in_options = false;
}
else
{
if (!in_options && strcmp(name, "Options") == 0)
{
in_options = true;
}
else
{
return MakeError("Unknown plugin sub-section: \"%s\"", name);
}
}
}
return SMCResult_Continue;
}
+106
View File
@@ -0,0 +1,106 @@
/**
* 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_CORE_SYSTEM_PLUGININFODATABASE_H_
#define _INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
/**
* This file parses plugin_settings.cfg and stores the information in cached memory.
* It provides simplistic abstraction to retrieving the info.
* :TODO: currently untested
*/
#include "sm_memtable.h"
#include "ITextParsers.h"
#include "IPluginSys.h"
#include "sm_globals.h"
struct PluginOpts
{
int key;
int val;
};
struct PluginSettings
{
void Init();
int name;
bool pause_val;
PluginType type_val;
int optarray;
size_t opts_num;
size_t opts_size;
bool blockload_val;
};
class CPluginInfoDatabase : public ITextListener_SMC
{
public:
CPluginInfoDatabase();
~CPluginInfoDatabase();
public: //ITextListener_SMC
void ReadSMC_ParseStart();
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
public:
/**
* Returns the number of plugin settings available.
*/
unsigned int GetSettingsNum();
/**
* Given an index, returns the plugin settings block if the filename matches.
* Otherwise, returns NULL.
*/
PluginSettings *GetSettingsIfMatch(unsigned int index, const char *filename);
/**
* Given a plugin settings struct and an index,
* returns the given JIT key/value option pair at that index.
* If the input is invalid, key and val will be set to NULL.
*/
void GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val);
private:
SMCResult MakeError(const char *fmt, ...);
private:
BaseStringTable *m_strtab;
int m_errmsg;
bool in_plugins;
bool in_options;
int m_infodb;
size_t m_infodb_count;
size_t m_infodb_size;
int cur_plugin;
};
#endif //_INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
File diff suppressed because it is too large Load Diff
+44 -45
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -42,10 +42,20 @@
#include <sh_stack.h>
#include <sh_vector.h>
#include <sh_string.h>
#include "common_logic.h"
#include "sm_globals.h"
#include "PluginInfoDatabase.h"
#include "sm_trie.h"
#include "sourcemod.h"
#include <IRootConsoleMenu.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
#if SOURCE_ENGINE >= SE_ALIENSWARM
#include "convar_sm_swarm.h"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#include "convar_sm_l4d.h"
#elif SOURCE_ENGINE >= SE_ORANGEBOX
#include "convar_sm_ob.h"
#else
#include "convar_sm.h"
#endif
#include "ITranslator.h"
#include "IGameConfigs.h"
#include "NativeOwner.h"
@@ -121,8 +131,23 @@ enum APLRes
APLRes_SilentFailure
};
enum LibraryAction
{
LibraryAction_Removed,
LibraryAction_Added
};
struct AutoConfig
{
String autocfg;
String folder;
bool create;
};
class CPlugin;
class CPlugin :
public SMPlugin,
public IPlugin,
public CNativeOwner
{
friend class CPluginManager;
@@ -149,9 +174,6 @@ public:
bool GetProperty(const char *prop, void **ptr, bool remove=false);
void DropEverything();
SourcePawn::IPluginRuntime *GetRuntime();
CNativeOwner *ToNativeOwner() {
return this;
}
public:
/**
* Creates a plugin object with default values.
@@ -161,11 +183,6 @@ public:
* a valid (but error-stated) CPlugin will be returned.
*/
static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
static inline bool matches(const char *file, const CPlugin *plugin)
{
return strcmp(plugin->m_filename, file) == 0;
}
public:
/**
@@ -204,11 +221,6 @@ public:
*/
void Call_OnAllPluginsLoaded();
/**
* Calls the OnLibraryAdded function.
*/
void Call_OnLibraryAdded(const char *lib);
/**
* Returns true if a plugin is usable.
*/
@@ -238,8 +250,8 @@ public:
bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
void AddConfig(bool autoCreate, const char *cfg, const char *folder);
size_t GetConfigCount();
AutoConfig *GetConfig(size_t i);
unsigned int GetConfigCount();
AutoConfig *GetConfig(unsigned int i);
inline void AddLibrary(const char *name)
{
m_Libraries.push_back(name);
@@ -265,7 +277,7 @@ private:
IPhraseCollection *m_pPhrases;
List<String> m_RequiredLibs;
List<String> m_Libraries;
StringHashMap<void *> m_Props;
Trie *m_pProps;
bool m_FakeNativesMissing;
bool m_LibraryMissing;
CVector<AutoConfig *> m_configs;
@@ -278,7 +290,7 @@ private:
};
class CPluginManager :
public IScriptManager,
public IPluginManager,
public SMGlobalClass,
public IHandleTypeDispatch,
public IRootConsoleCommand
@@ -305,7 +317,7 @@ public:
List<CPlugin *>::iterator current;
};
friend class CPluginManager::CPluginIterator;
public: //IScriptManager
public: //IPluginManager
IPlugin *LoadPlugin(const char *path,
bool debug,
PluginType type,
@@ -318,26 +330,6 @@ public: //IScriptManager
IPluginIterator *GetPluginIterator();
void AddPluginsListener(IPluginsListener *listener);
void RemovePluginsListener(IPluginsListener *listener);
void LoadAll(const char *config_path, const char *plugins_path);
void RefreshAll();
SMPlugin *FindPluginByOrder(unsigned num) {
return GetPluginByOrder(num);
}
SMPlugin *FindPluginByIdentity(IdentityToken_t *ident) {
return GetPluginFromIdentity(ident);
}
SMPlugin *FindPluginByContext(IPluginContext *ctx) {
return GetPluginByCtx(ctx->GetContext());
}
SMPlugin *FindPluginByContext(sp_context_t *ctx) {
return GetPluginByCtx(ctx);
}
SMPlugin *FindPluginByConsoleArg(const char *text);
SMPlugin *FindPluginByHandle(Handle_t hndl, HandleError *errp) {
return static_cast<SMPlugin *>(PluginFromHandle(hndl, errp));
}
const CVector<SMPlugin *> *ListPlugins();
void FreePluginList(const CVector<SMPlugin *> *plugins);
public: //SMGlobalClass
void OnSourceModAllInitialized();
void OnSourceModShutdown();
@@ -397,6 +389,11 @@ public:
*/
const char *GetStatusText(PluginStatus status);
/**
* Reload or update plugins on level shutdown.
*/
void ReloadOrUnloadPlugins();
/**
* Add public functions from all running or paused
* plugins to the specified forward if the names match.
@@ -420,6 +417,8 @@ public:
void UnloadAll();
CPlugin *FindPluginByConsoleArg(const char *arg);
void SyncMaxClients(int max_clients);
void ListPluginsToClient(CPlayer *player, const CCommand &args);
@@ -464,14 +463,14 @@ public:
{
return m_MyIdent;
}
IPluginManager *GetOldAPI();
private:
void TryRefreshDependencies(CPlugin *pOther);
private:
List<IPluginsListener *> m_listeners;
List<CPlugin *> m_plugins;
CStack<CPluginManager::CPluginIterator *> m_iters;
NameHashSet<CPlugin *> m_LoadLookup;
CPluginInfoDatabase m_PluginInfo;
Trie *m_LoadLookup;
bool m_AllPluginsLoaded;
IdentityToken_t *m_MyIdent;
+230 -114
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,14 +30,11 @@
*/
#include "ShareSys.h"
#include "ExtensionSys.h"
#include <ILibrarySys.h>
#include "common_logic.h"
#include "PluginSys.h"
#include "HandleSys.h"
#include <assert.h>
using namespace ke;
#include "ExtensionSys.h"
#include "LibrarySys.h"
#include "PluginSys.h"
#include "sm_stringutil.h"
ShareSystem g_ShareSys;
static unsigned int g_mark_serial = 0;
@@ -64,36 +61,36 @@ void ShareSystem::Initialize()
{
TypeAccess sec;
handlesys->InitAccessDefaults(&sec, NULL);
g_HandleSys.InitAccessDefaults(&sec, NULL);
sec.ident = GetIdentRoot();
m_TypeRoot = handlesys->CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
m_IfaceType = handlesys->CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
/* Initialize our static identity handle */
m_IdentRoot.ident = handlesys->CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
/* Add the Handle System and others... they are too innocent and pure to do it themselves */
AddInterface(NULL, handlesys);
AddInterface(NULL, libsys);
AddInterface(NULL, &g_HandleSys);
AddInterface(NULL, &g_LibSys);
}
void ShareSystem::OnSourceModShutdown()
{
if (m_CoreType)
{
handlesys->RemoveType(m_CoreType, GetIdentRoot());
g_HandleSys.RemoveType(m_CoreType, GetIdentRoot());
}
handlesys->RemoveType(m_IfaceType, GetIdentRoot());
handlesys->RemoveType(m_TypeRoot, GetIdentRoot());
g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot());
g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot());
}
IdentityType_t ShareSystem::FindIdentType(const char *name)
{
HandleType_t type;
if (handlesys->FindHandleType(name, &type))
if (g_HandleSys.FindHandleType(name, &type))
{
if (g_HandleSys.TypeCheck(type, m_TypeRoot))
{
@@ -111,7 +108,7 @@ IdentityType_t ShareSystem::CreateIdentType(const char *name)
return 0;
}
return handlesys->CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
return g_HandleSys.CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
}
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
@@ -220,13 +217,13 @@ void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
sec.pOwner = GetIdentRoot();
sec.pIdentity = GetIdentRoot();
handlesys->FreeHandle(identity->ident, &sec);
g_HandleSys.FreeHandle(identity->ident, &sec);
delete identity;
}
void ShareSystem::DestroyIdentType(IdentityType_t type)
{
handlesys->RemoveType(type, GetIdentRoot());
g_HandleSys.RemoveType(type, GetIdentRoot());
}
void ShareSystem::RemoveInterfaces(IExtension *pExtension)
@@ -258,19 +255,51 @@ void ShareSystem::RegisterLibrary(IExtension *myself, const char *name)
void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives)
{
assert(false);
unsigned int i;
NativeEntry *pEntry;
CNativeOwner *pOwner;
pOwner = g_Extensions.GetNativeOwner(myself);
for (i = 0; natives[i].func != NULL && natives[i].name != NULL; i++)
{
if ((pEntry = FindNative(natives[i].name)) == NULL)
{
continue;
}
if (pEntry->owner != g_pCoreNatives)
{
continue;
}
if (pEntry->replacement.owner != NULL)
{
continue;
}
/* Now it's safe to add the override */
pEntry->replacement.func = natives[i].func;
pEntry->replacement.owner = pOwner;
pOwner->AddReplacedNative(pEntry);
}
}
PassRef<Native> ShareSystem::FindNative(const char *name)
NativeEntry *ShareSystem::FindNative(const char *name)
{
NativeCache::Result r = m_NtvCache.find(name);
if (!r.found())
NativeEntry **ppEntry;
if ((ppEntry = m_NtvCache.retrieve(name)) == NULL)
{
return NULL;
return *r;
}
return *ppEntry;
}
void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
{
NativeEntry *pEntry;
sp_native_t *native;
uint32_t i, native_count;
IPluginContext *pContext;
@@ -279,152 +308,230 @@ void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
/* Generate a new serial ID, mark our dependencies with it. */
g_mark_serial++;
pPlugin->PropagateMarkSerial(g_mark_serial);
pPlugin->PropogateMarkSerial(g_mark_serial);
native_count = pContext->GetNativesNum();
for (i = 0; i < native_count; i++)
{
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
{
continue;
}
// If we're already bound, no need to do anything else.
/* If we're bound, check if there is a replacement available.
* If not, this native is totally finalized.
*/
if (native->status == SP_NATIVE_BOUND)
continue;
{
pEntry = (NativeEntry *)native->user;
assert(pEntry != NULL);
if (pEntry->replacement.owner == NULL
|| (pEntry->replacement.owner != NULL
&& pEntry->replacement.func == native->pfn))
{
continue;
}
}
/* Otherwise, the native must be in our cache. */
Ref<Native> pEntry = FindNative(native->name);
if (!pEntry)
else if ((pEntry = FindNative(native->name)) == NULL)
{
continue;
}
if (bCoreOnly && pEntry->owner != &g_CoreNatives)
if (bCoreOnly && pEntry->owner != g_pCoreNatives)
{
continue;
}
BindNativeToPlugin(pPlugin, native, i, pEntry);
}
}
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, const Ref<Native> &entry)
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry)
{
if (!entry->owner)
return;
IPluginContext *pContext = pPlugin->GetBaseContext();
uint32_t i;
if (pContext->FindNativeByName(entry->name(), &i) != SP_ERROR_NONE)
return;
sp_native_t *native;
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
IPluginContext *pContext;
pContext = pPlugin->GetBaseContext();
if (pContext->FindNativeByName(pEntry->name, &i) != SP_ERROR_NONE)
{
return;
}
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
{
return;
}
if (native->status == SP_NATIVE_BOUND)
{
return;
}
BindNativeToPlugin(pPlugin, native, i, entry);
BindNativeToPlugin(pPlugin, native, i, pEntry);
}
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, sp_native_t *native, uint32_t index,
const Ref<Native> &pEntry)
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
sp_native_t *native,
uint32_t index,
NativeEntry *pEntry)
{
/* Mark as bound... we do the rest next. */
native->status = SP_NATIVE_BOUND;
native->pfn = pEntry->func();
native->user = pEntry;
if (pEntry->fake)
/* See if a replacement is available. */
if (pEntry->replacement.owner != NULL)
{
/* This native is not necessarily optional, but we don't guarantee
* that its address is long-lived. */
native->flags |= SP_NTVFLAG_EPHEMERAL;
/* Perform a replacement bind. */
native->pfn = pEntry->replacement.func;
pEntry->replacement.owner->AddWeakRef(WeakNative(pPlugin, index, pEntry));
}
/* We don't bother with dependency crap if the owner is Core. */
if (pEntry->owner != &g_CoreNatives)
else
{
/* The native is optional, this is a special case */
if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
/* Perform a normal bind. */
native->pfn = pEntry->func;
/* We don't bother with dependency crap if the owner is Core. */
if (pEntry->owner != g_pCoreNatives)
{
/* Only add if there is a valid owner. */
if (pEntry->owner)
pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
else
native->status = SP_NATIVE_UNBOUND;
}
/* Otherwise, we're a strong dependent and not a weak one */
else
{
/* See if this has already been marked as a dependent.
* If it has, it means this relationship has already occurred,
* and there is no reason to do it again.
*/
if (pEntry->owner != pPlugin->ToNativeOwner()
&& pEntry->owner->GetMarkSerial() != g_mark_serial)
/* The native is optional, this is a special case */
if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
{
/* This has not been marked as a dependency yet */
//pPlugin->AddDependency(pEntry->owner);
pEntry->owner->AddDependent(pPlugin);
pEntry->owner->SetMarkSerial(g_mark_serial);
/* Only add if there is a valid owner. */
if (pEntry->owner != NULL)
{
pEntry->owner->AddWeakRef(WeakNative(pPlugin, index));
}
else
{
native->status = SP_NATIVE_UNBOUND;
}
}
/* Otherwise, we're a strong dependent and not a weak one */
else
{
/* See if this has already been marked as a dependent.
* If it has, it means this relationship has already occurred,
* and there is no reason to do it again.
*/
if (pEntry->owner != pPlugin
&& pEntry->owner->GetMarkSerial() != g_mark_serial)
{
/* This has not been marked as a dependency yet */
//pPlugin->AddDependency(pEntry->owner);
pEntry->owner->AddDependent(pPlugin);
pEntry->owner->SetMarkSerial(g_mark_serial);
}
}
}
}
}
PassRef<Native> ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
NativeEntry *ShareSystem::AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv)
{
NativeCache::Insert i = m_NtvCache.findForAdd(ntv->name);
if (i.found())
NativeEntry *pEntry;
if ((pEntry = FindNative(ntv->name)) == NULL)
{
pEntry = new NativeEntry;
pEntry->owner = pOwner;
pEntry->name = ntv->name;
pEntry->func = ntv->func;
pEntry->replacement.func = NULL;
pEntry->replacement.owner = NULL;
pEntry->fake = NULL;
m_NtvCache.insert(ntv->name, pEntry);
return pEntry;
}
if (pEntry->owner != NULL)
{
return NULL;
}
Ref<Native> entry = new Native(pOwner, ntv);
m_NtvCache.insert(ntv->name, entry);
return entry;
}
pEntry->owner = pOwner;
pEntry->func = ntv->func;
pEntry->name = ntv->name;
FakeNative::~FakeNative()
{
g_pSourcePawn2->DestroyFakeNative(gate);
return pEntry;
}
void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
{
NativeCache::Result r = m_NtvCache.find(name);
if (!r.found())
NativeEntry *pEntry;
if ((pEntry = FindNative(name)) == NULL)
{
return;
}
Ref<Native> entry(*r);
if (entry->owner != pOwner)
if (pEntry->owner != pOwner)
{
return;
}
// Clear out the owner bit as a sanity measure.
entry->owner = NULL;
if (pEntry->fake != NULL)
{
g_pSourcePawn2->DestroyFakeNative(pEntry->func);
delete pEntry->fake;
pEntry->fake = NULL;
}
m_NtvCache.remove(r);
pEntry->func = NULL;
pEntry->name = NULL;
pEntry->owner = NULL;
pEntry->replacement.func = NULL;
pEntry->replacement.owner = NULL;
}
PassRef<Native> ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func)
{
Ref<Native> entry(FindNative(name));
if (entry)
FakeNative *pFake;
NativeEntry *pEntry;
SPVM_NATIVE_FUNC gate;
if ((pEntry = FindNative(name)) != NULL && pEntry->owner != NULL)
{
return NULL;
}
AutoPtr<FakeNative> fake(new FakeNative(name, pFunc));
pFake = new FakeNative;
fake->gate = g_pSourcePawn2->CreateFakeNative(func, fake);
if (!fake->gate)
if ((gate = g_pSourcePawn2->CreateFakeNative(func, pFake)) == NULL)
{
delete pFake;
return NULL;
}
CNativeOwner *owner = g_PluginSys.GetPluginByCtx(fake->ctx->GetContext());
if (pEntry == NULL)
{
pEntry = new NativeEntry;
m_NtvCache.insert(name, pEntry);
}
entry = new Native(owner, fake.take());
m_NtvCache.insert(name, entry);
pFake->call = pFunc;
pFake->ctx = pFunc->GetParentContext();
strncopy(pFake->name, name, sizeof(pFake->name));
pEntry->fake = pFake;
pEntry->func = gate;
pEntry->name = pFake->name;
pEntry->owner = g_PluginSys.GetPluginByCtx(pFake->ctx->GetContext());
pEntry->replacement.func = NULL;
pEntry->replacement.owner = NULL;
return entry;
return pEntry;
}
void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name)
{
if (m_caps.contains(name))
if (m_caps.retrieve(name) != NULL)
return;
Capability cap;
@@ -437,13 +544,14 @@ void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *pr
void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name)
{
StringHashMap<Capability>::Result r = m_caps.find(name);
if (!r.found())
return;
if (r->value.ext != myself || r->value.provider != provider)
Capability *pCap = m_caps.retrieve(name);
if (pCap == NULL)
return;
m_caps.remove(r);
if (pCap->ext != myself || pCap->provider != provider)
return;
m_caps.remove(name);
}
FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature,
@@ -478,18 +586,26 @@ FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name
}
}
Ref<Native> entry = FindNative(name);
if (!entry)
NativeEntry *entry = FindNative(name);
if (entry == NULL)
return FeatureStatus_Unknown;
return FeatureStatus_Unavailable;
if ((entry->replacement.owner != NULL || entry->owner != NULL) &&
(entry->replacement.func != NULL || entry->func != NULL))
{
return FeatureStatus_Available;
}
else
{
return FeatureStatus_Unavailable;
}
}
FeatureStatus ShareSystem::TestCap(const char *name)
{
StringHashMap<Capability>::Result r = m_caps.find(name);
if (!r.found())
Capability *cap = m_caps.retrieve(name);
if (cap == NULL)
return FeatureStatus_Unknown;
return r->value.provider->GetFeatureStatus(FeatureType_Capability, name);
return cap->provider->GetFeatureStatus(FeatureType_Capability, name);
}
+37 -17
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,14 +34,10 @@
#include <IShareSys.h>
#include <IHandleSys.h>
#include <am-string.h>
#include <am-utility.h>
#include <am-refcounting.h>
#include <sh_list.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
#include "common_logic.h"
#include "Native.h"
#include <sm_trie_tpl.h>
#include "sm_globals.h"
#include "sourcemod.h"
using namespace SourceHook;
@@ -67,6 +63,29 @@ struct IfaceInfo
class CNativeOwner;
class CPlugin;
struct NativeEntry;
struct ReplaceNative
{
CNativeOwner *owner;
SPVM_NATIVE_FUNC func;
};
struct FakeNative
{
char name[64];
IPluginContext *ctx;
IPluginFunction *call;
};
struct NativeEntry
{
CNativeOwner *owner;
SPVM_NATIVE_FUNC func;
const char *name;
ReplaceNative replacement;
FakeNative *fake;
};
struct Capability
{
@@ -120,23 +139,24 @@ public:
}
public:
void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly);
void BindNativeToPlugin(CPlugin *pPlugin, const ke::Ref<Native> &pEntry);
ke::PassRef<Native> AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
ke::PassRef<Native> FindNative(const char *name);
void BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry);
NativeEntry *AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
NativeEntry *FindNative(const char *name);
private:
ke::PassRef<Native> AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv);
NativeEntry *AddNativeToCache(CNativeOwner *pOwner, const sp_nativeinfo_t *ntv);
void ClearNativeFromCache(CNativeOwner *pOwner, const char *name);
void BindNativeToPlugin(CPlugin *pPlugin, sp_native_t *ntv, uint32_t index, const ke::Ref<Native> &pEntry);
void BindNativeToPlugin(CPlugin *pPlugin,
sp_native_t *ntv,
uint32_t index,
NativeEntry *pEntry);
private:
typedef NameHashSet<ke::Ref<Native>, Native> NativeCache;
List<IfaceInfo> m_Interfaces;
HandleType_t m_TypeRoot;
IdentityToken_t m_IdentRoot;
HandleType_t m_IfaceType;
IdentityType_t m_CoreType;
NativeCache m_NtvCache;
StringHashMap<Capability> m_caps;
KTrie<NativeEntry *> m_NtvCache;
KTrie<Capability> m_caps;
};
extern ShareSystem g_ShareSys;
+6 -6
View File
@@ -31,10 +31,10 @@
#include <time.h>
#include "TimerSys.h"
#include "ForwardSys.h"
#include "sourcemm_api.h"
#include "frame_hooks.h"
#include "ConVarManager.h"
#include "logic_bridge.h"
#define TIMER_MIN_ACCURACY 0.1
@@ -180,9 +180,9 @@ TimerSystem::~TimerSystem()
void TimerSystem::OnSourceModAllInitialized()
{
sharesys->AddInterface(NULL, this);
m_pOnGameFrame = forwardsys->CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
m_pOnMapTimeLeftChanged = forwardsys->CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
g_ShareSys.AddInterface(NULL, this);
m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
m_pOnMapTimeLeftChanged = g_Forwards.CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
}
void TimerSystem::OnSourceModGameInitialized()
@@ -198,8 +198,8 @@ void TimerSystem::OnSourceModGameInitialized()
void TimerSystem::OnSourceModShutdown()
{
SetMapTimer(NULL);
forwardsys->ReleaseForward(m_pOnGameFrame);
forwardsys->ReleaseForward(m_pOnMapTimeLeftChanged);
g_Forwards.ReleaseForward(m_pOnGameFrame);
g_Forwards.ReleaseForward(m_pOnMapTimeLeftChanged);
}
void TimerSystem::OnSourceModLevelEnd()
+1 -1
View File
@@ -32,11 +32,11 @@
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
#include "ShareSys.h"
#include <ITimerSystem.h>
#include <sh_stack.h>
#include <sh_list.h>
#include "sourcemm_api.h"
#include "sm_globals.h"
using namespace SourceHook;
using namespace SourceMod;
+16 -103
View File
@@ -56,15 +56,6 @@
return false; \
}
#define CHECK_FIELD_TYPE3(type1, type2, type3) \
protobuf::FieldDescriptor::CppType fieldType = field->cpp_type(); \
if (fieldType != protobuf::FieldDescriptor::CPPTYPE_##type1 \
&& fieldType != protobuf::FieldDescriptor::CPPTYPE_##type2 \
&& fieldType != protobuf::FieldDescriptor::CPPTYPE_##type3) \
{ \
return false; \
}
#define CHECK_FIELD_REPEATED() \
if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED) \
{ \
@@ -102,7 +93,7 @@ public:
Handle_t &hndl = (*iter);
HandleSecurity sec;
sec.pIdentity = g_pCoreIdent;
handlesys->FreeHandle(hndl, &sec);
g_HandleSys.FreeHandle(hndl, &sec);
iter = childHandles.erase(iter);
}
}
@@ -325,114 +316,74 @@ public:
return true;
}
inline bool GetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 *out)
inline bool GetInt32OrUnsigned(const char *pszFieldName, int32 *out)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
*out = (int32)msg->GetReflection()->GetUInt32(*msg, field);
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
else
*out = msg->GetReflection()->GetInt32(*msg, field);
else // CPPTYPE_ENUM
*out = msg->GetReflection()->GetEnum(*msg, field)->number();
return true;
}
inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
inline bool SetInt32OrUnsigned(const char *pszFieldName, int32 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
{
msg->GetReflection()->SetUInt32(msg, field, (uint32)value);
}
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
{
else
msg->GetReflection()->SetInt32(msg, field, value);
}
else // CPPTYPE_ENUM
{
const protobuf::EnumValueDescriptor *pEnumValue = field->enum_type()->FindValueByNumber(value);
if (!pEnumValue)
return false;
msg->GetReflection()->SetEnum(msg, field, pEnumValue);
}
return true;
}
inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out)
inline bool GetRepeatedInt32OrUnsigned(const char *pszFieldName, int index, int32 *out)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
*out = (int32)msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
else
*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
else // CPPTYPE_ENUM
*out = msg->GetReflection()->GetRepeatedEnum(*msg, field, index)->number();
return true;
}
inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value)
inline bool SetRepeatedInt32OrUnsigned(const char *pszFieldName, int index, int32 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
{
msg->GetReflection()->SetRepeatedUInt32(msg, field, index, (uint32)value);
}
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
{
else
msg->GetReflection()->SetRepeatedInt32(msg, field, index, value);
}
else // CPPTYPE_ENUM
{
const protobuf::EnumValueDescriptor *pEnumValue = field->enum_type()->FindValueByNumber(value);
if (!pEnumValue)
return false;
msg->GetReflection()->SetRepeatedEnum(msg, field, index, pEnumValue);
}
return true;
}
inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value)
inline bool AddInt32OrUnsigned(const char *pszFieldName, int32 value)
{
GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM);
CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
{
msg->GetReflection()->AddUInt32(msg, field, (uint32)value);
}
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
{
else
msg->GetReflection()->AddInt32(msg, field, value);
}
else // CPPTYPE_ENUM
{
const protobuf::EnumValueDescriptor *pEnumValue = field->enum_type()->FindValueByNumber(value);
if (!pEnumValue)
return false;
msg->GetReflection()->AddEnum(msg, field, pEnumValue);
}
return true;
}
@@ -724,9 +675,6 @@ public:
inline bool GetColor(const char *pszFieldName, Color *out)
{
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_NOT_REPEATED();
@@ -740,14 +688,10 @@ public:
);
return true;
#endif
}
inline bool SetColor(const char *pszFieldName, const Color &value)
{
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_NOT_REPEATED();
@@ -759,14 +703,10 @@ public:
msgRGBA->set_a(value.a());
return true;
#endif
}
inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out)
{
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_REPEATED();
@@ -781,14 +721,10 @@ public:
);
return true;
#endif
}
inline bool SetRepeatedColor(const char *pszFieldName, int index, const Color &value)
{
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_REPEATED();
@@ -801,14 +737,10 @@ public:
msgRGBA->set_a(value.a());
return true;
#endif
}
inline bool AddColor(const char *pszFieldName, const Color &value)
{
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_REPEATED();
@@ -820,7 +752,6 @@ public:
msgRGBA->set_a(value.a());
return true;
#endif
}
inline bool GetVector2D(const char *pszFieldName, Vector2D *out)
@@ -1093,24 +1024,6 @@ public:
return msg->GetReflection()->FieldSize(*msg, field);
}
inline bool RemoveRepeatedFieldValue(const char *pszFieldName, int index)
{
GETCHECK_FIELD();
CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index);
// Protobuf guarantees that repeated field values will stay in order and so must we.
const protobuf::Reflection *pReflection = msg->GetReflection();
for (int i = index; i < elemCount - 1; ++i)
{
pReflection->SwapElements(msg, field, i, i + 1);
}
pReflection->RemoveLast(msg, field);
return true;
}
private:
protobuf::Message *msg;
PBHandleList childHandles;
+52 -76
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -31,17 +31,14 @@
#include "UserMessages.h"
#include "sm_stringutil.h"
#include "logic_bridge.h"
#if SOURCE_ENGINE == SE_DOTA
#include <dota_usermessage_helpers.h>
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessage_helpers.h>
#endif
UserMessages g_UserMsgs;
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
#else
#if SOURCE_ENGINE >= SE_LEFT4DEAD
@@ -56,6 +53,7 @@ UserMessages::UserMessages()
#ifndef USE_PROTOBUF_USERMESSAGES
: m_InterceptBuffer(m_pBase, 2500)
{
m_Names = sm_trie_create();
#else
: m_InterceptBuffer(NULL)
{
@@ -69,6 +67,10 @@ UserMessages::UserMessages()
UserMessages::~UserMessages()
{
#ifndef USE_PROTOBUF_USERMESSAGES
sm_trie_destroy(m_Names);
#endif
CStack<ListenerInfo *>::iterator iter;
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
{
@@ -87,21 +89,21 @@ void UserMessages::OnSourceModStartup(bool late)
void UserMessages::OnSourceModAllInitialized()
{
sharesys->AddInterface(NULL, this);
g_ShareSys.AddInterface(NULL, this);
}
void UserMessages::OnSourceModAllShutdown()
{
if (m_HookCount)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
#if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else
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);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif
}
m_HookCount = 0;
@@ -109,16 +111,13 @@ void UserMessages::OnSourceModAllShutdown()
int UserMessages::GetMessageIndex(const char *msg)
{
#if SOURCE_ENGINE == SE_DOTA
// Can split this per engine and/or game later
return g_DotaUsermessageHelpers.GetIndex(msg);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
// Can split this per engine and/or game later
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
#else
int msgid;
if (!m_Names.retrieve(msg, &msgid))
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
{
if (m_FallbackSearch)
{
@@ -130,7 +129,7 @@ int UserMessages::GetMessageIndex(const char *msg)
{
if (strcmp(msgbuf, msg) == 0)
{
m_Names.insert(msg, msgid);
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
return msgid;
}
msgid++;
@@ -140,7 +139,9 @@ int UserMessages::GetMessageIndex(const char *msg)
msgid = g_SMAPI->FindUserMessage(msg);
if (msgid != INVALID_MESSAGE_ID)
m_Names.insert(msg, msgid);
{
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
}
}
return msgid;
@@ -149,12 +150,8 @@ int UserMessages::GetMessageIndex(const char *msg)
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
{
#ifdef USE_PROTOBUF_USERMESSAGES
#if SOURCE_ENGINE == SE_DOTA
const char *pszName = g_DotaUsermessageHelpers.GetName(msgid);
#elif SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_CSGO
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
#endif
if (!pszName)
return false;
@@ -262,7 +259,7 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
// direct message creation, return buffer "from engine". keep track
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
} else {
char messageName[32];
@@ -277,12 +274,12 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const
{
case MRES_IGNORED:
case MRES_HANDLED:
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
break;
case MRES_OVERRIDE:
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
// fallthrough
case MRES_SUPERCEDE:
buffer = msg;
@@ -303,7 +300,7 @@ bool UserMessages::EndMessage()
return false;
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
@@ -333,7 +330,7 @@ bool UserMessages::EndMessage()
} else {
engine->MessageEnd();
}
#endif // SE_CSGO || SE_DOTA
#endif // SE_CSGO
m_InExec = false;
m_CurFlags = 0;
@@ -418,14 +415,14 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
if (!m_HookCount++)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
#if SOURCE_ENGINE == SE_CSGO
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else
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);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif
}
@@ -439,17 +436,6 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
return true;
}
#ifdef USE_PROTOBUF_USERMESSAGES
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
{
#if SOURCE_ENGINE == SE_DOTA
return g_DotaUsermessageHelpers.GetPrototype(msg_type);
#elif SOURCE_ENGINE == SE_CSGO
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
@@ -495,26 +481,22 @@ void UserMessages::_DecRefCounter()
{
if (--m_HookCount == 0)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true);
#if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else
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);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif
}
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
{
#if SOURCE_ENGINE == SE_DOTA
OnStartMessage_Pre(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
#elif SOURCE_ENGINE == SE_CSGO
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
if (m_FakeMetaRes == MRES_SUPERCEDE)
{
int size = msg.ByteSize();
@@ -527,11 +509,7 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type,
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
}
#if SOURCE_ENGINE == SE_DOTA
OnStartMessage_Post(&filter, msg_type, g_DotaUsermessageHelpers.GetName(msg_type));
#elif SOURCE_ENGINE == SE_CSGO
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
OnMessageEnd_Pre();
if (m_FakeMetaRes == MRES_SUPERCEDE)
@@ -563,7 +541,7 @@ void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type
RETURN_META(res)
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
@@ -591,8 +569,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
#ifdef USE_PROTOBUF_USERMESSAGES
if (m_InterceptBuffer)
delete m_InterceptBuffer;
m_InterceptBuffer = GetMessagePrototype(msg_type)->New();
m_InterceptBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
#else
m_InterceptBuffer.Reset();
@@ -603,7 +580,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
@@ -768,7 +745,7 @@ void UserMessages::OnMessageEnd_Pre()
if (!handled && intercepted)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
#else
bf_write *engine_bfw;
@@ -780,16 +757,15 @@ void UserMessages::OnMessageEnd_Pre()
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
ENGINE_CALL(MessageEnd)();
#endif // SE_CSGO || SE_DOTA
#endif // SE_CSGO
}
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
int size = m_OrigBuffer->ByteSize();
uint8 *data = (uint8 *)stackalloc(size);
m_OrigBuffer->SerializePartialToArray(data, size);
protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New();
protobuf::Message *pTempMsg = g_Cstrike15UsermessageHelpers.GetPrototype(m_CurId)->New();
pTempMsg->ParsePartialFromArray(data, size);
#else
bf_write *pTempMsg = m_OrigBuffer;
@@ -814,7 +790,7 @@ void UserMessages::OnMessageEnd_Pre()
iter++;
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
delete pTempMsg;
#endif
}
+7 -10
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -32,19 +32,17 @@
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
#include "ShareSys.h"
#include <IUserMessages.h>
#include "sourcemm_api.h"
#include <sm_stringhashmap.h>
#include "sm_trie.h"
#include "sm_stringutil.h"
#include "CellRecipientFilter.h"
#include "sm_globals.h"
#include <sh_list.h>
#include <sh_stack.h>
using namespace SourceHook;
using namespace SourceMod;
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
#define USE_PROTOBUF_USERMESSAGES
#endif
@@ -102,12 +100,12 @@ public: //IUserMessages
bool intercept=false);
UserMessageType GetUserMessageType() const;
public:
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
@@ -121,7 +119,6 @@ public:
void OnMessageEnd_Post();
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
@@ -153,7 +150,7 @@ private:
#ifndef USE_PROTOBUF_USERMESSAGES
bool m_FallbackSearch;
StringHashMap<int> m_Names;
Trie *m_Names;
#endif
CellRecipientFilter m_CellRecFilter;
bool m_InExec;
+6 -6
View File
@@ -64,20 +64,20 @@ public:
void OnSourceModAllInitialized()
{
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_ADD_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
SH_ADD_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#else
SH_ADD_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#endif
}
void OnSourceModShutdown()
{
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_REMOVE_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
SH_REMOVE_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#else
SH_REMOVE_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false);
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#endif
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -381,7 +381,7 @@ public:
FnChangeCallback_t GetChangeCallback( int slot ) const { return m_pParent->m_fnChangeCallbacks[ slot ]; }
// Retrieve value
#if SOURCE_ENGINE >= SE_INSURGENCY
#if SOURCE_ENGINE == SE_CSGO
virtual float GetFloat( void ) const;
virtual int GetInt( void ) const;
#else
+2 -1
View File
@@ -30,6 +30,7 @@
*/
#include "frame_hooks.h"
#include "TimerSys.h"
#include "Database.h"
#include "HalfLife2.h"
#include "MenuStyle_Valve.h"
#include "MenuStyle_Radio.h"
@@ -37,7 +38,6 @@
#include "CoreConfig.h"
#include <sm_queue.h>
#include <IThreader.h>
#include "sourcemod.h"
static IMutex *frame_mutex;
static Queue<FrameAction> *frame_queue;
@@ -95,6 +95,7 @@ void RunFrameHooks(bool simulating)
}
/* Frame based hooks */
g_DBMan.RunFrame();
g_HL2.ProcessFakeCliCmdQueue();
g_HL2.ProcessDelayedKicks();
+1 -26
View File
@@ -19,18 +19,11 @@ if builder.target_platform == 'linux':
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',
@@ -39,13 +32,13 @@ binary.sources += [
'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',
@@ -54,27 +47,9 @@ binary.sources += [
'smn_handles.cpp',
'smn_datapacks.cpp',
'smn_gameconfigs.cpp',
'smn_fakenatives.cpp',
'GameConfigs.cpp',
'sm_crc32.cpp',
'smn_profiler.cpp',
'ShareSys.cpp',
'PluginSys.cpp',
'HandleSys.cpp',
'NativeOwner.cpp',
'NativeInvoker.cpp',
'ExtensionSys.cpp',
'DebugReporter.cpp',
'Database.cpp',
'smn_database.cpp',
'ForwardSys.cpp',
'AdminCache.cpp',
'sm_trie.cpp',
'smn_console.cpp',
'ProfileTools.cpp',
'Logger.cpp',
'smn_core.cpp',
'smn_menus.cpp',
]
if builder.target_platform == 'windows':
binary.sources += ['thread/WinThreads.cpp']
@@ -32,6 +32,7 @@
#ifndef _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
#define _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
#include "common_logic.h"
#include <IHandleSys.h>
class AutoHandleRooter
+114 -116
View File
@@ -77,12 +77,10 @@ static const char *g_pParseEngine = NULL;
#define PLATFORM_SERVER_BINARY "server.dll"
#elif defined PLATFORM_LINUX
#define PLATFORM_NAME "linux"
#define PLATFORM_COMPAT_ALT "mac" /* Alternate platform name if game data is missing for primary one */
#define PLATFORM_SERVER_BINARY "server_i486.so"
#elif defined PLATFORM_APPLE
#define PLATFORM_NAME "mac"
#define PLATFORM_COMPAT_ALT "linux"
#define PLATFORM_SERVER_BINARY "server.dylib"
#define PLATFORM_NAME "mac"
#define PLATFORM_SERVER_BINARY "server.dylib"
#endif
struct TempSigInfo
@@ -118,33 +116,12 @@ static bool DoesEngineMatch(const char *value)
return strcmp(value, g_pParseEngine) == 0;
}
static inline bool DoesPlatformMatch(const char *platform)
{
return strcmp(platform, PLATFORM_NAME) == 0;
}
static inline bool IsPlatformCompatible(const char *platform, bool *hadPrimaryMatch)
{
if (DoesPlatformMatch(platform))
{
#if defined PLATFORM_COMPAT_ALT
*hadPrimaryMatch = true;
#endif
return true;
}
#if defined PLATFORM_COMPAT_ALT
/* If entry hasn't been found for the primary platform name, check for compatible alternate */
if (!*hadPrimaryMatch)
return strcmp(platform, PLATFORM_COMPAT_ALT) == 0;
#endif
return false;
}
CGameConfig::CGameConfig(const char *file, const char *engine)
{
strncopy(m_File, file, sizeof(m_File));
m_pAddresses = new KTrie<AddressConf>();
m_pStrings = new BaseStringTable(512);
m_RefCount = 0;
m_CustomLevel = 0;
m_CustomHandler = NULL;
@@ -164,7 +141,8 @@ CGameConfig::CGameConfig(const char *file, const char *engine)
CGameConfig::~CGameConfig()
{
g_GameConfigs.RemoveCachedConfig(this);
delete m_pAddresses;
delete m_pStrings;
}
SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name)
@@ -236,10 +214,13 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
}
else
{
if (g_GameConfigs.m_customHandlers.retrieve(name, &m_CustomHandler))
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;
}
@@ -254,7 +235,6 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
m_Class[0] = '\0';
strncopy(m_offset, name, sizeof(m_offset));
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
matched_platform = false;
break;
}
case PSTATE_GAMEDEFS_SIGNATURES:
@@ -262,7 +242,6 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
strncopy(m_offset, name, sizeof(m_offset));
s_TempSig.Reset();
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
matched_platform = false;
break;
}
case PSTATE_GAMEDEFS_CRC:
@@ -301,8 +280,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
if (error[0] != '\0')
{
m_IgnoreLevel = 1;
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
logger->LogError("[SM] %s", error);
smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
smcore.LogError("[SM] %s", error);
} else {
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY;
}
@@ -327,7 +306,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
}
case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
{
if (DoesPlatformMatch(name))
if (strcmp(name, PLATFORM_NAME) == 0)
{
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ;
}
@@ -335,8 +314,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
{
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0 && strcmp(name, "mac") != 0)
{
logger->LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
logger->LogError("[SM] Unrecognized platform \"%s\"", name);
smcore.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
smcore.LogError("[SM] Unrecognized platform \"%s\"", name);
}
m_IgnoreLevel = 1;
}
@@ -375,12 +354,11 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
strncopy(m_Class, value, sizeof(m_Class));
} else if (strcmp(key, "prop") == 0) {
strncopy(m_Prop, value, sizeof(m_Prop));
} else if (IsPlatformCompatible(key, &matched_platform)) {
} else if (strcmp(key, PLATFORM_NAME) == 0) {
m_Offsets.replace(m_offset, atoi(value));
}
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
ke::AString vstr(value);
m_Keys.replace(key, ke::Move(vstr));
m_Keys.replace(key, m_pStrings->AddString(value));
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
if (strcmp(key, "game") == 0)
{
@@ -407,14 +385,14 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
}
}
} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
if (IsPlatformCompatible(key, &matched_platform))
if (strcmp(key, PLATFORM_NAME) == 0)
{
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) {
if (DoesPlatformMatch(key)
if (strcmp(key, PLATFORM_NAME) == 0
&& s_ServerBinCRC_Ok
&& !bShouldBeReadingDefault)
{
@@ -435,7 +413,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
}
else
{
logger->LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
smcore.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
}
} else if (strcmp(key, "signature") == 0) {
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
@@ -503,7 +481,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
&& (!m_Offsets.retrieve(m_offset)))
{
logger->LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
smcore.LogError("[SM] Unable to find property %s.%s (file \"%s\") (mod \"%s\")",
m_Class,
m_Prop,
m_CurFile,
@@ -556,12 +534,10 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
void *final_addr = NULL;
if (addrInBase == NULL)
{
logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
s_TempSig.library,
m_CurFile);
}
else if (s_TempSig.sig[0])
{
} else {
if (s_TempSig.sig[0] == '@')
{
#if defined PLATFORM_WINDOWS
@@ -570,7 +546,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (VirtualQuery(addrInBase, &mem, sizeof(mem)))
final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]);
else
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")", s_TempSig.library, m_File);
#elif defined PLATFORM_POSIX
Dl_info info;
/* GNU only: returns 0 on error, inconsistent! >:[ */
@@ -585,39 +561,39 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
final_addr = dlsym(handle, &s_TempSig.sig[1]);
dlclose(handle);
} else {
logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
s_TempSig.library,
m_File);
}
} else {
logger->LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
smcore.LogError("[SM] Unable to find library \"%s\" in memory (gameconf \"%s\")",
s_TempSig.library,
m_File);
}
#endif
}
if (!final_addr)
if (final_addr)
{
/* First, preprocess the signature */
unsigned char real_sig[511];
size_t real_bytes;
size_t length;
real_bytes = 0;
length = strlen(s_TempSig.sig);
real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), s_TempSig.sig);
if (real_bytes >= 1)
{
final_addr = g_MemUtils.FindPattern(addrInBase, (char*) real_sig, real_bytes);
}
goto skip_find;
}
/* First, preprocess the signature */
unsigned char real_sig[511];
size_t real_bytes;
size_t length;
m_Sigs.replace(m_offset, final_addr);
real_bytes = 0;
length = strlen(s_TempSig.sig);
real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), s_TempSig.sig);
if (real_bytes >= 1)
{
final_addr = g_MemUtils.FindPattern(addrInBase, (char*)real_sig, real_bytes);
}
}
skip_find:
m_Sigs.replace(m_offset, final_addr);
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
break;
@@ -634,7 +610,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0')
{
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead);
m_Addresses.replace(m_Address, addrConf);
m_pAddresses->replace(m_Address, addrConf);
}
break;
@@ -779,10 +755,11 @@ static MasterReader master_reader;
bool CGameConfig::Reparse(char *error, size_t maxlength)
{
/* Reset cached data */
m_pStrings->Reset();
m_Offsets.clear();
m_Props.clear();
m_Keys.clear();
m_Addresses.clear();
m_pAddresses->clear();
char path[PLATFORM_MAX_PATH];
@@ -792,19 +769,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
{
/* Nope, use the old mechanism. */
smcore.Format(path, sizeof(path), "%s.txt", m_File);
if (!EnterFile(path, error, maxlength))
{
return false;
}
/* Allow customization. */
g_pSM->BuildPath(Path_SM, path, sizeof(path), "gamedata/custom/%s.txt", m_File);
if (libsys->PathExists(path))
{
smcore.Format(path, sizeof(path), "custom/%s.txt", m_File);
return EnterFile(path, error, maxlength);
}
return true;
return EnterFile(path, error, maxlength);
}
/* Otherwise, it's time to parse the master. */
@@ -827,8 +792,8 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
{
const char *msg = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path);
logger->LogError("[SM] Error %d on line %d, col %d: %s",
smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
err,
state.line,
state.col,
@@ -915,8 +880,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
{
const char *msg = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
logger->LogError("[SM] Error %d on line %d, col %d: %s",
smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
smcore.LogError("[SM] Error %d on line %d, col %d: %s",
err,
state.line,
state.col,
@@ -949,15 +914,20 @@ void CGameConfig::SetParseEngine(const char *engine)
bool CGameConfig::GetOffset(const char *key, int *value)
{
return m_Offsets.retrieve(key, value);
int *pvalue;
if ((pvalue = m_Offsets.retrieve(key)) == NULL)
return false;
*value = *pvalue;
return true;
}
const char *CGameConfig::GetKeyValue(const char *key)
{
StringHashMap<ke::AString>::Result r = m_Keys.find(key);
if (!r.found())
int *pkey;
if ((pkey = m_Keys.retrieve(key)) == NULL)
return NULL;
return r->value.chars();
return m_pStrings->GetString(*pkey);
}
//memory addresses below 0x10000 are automatically considered invalid for dereferencing
@@ -965,25 +935,25 @@ const char *CGameConfig::GetKeyValue(const char *key)
bool CGameConfig::GetAddress(const char *key, void **retaddr)
{
StringHashMap<AddressConf>::Result r = m_Addresses.find(key);
if (!r.found())
AddressConf *addrConf;
addrConf = m_pAddresses->retrieve(key);
if (!addrConf)
{
*retaddr = NULL;
return false;
}
AddressConf &addrConf = r->value;
void *addr;
if (!GetMemSig(addrConf.signatureName, &addr))
if (!GetMemSig(addrConf->signatureName, &addr))
{
*retaddr = NULL;
return false;
}
for (int i = 0; i < addrConf.readCount; ++i)
for (int i = 0; i < addrConf->readCount; ++i)
{
int offset = addrConf.read[i];
int offset = addrConf->read[i];
//NULLs in the middle of an indirection chain are bad, end NULL is ok
if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
@@ -1014,15 +984,32 @@ CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigne
SendProp *CGameConfig::GetSendProp(const char *key)
{
SendProp *prop;
if (!m_Props.retrieve(key, &prop))
SendProp **pProp;
if ((pProp = m_Props.retrieve(key)) == NULL)
return NULL;
return prop;
return *pProp;
}
bool CGameConfig::GetMemSig(const char *key, void **addr)
{
return m_Sigs.retrieve(key, addr);
void **paddr;
if ((paddr = m_Sigs.retrieve(key)) == NULL)
return false;
*addr = *paddr;
return true;
}
void CGameConfig::IncRefCount()
{
m_RefCount++;
}
unsigned int CGameConfig::DecRefCount()
{
m_RefCount--;
return m_RefCount;
}
GameConfigManager::GameConfigManager()
@@ -1073,16 +1060,17 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
#endif
CGameConfig *pConfig;
CGameConfig **ppConfig;
if (m_Lookup.retrieve(file, &pConfig))
if ((ppConfig = m_Lookup.retrieve(file)) != NULL)
{
pConfig->AddRef();
pConfig = *ppConfig;
pConfig->IncRefCount();
*_pConfig = pConfig;
return true;
}
pConfig = new CGameConfig(file);
pConfig->AddRef();
/* :HACKHACK: Don't parse the main config file */
bool retval = true;
@@ -1091,16 +1079,25 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
retval = pConfig->Reparse(error, maxlength);
}
m_cfgs.push_back(pConfig);
m_Lookup.insert(file, pConfig);
pConfig->IncRefCount();
*_pConfig = pConfig;
return retval;
}
void GameConfigManager::CloseGameConfigFile(IGameConfig *cfg)
{
CGameConfig *pConfig = (CGameConfig *)cfg;
pConfig->Release();
if (pConfig->DecRefCount() == 0)
{
m_Lookup.remove(pConfig->m_File);
delete pConfig;
}
}
extern Handle_t g_GameConfigsType;
@@ -1124,16 +1121,22 @@ void GameConfigManager::AddUserConfigHook(const char *sectionname, ITextListener
m_customHandlers.insert(sectionname, listener);
}
void GameConfigManager::RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *aListener)
void GameConfigManager::RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener)
{
ITextListener_SMC *listener;
if (!m_customHandlers.retrieve(sectionname, &listener))
return;
ITextListener_SMC **pListener = m_customHandlers.retrieve(sectionname);
if (listener != aListener)
if (pListener == NULL)
{
return;
}
if (*pListener != listener)
{
return;
}
m_customHandlers.remove(sectionname);
return;
}
@@ -1144,8 +1147,3 @@ void GameConfigManager::AcquireLock()
void GameConfigManager::ReleaseLock()
{
}
void GameConfigManager::RemoveCachedConfig(CGameConfig *config)
{
m_Lookup.remove(config->m_File);
}
+18 -21
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet:
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -35,9 +35,9 @@
#include "common_logic.h"
#include <IGameConfigs.h>
#include <ITextParsers.h>
#include <am-refcounting.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
#include <sh_list.h>
#include "sm_memtable.h"
#include <sm_trie_tpl.h>
using namespace SourceMod;
using namespace SourceHook;
@@ -46,8 +46,7 @@ class SendProp;
class CGameConfig :
public ITextListener_SMC,
public IGameConfig,
public ke::Refcounted<CGameConfig>
public IGameConfig
{
friend class GameConfigManager;
public:
@@ -68,18 +67,18 @@ public: //IGameConfig
SendProp *GetSendProp(const char *key);
bool GetMemSig(const char *key, void **addr);
bool GetAddress(const char *key, void **addr);
public: //NameHashSet
static inline bool matches(const char *key, const CGameConfig *value)
{
return strcmp(key, value->m_File) == 0;
}
public:
void IncRefCount();
unsigned int DecRefCount();
private:
BaseStringTable *m_pStrings;
char m_File[PLATFORM_MAX_PATH];
char m_CurFile[PLATFORM_MAX_PATH];
StringHashMap<int> m_Offsets;
StringHashMap<SendProp *> m_Props;
StringHashMap<ke::AString> m_Keys;
StringHashMap<void *> m_Sigs;
KTrie<int> m_Offsets;
KTrie<SendProp *> m_Props;
KTrie<int> m_Keys;
KTrie<void *> m_Sigs;
unsigned int m_RefCount;
/* Parse states */
int m_ParseState;
unsigned int m_IgnoreLevel;
@@ -92,7 +91,6 @@ private:
bool matched_game;
bool had_engine;
bool matched_engine;
bool matched_platform;
/* Custom Sections */
unsigned int m_CustomLevel;
@@ -114,7 +112,7 @@ private:
char m_AddressSignature[64];
int m_AddressReadCount;
int m_AddressRead[8];
StringHashMap<AddressConf> m_Addresses;
KTrie<AddressConf> *m_pAddresses;
const char *m_pEngine;
const char *m_pBaseEngine;
};
@@ -140,12 +138,11 @@ public: //SMGlobalClass
void OnSourceModStartup(bool late);
void OnSourceModAllInitialized();
void OnSourceModAllShutdown();
public:
void RemoveCachedConfig(CGameConfig *config);
private:
NameHashSet<CGameConfig *> m_Lookup;
List<CGameConfig *> m_cfgs;
KTrie<CGameConfig *> m_Lookup;
public:
StringHashMap<ITextListener_SMC *> m_customHandlers;
KTrie<ITextListener_SMC *> m_customHandlers;
};
extern GameConfigManager g_GameConfigs;
-551
View File
@@ -1,551 +0,0 @@
/**
* vim: set ts=4 sw=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <time.h>
#include <cstdarg>
#include "Logger.h"
#include <sourcemod_version.h>
#include <ISourceMod.h>
Logger g_Logger;
/**
* :TODO: This should be creating the log folder if it doesn't exist
*/
ConfigResult Logger::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{
if (strcasecmp(key, "Logging") == 0)
{
bool state;
if (strcasecmp(value, "on") == 0)
{
state = true;
} else if (strcasecmp(value, "off") == 0) {
state = false;
} else {
smcore.Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
return ConfigResult_Reject;
}
if (source == ConfigSource_Console)
{
state ? EnableLogging() : DisableLogging();
} else {
m_InitialState = state;
}
return ConfigResult_Accept;
} else if (strcasecmp(key, "LogMode") == 0) {
if (strcasecmp(value, "daily") == 0)
{
m_Mode = LoggingMode_Daily;
} else if (strcasecmp(value, "map") == 0) {
m_Mode = LoggingMode_PerMap;
} else if (strcasecmp(value, "game") == 0) {
m_Mode = LoggingMode_Game;
} else {
smcore.Format(error, maxlength, "Invalid value: must be [daily|map|game]");
return ConfigResult_Reject;
}
return ConfigResult_Accept;
}
return ConfigResult_Ignore;
}
void Logger::OnSourceModStartup(bool late)
{
InitLogger(m_Mode);
}
void Logger::OnSourceModAllShutdown()
{
CloseLogger();
}
void Logger::OnSourceModLevelChange(const char *mapName)
{
MapChange(mapName);
}
void Logger::_NewMapFile()
{
if (!m_Active)
{
return;
}
/* Append "Log file closed" to previous log file */
_CloseFile();
char _filename[256];
int i = 0;
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
while (true)
{
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i);
FILE *fp = fopen(_filename, "r");
if (!fp)
{
break;
}
fclose(fp);
i++;
}
m_NrmFileName.assign(_filename);
FILE *fp = fopen(m_NrmFileName.c_str(), "w");
if (!fp)
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return;
} else {
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file started (file \"L%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION);
fclose(fp);
}
}
void Logger::_CloseFile()
{
if (!m_Active)
{
return;
}
FILE *fp = NULL;
if (!m_NrmFileName.empty())
{
fp = fopen(m_NrmFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogMessage("Log file closed.");
fclose(fp);
}
m_NrmFileName.clear();
}
if (!m_ErrMapStart)
{
return;
}
fp = fopen(m_ErrFileName.c_str(), "r+");
if (fp)
{
fseek(fp, 0, SEEK_END);
LogError("Error log file session closed.");
fclose(fp);
}
m_ErrFileName.clear();
}
void Logger::InitLogger(LoggingMode mode)
{
m_Mode = mode;
m_Active = m_InitialState;
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
m_NrmCurDay = curtime->tm_mday;
m_ErrCurDay = curtime->tm_mday;
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrFileName.assign(_filename);
switch (m_Mode)
{
case LoggingMode_PerMap:
{
if (!m_Active)
{
m_DelayedStart = true;
}
break;
}
case LoggingMode_Daily:
{
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_NrmFileName.assign(_filename);
m_DailyPrintHdr = true;
break;
}
default:
{
/* do nothing... */
break;
}
}
}
void Logger::CloseLogger()
{
_CloseFile();
}
void Logger::LogToOpenFile(FILE *fp, const char *msg, ...)
{
if (!m_Active)
{
return;
}
va_list ap;
va_start(ap, msg);
LogToOpenFileEx(fp, msg, 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)
{
if (!m_Active)
{
return;
}
static ConVar *sv_logecho = smcore.FindConVar("sv_logecho");
char buffer[3072];
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer);
if (!sv_logecho || smcore.GetCvarBool(sv_logecho))
{
static char conBuffer[4096];
smcore.Format(conBuffer, sizeof(conBuffer), "L %s: %s\n", date, buffer);
smcore.ConPrint(conBuffer);
}
}
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
{
if (!m_Active)
{
return;
}
char buffer[3072];
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap);
char date[32];
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer);
fflush(fp);
}
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)
{
return;
}
if (m_Mode == LoggingMode_Game)
{
_PrintToGameLog(vafmt, ap);
return;
}
if (m_DelayedStart)
{
m_DelayedStart = false;
_NewMapFile();
}
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
FILE *fp = NULL;
if (m_Mode == LoggingMode_PerMap)
{
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
_NewMapFile();
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
{
goto print_error;
}
}
} else {
if (m_NrmCurDay != curtime->tm_mday)
{
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/L%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_NrmFileName.assign(_filename);
m_NrmCurDay = curtime->tm_mday;
m_DailyPrintHdr = true;
}
fp = fopen(m_NrmFileName.c_str(), "a+");
}
if (fp)
{
if (m_DailyPrintHdr)
{
char date[32];
m_DailyPrintHdr = false;
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod log file session started (file \"L%04d%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION);
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
} else {
goto print_error;
}
return;
print_error:
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
}
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)
{
return;
}
time_t t = g_pSM->GetAdjustedTime();
tm *curtime = localtime(&t);
if (curtime->tm_mday != m_ErrCurDay)
{
char _filename[256];
g_pSM->BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%04d%02d%02d.log", curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrFileName.assign(_filename);
m_ErrCurDay = curtime->tm_mday;
m_ErrMapStart = false;
}
FILE *fp = fopen(m_ErrFileName.c_str(), "a+");
if (fp)
{
if (!m_ErrMapStart)
{
char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: SourceMod error session started\n", date);
fprintf(fp, "L %s: Info (map \"%s\") (file \"errors_%04d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_year + 1900, curtime->tm_mon + 1, curtime->tm_mday);
m_ErrMapStart = true;
}
LogToOpenFileEx(fp, vafmt, ap);
fclose(fp);
}
else
{
char error[255];
libsys->GetPlatformError(error, sizeof(error));
LogFatal("[SM] Unexpected fatal logging error (file \"%s\")", m_NrmFileName.c_str());
LogFatal("[SM] Platform returned error: \"%s\"", error);
LogFatal("[SM] Logging has been disabled.");
m_Active = false;
return;
}
}
void Logger::MapChange(const char *mapname)
{
m_CurMapName.assign(mapname);
switch (m_Mode)
{
case LoggingMode_Daily:
{
LogMessage("-------- Mapchange to %s --------", mapname);
break;
}
case LoggingMode_PerMap:
{
_NewMapFile();
break;
}
default:
{
/* Do nothing... */
break;
}
}
if (m_ErrMapStart)
{
LogError("Error log file session closed.");
}
m_ErrMapStart = false;
}
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
{
char msg[3072];
size_t len;
len = vsnprintf(msg, sizeof(msg)-2, fmt, ap);
len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len;
msg[len++] = '\n';
msg[len] = '\0';
smcore.LogToGame(msg);
}
const char *Logger::GetLogFileName(LogType type) const
{
switch (type)
{
case LogType_Normal:
{
return m_NrmFileName.c_str();
}
case LogType_Error:
{
return m_ErrFileName.c_str();
}
default:
{
return "";
}
}
}
LoggingMode Logger::GetLoggingMode() const
{
return m_Mode;
}
void Logger::EnableLogging()
{
if (m_Active)
{
return;
}
m_Active = true;
LogMessage("[SM] Logging enabled manually by user.");
}
void Logger::DisableLogging()
{
if (!m_Active)
{
return;
}
LogMessage("[SM] Logging disabled manually by user.");
m_Active = false;
}
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
* In fact, the pretty log printing function should be abstracted.
* It's already implemented twice which is bad.
*/
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
FILE *fp = fopen(path, "at");
if (fp)
{
m_Active = true;
LogToOpenFileEx(fp, msg, ap);
m_Active = false;
fclose(fp);
}
}
-111
View File
@@ -1,111 +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_CLOGGER_H_
#define _INCLUDE_SOURCEMOD_CLOGGER_H_
#include <stdio.h>
#include <sh_string.h>
#include "common_logic.h"
using namespace SourceHook;
enum LogType
{
LogType_Normal,
LogType_Error
};
enum LoggingMode
{
LoggingMode_Daily,
LoggingMode_PerMap,
LoggingMode_Game
};
class Logger : public SMGlobalClass, public ILogger
{
public:
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
m_InitialState(true)
{
}
public: //SMGlobalClass
ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength);
void OnSourceModStartup(bool late);
void OnSourceModAllShutdown();
void OnSourceModLevelChange(const char *mapName);
public:
void InitLogger(LoggingMode mode);
void CloseLogger();
void EnableLogging();
void DisableLogging();
void LogMessage(const char *msg, ...);
void LogMessageEx(const char *msg, va_list ap);
void LogError(const char *msg, ...);
void LogErrorEx(const char *msg, va_list ap);
void LogFatal(const char *msg, ...);
void LogFatalEx(const char *msg, va_list ap);
void LogToOpenFile(FILE *fp, const char *msg, ...);
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);
const char *GetLogFileName(LogType type) const;
LoggingMode GetLoggingMode() const;
private:
void _CloseFile();
void _NewMapFile();
void _PrintToGameLog(const char *fmt, va_list ap);
private:
String m_NrmFileName;
String m_ErrFileName;
String m_CurMapName;
LoggingMode m_Mode;
int m_NrmCurDay;
int m_ErrCurDay;
bool m_ErrMapStart;
bool m_Active;
bool m_DelayedStart;
bool m_DailyPrintHdr;
bool m_InitialState;
};
extern Logger g_Logger;
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
-143
View File
@@ -1,143 +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 "NativeOwner.h"
#include "ShareSys.h"
#include "PluginSys.h"
CNativeOwner::CNativeOwner() : m_nMarkSerial(0)
{
}
void CNativeOwner::SetMarkSerial(unsigned int serial)
{
m_nMarkSerial = serial;
}
unsigned int CNativeOwner::GetMarkSerial()
{
return m_nMarkSerial;
}
void CNativeOwner::AddDependent(CPlugin *pPlugin)
{
m_Dependents.push_back(pPlugin);
}
void CNativeOwner::AddWeakRef(const WeakNative & ref)
{
m_WeakRefs.push_back(ref);
}
void CNativeOwner::AddNatives(const sp_nativeinfo_t *natives)
{
for (const sp_nativeinfo_t *native = natives; native->func && native->name; native++)
g_ShareSys.AddNativeToCache(this, native);
m_natives.append(natives);
}
void CNativeOwner::PropagateMarkSerial(unsigned int serial)
{
CNativeOwner *pOwner;
List<CPlugin *>::iterator iter;
for (iter = m_Dependents.begin();
iter != m_Dependents.end();
iter++)
{
pOwner = (*iter);
pOwner->SetMarkSerial(serial);
}
}
void CNativeOwner::UnbindWeakRef(const WeakNative &ref)
{
sp_native_t *native;
IPluginContext *pContext;
pContext = ref.pl->GetBaseContext();
if ((pContext->GetNativeByIndex(ref.idx, &native)) == SP_ERROR_NONE)
{
native->status = SP_NATIVE_UNBOUND;
native->pfn = NULL;
}
}
void CNativeOwner::DropEverything()
{
List<WeakNative>::iterator iter;
/* Unbind and remove all weak references to us */
iter = m_WeakRefs.begin();
while (iter != m_WeakRefs.end())
{
UnbindWeakRef((*iter));
iter = m_WeakRefs.erase(iter);
}
/* Strip all of our natives from the cache */
for (size_t i = 0; i < m_natives.length(); i++) {
const sp_nativeinfo_t *natives = m_natives[i];
for (const sp_nativeinfo_t *native = natives; native->func && native->name; native++)
g_ShareSys.ClearNativeFromCache(this, native->name);
}
m_natives.clear();
for (size_t i = 0; i < m_fakes.length(); i++)
g_ShareSys.ClearNativeFromCache(this, m_fakes[i]->name());
m_fakes.clear();
}
void CNativeOwner::DropWeakRefsTo(CPlugin *pPlugin)
{
List<WeakNative>::iterator iter;
iter = m_WeakRefs.begin();
while (iter != m_WeakRefs.end())
{
WeakNative & ref = (*iter);
if (ref.pl == pPlugin)
{
iter = m_WeakRefs.erase(iter);
}
else
{
iter++;
}
}
}
void CNativeOwner::DropRefsTo(CPlugin *pPlugin)
{
m_Dependents.remove(pPlugin);
DropWeakRefsTo(pPlugin);
}
-89
View File
@@ -1,89 +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$
*/
#ifndef _INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
#include <sp_vm_types.h>
#include <sh_list.h>
#include <am-linkedlist.h>
#include <am-vector.h>
#include "common_logic.h"
#include "Native.h"
struct Native;
class CPlugin;
using namespace SourceMod;
struct WeakNative
{
WeakNative(IPlugin *plugin, uint32_t index) :
pl(plugin), idx(index)
{
pl = plugin;
idx = index;
}
IPlugin *pl;
uint32_t idx;
};
using namespace SourceHook;
class CNativeOwner
{
public:
CNativeOwner();
public:
virtual void DropEverything();
public:
void AddNatives(const sp_nativeinfo_t *info);
public:
void SetMarkSerial(unsigned int serial);
unsigned int GetMarkSerial();
void PropagateMarkSerial(unsigned int serial);
public:
void AddDependent(CPlugin *pPlugin);
void AddWeakRef(const WeakNative & ref);
void DropRefsTo(CPlugin *pPlugin);
private:
void DropWeakRefsTo(CPlugin *pPlugin);
void UnbindWeakRef(const WeakNative & ref);
protected:
List<CPlugin *> m_Dependents;
unsigned int m_nMarkSerial;
List<WeakNative> m_WeakRefs;
ke::Vector<const sp_nativeinfo_t *> m_natives;
ke::Vector<ke::Ref<Native> > m_fakes;
};
extern CNativeOwner g_CoreNatives;
#endif //_INCLUDE_SOURCEMOD_NATIVE_OWNER_H_
-190
View File
@@ -1,190 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet :
// =============================================================================
// SourceMod
// Copyright (C) 2004-2014 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 "ProfileTools.h"
#include <stdarg.h>
ProfileToolManager g_ProfileToolManager;
ProfileToolManager::ProfileToolManager()
: active_(nullptr),
default_(nullptr)
{
}
void
ProfileToolManager::OnSourceModAllInitialized()
{
rootmenu->AddRootConsoleCommand2("prof", "Profiling", this);
}
void
ProfileToolManager::OnSourceModShutdown()
{
rootmenu->RemoveRootConsoleCommand("prof", this);
}
IProfilingTool *
ProfileToolManager::FindToolByName(const char *name)
{
for (size_t i = 0; i < tools_.length(); i++) {
if (strcmp(tools_[i]->Name(), name) == 0)
return tools_[i];
}
return nullptr;
}
static void
render_help(const char *fmt, ...)
{
char buffer[2048];
va_list ap;
va_start(ap, fmt);
smcore.FormatArgs(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
rootmenu->ConsolePrint("%s", buffer);
}
void
ProfileToolManager::StartFromConsole(IProfilingTool *tool)
{
if (active_) {
rootmenu->ConsolePrint("A profile is already active using %s.", active_->Name());
return;
}
active_ = tool;
if (!active_->Start()) {
rootmenu->ConsolePrint("Failed to attach to or start %s.", active_->Name());
active_ = nullptr;
return;
}
g_pSourcePawn2->SetProfilingTool(active_);
g_pSourcePawn2->EnableProfiling();
rootmenu->ConsolePrint("Started profiling with %s.", active_->Name());
default_ = active_;
}
void
ProfileToolManager::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *args)
{
if (tools_.length() == 0) {
rootmenu->ConsolePrint("No profiling tools are enabled.");
return;
}
if (args->ArgC() >= 3) {
cmdname = args->Arg(2);
if (strcmp(cmdname, "list") == 0) {
rootmenu->ConsolePrint("Profiling tools:");
for (size_t i = 0; i < tools_.length(); i++) {
rootmenu->DrawGenericOption(tools_[i]->Name(), tools_[i]->Description());
}
return;
}
if (strcmp(cmdname, "stop") == 0) {
if (!active_) {
rootmenu->ConsolePrint("No profiler is active.");
return;
}
g_pSourcePawn2->DisableProfiling();
g_pSourcePawn2->SetProfilingTool(nullptr);
active_->Stop(render_help);
active_ = nullptr;
return;
}
if (strcmp(cmdname, "dump") == 0) {
if (active_) {
// if we have an active profiler, dump it
active_->Dump();
return;
}
}
if (args->ArgC() < 4) {
if (strcmp(cmdname, "start") == 0) {
if (!default_) {
default_ = FindToolByName("vprof");
if (!default_ && tools_.length() > 0)
default_ = tools_[0];
if (!default_) {
rootmenu->ConsolePrint("Could not find any profiler to use.");
return;
}
}
StartFromConsole(default_);
return;
}
}
if (args->ArgC() < 4) {
rootmenu->ConsolePrint("You must specify a profiling tool name.");
return;
}
const char *toolname = args->Arg(3);
if (strcmp(cmdname, "start") == 0) {
IProfilingTool *tool = FindToolByName(toolname);
if (!tool) {
rootmenu->ConsolePrint("No tool with the name \"%s\" was found.", toolname);
return;
}
StartFromConsole(tool);
return;
}
if (strcmp(cmdname, "dump") == 0) {
IProfilingTool *tool = FindToolByName(toolname);
if (!tool) {
rootmenu->ConsolePrint("No tool with the name \"%s\" was found.", toolname);
return;
}
tool->Dump();
return;
}
if (strcmp(cmdname, "help") == 0) {
IProfilingTool *tool = FindToolByName(toolname);
if (!tool) {
rootmenu->ConsolePrint("No tool with the name \"%s\" was found.", toolname);
return;
}
tool->RenderHelp(render_help);
return;
}
}
rootmenu->ConsolePrint("Profiling commands:");
rootmenu->DrawGenericOption("list", "List all available profiling tools.");
rootmenu->DrawGenericOption("start", "Start a profile with a given tool.");
rootmenu->DrawGenericOption("stop", "Stop the current profile session.");
rootmenu->DrawGenericOption("dump", "Dumps output from the current profile session.");
rootmenu->DrawGenericOption("help", "Display help text for a profiler.");
}
-87
View File
@@ -1,87 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet :
// =============================================================================
// SourceMod
// Copyright (C) 2004-2014 AlliedModders LLC. All rights reserved.
// =============================================================================
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License, version 3.0, as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
//
// As a special exception, AlliedModders LLC gives you permission to link the
// code of this program (as well as its derivative works) to "Half-Life 2," the
// "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
// by the Valve Corporation. You must obey the GNU General Public License in
// all respects for all other code used. Additionally, AlliedModders LLC grants
// this exception to all derivative works. AlliedModders LLC defines further
// exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
// or <http://www.sourcemod.net/license.php>.
#ifndef _include_sourcemod_logic_profile_tool_manager_h_
#define _include_sourcemod_logic_profile_tool_manager_h_
#include <sp_vm_api.h>
#include <am-vector.h>
#include <IShareSys.h>
#include <IRootConsoleMenu.h>
#include "common_logic.h"
using namespace SourcePawn;
class ProfileToolManager
: public SMGlobalClass,
public IRootConsoleCommand
{
public:
ProfileToolManager();
// SMGlobalClass
void OnSourceModAllInitialized() KE_OVERRIDE;
void OnSourceModShutdown() KE_OVERRIDE;
// IRootConsoleCommand
void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *args) KE_OVERRIDE;
void RegisterTool(IProfilingTool *tool) {
tools_.append(tool);
}
bool IsActive() const {
return !!active_;
}
// If we get problems with plugins not being able to balance the profile
// scopes, we should add a safety net that automatically clears any pending
// scopes.
void EnterScope(const char *group, const char *name) {
if (active_)
active_->EnterScope(group, name);
}
void LeaveScope() {
if (active_)
active_->LeaveScope();
}
IProfilingTool *FindToolByName(const char *name);
private:
void StartFromConsole(IProfilingTool *tool);
private:
ke::Vector<IProfilingTool *> tools_;
IProfilingTool *active_;
IProfilingTool *default_;
bool enabled_;
};
extern ProfileToolManager g_ProfileToolManager;
#endif // _include_sourcemod_logic_profile_tool_manager_h_
+518
View File
@@ -0,0 +1,518 @@
/**
* 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 "Profiler.h"
#include <ISourceMod.h>
#if defined PLATFORM_POSIX
#include <sys/time.h>
#include <time.h>
#endif
#include <IPluginSys.h>
#include "stringutil.h"
ProfileEngine g_Profiler;
IProfiler *sm_profiler = &g_Profiler;
#if defined PLATFORM_WINDOWS
double WINDOWS_PERFORMANCE_FREQUENCY;
#endif
class EmptyProfiler : public IProfiler
{
public:
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native)
{
}
void OnNativeEnd()
{
}
void OnFunctionBegin(IPluginContext *pContext, const char *name)
{
}
void OnFunctionEnd()
{
}
int OnCallbackBegin(IPluginContext *pContext, sp_public_t *pubfunc)
{
return 0;
}
void OnCallbackEnd(int serial)
{
}
} s_EmptyProfiler;
inline void InitProfPoint(prof_point_t &pt)
{
#if defined PLATFORM_WINDOWS
QueryPerformanceCounter(&pt.value);
#elif defined PLATFORM_POSIX
gettimeofday(&pt.value, NULL);
#endif
pt.is_set = true;
}
ProfileEngine::ProfileEngine()
{
m_serial = 0;
#if defined PLATFORM_WINDOWS
LARGE_INTEGER pf;
if (QueryPerformanceFrequency(&pf))
{
WINDOWS_PERFORMANCE_FREQUENCY = 1.0 / (double)(pf.QuadPart);
}
else
{
WINDOWS_PERFORMANCE_FREQUENCY = -1.0;
}
#endif
if (IsEnabled())
{
InitProfPoint(m_ProfStart);
}
else
{
sm_profiler = &s_EmptyProfiler;
}
}
bool ProfileEngine::IsEnabled()
{
#if defined PLATFORM_WINDOWS
return (WINDOWS_PERFORMANCE_FREQUENCY > 0.0);
#elif defined PLATFORM_POSIX
return true;
#endif
}
inline double DiffProfPoints(const prof_point_t &start, const prof_point_t &end)
{
double seconds;
#if defined PLATFORM_WINDOWS
LONGLONG diff;
diff = end.value.QuadPart - start.value.QuadPart;
seconds = diff * WINDOWS_PERFORMANCE_FREQUENCY;
#elif defined PLATFORM_POSIX
seconds = (double)(end.value.tv_sec - start.value.tv_sec);
if (start.value.tv_usec > end.value.tv_usec)
{
seconds -= 1.0;
seconds += (double)(1000000 - (start.value.tv_usec - end.value.tv_usec)) / 1000000.0;
}
else
{
seconds += (double)(end.value.tv_usec - start.value.tv_usec) / 1000000.0;
}
#endif
return seconds;
}
inline double CalcAtomTime(const prof_atom_t &atom)
{
if (!atom.end.is_set)
{
return atom.base_time;
}
return atom.base_time + DiffProfPoints(atom.start, atom.end);
}
void ProfileEngine::OnNativeBegin(IPluginContext *pContext, sp_native_t *native)
{
PushProfileStack(pContext, SP_PROF_NATIVES, native->name);
}
void ProfileEngine::OnNativeEnd()
{
assert(!m_AtomStack.empty());
assert(m_AtomStack.front().atom_type == SP_PROF_NATIVES);
PopProfileStack(&m_Natives);
}
void ProfileEngine::OnFunctionBegin(IPluginContext *pContext, const char *name)
{
PushProfileStack(pContext, SP_PROF_FUNCTIONS, name);
}
void ProfileEngine::OnFunctionEnd()
{
assert(!m_AtomStack.empty());
assert(m_AtomStack.front().atom_type == SP_PROF_FUNCTIONS);
PopProfileStack(&m_Functions);
}
int ProfileEngine::OnCallbackBegin(IPluginContext *pContext, sp_public_t *pubfunc)
{
PushProfileStack(pContext, SP_PROF_CALLBACKS, pubfunc->name);
return m_serial;
}
void ProfileEngine::OnCallbackEnd(int serial)
{
assert(!m_AtomStack.empty());
/**
* Account for the situation where the JIT discards the
* stack because there was an RTE of sorts.
*/
if (m_AtomStack.front().atom_type != SP_PROF_CALLBACKS
&& m_AtomStack.front().atom_serial != serial)
{
prof_atom_t atom;
double total_time;
/* There was an error, and we need to discard things. */
total_time = 0.0;
while (!m_AtomStack.empty()
&& m_AtomStack.front().atom_type != SP_PROF_CALLBACKS
&& m_AtomStack.front().atom_serial != serial)
{
total_time += CalcAtomTime(m_AtomStack.front());
m_AtomStack.pop();
}
/**
* Now we can end and discard ourselves, without saving the data.
* Since this data is all erroneous anyway, we don't care if it's
* not totally accurate.
*/
assert(!m_AtomStack.empty());
atom = m_AtomStack.front();
m_AtomStack.pop();
/* Note: We don't need to resume ourselves because end is set by Pause(). */
total_time += CalcAtomTime(atom);
ResumeParent(total_time);
return;
}
PopProfileStack(&m_Callbacks);
}
void ProfileEngine::PushProfileStack(IPluginContext *ctx, int type, const char *name)
{
prof_atom_t atom;
PauseParent();
atom.atom_type = type;
atom.base_time = 0.0;
atom.ctx = ctx->GetContext();
atom.name = name;
atom.end.is_set = false;
if (type == SP_PROF_CALLBACKS)
{
atom.atom_serial = ++m_serial;
}
else
{
atom.atom_serial = 0;
}
m_AtomStack.push(atom);
/* Note: We do this after because the stack could grow and skew results */
InitProfPoint(m_AtomStack.front().start);
}
void ProfileEngine::PopProfileStack(ProfileReport *reporter)
{
double total_time;
prof_atom_t &atom = m_AtomStack.front();
/* We're okay to cache our used time. */
InitProfPoint(atom.end);
total_time = CalcAtomTime(atom);
/* Now it's time to save this! This may do a lot of computations which
* is why we've cached the time beforehand.
*/
reporter->SaveAtom(atom);
m_AtomStack.pop();
/* Finally, tell our parent how much time we used. */
ResumeParent(total_time);
}
void ProfileEngine::PauseParent()
{
if (m_AtomStack.empty())
{
return;
}
InitProfPoint(m_AtomStack.front().end);
}
void ProfileEngine::ResumeParent(double addTime)
{
if (m_AtomStack.empty())
{
return;
}
prof_atom_t &atom = m_AtomStack.front();
/* Move its "paused time" to its base (known) time,
* then reset the start/end. Note that since CalcAtomTime()
* reads the base time, we SHOULD NOT use += to add.
*/
atom.base_time = CalcAtomTime(atom);
atom.base_time += addTime;
InitProfPoint(atom.start);
atom.end.is_set = false;
}
void ProfileEngine::Clear()
{
m_Natives.Clear();
m_Callbacks.Clear();
m_Functions.Clear();
InitProfPoint(m_ProfStart);
}
void ProfileEngine::OnSourceModAllInitialized()
{
rootmenu->AddRootConsoleCommand2("profiler", "Profiler commands", this);
}
void ProfileEngine::OnSourceModShutdown()
{
rootmenu->RemoveRootConsoleCommand("profiler", this);
}
void ProfileEngine::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command)
{
if (command->ArgC() >= 3)
{
if (strcmp(command->Arg(2), "flush") == 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);
Clear();
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
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:");
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)
{
time_t t;
double total_time;
prof_point_t end_time;
InitProfPoint(end_time);
total_time = DiffProfPoints(m_ProfStart, end_time);
t = time(NULL);
fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
fprintf(fp, "<profile time=\"%d\" uptime=\"%f\">\n", (int)t, total_time);
WriteReport(fp, &m_Natives, "natives");
WriteReport(fp, &m_Callbacks, "callbacks");
WriteReport(fp, &m_Functions, "functions");
fprintf(fp, "</profile>\n");
return true;
}
void ProfileEngine::WriteReport(FILE *fp, ProfileReport *report, const char *name)
{
size_t i, num;
prof_atom_report_t *ar;
char new_name[512];
fprintf(fp, " <report name=\"%s\">\n", name);
num = report->GetNumReports();
for (i = 0; i < num; i++)
{
ar = report->GetReport(i);
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), ">", "&gt;", true);
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
new_name,
ar->num_calls,
ar->min_time,
ar->max_time,
ar->total_time);
}
fprintf(fp, " </report>\n");
}
ProfileReport::~ProfileReport()
{
for (size_t i = 0; i < m_Reports.size(); i++)
{
delete m_Reports[i];
}
}
void ProfileReport::Clear()
{
m_ReportLookup.clear();
for (size_t i = 0; i < m_Reports.size(); i++)
{
delete m_Reports[i];
}
m_Reports.clear();
}
size_t ProfileReport::GetNumReports()
{
return m_Reports.size();
}
prof_atom_report_t *ProfileReport::GetReport(size_t i)
{
return m_Reports[i];
}
void ProfileReport::SaveAtom(const prof_atom_t &atom)
{
double atom_time;
char full_name[256];
prof_atom_report_t **pReport, *report;
if (atom.atom_type == SP_PROF_NATIVES)
{
smcore.strncopy(full_name, atom.name, sizeof(full_name));
}
else
{
IPlugin *pl;
const char *file;
file = "unknown";
if ((pl = pluginsys->FindPluginByContext(atom.ctx)) != NULL)
{
file = pl->GetFilename();
}
smcore.Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
}
atom_time = CalcAtomTime(atom);
if ((pReport = m_ReportLookup.retrieve(full_name)) == NULL)
{
report = new prof_atom_report_t;
smcore.strncopy(report->atom_name, full_name, sizeof(report->atom_name));
report->max_time = atom_time;
report->min_time = atom_time;
report->num_calls = 1;
report->total_time = atom_time;
m_ReportLookup.insert(full_name, report);
m_Reports.push_back(report);
}
else
{
report = *pReport;
if (atom_time > report->max_time)
{
report->max_time = atom_time;
}
if (atom_time < report->min_time)
{
report->min_time = atom_time;
}
report->num_calls++;
report->total_time += atom_time;
}
}
+131
View File
@@ -0,0 +1,131 @@
/**
* 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_PLUGIN_PROFILER_H_
#define _INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
#include <sp_vm_api.h>
#include <sm_platform.h>
#include <sm_trie_tpl.h>
#include <sh_vector.h>
#include <sh_stack.h>
#include <stdio.h>
#include "common_logic.h"
#include <IRootConsoleMenu.h>
using namespace SourcePawn;
using namespace SourceHook;
struct prof_point_t
{
#if defined PLATFORM_WINDOWS
LARGE_INTEGER value;
#elif defined PLATFORM_POSIX
struct timeval value;
#endif
bool is_set;
};
struct prof_atom_t
{
int atom_type; /* Type of object we're profiling */
int atom_serial; /* Serial number, if appropriate */
sp_context_t *ctx; /* Plugin context. */
const char *name; /* Name of the function */
prof_point_t start; /* Start time */
prof_point_t end; /* End time */
double base_time; /* Known time from children or pausing. */
};
struct prof_atom_report_t
{
char atom_name[256]; /* Full name to shove to logs */
double total_time; /* Total time spent executing, in s */
unsigned int num_calls; /* Number of invocations */
double min_time; /* Min time spent in one call, in s */
double max_time; /* Max time spent in one call, in s */
};
class ProfileReport
{
public:
~ProfileReport();
public:
void SaveAtom(const prof_atom_t &atom);
size_t GetNumReports();
prof_atom_report_t *GetReport(size_t i);
void Clear();
private:
KTrie<prof_atom_report_t *> m_ReportLookup;
CVector<prof_atom_report_t *> m_Reports;
};
class ProfileEngine :
public SMGlobalClass,
public IRootConsoleCommand,
public IProfiler
{
public:
ProfileEngine();
public:
bool IsEnabled();
bool GenerateReport(FILE *fp);
void Clear();
public: //SMGlobalClass
void OnSourceModAllInitialized();
void OnSourceModShutdown();
public: //IRootConsoleCommand
void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command);
public: //IProfiler
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native);
void OnNativeEnd() ;
void OnFunctionBegin(IPluginContext *pContext, const char *name);
void OnFunctionEnd();
int OnCallbackBegin(IPluginContext *pContext, sp_public_t *pubfunc);
void OnCallbackEnd(int serial);
private:
void PushProfileStack(IPluginContext *ctx, int type, const char *name);
void PopProfileStack(ProfileReport *reporter);
void PauseParent();
void ResumeParent(double addTime);
void WriteReport(FILE *fp, ProfileReport *report, const char *name);
private:
CStack<prof_atom_t> m_AtomStack;
ProfileReport m_Callbacks;
ProfileReport m_Functions;
ProfileReport m_Natives;
int m_serial;
prof_point_t m_ProfStart;
};
extern IProfiler *sm_profiler;
#endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
+1 -1
View File
@@ -1077,7 +1077,7 @@ const char *TextParsers::GetSMCErrorString(SMCError err)
NULL,
"Stream failed to open",
"Stream returned read error",
"Callback error",
NULL,
"Un-quoted section has invalid tokens",
"Section declared without header",
"Section declared with unknown tokens",
-39
View File
@@ -33,48 +33,9 @@
#define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
#include <IThreader.h>
#include <am-thread-utils.h>
#include <am-utility.h>
using namespace SourceMod;
class CompatMutex : public IMutex
{
public:
bool TryLock() {
return mutex_.TryLock();
}
void Lock() {
mutex_.Lock();
}
void Unlock() {
mutex_.Unlock();
}
void DestroyThis() {
delete this;
}
private:
ke::Mutex mutex_;
};
class CompatCondVar : public IEventSignal
{
public:
void Wait() {
ke::AutoLock lock(&cv_);
cv_.Wait();
}
void Signal() {
ke::AutoLock lock(&cv_);
cv_.Notify();
}
void DestroyThis() {
delete this;
}
private:
ke::ConditionVariable cv_;
};
extern IThreader *g_pThreader;
#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
+60 -37
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet:
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...)
if (!m_FileLogged)
{
logger->LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
m_FileLogged = true;
}
logger->LogError("[SM] %s", buffer);
smcore.LogError("[SM] %s", buffer);
}
void CPhraseFile::ReparseFile()
@@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str();
}
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
logger->LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
smcore.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);
}
const char *code;
@@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str();
}
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
code,
m_File.c_str());
logger->LogError("[SM] Error (line %d, column %d): %s",
smcore.LogError("[SM] Error (line %d, column %d): %s",
states.line,
states.col,
msg);
@@ -210,7 +210,12 @@ SMCResult CPhraseFile::ReadSMC_NewSection(const SMCStates *states, const char *n
m_ParseState = PPS_InPhrase;
recognized = true;
if (!m_PhraseLookup.retrieve(name, &m_CurPhrase))
int *pvalue;
if ((pvalue = m_PhraseLookup.retrieve(name)) != NULL)
{
m_CurPhrase = *pvalue;
}
else
{
phrase_t *pPhrase;
@@ -647,11 +652,11 @@ TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_i
return Trans_BadLanguage;
}
int address;
if (!m_PhraseLookup.retrieve(szPhrase, &address))
int *pvalue;
if ((pvalue = m_PhraseLookup.retrieve(szPhrase)) == NULL)
return Trans_BadPhrase;
phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(address);
phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(*pvalue);
trans_t *trans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl);
trans = &trans[lang_id];
@@ -728,7 +733,10 @@ ConfigResult Translator::OnSourceModConfigChanged(const char *key,
void Translator::OnSourceModLevelChange(const char *mapName)
{
RebuildLanguageDatabase();
/* Refresh language stuff */
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
RebuildLanguageDatabase(path);
}
void Translator::OnSourceModAllInitialized()
@@ -754,7 +762,15 @@ void Translator::OnSourceModShutdown()
bool Translator::GetLanguageByCode(const char *code, unsigned int *index)
{
return m_LCodeLookup.retrieve(code, index);
unsigned int *pindex;
if ((pindex = m_LCodeLookup.retrieve(code)) == NULL)
return false;
if (index)
*index = *pindex;
return true;
}
bool Translator::GetLanguageByName(const char *name, unsigned int *index)
@@ -771,7 +787,15 @@ bool Translator::GetLanguageByName(const char *name, unsigned int *index)
}
lower[len] = '\0';
return m_LAliases.retrieve(lower, index);
unsigned int *pIndex;
if ((pIndex = m_LAliases.retrieve(lower)) == NULL)
return false;
if (index)
*index = *pIndex;
return true;
}
unsigned int Translator::GetLanguageCount()
@@ -804,7 +828,7 @@ unsigned int Translator::FindOrAddPhraseFile(const char *phrase_file)
return idx;
}
void Translator::RebuildLanguageDatabase()
void Translator::RebuildLanguageDatabase(const char *lang_header_file)
{
/* Erase everything we have */
m_LCodeLookup.clear();
@@ -818,12 +842,9 @@ void Translator::RebuildLanguageDatabase()
m_Languages.clear();
/* Start anew */
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
SMCError err;
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);
if (!str_err)
@@ -831,21 +852,27 @@ void Translator::RebuildLanguageDatabase()
str_err = m_CustomError.c_str();
}
logger->LogError("[SM] Failed to parse language header file: \"%s\"", path);
logger->LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
smcore.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);
}
if (!m_LCodeLookup.retrieve(m_InitialLang, &m_ServerLang))
unsigned int *pServerLang;
if ((pServerLang = m_LCodeLookup.retrieve(m_InitialLang)) == NULL)
{
logger->LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
}
else
{
m_ServerLang = *pServerLang;
}
if (!m_Languages.size())
{
logger->LogError("[SM] Fatal error, no languages found! Translation will not work.");
smcore.LogError("[SM] Fatal error, no languages found! Translation will not work.");
}
for (size_t i=0; i<m_Files.size(); i++)
@@ -872,7 +899,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
if (!m_InLanguageSection)
{
logger->LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
}
return SMCResult_Continue;
@@ -887,14 +914,6 @@ SMCResult Translator::ReadSMC_LeavingSection(const SMCStates *states)
SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{
size_t len = strlen(key);
if (len >= sizeof(((Language *)0)->m_code2))
{
logger->LogError("[SM] Warning encountered parsing languages.cfg file.");
logger->LogError("[SM] Invalid language code \"%s\" is too long.", key);
}
AddLanguage(key, value);
return SMCResult_Continue;
@@ -914,11 +933,15 @@ bool Translator::AddLanguage(const char *langcode, const char *description)
}
lower[len] = '\0';
if (m_LAliases.contains(lower))
if (m_LAliases.retrieve(lower))
return false;
unsigned int idx;
if (!m_LCodeLookup.retrieve(langcode, &idx))
if (unsigned int *pIdx = m_LCodeLookup.retrieve(langcode))
{
idx = *pIdx;
}
else
{
Language *pLanguage = new Language;
idx = m_Languages.size();
@@ -1033,11 +1056,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned
{
if (fail_phrase != NULL)
{
logger->LogError("[SM] Could not find core phrase: %s", fail_phrase);
smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase);
}
else
{
logger->LogError("[SM] Unknown fatal error while translating a core phrase.");
smcore.LogError("[SM] Unknown fatal error while translating a core phrase.");
}
return false;
+6 -6
View File
@@ -33,7 +33,7 @@
#define _INCLUDE_SOURCEMOD_TRANSLATOR_H_
#include "common_logic.h"
#include <sm_stringhashmap.h>
#include <sm_trie_tpl.h>
#include <sh_string.h>
#include <sh_vector.h>
#include "sm_memtable.h"
@@ -54,7 +54,7 @@ enum PhraseParseState
struct Language
{
char m_code2[32];
char m_code2[4];
int m_CanonicalName;
};
@@ -79,7 +79,7 @@ private:
void ParseError(const char *message, ...);
void ParseWarning(const char *message, ...);
private:
StringHashMap<int> m_PhraseLookup;
KTrie<int> m_PhraseLookup;
String m_File;
Translator *m_pTranslator;
PhraseParseState m_ParseState;
@@ -115,6 +115,7 @@ public: // ITextListener_SMC
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
public:
void RebuildLanguageDatabase(const char *lang_header_file);
unsigned int FindOrAddPhraseFile(const char *phrase_file);
BaseStringTable *GetStringTable();
unsigned int GetLanguageCount();
@@ -145,15 +146,14 @@ public: //ITranslator
size_t *pOutLength,
const char **pFailPhrase);
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
void RebuildLanguageDatabase();
private:
bool AddLanguage(const char *langcode, const char *description);
private:
CVector<Language *> m_Languages;
CVector<CPhraseFile *> m_Files;
BaseStringTable *m_pStringTab;
StringHashMap<unsigned int> m_LCodeLookup;
StringHashMap<unsigned int> m_LAliases;
KTrie<unsigned int> m_LCodeLookup;
KTrie<unsigned int> m_LAliases;
bool m_InLanguageSection;
String m_CustomError;
unsigned int m_ServerLang;
+16 -82
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet:
* vim: set ts=4 sw=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -32,50 +32,33 @@
#include <stdlib.h>
#include <sm_platform.h>
#include <string.h>
#include <stdarg.h>
#include "common_logic.h"
#include "TextParsers.h"
#include "Profiler.h"
#include "sm_crc32.h"
#include "MemoryUtils.h"
#include "stringutil.h"
#include "ThreadSupport.h"
#include "Translator.h"
#include "GameConfigs.h"
#include "DebugReporter.h"
#include "PluginSys.h"
#include "ShareSys.h"
#include "NativeOwner.h"
#include "HandleSys.h"
#include "ExtensionSys.h"
#include "ForwardSys.h"
#include "AdminCache.h"
#include "ProfileTools.h"
#include "Logger.h"
sm_core_t smcore;
IHandleSys *handlesys = &g_HandleSys;
IHandleSys *handlesys;
IdentityToken_t *g_pCoreIdent;
SMGlobalClass *SMGlobalClass::head = NULL;
ISourceMod *g_pSM;
ILibrarySys *libsys;
ITextParsers *textparser = &g_TextParser;
IVEngineServer *engine;
IShareSys *sharesys = &g_ShareSys;
IShareSys *sharesys;
IRootConsole *rootmenu;
IPluginManager *pluginsys = g_PluginSys.GetOldAPI();
IForwardManager *forwardsys = &g_Forwards;
IPluginManager *pluginsys;
IForwardManager *forwardsys;
ITimerSystem *timersys;
ServerGlobals serverGlobals;
IPlayerManager *playerhelpers;
IAdminSystem *adminsys = &g_Admins;
IAdminSystem *adminsys;
IGameHelpers *gamehelpers;
ISourcePawnEngine *g_pSourcePawn;
ISourcePawnEngine2 *g_pSourcePawn2;
CNativeOwner g_CoreNatives;
IScriptManager *scripts = &g_PluginSys;
IExtensionSys *extsys = &g_Extensions;
ILogger *logger = &g_Logger;
IMenuManager *menus;
static void AddCorePhraseFile(const char *filename)
{
@@ -87,41 +70,11 @@ static IGameConfig *GetCoreGameConfig()
return g_pGameConf;
}
// Defined in smn_filesystem.cpp.
extern bool OnLogPrint(const char *msg);
static void GenerateError(IPluginContext *ctx, cell_t idx, int err, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
g_DbgReporter.GenerateErrorVA(ctx, idx, err, msg, ap);
va_end(ap);
}
static void AddNatives(sp_nativeinfo_t *natives)
{
g_CoreNatives.AddNatives(natives);
}
static void DumpHandles(void (*dumpfn)(const char *fmt, ...))
{
g_HandleSys.Dump(dumpfn);
}
static bool DumpAdminCache(const char *filename)
{
return g_Admins.DumpCache(filename);
}
static void RegisterProfiler(IProfilingTool *tool)
{
g_ProfileToolManager.RegisterTool(tool);
}
static sm_logic_t logic =
{
NULL,
g_pThreader,
sm_profiler,
&g_Translator,
stristr,
CoreTranslate,
@@ -129,23 +82,7 @@ static sm_logic_t logic =
UTIL_ReplaceAll,
UTIL_ReplaceEx,
UTIL_DecodeHexString,
GetCoreGameConfig,
OnLogPrint,
&g_DbgReporter,
GenerateError,
AddNatives,
DumpHandles,
DumpAdminCache,
RegisterProfiler,
&g_PluginSys,
&g_ShareSys,
&g_Extensions,
&g_HandleSys,
&g_Forwards,
&g_Admins,
NULL,
&g_Logger,
-1.0f
GetCoreGameConfig
};
static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
@@ -156,22 +93,19 @@ static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
memcpy(_logic, &logic, sizeof(sm_logic_t));
memcpy(&serverGlobals, core->serverGlobals, sizeof(ServerGlobals));
handlesys = core->handlesys;
libsys = core->libsys;
engine = core->engine;
g_pCoreIdent = core->core_ident;
g_pSM = core->sm;
sharesys = core->sharesys;
rootmenu = core->rootmenu;
pluginsys = core->pluginsys;
forwardsys = core->forwardsys;
timersys = core->timersys;
playerhelpers = core->playerhelpers;
adminsys = core->adminsys;
gamehelpers = core->gamehelpers;
menus = core->menus;
g_pSourcePawn = *core->spe1;
g_pSourcePawn2 = *core->spe2;
SMGlobalClass::head = core->listeners;
g_ShareSys.Initialize();
g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
_logic->core_ident = g_pCoreIdent;
}
PLATFORM_EXTERN_C ITextParsers *get_textparsers()
@@ -191,7 +125,7 @@ PLATFORM_EXTERN_C LogicInitFunction logic_load(uint32_t magic)
void CoreNativesToAdd::OnSourceModAllInitialized()
{
g_CoreNatives.AddNatives(m_NativeList);
smcore.AddNatives(m_NativeList);
}
/* Overload a few things to prevent libstdc++ linking */
-4
View File
@@ -52,10 +52,6 @@ extern ServerGlobals serverGlobals;
extern IPlayerManager *playerhelpers;
extern IAdminSystem *adminsys;
extern IGameHelpers *gamehelpers;
extern IScriptManager *scripts;
extern IExtensionSys *extsys;
extern ILogger *logger;
extern IMenuManager *menus;
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
-95
View File
@@ -1,95 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2014 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_handle_helpers_h_
#define _include_sourcemod_handle_helpers_h_
#include "common_logic.h"
// T must be a pointer type.
template <typename T>
class OpenHandle
{
public:
OpenHandle()
: t_(),
error_(HandleError_None)
{}
explicit OpenHandle(T *t)
: t_(t),
error_(HandleError_None)
{}
OpenHandle(const OpenHandle &other)
: t_(other.t_),
error_(other.error_)
{}
OpenHandle(IPluginContext *cx, Handle_t handle, HandleType_t type)
: t_(NULL)
{
HandleSecurity sec(cx->GetIdentity(), g_pCoreIdent);
error_ = handlesys->ReadHandle(handle, type, &sec, (void **)&t_);
if (error_ != HandleError_None)
cx->ThrowNativeError("invalid handle %x (error: %d)", handle, error_);
}
bool Ok() const {
return t_ && error_ == HandleError_None;
}
operator T *() const {
assert(Ok());
return t_;
}
T *operator *() const {
assert(Ok());
return t_;
}
T *operator ->() const {
assert(Ok());
return t_;
}
OpenHandle &operator =(T *t) {
t_ = t;
error_ = HandleError_None;
return *this;
}
OpenHandle &operator =(const OpenHandle &other) {
t_ = other.t_;
error_ = other.error_;
return *this;
}
private:
T *t_;
HandleError error_;
};
#endif // _include_sourcemod_handle_helpers_h_
+16 -224
View File
@@ -1,5 +1,5 @@
/**
* vim: set ts=4 sw=4 tw=99 noet:
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
@@ -29,30 +29,20 @@
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_INTERCOM_H_
#define _INCLUDE_SOURCEMOD_INTERCOM_H_
#include <sp_vm_api.h>
#include <IHandleSys.h>
#include <IShareSys.h>
#include <IPluginSys.h>
#include <IDBDriver.h>
#include <sh_string.h>
#include <sp_vm_api.h>
#include <sh_vector.h>
#include <IExtensionSys.h>
#include <IForwardSys.h>
#include <IAdminSystem.h>
#ifndef _INCLUDE_SOURCEMOD_INTERCOM_H_
#define _INCLUDE_SOURCEMOD_INTERCOM_H_
using namespace SourceMod;
using namespace SourcePawn;
using namespace SourceHook;
/**
* Add 1 to the RHS of this expression to bump the intercom file
* This is to prevent mismatching core/logic binaries
*/
#define SM_LOGIC_MAGIC (0x0F47C0DE - 29)
#define SM_LOGIC_MAGIC (0x0F47C0DE - 18)
#if defined SM_LOGIC
class IVEngineServer
@@ -62,16 +52,9 @@ class IVEngineServer_Logic
{
public:
virtual bool IsMapValid(const char *map) = 0;
virtual bool IsDedicatedServer() = 0;
virtual void InsertServerCommand(const char *cmd) = 0;
virtual void ServerCommand(const char *cmd) = 0;
virtual void ServerExecute() = 0;
virtual const char *GetClientConVarValue(int clientIndex, const char *name) = 0;
virtual void ClientCommand(edict_t *pEdict, const char *szCommand) = 0;
virtual void FakeClientCommand(edict_t *pEdict, const char *szCommand) = 0;
};
typedef void * FileHandle_t;
typedef int FileFindHandle_t;
#if defined SM_LOGIC
@@ -83,25 +66,7 @@ class IFileSystem_Logic
public:
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
virtual const char *FindNext(FileFindHandle_t handle) = 0;
virtual bool FindIsDirectory(FileFindHandle_t handle) = 0;
virtual void FindClose(FileFindHandle_t handle) = 0;
virtual FileHandle_t Open(const char *pFileName, const char *pOptions, const char *pathID = 0) = 0;
virtual void Close(FileHandle_t file) = 0;
virtual char *ReadLine(char *pOutput, int maxChars, FileHandle_t file) = 0;
virtual bool EndOfFile(FileHandle_t file) = 0;
virtual bool FileExists(const char *pFileName, const char *pPathID = 0) = 0;
virtual unsigned int Size(const char *pFileName, const char *pPathID = 0) = 0;
virtual int Read(void* pOutput, int size, FileHandle_t file) = 0;
virtual int Write(void const* pInput, int size, FileHandle_t file) = 0;
virtual void Seek(FileHandle_t file, int post, int seekType) = 0;
virtual unsigned int Tell(FileHandle_t file) = 0;
virtual int FPrint(FileHandle_t file, const char *pData) = 0;
virtual void Flush(FileHandle_t file) = 0;
virtual bool IsOk(FileHandle_t file) = 0;
virtual void RemoveFile(const char *pRelativePath, const char *pathID = 0) = 0;
virtual void RenameFile(char const *pOldPath, char const *pNewPath, const char *pathID = 0) = 0;
virtual bool IsDirectory(const char *pFileName, const char *pathID = 0) = 0;
virtual void CreateDirHierarchy(const char *path, const char *pathID = 0) = 0;
};
namespace SourceMod
@@ -120,38 +85,11 @@ namespace SourceMod
class IPhraseCollection;
class ITranslator;
class IGameConfig;
class IMenuManager;
}
class IVEngineServer;
class IFileSystem;
class ConVar;
class KeyValues;
class SMGlobalClass;
class IPlayerInfo;
class IPlayerInfo_Logic
{
public:
virtual bool IsObserver(IPlayerInfo *pInfo) = 0;
virtual int GetTeamIndex(IPlayerInfo *pInfo) = 0;
virtual int GetFragCount(IPlayerInfo *pInfo) = 0;
virtual int GetDeathCount(IPlayerInfo *pInfo) = 0;
virtual int GetArmorValue(IPlayerInfo *pInfo) = 0;
virtual void GetAbsOrigin(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual void GetAbsAngles(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual void GetPlayerMins(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual void GetPlayerMaxs(IPlayerInfo *pInfo, float *x, float *y, float *z) = 0;
virtual const char *GetWeaponName(IPlayerInfo *pInfo) = 0;
virtual const char *GetModelName(IPlayerInfo *pInfo) = 0;
virtual int GetHealth(IPlayerInfo *pInfo) = 0;
virtual void ChangeTeam(IPlayerInfo *pInfo, int iTeamNum) = 0;
};
namespace SourceMod
{
class IChangeableForward;
}
struct ServerGlobals
{
@@ -160,148 +98,32 @@ struct ServerGlobals
float *frametime;
};
struct AutoConfig
{
SourceHook::String autocfg;
SourceHook::String folder;
bool create;
};
enum LibraryAction
{
LibraryAction_Removed,
LibraryAction_Added
};
class CNativeOwner;
class SMPlugin : public IPlugin
{
public:
virtual size_t GetConfigCount() = 0;
virtual AutoConfig *GetConfig(size_t i) = 0;
virtual void AddLibrary(const char *name) = 0;
virtual void AddConfig(bool create, const char *cfg, const char *folder) = 0;
virtual void SetErrorState(PluginStatus status, const char *fmt, ...) = 0;
};
class IScriptManager
{
public:
virtual void LoadAll(const char *config_path, const char *plugins_path) = 0;
virtual void RefreshAll() = 0;
virtual void Shutdown() = 0;
virtual IdentityToken_t *GetIdentity() = 0;
virtual void SyncMaxClients(int maxClients) = 0;
virtual void AddPluginsListener(IPluginsListener *listener) = 0;
virtual void RemovePluginsListener(IPluginsListener *listener) = 0;
virtual IPluginIterator *GetPluginIterator() = 0;
virtual void OnLibraryAction(const char *name, LibraryAction action) = 0;
virtual bool LibraryExists(const char *name) = 0;
virtual SMPlugin *FindPluginByOrder(unsigned num) = 0;
virtual SMPlugin *FindPluginByIdentity(IdentityToken_t *ident) = 0;
virtual SMPlugin *FindPluginByContext(IPluginContext *ctx) = 0;
virtual SMPlugin *FindPluginByContext(sp_context_t *ctx) = 0;
virtual SMPlugin *FindPluginByConsoleArg(const char *text) = 0;
virtual SMPlugin *FindPluginByHandle(Handle_t hndl, HandleError *errp) = 0;
virtual bool UnloadPlugin(IPlugin *plugin) = 0;
virtual const CVector<SMPlugin *> *ListPlugins() = 0;
virtual void FreePluginList(const CVector<SMPlugin *> *list) = 0;
virtual void AddFunctionsToForward(const char *name, IChangeableForward *fwd) = 0;
};
class IExtensionSys : public IExtensionManager
{
public:
virtual IExtension *LoadAutoExtension(const char *name, bool bErrorOnMissing=true) = 0;
virtual void TryAutoload() = 0;
virtual void Shutdown() = 0;
virtual IExtension *FindExtensionByFile(const char *name) = 0;
virtual bool LibraryExists(const char *name) = 0;
virtual void CallOnCoreMapStart(edict_t *edictList, int edictCount, int maxClients) = 0;
virtual IExtension *GetExtensionFromIdent(IdentityToken_t *token) = 0;
virtual void BindChildPlugin(IExtension *ext, SMPlugin *plugin) = 0;
virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0;
virtual const CVector<IExtension *> *ListExtensions() = 0;
virtual void FreeExtensionList(const CVector<IExtension *> *list) = 0;
virtual void CallOnCoreMapEnd() = 0;
};
class ILogger
{
public:
virtual void LogMessage(const char *msg, ...) = 0;
virtual void LogError(const char *msg, ...) = 0;
virtual void LogFatal(const char *msg, ...) = 0;
};
class AutoPluginList
{
public:
AutoPluginList(IScriptManager *scripts)
: scripts_(scripts), list_(scripts->ListPlugins())
{
}
~AutoPluginList()
{
scripts_->FreePluginList(list_);
}
const CVector<SMPlugin *> *operator ->()
{
return list_;
}
private:
IScriptManager *scripts_;
const CVector<SMPlugin *> *list_;
};
class AutoExtensionList
{
public:
AutoExtensionList(IExtensionSys *extensions)
: extensions_(extensions), list_(extensions_->ListExtensions())
{
}
~AutoExtensionList()
{
extensions_->FreeExtensionList(list_);
}
const CVector<IExtension *> *operator ->()
{
return list_;
}
private:
IExtensionSys *extensions_;
const CVector<IExtension *> *list_;
};
class CCommand;
struct sm_core_t
{
/* Objects */
IHandleSys *handlesys;
IdentityToken_t *core_ident;
ISourceMod *sm;
ILibrarySys *libsys;
IVEngineServer *engine;
IFileSystem *filesystem;
IPlayerInfo_Logic *playerInfo;
IShareSys *sharesys;
IRootConsole *rootmenu;
IPluginManager *pluginsys;
IForwardManager *forwardsys;
ITimerSystem *timersys;
IPlayerManager *playerhelpers;
IAdminSystem *adminsys;
IGameHelpers *gamehelpers;
IMenuManager *menus;
ISourcePawnEngine **spe1;
ISourcePawnEngine2 **spe2;
/* Functions */
void (*AddNatives)(sp_nativeinfo_t* nlist);
ConVar * (*FindConVar)(const char*);
unsigned int (*strncopy)(char*, const char*, size_t);
char * (*TrimWhitespace)(char *, size_t &);
void (*LogToGame)(const char *message);
void (*ConPrint)(const char *message);
void (*LogError)(const char*, ...);
const char * (*GetCvarString)(ConVar*);
bool (*GetCvarBool)(ConVar*);
size_t (*Format)(char*, size_t, const char*, ...);
size_t (*FormatArgs)(char*, size_t, const char*,va_list ap);
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
unsigned int, unsigned int &, size_t *, const char **);
size_t (*atcprintf)(char *, size_t, const char *, IPluginContext *, const cell_t *, int *);
@@ -310,33 +132,18 @@ struct sm_core_t
const char * (*GetSourceEngineName)();
bool (*SymbolsAreHidden)();
const char * (*GetCoreConfigValue)(const char*);
bool (*IsMapLoading)();
bool (*IsMapRunning)();
int (*Argc)(const CCommand &args);
const char * (*Arg)(const CCommand &args, int arg);
int (*LoadMMSPlugin)(const char *file, bool *ok, char *error, size_t maxlength);
void (*UnloadMMSPlugin)(int id);
void (*DoGlobalPluginLoads)();
bool (*AreConfigsExecuted)();
void (*ExecuteConfigs)(IPluginContext *ctx);
DatabaseInfo (*GetDBInfoFromKeyValues)(KeyValues *);
int (*GetActivityFlags)();
int (*GetImmunityMode)();
void (*UpdateAdminCmdFlags)(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool (*LookForCommandAdminFlags)(const char *cmd, FlagBits *pFlags);
const char *gamesuffix;
/* Data */
ServerGlobals *serverGlobals;
void * serverFactory;
void * engineFactory;
void * matchmakingDSFactory;
SMGlobalClass * listeners;
};
struct sm_logic_t
{
SMGlobalClass *head;
IThreader *threader;
IProfiler *profiler;
ITranslator *translator;
const char *(*stristr)(const char *, const char *);
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...);
@@ -345,22 +152,6 @@ struct sm_logic_t
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
IGameConfig * (*GetCoreGameConfig)();
bool (*OnLogPrint)(const char *msg); // true to supersede
IDebugListener *debugger;
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
void (*AddNatives)(sp_nativeinfo_t *natives);
void (*DumpHandles)(void (*dumpfn)(const char *fmt, ...));
bool (*DumpAdminCache)(const char *filename);
void (*RegisterProfiler)(IProfilingTool *tool);
IScriptManager *scripts;
IShareSys *sharesys;
IExtensionSys *extsys;
IHandleSys *handlesys;
IForwardManager *forwardsys;
IAdminSystem *adminsys;
IdentityToken_t *core_ident;
ILogger *logger;
float sentinel;
};
typedef void (*LogicInitFunction)(const sm_core_t *core, sm_logic_t *logic);
@@ -368,3 +159,4 @@ typedef LogicInitFunction (*LogicLoadFunction)(uint32_t magic);
typedef ITextParsers *(*GetITextParsers)();
#endif /* _INCLUDE_SOURCEMOD_INTERCOM_H_ */
+3 -14
View File
@@ -112,19 +112,10 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\common_logic.cpp" />
<ClCompile Include="..\DebugReporter.cpp" />
<ClCompile Include="..\ExtensionSys.cpp" />
<ClCompile Include="..\GameConfigs.cpp" />
<ClCompile Include="..\HandleSys.cpp" />
<ClCompile Include="..\MemoryUtils.cpp" />
<ClCompile Include="..\NativeInvoker.cpp" />
<ClCompile Include="..\NativeOwner.cpp" />
<ClCompile Include="..\PhraseCollection.cpp" />
<ClCompile Include="..\PluginSys.cpp" />
<ClCompile Include="..\Profiler.cpp" />
<ClCompile Include="..\ShareSys.cpp" />
<ClCompile Include="..\smn_fakenatives.cpp" />
<ClCompile Include="..\smn_filesystem.cpp" />
<ClCompile Include="..\sm_crc32.cpp" />
<ClCompile Include="..\smn_admin.cpp" />
<ClCompile Include="..\smn_adt_array.cpp" />
@@ -158,17 +149,12 @@
<ClInclude Include="..\AutoHandleRooter.h" />
<ClInclude Include="..\CellArray.h" />
<ClInclude Include="..\common_logic.h" />
<ClInclude Include="..\ExtensionSys.h" />
<ClInclude Include="..\GameConfigs.h" />
<ClInclude Include="..\intercom.h" />
<ClInclude Include="..\MemoryUtils.h" />
<ClInclude Include="..\MersenneTwister.h" />
<ClInclude Include="..\NativeInvoker.h" />
<ClInclude Include="..\NativeOwner.h" />
<ClInclude Include="..\PhraseCollection.h" />
<ClInclude Include="..\PluginSys.h" />
<ClInclude Include="..\Profiler.h" />
<ClInclude Include="..\ShareSys.h" />
<ClInclude Include="..\sm_crc32.h" />
<ClInclude Include="..\sm_memtable.h" />
<ClInclude Include="..\sm_symtable.h" />
@@ -180,6 +166,9 @@
<ClInclude Include="..\thread\WinThreads.h" />
<ClInclude Include="..\Translator.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

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