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): class SDK(object):
def __init__(self, sdk, ext, aDef, name, platform, dir): 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.envvar = sdk
self.ext = ext self.ext = ext
self.code = aDef self.code = aDef
self.define = name self.define = name
self.platform = platform self.platform = platform
self.folder = folder # Default folder name.
self.name = dir self.name = dir
self.path = None # Actual path self.path = None # Actual path
@@ -17,26 +21,27 @@ WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac'] WinLinuxMac = ['windows', 'linux', 'mac']
PossibleSDKs = { PossibleSDKs = {
'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'), 'ep1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'ep1'),
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'), 'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'ob'),
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'), 'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'), 'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'), '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'), 'tf2': SDK('HL2SDKTF2', '2.tf2', '10', 'TF2', WinLinuxMac, 'tf2'),
'l4d': SDK('HL2SDKL4D', '2.l4d', '11', 'LEFT4DEAD', WinLinuxMac, 'l4d'), 'l4d': SDK('HL2SDKL4D', '2.l4d', '11', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
'nucleardawn': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'), 'nd': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nd'),
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '14', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'), 'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '13', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'), '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'), 'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'), 'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '19', 'CSGO', WinLinuxMac, 'csgo'), 'csgo': SDK('HL2SDKCSGO', '2.csgo', '18', 'CSGO', WinLinuxMac, 'csgo'),
'dota': SDK('HL2SDKDOTA', '2.dota', '20', 'DOTA', WinLinuxMac, 'dota'), 'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '15', 'PORTAL2', [], 'portal2'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '16', 'PORTAL2', [], 'portal2'),
'blade': SDK('HL2SDKBLADE', '2.blade', '17', 'BLADE', WinLinux, 'blade'), # These engines are only supported on SourceMod 1.6.
'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '18', 'INSURGENCY', WinLinuxMac, 'insurgency'), # 'blade': SDK('HL2SDKBLADE', '2.blade', '16', 'BLADE', WinLinux, 'blade'),
'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '13', 'CONTAGION', WinOnly, 'contagion'), # '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): def ResolveEnvPath(env, folder):
@@ -44,22 +49,17 @@ def ResolveEnvPath(env, folder):
path = os.environ[env] path = os.environ[env]
if os.path.isdir(path): if os.path.isdir(path):
return path return path
return None else:
head = os.getcwd()
head = os.getcwd() oldhead = None
oldhead = None while head != None and head != oldhead:
while head != None and head != oldhead: path = os.path.join(head, folder)
path = os.path.join(head, folder) if os.path.isdir(path):
if os.path.isdir(path): return path
return path oldhead = head
oldhead = head head, tail = os.path.split(head)
head, tail = os.path.split(head)
return None return None
def Normalize(path):
return os.path.abspath(os.path.normpath(path))
class SMConfig(object): class SMConfig(object):
def __init__(self): def __init__(self):
self.sdks = {} self.sdks = {}
@@ -72,17 +72,6 @@ class SMConfig(object):
self.smx_files = {} self.smx_files = {}
self.versionlib = None 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): def detectProductVersion(self):
builder.AddConfigureFile('product.version') builder.AddConfigureFile('product.version')
@@ -105,54 +94,40 @@ class SMConfig(object):
for sdk_name in PossibleSDKs: for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name] sdk = PossibleSDKs[sdk_name]
if builder.target_platform in sdk.platform: if builder.target_platform in sdk.platform:
if builder.options.hl2sdk_root: sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder) if sdk_path is None:
else:
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
if sdk_path is None or not os.path.isdir(sdk_path):
if use_all or sdk_name in sdk_list: if use_all or sdk_name in sdk_list:
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar)) raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
continue continue
if use_all or use_present or sdk_name in sdk_list: 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 self.sdks[sdk_name] = sdk
if len(self.sdks) < 1: if len(self.sdks) < 1:
raise Exception('At least one SDK must be available.') raise Exception('At least one SDK must be available.')
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
if builder.options.mms_path: if not self.mms_root:
self.mms_root = builder.options.mms_path self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
else:
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
if not self.mms_root: if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source') raise Exception('Could not find a source copy of Metamod:Source')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
if not self.mms_root or not os.path.isdir(self.mms_root):
raise Exception('Could not find a source copy of Metamod:Source')
self.mms_root = Normalize(self.mms_root)
if builder.options.hasMySql: if builder.options.hasMySql:
if builder.options.mysql_path: for i in range(7):
self.mysql_root = builder.options.mysql_path self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
else: if self.mysql_root:
for i in range(7): break
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i)) if not self.mysql_root:
if self.mysql_root:
break
if not self.mysql_root or not os.path.isdir(self.mysql_root):
raise Exception('Could not find a path to MySQL!') raise Exception('Could not find a path to MySQL!')
self.mysql_root = Normalize(self.mysql_root)
def configure(self): def configure(self):
builder.AddConfigureFile('pushbuild.txt') builder.AddConfigureFile('pushbuild.txt')
cxx = builder.DetectCompilers() cfg = builder.DetectCompilers()
cxx = cfg.cxx
if cxx.like('gcc'): if cxx.behavior == 'gcc':
cxx.defines += [ cfg.defines += [
'stricmp=strcasecmp', 'stricmp=strcasecmp',
'_stricmp=strcasecmp', '_stricmp=strcasecmp',
'_snprintf=snprintf', '_snprintf=snprintf',
@@ -160,42 +135,35 @@ class SMConfig(object):
'HAVE_STDINT_H', 'HAVE_STDINT_H',
'GNUC', 'GNUC',
] ]
cxx.cflags += [ cfg.cflags += [
'-pipe', '-pipe',
'-fno-strict-aliasing', '-fno-strict-aliasing',
'-Wall', '-Wall',
'-Werror', '-Werror',
'-Wno-uninitialized',
'-Wno-unused', '-Wno-unused',
'-Wno-switch', '-Wno-switch',
'-Wno-array-bounds',
'-msse', '-msse',
'-m32', '-m32',
] ]
cxx.cxxflags += [
'-std=c++11',
]
have_gcc = cxx.vendor == 'gcc' have_gcc = cxx.name == 'gcc'
have_clang = cxx.vendor == 'clang' have_clang = cxx.name == 'clang'
if have_clang or (have_gcc and cxx.version >= '4'): if have_clang or (have_gcc and cxx.majorVersion >= 4):
cxx.cflags += ['-fvisibility=hidden'] cfg.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden'] cfg.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.version >= '4.6'): if have_clang or (have_gcc and cxx.minorVersion >= 6):
cxx.cflags += ['-Wno-narrowing'] cfg.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'): if (have_gcc and cxx.minorVersion >= 7) or (have_clang and cxx.majorVersion >= 3):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] cfg.cxxflags += ['-Wno-delete-non-virtual-dtor']
if have_gcc and cxx.version >= '4.8':
cxx.cflags += ['-Wno-unused-result']
if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
cxx.linkflags += ['-m32'] if have_gcc:
cxx.cxxflags += [ cfg.cflags += ['-Wno-parentheses']
elif have_clang:
cfg.cflags += ['-Wno-logical-op-parentheses']
cfg.linkflags += ['-m32']
cfg.cxxflags += [
'-fno-exceptions', '-fno-exceptions',
'-fno-threadsafe-statics', '-fno-threadsafe-statics',
'-Wno-non-virtual-dtor', '-Wno-non-virtual-dtor',
@@ -203,30 +171,28 @@ class SMConfig(object):
] ]
if have_gcc: if have_gcc:
cxx.cflags += ['-mfpmath=sse'] cfg.cflags += ['-mfpmath=sse']
elif cxx.vendor == 'msvc': elif cxx.name == 'msvc':
if builder.options.debug == '1': if builder.options.debug == '1':
cxx.cflags += ['/MTd'] cfg.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt'] cfg.linkflags += ['/NODEFAULTLIB:libcmt']
else: else:
cxx.cflags += ['/MT'] cfg.cflags += ['/MT']
cxx.defines += [ cfg.defines += [
'_CRT_SECURE_NO_DEPRECATE', '_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS', '_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE',
'_ITERATOR_DEBUG_LEVEL=0', '_ITERATOR_DEBUG_LEVEL=0',
] ]
if cxx.version < 1800: cfg.cflags += [
cxx.defines += 'strtoull=_strtoui64'
cxx.cflags += [
'/W3', '/W3',
] ]
cxx.cxxflags += [ cfg.cxxflags += [
'/EHsc', '/EHsc',
'/GR-', '/GR-',
'/TP', '/TP',
] ]
cxx.linkflags += [ cfg.linkflags += [
'/MACHINE:X86', '/MACHINE:X86',
'/SUBSYSTEM:WINDOWS', '/SUBSYSTEM:WINDOWS',
'kernel32.lib', 'kernel32.lib',
@@ -245,83 +211,96 @@ class SMConfig(object):
# Optimization # Optimization
if builder.options.opt == '1': if builder.options.opt == '1':
cxx.defines += ['NDEBUG'] cfg.defines += ['NDEBUG']
if cxx.like('gcc'): if cxx.behavior == 'gcc':
cxx.cflags += ['-O3'] cfg.cflags += ['-O3']
elif cxx.like('msvc'): elif cxx.behavior == 'msvc':
cxx.cflags += ['/Ox', '/Zo'] cfg.cflags += ['/Ox']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] cfg.linkflags += ['/OPT:ICF', '/OPT:REF']
# Debugging # Debugging
if builder.options.debug == '1': if builder.options.debug == '1':
cxx.defines += ['DEBUG', '_DEBUG'] cfg.defines += ['DEBUG', '_DEBUG']
if cxx.like('msvc'): if cxx.behavior == 'msvc':
cxx.cflags += ['/Od', '/RTC1'] 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. # 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. # Don't omit the frame pointer.
cxx.cflags += ['/Oy-'] cfg.cflags += ['/Oy-']
# Platform-specifics # Platform-specifics
if builder.target_platform == 'linux': if builder.target_platform == 'linux':
cxx.defines += ['_LINUX', 'POSIX'] cfg.defines += ['_LINUX', 'POSIX']
if cxx.vendor == 'gcc': if cxx.name == 'gcc':
cxx.linkflags += ['-static-libgcc'] cfg.linkflags += ['-static-libgcc']
elif cxx.vendor == 'clang': elif cxx.name == 'clang':
cxx.linkflags += ['-lgcc_eh'] cfg.linkflags += ['-lgcc_eh']
elif builder.target_platform == 'mac': elif builder.target_platform == 'mac':
cxx.defines += ['OSX', '_OSX', 'POSIX'] cfg.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += ['-mmacosx-version-min=10.5'] cfg.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [ cfg.linkflags += [
'-mmacosx-version-min=10.5', '-mmacosx-version-min=10.5',
'-arch', 'i386', '-arch', 'i386',
'-lstdc++', '-lstdc++',
'-stdlib=libstdc++', '-stdlib=libstdc++',
] ]
cxx.cxxflags += ['-stdlib=libstdc++'] cfg.cxxflags += ['-stdlib=libstdc++']
elif builder.target_platform == 'windows': elif builder.target_platform == 'windows':
cxx.defines += ['WIN32', '_WINDOWS'] cfg.defines += ['WIN32', '_WINDOWS']
# Finish up. # Finish up.
cxx.defines += [ cfg.defines += [
'SOURCEMOD_BUILD', 'SOURCEMOD_BUILD',
'SM_GENERATED_BUILD',
'SM_USE_VERSIONLIB', 'SM_USE_VERSIONLIB',
] ]
if self.use_auto_versioning(): cfg.includes += [os.path.join(builder.buildPath, 'includes')]
cxx.defines += ['SM_GENERATED_BUILD'] cfg.includes += [os.path.join(builder.sourcePath, 'versionlib')]
cxx.includes += [os.path.join(builder.buildPath, 'includes')]
cxx.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': if builder.target_platform == 'windows':
binary.sources += ['version.rc'] binary.sources += ['version.rc']
binary.compiler.rcdefines += [ binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile), 'BINARY_NAME="{0}"'.format(binary.outputFile),
'SM_GENERATED_BUILD',
'RC_COMPILE', 'RC_COMPILE',
] ]
if self.use_auto_versioning():
binary.compiler.rcdefines += ['SM_GENERATED_BUILD']
elif builder.target_platform == 'mac': elif builder.target_platform == 'mac':
if binary.type == 'library': binary.compiler.postlink += [
binary.compiler.postlink += [ '-compatibility_version', '1.0.0',
'-compatibility_version', '1.0.0', '-current_version', self.productVersion
'-current_version', self.productVersion ]
] binary.compiler.linkflags += [self.versionlib]
if self.use_auto_versioning(): binary.compiler.sourcedeps += SM.generated_headers
binary.compiler.linkflags += [self.versionlib] return binary
binary.compiler.sourcedeps += SM.generated_headers
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 return binary
def Library(self, context, name): def Library(self, context, name):
binary = context.compiler.Library(name) compiler = context.compiler.clone()
return self.AddVersioning(binary) return self.LibraryBuilder(compiler, name)
def Program(self, context, name): def Program(self, context, name):
binary = context.compiler.Program(name) compiler = context.compiler.clone()
return self.AddVersioning(binary) return self.ProgramBuilder(compiler, name)
def ConfigureForExtension(self, context, compiler): def ExtCompiler(self, context):
compiler = context.compiler.clone()
compiler.cxxincludes += [ compiler.cxxincludes += [
os.path.join(context.currentSourcePath), os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sdk'), os.path.join(context.currentSourcePath, 'sdk'),
@@ -332,15 +311,10 @@ class SMConfig(object):
] ]
return compiler return compiler
def ExtLibrary(self, context, name): def HL2Compiler(self, context, sdk):
binary = context.compiler.Library(name) compiler = self.ExtCompiler(context)
self.ConfigureForExtension(context, binary.compiler)
return self.AddVersioning(binary)
def ConfigureForHL2(self, binary, sdk): if sdk.name == 'ep1':
compiler = binary.compiler
if sdk.name == 'episode1':
mms_path = os.path.join(self.mms_root, 'core-legacy') mms_path = os.path.join(self.mms_root, 'core-legacy')
else: else:
mms_path = os.path.join(self.mms_root, 'core') 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] defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines compiler.defines += defines
paths = [ paths = [
['public'], ['public'],
['public', 'engine'], ['public', 'engine'],
@@ -361,7 +334,7 @@ class SMConfig(object):
['public', 'tier0'], ['public', 'tier0'],
['public', 'tier1'] ['public', 'tier1']
] ]
if sdk.name == 'episode1' or sdk.name == 'darkm': if sdk.name == 'ep1' or sdk.name == 'darkm':
paths.append(['public', 'dlls']) paths.append(['public', 'dlls'])
paths.append(['game_shared']) paths.append(['game_shared'])
else: else:
@@ -372,48 +345,55 @@ class SMConfig(object):
compiler.defines += ['SOURCE_ENGINE=' + sdk.code] 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 # The 2013 SDK already has these in public/tier0/basetypes.h
compiler.defines.remove('stricmp=strcasecmp') compiler.defines.remove('stricmp=strcasecmp')
compiler.defines.remove('_stricmp=strcasecmp') compiler.defines.remove('_stricmp=strcasecmp')
compiler.defines.remove('_snprintf=snprintf') compiler.defines.remove('_snprintf=snprintf')
compiler.defines.remove('_vsnprintf=vsnprintf') compiler.defines.remove('_vsnprintf=vsnprintf')
if compiler.like('msvc'): if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32'] if compiler.cc.behavior == 'msvc':
else: compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
compiler.defines += ['COMPILER_GCC'] else:
compiler.defines += ['COMPILER_GCC']
# For everything after Swarm, this needs to be defined for entity networking
# to work properly with sendprop value changes. # For everything after Swarm, this needs to be defined for entity networking
# to work properly with sendprop value changes.
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']: if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.defines += ['NETWORK_VARS_ENABLED'] 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']: if builder.target_platform in ['linux', 'mac']:
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE'] compiler.defines += ['NO_MALLOC_OVERRIDE']
if sdk.name == 'csgo' and builder.target_platform == 'linux':
compiler.linkflags += ['-lstdc++']
for path in paths: for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)] 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 builder.target_platform == 'linux':
if sdk.name == 'episode1': if sdk.name == 'ep1':
lib_folder = os.path.join(sdk.path, 'linux_sdk') 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') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
else: else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux') lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target_platform == 'mac': elif builder.target_platform == 'mac':
if sdk.name == 'sdk2013': if sdk.name == '2013':
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
else: else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac') lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target_platform in ['linux', 'mac']: if builder.target_platform in ['linux', 'mac']:
if sdk.name == 'sdk2013': if sdk.name == '2013':
compiler.postlink += [ compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')), compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a')) compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
@@ -427,19 +407,19 @@ class SMConfig(object):
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']: if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))] compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
self.AddVersioning(binary) binary = self.LibraryBuilder(compiler, name)
dynamic_libs = [] dynamic_libs = []
if builder.target_platform == 'linux': if builder.target_platform == 'linux':
compiler.linkflags[0:0] = ['-lm'] 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'] 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'] dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else: else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so'] dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac': elif builder.target_platform == 'mac':
compiler.linkflags.append('-liconv') binary.compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib'] dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows': elif builder.target_platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib'] libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
@@ -447,7 +427,7 @@ class SMConfig(object):
libs.append('interfaces') libs.append('interfaces')
for lib in libs: for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib' 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: for library in dynamic_libs:
source_path = os.path.join(lib_folder, library) source_path = os.path.join(lib_folder, library)
@@ -460,67 +440,51 @@ class SMConfig(object):
return link return link
linker = make_linker(source_path, output_path) 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 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 = SMConfig()
SM.detectProductVersion() SM.detectProductVersion()
SM.detectSDKs() SM.detectSDKs()
SM.configure() SM.configure()
if SM.use_auto_versioning(): SM.generated_headers = builder.RunScript(
SM.generated_headers = builder.RunScript( 'tools/buildbot/Versioning',
'tools/buildbot/Versioning', { 'SM': SM }
{ 'SM': SM } )
) SM.versionlib = builder.RunScript(
SM.versionlib = builder.RunScript( 'versionlib/AMBuilder',
'versionlib/AMBuilder', { 'SM': SM }
{ 'SM': SM } )
)
BuildScripts = [ builder.RunBuildScripts(
'loader/AMBuilder', [
'core/AMBuilder', 'loader/AMBuilder',
'core/logic/AMBuilder', 'core/AMBuilder',
'extensions/bintools/AMBuilder', 'core/logic/AMBuilder',
'extensions/clientprefs/AMBuilder', 'extensions/bintools/AMBuilder',
'extensions/curl/AMBuilder', 'extensions/clientprefs/AMBuilder',
'extensions/cstrike/AMBuilder', 'extensions/curl/AMBuilder',
'extensions/geoip/AMBuilder', 'extensions/cstrike/AMBuilder',
'extensions/mysql/AMBuilder', 'extensions/geoip/AMBuilder',
'extensions/regex/AMBuilder', 'extensions/mysql/AMBuilder',
'extensions/sdkhooks/AMBuilder', 'extensions/regex/AMBuilder',
'extensions/sdktools/AMBuilder', 'extensions/sdkhooks/AMBuilder',
'extensions/sqlite/AMBuilder', 'extensions/sdktools/AMBuilder',
'extensions/tf2/AMBuilder', 'extensions/sqlite/AMBuilder',
'extensions/topmenus/AMBuilder', 'extensions/tf2/AMBuilder',
'extensions/updater/AMBuilder', 'extensions/topmenus/AMBuilder',
'sourcepawn/compiler/AMBuilder', 'extensions/updater/AMBuilder',
'sourcepawn/jit/AMBuilder', 'sourcepawn/compiler/AMBuilder',
] 'sourcepawn/jit/AMBuilder',
if builder.backend == 'amb2':
BuildScripts += [
'plugins/AMBuilder', 'plugins/AMBuilder',
'tools/buildbot/PackageScript', 'tools/buildbot/PackageScript',
] ],
{
builder.RunBuildScripts(BuildScripts, { 'SM': SM }) 'SM': SM
}
)
if builder.options.breakpad_dump: if builder.options.breakpad_dump:
builder.RunScript('tools/buildbot/BreakpadSymbols', { 'SM': SM }) 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 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] SourceMod 1.5.3 [2014-03-22]
URL: http://wiki.alliedmods.net/SourceMod_1.5.3_Release_Notes 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) // 1 (Enabled)
// -- // --
// Requires: basetriggers.smx // Requires: basetriggers.smx
// Default: 0 // Default: 1
sm_trigger_show 0 sm_trigger_show 1
// Specifies whether or not to display vote progress to clients in the // Specifies whether or not to display vote progress to clients in the
// "hint" box (near the bottom of the screen in most games). // "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. * 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. * 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. * 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 * "no" - Warn about malware or illegal plugins loading
*/ */
"BlockBadPlugins" "yes" "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 = run.PrepareBuild(sourcePath=sys.path[0])
run.default_build_folder = 'obj-' + run.target_platform 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', run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
help='Enable debugging symbols') help='Enable debugging symbols')
run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', 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)') 'comma-delimited list of engine names (default: %default)')
run.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump', run.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
default=False, help='Dump and upload breakpad symbols') 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() run.Configure()
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,6 +30,7 @@
*/ */
#include "ADTFactory.h" #include "ADTFactory.h"
#include "sm_globals.h"
#include "ShareSys.h" #include "ShareSys.h"
ADTFactory g_AdtFactory; ADTFactory g_AdtFactory;
@@ -56,30 +57,32 @@ IBasicTrie *ADTFactory::CreateBasicTrie()
BaseTrie::BaseTrie() BaseTrie::BaseTrie()
{ {
m_pTrie = sm_trie_create();
} }
BaseTrie::~BaseTrie() BaseTrie::~BaseTrie()
{ {
sm_trie_destroy(m_pTrie);
} }
bool BaseTrie::Insert(const char *key, void *value) bool BaseTrie::Insert(const char *key, void *value)
{ {
return map_.insert(key, value); return sm_trie_insert(m_pTrie, key, value);
} }
bool BaseTrie::Retrieve(const char *key, void **value) bool BaseTrie::Retrieve(const char *key, void **value)
{ {
return map_.retrieve(key, value); return sm_trie_retrieve(m_pTrie, key, value);
} }
bool BaseTrie::Delete(const char *key) bool BaseTrie::Delete(const char *key)
{ {
return map_.remove(key); return sm_trie_delete(m_pTrie, key);
} }
void BaseTrie::Clear() void BaseTrie::Clear()
{ {
map_.clear(); sm_trie_clear(m_pTrie);
} }
void BaseTrie::Destroy() void BaseTrie::Destroy()
@@ -89,5 +92,5 @@ void BaseTrie::Destroy()
bool BaseTrie::Replace(const char *key, void *value) bool BaseTrie::Replace(const char *key, void *value)
{ {
return map_.replace(key, value); return sm_trie_replace(m_pTrie, key, value);
} }
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -33,8 +33,8 @@
#define _INCLUDE_SOURCEMOD_ADTFACTORY_H_ #define _INCLUDE_SOURCEMOD_ADTFACTORY_H_
#include <IADTFactory.h> #include <IADTFactory.h>
#include "common_logic.h" #include "sm_globals.h"
#include <sm_stringhashmap.h> #include "sm_trie.h"
using namespace SourceMod; using namespace SourceMod;
@@ -50,7 +50,7 @@ public:
virtual void Clear(); virtual void Clear();
virtual void Destroy(); virtual void Destroy();
private: private:
StringHashMap<void *> map_; Trie *m_pTrie;
}; };
class ADTFactory : class ADTFactory :
+67 -61
View File
@@ -1,65 +1,25 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os import os
project = SM.HL2Project(builder, 'sourcemod')
project.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: for sdk_name in SM.sdks:
sdk = SM.sdks[sdk_name] sdk = SM.sdks[sdk_name]
binary_name = 'sourcemod.' + sdk.ext binary_name = 'sourcemod.' + sdk.ext
binary = SM.HL2Config(project, binary_name, sdk) binary = SM.HL2Library(builder, binary_name, sdk)
compiler = binary.compiler compiler = binary.compiler
if sdk.name == 'csgo': 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 += [ 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', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf') os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
] ]
elif sdk.name == 'dota': elif sdk.name == 'dota':
compiler.cxxincludes += [ 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', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'), os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', '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': elif builder.target_platform == 'mac':
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a') lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
elif builder.target_platform == 'windows': 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: 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: 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)) 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']: if sdk.name in ['csgo', 'dota']:
binary.sources += ['smn_protobuf.cpp'] binary.sources += ['smn_protobuf.cpp']
@@ -106,7 +113,6 @@ for sdk_name in SM.sdks:
binary.sources += [ binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'), 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', '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', 'ai_activity.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'), os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_commonmessages.pb.cc'), os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_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'), 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 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the * the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation. * Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* *
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
* *
* As a special exception, AlliedModders LLC gives you permission to link the * As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the * code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in * by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants * all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
* *
* Version: $Id$ * Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_ #ifndef _INCLUDE_SOURCEMOD_ADMINCACHE_H_
#define _INCLUDE_SOURCEMOD_ADMINCACHE_H_ #define _INCLUDE_SOURCEMOD_ADMINCACHE_H_
#include "common_logic.h" #include "sm_memtable.h"
#include <IAdminSystem.h> #include <sm_trie.h>
#include "sm_memtable.h" #include <sh_list.h>
#include <sm_trie.h> #include <sh_string.h>
#include <sh_list.h> #include <IAdminSystem.h>
#include <sh_string.h> #include "sm_globals.h"
#include <IForwardSys.h> #include <IForwardSys.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h> using namespace SourceHook;
using namespace SourceHook; #define GRP_MAGIC_SET 0xDEADFADE
#define GRP_MAGIC_UNSET 0xFACEFACE
#define GRP_MAGIC_SET 0xDEADFADE #define USR_MAGIC_SET 0xDEADFACE
#define GRP_MAGIC_UNSET 0xFACEFACE #define USR_MAGIC_UNSET 0xFADEDEAD
#define USR_MAGIC_SET 0xDEADFACE
#define USR_MAGIC_UNSET 0xFADEDEAD struct AdminGroup
{
typedef StringHashMap<OverrideRule> OverrideMap; uint32_t magic; /* Magic flag, for memory validation (ugh) */
unsigned int immunity_level; /* Immunity level */
struct AdminGroup /* Immune from target table (-1 = nonexistent)
{ * [0] = number of entries
uint32_t magic; /* Magic flag, for memory validation (ugh) */ * [1...N] = immune targets
unsigned int immunity_level; /* Immunity level */ */
/* Immune from target table (-1 = nonexistent) int immune_table;
* [0] = number of entries Trie *pCmdTable; /* Command override table (can be NULL) */
* [1...N] = immune targets Trie *pCmdGrpTable; /* Command group override table (can be NULL) */
*/ int next_grp; /* Next group in the chain */
int immune_table; int prev_grp; /* Previous group in the chain */
OverrideMap *pCmdTable; /* Command override table (can be NULL) */ int nameidx; /* Name */
OverrideMap *pCmdGrpTable; /* Command group override table (can be NULL) */ FlagBits addflags; /* Additive flags */
int next_grp; /* Next group in the chain */ };
int prev_grp; /* Previous group in the chain */
int nameidx; /* Name */ struct AuthMethod
FlagBits addflags; /* Additive flags */ {
}; String name;
Trie *table;
struct AuthMethod };
{
String name; struct UserAuth
StringHashMap<AdminId> identities; {
unsigned int index; /* Index into auth table */
AuthMethod(const char *name) int identidx; /* Index into the string table */
: name(name) };
{
} struct AdminUser
{
static inline bool matches(const char *name, const AuthMethod *method) uint32_t magic; /* Magic flag, for memory validation */
{ FlagBits flags; /* Flags */
return strcmp(name, method->name.c_str()) == 0; FlagBits eflags; /* Effective flags */
} int nameidx; /* Name index */
}; int password; /* Password index */
unsigned int grp_count; /* Number of groups */
struct UserAuth unsigned int grp_size; /* Size of groups table */
{ int grp_table; /* Group table itself */
unsigned int index; /* Index into auth table */ int next_user; /* Next user in the list */
int identidx; /* Index into the string table */ int prev_user; /* Previous user in the list */
}; UserAuth auth; /* Auth method for this user */
unsigned int immunity_level; /* Immunity level */
struct AdminUser unsigned int serialchange; /* Serial # for changes */
{ };
uint32_t magic; /* Magic flag, for memory validation */
FlagBits flags; /* Flags */ class AdminCache :
FlagBits eflags; /* Effective flags */ public IAdminSystem,
int nameidx; /* Name index */ public SMGlobalClass
int password; /* Password index */ {
unsigned int grp_count; /* Number of groups */ public:
unsigned int grp_size; /* Size of groups table */ AdminCache();
int grp_table; /* Group table itself */ ~AdminCache();
int next_user; /* Next user in the list */ public: //SMGlobalClass
int prev_user; /* Previous user in the list */ void OnSourceModStartup(bool late);
UserAuth auth; /* Auth method for this user */ void OnSourceModAllInitialized();
unsigned int immunity_level; /* Immunity level */ void OnSourceModLevelChange(const char *mapName);
unsigned int serialchange; /* Serial # for changes */ void OnSourceModShutdown();
}; void OnSourceModPluginsLoaded();
public: //IAdminSystem
class AdminCache : /** Command cache stuff */
public IAdminSystem, void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags);
public SMGlobalClass bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags);
{ void UnsetCommandOverride(const char *cmd, OverrideType type);
public: /** Group cache stuff */
AdminCache(); GroupId AddGroup(const char *group_name);
~AdminCache(); GroupId FindGroupByName(const char *group_name);
public: //SMGlobalClass void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled);
void OnSourceModStartup(bool late); bool GetGroupAddFlag(GroupId id, AdminFlag flag);
void OnSourceModAllInitialized(); FlagBits GetGroupAddFlags(GroupId id);
void OnSourceModLevelChange(const char *mapName); void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled);
void OnSourceModShutdown(); bool GetGroupGenericImmunity(GroupId id, ImmunityType type);
void OnSourceModPluginsLoaded(); void InvalidateGroup(GroupId id);
public: //IAdminSystem void AddGroupImmunity(GroupId id, GroupId other_id);
/** Command cache stuff */ unsigned int GetGroupImmunityCount(GroupId id);
void AddCommandOverride(const char *cmd, OverrideType type, FlagBits flags); GroupId GetGroupImmunity(GroupId id, unsigned int number);
bool GetCommandOverride(const char *cmd, OverrideType type, FlagBits *flags); void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule);
void UnsetCommandOverride(const char *cmd, OverrideType type); bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule);
/** Group cache stuff */ void DumpAdminCache(AdminCachePart part, bool rebuild);
GroupId AddGroup(const char *group_name); void AddAdminListener(IAdminListener *pListener);
GroupId FindGroupByName(const char *group_name); void RemoveAdminListener(IAdminListener *pListener);
void SetGroupAddFlag(GroupId id, AdminFlag flag, bool enabled); /** User stuff */
bool GetGroupAddFlag(GroupId id, AdminFlag flag); void RegisterAuthIdentType(const char *name);
FlagBits GetGroupAddFlags(GroupId id); AdminId CreateAdmin(const char *name);
void SetGroupGenericImmunity(GroupId id, ImmunityType type, bool enabled); const char *GetAdminName(AdminId id);
bool GetGroupGenericImmunity(GroupId id, ImmunityType type); bool BindAdminIdentity(AdminId id, const char *auth, const char *ident);
void InvalidateGroup(GroupId id); virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled);
void AddGroupImmunity(GroupId id, GroupId other_id); bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode);
unsigned int GetGroupImmunityCount(GroupId id); FlagBits GetAdminFlags(AdminId id, AccessMode mode);
GroupId GetGroupImmunity(GroupId id, unsigned int number); bool AdminInheritGroup(AdminId id, GroupId gid);
void AddGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule rule); unsigned int GetAdminGroupCount(AdminId id);
bool GetGroupCommandOverride(GroupId id, const char *name, OverrideType type, OverrideRule *pRule); GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name);
void DumpAdminCache(AdminCachePart part, bool rebuild); void SetAdminPassword(AdminId id, const char *password);
void AddAdminListener(IAdminListener *pListener); const char *GetAdminPassword(AdminId id);
void RemoveAdminListener(IAdminListener *pListener); AdminId FindAdminByIdentity(const char *auth, const char *identity);
/** User stuff */ bool InvalidateAdmin(AdminId id);
void RegisterAuthIdentType(const char *name); unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize);
AdminId CreateAdmin(const char *name); FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize);
const char *GetAdminName(AdminId id); FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags);
bool BindAdminIdentity(AdminId id, const char *auth, const char *ident); unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize);
virtual void SetAdminFlag(AdminId id, AdminFlag flag, bool enabled); bool CheckAdminFlags(AdminId id, FlagBits bits);
bool GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode); bool CanAdminTarget(AdminId id, AdminId target);
FlagBits GetAdminFlags(AdminId id, AccessMode mode); void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits);
bool AdminInheritGroup(AdminId id, GroupId gid); bool FindFlag(const char *str, AdminFlag *pFlag);
unsigned int GetAdminGroupCount(AdminId id); bool FindFlag(char c, AdminFlag *pAdmFlag);
GroupId GetAdminGroup(AdminId id, unsigned int index, const char **name); FlagBits ReadFlagString(const char *flags, const char **end);
void SetAdminPassword(AdminId id, const char *password); size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen);
const char *GetAdminPassword(AdminId id); unsigned int GetAdminSerialChange(AdminId id);
AdminId FindAdminByIdentity(const char *auth, const char *identity); bool CanAdminUseCommand(int client, const char *cmd);
bool InvalidateAdmin(AdminId id); const char *GetGroupName(GroupId gid);
unsigned int FlagBitsToBitArray(FlagBits bits, bool array[], unsigned int maxSize); unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level);
FlagBits FlagBitArrayToBits(const bool array[], unsigned int maxSize); unsigned int GetGroupImmunityLevel(GroupId gid);
FlagBits FlagArrayToBits(const AdminFlag array[], unsigned int numFlags); unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level);
unsigned int FlagBitsToArray(FlagBits bits, AdminFlag array[], unsigned int maxSize); unsigned int GetAdminImmunityLevel(AdminId id);
bool CheckAdminFlags(AdminId id, FlagBits bits); bool CheckAccess(int client,
bool CanAdminTarget(AdminId id, AdminId target); const char *cmd,
void SetAdminFlags(AdminId id, AccessMode mode, FlagBits bits); FlagBits flags,
bool FindFlag(const char *str, AdminFlag *pFlag); bool override_only);
bool FindFlag(char c, AdminFlag *pAdmFlag); bool FindFlagChar(AdminFlag flag, char *c);
FlagBits ReadFlagString(const char *flags, const char **end); public:
size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen); bool IsValidAdmin(AdminId id);
unsigned int GetAdminSerialChange(AdminId id); void DumpCache(FILE *fp);
bool CanAdminUseCommand(int client, const char *cmd); AdminGroup *GetGroup(GroupId gid);
const char *GetGroupName(GroupId gid); AdminUser *GetUser(AdminId id);
unsigned int SetGroupImmunityLevel(GroupId gid, unsigned int level); const char *GetString(int idx);
unsigned int GetGroupImmunityLevel(GroupId gid); private:
unsigned int SetAdminImmunityLevel(AdminId id, unsigned int level); void _UnsetCommandOverride(const char *cmd);
unsigned int GetAdminImmunityLevel(AdminId id); void _UnsetCommandGroupOverride(const char *group);
bool CheckAccess(int client, void InvalidateGroupCache();
const char *cmd, void InvalidateAdminCache(bool unlink_admins);
FlagBits flags, void DumpCommandOverrideCache(OverrideType type);
bool override_only); Trie *GetMethodByIndex(unsigned int index);
bool FindFlagChar(AdminFlag flag, char *c); bool GetMethodIndex(const char *name, unsigned int *_index);
bool IsValidAdmin(AdminId id); const char *GetMethodName(unsigned int index);
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags); void NameFlag(const char *str, AdminFlag flag);
public: public:
bool DumpCache(const char *filename); BaseStringTable *m_pStrings;
AdminGroup *GetGroup(GroupId gid); BaseMemTable *m_pMemory;
AdminUser *GetUser(AdminId id); Trie *m_pCmdOverrides;
const char *GetString(int idx); Trie *m_pCmdGrpOverrides;
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags); int m_FirstGroup;
private: int m_LastGroup;
void _UnsetCommandOverride(const char *cmd); int m_FreeGroupList;
void _UnsetCommandGroupOverride(const char *group); Trie *m_pGroups;
void InvalidateGroupCache(); List<IAdminListener *> m_hooks;
void InvalidateAdminCache(bool unlink_admins); List<AuthMethod> m_AuthMethods;
void DumpCommandOverrideCache(OverrideType type); Trie *m_pAuthTables;
AuthMethod *GetMethodByIndex(unsigned int index); IForward *m_pCacheFwd;
bool GetMethodIndex(const char *name, unsigned int *_index); int m_FirstUser;
const char *GetMethodName(unsigned int index); int m_LastUser;
void NameFlag(const char *str, AdminFlag flag); int m_FreeUserList;
bool GetUnifiedSteamIdentity(const char *ident, char *out, size_t maxlen); bool m_InvalidatingAdmins;
public: bool m_destroying;
typedef StringHashMap<FlagBits> FlagMap; Trie *m_pLevelNames;
};
BaseStringTable *m_pStrings;
BaseMemTable *m_pMemory; extern AdminCache g_Admins;
FlagMap m_CmdOverrides;
FlagMap m_CmdGrpOverrides; #endif //_INCLUDE_SOURCEMOD_ADMINCACHE_H_
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_
+10 -84
View File
@@ -76,12 +76,9 @@ void CDataPack::ResetSize()
size_t CDataPack::CreateMemory(size_t size, void **addr) size_t CDataPack::CreateMemory(size_t size, void **addr)
{ {
CheckSize(sizeof(char) + sizeof(size_t) + size); CheckSize(sizeof(size_t) + size);
size_t pos = m_curptr - m_pBase; size_t pos = m_curptr - m_pBase;
*(char *)m_curptr = Raw;
m_curptr += sizeof(char);
*(size_t *)m_curptr = size; *(size_t *)m_curptr = size;
m_curptr += sizeof(size_t); m_curptr += sizeof(size_t);
@@ -91,17 +88,14 @@ size_t CDataPack::CreateMemory(size_t size, void **addr)
} }
m_curptr += size; m_curptr += size;
m_size += sizeof(char) + sizeof(size_t) + size; m_size += sizeof(size_t) + size;
return pos; return pos;
} }
void CDataPack::PackCell(cell_t cell) void CDataPack::PackCell(cell_t cell)
{ {
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(cell_t)); CheckSize(sizeof(size_t) + sizeof(cell_t));
*(char *)m_curptr = Cell;
m_curptr += sizeof(char);
*(size_t *)m_curptr = sizeof(cell_t); *(size_t *)m_curptr = sizeof(cell_t);
m_curptr += sizeof(size_t); m_curptr += sizeof(size_t);
@@ -109,15 +103,12 @@ void CDataPack::PackCell(cell_t cell)
*(cell_t *)m_curptr = cell; *(cell_t *)m_curptr = cell;
m_curptr += sizeof(cell_t); 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) void CDataPack::PackFloat(float val)
{ {
CheckSize(sizeof(char) + sizeof(size_t) + sizeof(float)); CheckSize(sizeof(size_t) + sizeof(float));
*(char *)m_curptr = Float;
m_curptr += sizeof(char);
*(size_t *)m_curptr = sizeof(float); *(size_t *)m_curptr = sizeof(float);
m_curptr += sizeof(size_t); m_curptr += sizeof(size_t);
@@ -125,18 +116,15 @@ void CDataPack::PackFloat(float val)
*(float *)m_curptr = val; *(float *)m_curptr = val;
m_curptr += sizeof(float); 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) void CDataPack::PackString(const char *string)
{ {
size_t len = strlen(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); CheckSize(maxsize);
*(char *)m_curptr = String;
m_curptr += sizeof(char);
// Pack the string length first for buffer overrun checking. // Pack the string length first for buffer overrun checking.
*(size_t *)m_curptr = len; *(size_t *)m_curptr = len;
m_curptr += sizeof(size_t); m_curptr += sizeof(size_t);
@@ -172,16 +160,10 @@ bool CDataPack::SetPosition(size_t pos) const
cell_t CDataPack::ReadCell() 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; 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)) if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(cell_t))
{ {
return 0; return 0;
@@ -196,16 +178,10 @@ cell_t CDataPack::ReadCell() const
float CDataPack::ReadFloat() const float CDataPack::ReadFloat() const
{ {
if (!IsReadable(sizeof(char) + sizeof(size_t) + sizeof(float))) if (!IsReadable(sizeof(size_t) + sizeof(float)))
{ {
return 0; return 0;
} }
if (*reinterpret_cast<char *>(m_curptr) != Float)
{
return 0;
}
m_curptr += sizeof(char);
if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float)) if (*reinterpret_cast<size_t *>(m_curptr) != sizeof(float))
{ {
return 0; return 0;
@@ -225,15 +201,10 @@ bool CDataPack::IsReadable(size_t bytes) const
const char *CDataPack::ReadString(size_t *len) const const char *CDataPack::ReadString(size_t *len) const
{ {
if (!IsReadable(sizeof(char) + sizeof(size_t))) if (!IsReadable(sizeof(size_t)))
{ {
return NULL; return NULL;
} }
if (*reinterpret_cast<char *>(m_curptr) != String)
{
return NULL;
}
m_curptr += sizeof(char);
size_t real_len = *(size_t *)m_curptr; size_t real_len = *(size_t *)m_curptr;
@@ -266,11 +237,6 @@ void *CDataPack::ReadMemory(size_t *size) const
{ {
return NULL; return NULL;
} }
if (*reinterpret_cast<char *>(m_curptr) != Raw)
{
return NULL;
}
m_curptr += sizeof(char);
size_t bytecount = *(size_t *)m_curptr; size_t bytecount = *(size_t *)m_curptr;
m_curptr += sizeof(size_t); m_curptr += sizeof(size_t);
@@ -291,43 +257,3 @@ void *CDataPack::ReadMemory(size_t *size) const
return ptr; 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; const char *ReadString(size_t *len) const;
void *GetMemory() const; void *GetMemory() const;
void *ReadMemory(size_t *size) const; void *ReadMemory(size_t *size) const;
cell_t ReadFunction() const;
public: //IDataPack public: //IDataPack
void ResetSize(); void ResetSize();
void PackCell(cell_t cell); void PackCell(cell_t cell);
void PackFloat(float val); void PackFloat(float val);
void PackString(const char *string); void PackString(const char *string);
size_t CreateMemory(size_t size, void **addr); size_t CreateMemory(size_t size, void **addr);
void PackFunction(cell_t function);
public: public:
void Initialize(); void Initialize();
private: private:
@@ -68,14 +66,6 @@ private:
mutable char *m_curptr; mutable char *m_curptr;
size_t m_capacity; size_t m_capacity;
size_t m_size; size_t m_size;
enum DataPackType {
Raw,
Cell,
Float,
String,
Function
};
}; };
#endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_ #endif //_INCLUDE_SOURCEMOD_CDATAPACK_H_
+2 -20
View File
@@ -44,11 +44,7 @@ public: //IRecipientFilter
bool IsReliable() const; bool IsReliable() const;
bool IsInitMessage() const; bool IsInitMessage() const;
int GetRecipientCount() const; int GetRecipientCount() const;
#if SOURCE_ENGINE == SE_DOTA
CEntityIndex GetRecipientIndex(int slot) const;
#else
int GetRecipientIndex(int slot) const; int GetRecipientIndex(int slot) const;
#endif
public: public:
void Initialize(const cell_t *ptr, size_t count); void Initialize(const cell_t *ptr, size_t count);
void SetToReliable(bool isreliable); void SetToReliable(bool isreliable);
@@ -83,27 +79,13 @@ inline int CellRecipientFilter::GetRecipientCount() const
return m_Size; return m_Size;
} }
#if SOURCE_ENGINE == SE_DOTA
inline CEntityIndex CellRecipientFilter::GetRecipientIndex(int slot) const
#else
inline int CellRecipientFilter::GetRecipientIndex(int slot) const inline int CellRecipientFilter::GetRecipientIndex(int slot) const
#endif
{ {
int ret;
if ((slot < 0) || (slot >= GetRecipientCount())) if ((slot < 0) || (slot >= GetRecipientCount()))
{ {
ret = -1; return -1;
} }
else return static_cast<int>(m_Players[slot]);
{
ret = static_cast<int>(m_Players[slot]);
}
#if SOURCE_ENGINE == SE_DOTA
return CEntityIndex(ret);
#else
return ret;
#endif
} }
inline void CellRecipientFilter::SetToInit(bool isinitmsg) inline void CellRecipientFilter::SetToInit(bool isinitmsg)
+84 -121
View File
@@ -36,35 +36,37 @@
#include "PlayerManager.h" #include "PlayerManager.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "logic_bridge.h" #include "logic_bridge.h"
#include "sourcemod.h"
#if SOURCE_ENGINE == SE_DOTA /* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does.
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &); * While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
#elif SOURCE_ENGINE >= SE_ORANGEBOX * can technically be compiled against any MM:S version after 1.4.2.
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); */
#elif SOURCE_ENGINE == SE_DARKMESSIAH #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate1<const CCommand &, void>);
#else #else
# if SH_IMPL_VERSION >= 4 extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); #if SH_IMPL_VERSION >= 5
# else extern int __SourceHook_FHAddConCommandDispatch(void *, ISourceHook::AddHookMode, bool, class fastdelegate::FastDelegate0<void>);
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); #elif SH_IMPL_VERSION == 4
# endif extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); #elif SH_IMPL_VERSION == 3
#endif extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
#endif //SH_IMPL_VERSION
#endif //SE_ORANGEBOX
ChatTriggers g_ChatTriggers; ChatTriggers g_ChatTriggers;
bool g_bSupressSilentFails = false; bool g_bSupressSilentFails = false;
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false), ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
m_ReplyTo(SM_REPLY_CONSOLE), m_ArgSBackup(NULL) m_ReplyTo(SM_REPLY_CONSOLE)
{ {
m_PubTrigger = sm_strdup("!"); m_PubTrigger = sm_strdup("!");
m_PrivTrigger = sm_strdup("/"); m_PrivTrigger = sm_strdup("/");
m_PubTriggerSize = 1; m_PubTriggerSize = 1;
m_PrivTriggerSize = 1; m_PrivTriggerSize = 1;
m_bIsChatTrigger = false; m_bIsChatTrigger = false;
m_bPluginIgnored = true; m_bPluginIgnored = false;
#if SOURCE_ENGINE == SE_EPISODEONE #if SOURCE_ENGINE == SE_EPISODEONE
m_bIsINS = false; m_bIsINS = false;
#endif #endif
@@ -76,8 +78,6 @@ ChatTriggers::~ChatTriggers()
m_PubTrigger = NULL; m_PubTrigger = NULL;
delete [] m_PrivTrigger; delete [] m_PrivTrigger;
m_PrivTrigger = NULL; m_PrivTrigger = NULL;
delete [] m_ArgSBackup;
m_ArgSBackup = NULL;
} }
ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key, ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
@@ -111,10 +111,10 @@ ConfigResult ChatTriggers::OnSourceModConfigChanged(const char *key,
void ChatTriggers::OnSourceModAllInitialized() void ChatTriggers::OnSourceModAllInitialized()
{ {
m_pShouldFloodBlock = forwardsys->CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell); m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
m_pDidFloodBlock = forwardsys->CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell); m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
m_pOnClientSayCmd = forwardsys->CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String); m_pOnClientSayCmd = g_Forwards.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_pOnClientSayCmd_Post = g_Forwards.CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
} }
void ChatTriggers::OnSourceModAllInitialized_Post() void ChatTriggers::OnSourceModAllInitialized_Post()
@@ -129,13 +129,13 @@ void ChatTriggers::OnSourceModGameInitialized()
if (m_pSayCmd) if (m_pSayCmd)
{ {
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Post, true);
} }
if (m_pSayTeamCmd) if (m_pSayTeamCmd)
{ {
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
} }
#if SOURCE_ENGINE == SE_EPISODEONE #if SOURCE_ENGINE == SE_EPISODEONE
@@ -165,8 +165,8 @@ void ChatTriggers::OnSourceModShutdown()
{ {
if (m_pSayCmd) if (m_pSayCmd)
{ {
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true); SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, 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_Pre, false);
} }
if (m_pSayTeamCmd) if (m_pSayTeamCmd)
@@ -189,16 +189,13 @@ void ChatTriggers::OnSourceModShutdown()
} }
#endif #endif
forwardsys->ReleaseForward(m_pShouldFloodBlock); g_Forwards.ReleaseForward(m_pShouldFloodBlock);
forwardsys->ReleaseForward(m_pDidFloodBlock); g_Forwards.ReleaseForward(m_pDidFloodBlock);
forwardsys->ReleaseForward(m_pOnClientSayCmd); g_Forwards.ReleaseForward(m_pOnClientSayCmd);
forwardsys->ReleaseForward(m_pOnClientSayCmd_Post); g_Forwards.ReleaseForward(m_pOnClientSayCmd_Post);
} }
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Pre(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Pre(const CCommand &command) void ChatTriggers::OnSayCommand_Pre(const CCommand &command)
{ {
#else #else
@@ -209,10 +206,10 @@ void ChatTriggers::OnSayCommand_Pre()
int client = g_ConCmds.GetCommandClient(); int client = g_ConCmds.GetCommandClient();
m_bIsChatTrigger = false; m_bIsChatTrigger = false;
m_bWasFloodedMessage = false; m_bWasFloodedMessage = false;
m_bPluginIgnored = true; m_bPluginIgnored = false;
const char *args = command.ArgS(); const char *args = command.ArgS();
if (!args) if (!args)
{ {
RETURN_META(MRES_IGNORED); 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 /* 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. */ * can be NULL, despite the data still being there and valid. */
m_Arg0Backup = command.Arg(0); m_Arg0Backup = command.Arg(0);
size_t len = strlen(args); m_ArgSBackup = command.ArgS();
#if SOURCE_ENGINE == SE_EPISODEONE
if (m_bIsINS)
{
if (strcmp(m_Arg0Backup, "say2") == 0 && len >= 4)
{
args += 4;
len -= 4;
}
if (len == 0)
{
RETURN_META(MRES_SUPERCEDE);
}
}
#endif
/* The first pair of quotes are stripped from client say commands, but not console ones.
* We do not want the forwards to differ from what is displayed.
* So only strip the first pair of quotes from client say commands. */
bool is_quoted = false;
if (
#if SOURCE_ENGINE == SE_EPISODEONE
!m_bIsINS &&
#endif
client != 0 && args[0] == '"' && args[len-1] == '"')
{
/* The server normally won't display empty say commands, but in this case it does.
* I don't think it's desired so let's block it. */
if (len <= 2)
{
RETURN_META(MRES_SUPERCEDE);
}
args++;
len--;
is_quoted = true;
}
/* Some? engines strip the last quote when printing the string to chat.
* This results in having a double-quoted message passed to the OnClientSayCommand ("message") forward,
* but losing the last quote in the OnClientSayCommand_Post ("message) forward.
* To compensate this, we copy the args into our own buffer where the engine won't mess with
* and strip the quotes. */
delete [] m_ArgSBackup;
m_ArgSBackup = new char[CCommand::MaxCommandLength()+1];
memcpy(m_ArgSBackup, args, len+1);
/* Strip the quotes from the argument */
if (is_quoted)
{
if (m_ArgSBackup[len-1] == '"')
{
m_ArgSBackup[--len] = '\0';
}
}
/* The server console cannot do this */ /* The server console cannot do this */
if (client == 0) if (client == 0)
{ {
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_SUPERCEDE);
} }
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@@ -318,26 +259,41 @@ void ChatTriggers::OnSayCommand_Pre()
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
/* Handle quoted string sets */
bool is_quoted = false;
if (args[0] == '"')
{
args++;
is_quoted = true;
}
#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_trigger = false;
bool is_silent = false; bool is_silent = false;
/* Check for either trigger */ /* Check for either trigger */
if (m_PubTriggerSize && strncmp(m_ArgSBackup, m_PubTrigger, m_PubTriggerSize) == 0) if (m_PubTriggerSize && strncmp(args, m_PubTrigger, m_PubTriggerSize) == 0)
{ {
is_trigger = true; is_trigger = true;
args = &m_ArgSBackup[m_PubTriggerSize]; args = &args[m_PubTriggerSize];
} }
else if (m_PrivTriggerSize && strncmp(m_ArgSBackup, m_PrivTrigger, m_PrivTriggerSize) == 0) else if (m_PrivTriggerSize && strncmp(args, m_PrivTrigger, m_PrivTriggerSize) == 0)
{ {
is_trigger = true; is_trigger = true;
is_silent = true; is_silent = true;
args = &m_ArgSBackup[m_PrivTriggerSize]; args = &args[m_PrivTriggerSize];
} }
/** /**
* Test if this is actually a command! * 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; m_bIsChatTrigger = true;
@@ -347,12 +303,15 @@ void ChatTriggers::OnSayCommand_Pre()
m_bWillProcessInPost = true; 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); 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); RETURN_META(MRES_SUPERCEDE);
} }
@@ -361,9 +320,7 @@ void ChatTriggers::OnSayCommand_Pre()
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Post(const CCommandContext &context, const CCommand &command)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void ChatTriggers::OnSayCommand_Post(const CCommand &command) void ChatTriggers::OnSayCommand_Post(const CCommand &command)
#else #else
void ChatTriggers::OnSayCommand_Post() void ChatTriggers::OnSayCommand_Post()
@@ -375,19 +332,19 @@ void ChatTriggers::OnSayCommand_Post()
{ {
/* Reset this for re-entrancy */ /* Reset this for re-entrancy */
m_bWillProcessInPost = false; m_bWillProcessInPost = false;
/* Execute the cached command */ /* Execute the cached command */
unsigned int old = SetReplyTo(SM_REPLY_CHAT); 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); serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
#endif
SetReplyTo(old); 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->PushCell(client);
m_pOnClientSayCmd_Post->PushString(m_Arg0Backup); m_pOnClientSayCmd_Post->PushString(m_Arg0Backup);
m_pOnClientSayCmd_Post->PushString(m_ArgSBackup); m_pOnClientSayCmd_Post->PushString(m_ArgSBackup);
@@ -398,7 +355,7 @@ void ChatTriggers::OnSayCommand_Post()
m_bWasFloodedMessage = false; m_bWasFloodedMessage = false;
} }
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args) bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted)
{ {
/* Extract a command. This is kind of sloppy. */ /* Extract a command. This is kind of sloppy. */
char cmd_buf[64]; char cmd_buf[64];
@@ -440,12 +397,12 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
{ {
return false; return false;
} }
prepended = true; prepended = true;
} }
/* See if we need to do extra string manipulation */ /* See if we need to do extra string manipulation */
if (prepended) if (is_quoted || prepended)
{ {
size_t len; size_t len;
@@ -456,6 +413,15 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
} else { } else {
len = strncopy(m_ToExecute, args, sizeof(m_ToExecute)); len = strncopy(m_ToExecute, args, sizeof(m_ToExecute));
} }
/* Check if we need to strip a quote */
if (is_quoted)
{
if (m_ToExecute[len-1] == '"')
{
m_ToExecute[--len] = '\0';
}
}
} else { } else {
strncopy(m_ToExecute, args, sizeof(m_ToExecute)); strncopy(m_ToExecute, args, sizeof(m_ToExecute));
} }
@@ -466,16 +432,13 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args)
cell_t ChatTriggers::CallOnClientSayCommand(int client) cell_t ChatTriggers::CallOnClientSayCommand(int client)
{ {
cell_t res = Pl_Continue; cell_t res = Pl_Continue;
if (m_pOnClientSayCmd->GetFunctionCount() != 0) if (!m_bIsChatTrigger && m_pOnClientSayCmd->GetFunctionCount() != 0)
{ {
m_pOnClientSayCmd->PushCell(client); m_pOnClientSayCmd->PushCell(client);
m_pOnClientSayCmd->PushString(m_Arg0Backup); m_pOnClientSayCmd->PushString(m_Arg0Backup);
m_pOnClientSayCmd->PushString(m_ArgSBackup); m_pOnClientSayCmd->PushString(m_ArgSBackup);
m_pOnClientSayCmd->Execute(&res); m_pOnClientSayCmd->Execute(&res);
} }
m_bPluginIgnored = (res >= Pl_Stop);
return res; return res;
} }
+3 -6
View File
@@ -54,10 +54,7 @@ public: //SMGlobalClass
char *error, char *error,
size_t maxlength); size_t maxlength);
private: //ConCommand private: //ConCommand
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
void OnSayCommand_Pre(const CCommandContext &, const CCommand &command);
void OnSayCommand_Post(const CCommandContext &, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void OnSayCommand_Pre(const CCommand &command); void OnSayCommand_Pre(const CCommand &command);
void OnSayCommand_Post(const CCommand &command); void OnSayCommand_Post(const CCommand &command);
#else #else
@@ -70,7 +67,7 @@ public:
bool IsChatTrigger(); bool IsChatTrigger();
bool WasFloodedMessage(); bool WasFloodedMessage();
private: private:
bool PreProcessTrigger(edict_t *pEdict, const char *args); bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
bool ClientIsFlooding(int client); bool ClientIsFlooding(int client);
cell_t CallOnClientSayCommand(int client); cell_t CallOnClientSayCommand(int client);
private: private:
@@ -92,7 +89,7 @@ private:
unsigned int m_ReplyTo; unsigned int m_ReplyTo;
char m_ToExecute[300]; char m_ToExecute[300];
const char *m_Arg0Backup; const char *m_Arg0Backup;
char *m_ArgSBackup; const char *m_ArgSBackup;
IForward *m_pShouldFloodBlock; IForward *m_pShouldFloodBlock;
IForward *m_pDidFloodBlock; IForward *m_pDidFloodBlock;
IForward *m_pOnClientSayCmd; 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -31,19 +31,16 @@
#include "ConCmdManager.h" #include "ConCmdManager.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include "AdminCache.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "ChatTriggers.h" #include "ChatTriggers.h"
#include "logic_bridge.h" #include "logic_bridge.h"
using namespace ke;
ConCmdManager g_ConCmds; ConCmdManager g_ConCmds;
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#else #else
SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false); 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); SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
typedef ke::LinkedList<CmdHook *> PluginHookList; struct PlCmdInfo
void RegisterInPlugin(CmdHook *hook);
ConCmdManager::ConCmdManager()
{ {
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; m_CmdClient = 0;
} }
ConCmdManager::~ConCmdManager() ConCmdManager::~ConCmdManager()
{ {
sm_trie_destroy(m_pCmds);
sm_trie_destroy(m_pCmdGrps);
} }
void ConCmdManager::OnSourceModAllInitialized() void ConCmdManager::OnSourceModAllInitialized()
{ {
scripts->AddPluginsListener(this); g_PluginSys.AddPluginsListener(this);
g_RootMenu.AddRootConsoleCommand("cmds", "List console commands", 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() void ConCmdManager::OnSourceModShutdown()
{ {
scripts->RemovePluginsListener(this);
/* All commands should already be removed by the time we're done */ /* 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); g_RootMenu.RemoveRootConsoleCommand("cmds", this);
} }
@@ -83,68 +90,122 @@ void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
/* Whoa, first get its information struct */ /* Whoa, first get its information struct */
ConCmdInfo *pInfo; ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(name, &pInfo)) if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
return;
CmdHookList::iterator iter = pInfo->hooks.begin();
while (iter != pInfo->hooks.end())
{ {
CmdHook *hook = *iter; return;
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;
} }
RemoveConCmds(pInfo->srvhooks);
RemoveConCmds(pInfo->conhooks);
RemoveConCmd(pInfo, name, is_read_safe, false); RemoveConCmd(pInfo, name, is_read_safe, false);
} }
void ConCmdManager::OnPluginDestroyed(IPlugin *plugin) void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist)
{ {
PluginHookList *pList; List<CmdHook *>::iterator iter = cmdlist.begin();
if (!plugin->GetProperty("CommandList", (void **)&pList, true))
return;
PluginHookList::iterator iter = pList->begin(); while (iter != cmdlist.end())
while (iter != pList->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); CmdList::iterator p_iter = pList->begin();
if (hook->admin) while (p_iter != pList->end())
hook->admin->group->hooks.remove(hook); {
PlCmdInfo &cmd = (*p_iter);
if (cmd.pHook == pHook)
{
p_iter = pList->erase(p_iter);
}
else
{
p_iter++;
}
}
if (hook->info->hooks.empty()) delete pHook->pAdmin;
RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true, true); delete pHook;
iter = pList->erase(iter); iter = cmdlist.erase(iter);
delete hook;
} }
delete pList;
} }
#if SOURCE_ENGINE == SE_DOTA void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext)
void CommandCallback(const CCommandContext &context, const CCommand &command)
{ {
#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) void CommandCallback(const CCommand &command)
{ {
#else #else
@@ -168,7 +229,7 @@ void ConCmdManager::SetCommandClient(int client)
ConCmdInfo *ConCmdManager::FindInTrie(const char *name) ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
{ {
ConCmdInfo *pInfo; ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(name, &pInfo)) if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
return NULL; return NULL;
return pInfo; return pInfo;
} }
@@ -200,34 +261,44 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
} }
cell_t result = type; 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; pHook = (*iter);
if (!pHook->pf->IsRunnable())
if (hook->type == CmdHook::Server || !hook->pf->IsRunnable())
continue;
if (hook->admin && !CheckAccess(client, cmd, hook->admin))
{ {
if (result < Pl_Handled)
result = Pl_Handled;
continue; continue;
} }
if (pHook->pAdmin && !CheckAccess(client, cmd, pHook->pAdmin))
hook->pf->PushCell(client); {
hook->pf->PushCell(args); if (result < Pl_Handled)
{
cell_t tempres = result; result = Pl_Handled;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE) }
continue;
}
pHook->pf->PushCell(client);
pHook->pf->PushCell(args);
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
{ {
if (tempres > result) if (tempres > result)
{
result = tempres; result = tempres;
}
if (result == Pl_Stop) if (result == Pl_Stop)
{
break; break;
}
} }
} }
return (ResultType)result; type = (ResultType)result;
return type;
} }
void ConCmdManager::InternalDispatch(const CCommand &command) void ConCmdManager::InternalDispatch(const CCommand &command)
@@ -238,7 +309,9 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
{ {
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer || !pPlayer->IsConnected()) if (!pPlayer || !pPlayer->IsConnected())
{
return; return;
}
} }
/** /**
@@ -270,78 +343,198 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
* "nicer" when we expose explicit say hooks. * "nicer" when we expose explicit say hooks.
*/ */
if (g_ChatTriggers.WasFloodedMessage()) if (g_ChatTriggers.WasFloodedMessage())
{
return; return;
}
cell_t result = Pl_Continue; cell_t result = Pl_Continue;
int args = command.ArgC() - 1; int args = command.ArgC() - 1;
// On a listen server, sometimes the server host's client index can be set List<CmdHook *>::iterator iter;
// as 0. So index 1 is passed to the command callback to correct this CmdHook *pHook;
// potential problem.
int realClient = (!engine->IsDedicatedServer() && client == 0)
? g_Players.ListenClient()
: client;
int dedicatedClient = engine->IsDedicatedServer() ? 0 : g_Players.ListenClient();
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; cell_t tempres = result;
for (iter=pInfo->srvhooks.begin();
if (!hook->pf->IsRunnable()) iter!=pInfo->srvhooks.end();
continue; iter++)
if (hook->type == CmdHook::Server)
{ {
// Don't execute unless we're in the server console. pHook = (*iter);
if (realClient != dedicatedClient) if (!pHook->pf->IsRunnable())
{
continue; continue;
} else { }
// Check admin rights if needed. realClient isn't needed since we pHook->pf->PushCell(args);
// should bypass admin checks if client == 0 anyway. if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
if (client && hook->admin && !CheckAccess(client, cmd, hook->admin)) {
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) if (result < Pl_Handled)
{
result = Pl_Handled; result = Pl_Handled;
}
continue; continue;
} }
// Client hooks get a client argument. /* On a listen server, sometimes the server host's client index can be set as 0.
hook->pf->PushCell(realClient); * 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 (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE) {
{ if (tempres > result)
if (tempres > result) {
result = tempres; result = tempres;
if (result == Pl_Stop) }
break; if (result == Pl_Stop)
{
break;
}
}
} }
} }
if (result >= Pl_Handled) if (result >= Pl_Handled)
{ {
if (!pInfo->sourceMod) if (!pInfo->sourceMod)
{
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
}
return; 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; return true;
} }
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); /* If running listen server, then client 1 is the server host and should have 'root' access */
if (!pPlayer) if (client == 1 && !engine->IsDedicatedServer())
{
return true;
}
CPlayer *player = g_Players.GetPlayerByIndex(client);
if (!player
|| player->GetEdict() == NULL
|| player->IsFakeClient())
{ {
return false; 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... */ /* If we got here, the command failed... */
char buffer[128]; char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client)) if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
@@ -354,7 +547,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
{ {
char fullbuffer[192]; char fullbuffer[192];
UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer); UTIL_Format(fullbuffer, sizeof(fullbuffer), "[SM] %s.\n", buffer);
pPlayer->PrintToConsole(fullbuffer); engine->ClientPrintf(pEdict, fullbuffer);
} }
else if (replyto == SM_REPLY_CHAT) else if (replyto == SM_REPLY_CHAT)
{ {
@@ -376,41 +569,72 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags); ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo) if (!pInfo)
return false;
GroupMap::Insert i = m_CmdGrps.findForAdd(group);
if (!i.found())
{ {
if (!m_CmdGrps.add(i, group)) return false;
return false;
i->value = new CommandGroup();
} }
Ref<CommandGroup> cmdgroup = i->value;
CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description); CmdHook *pHook = new CmdHook();
pHook->admin = new AdminCmdInfo(cmdgroup, adminflags); 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 */ /* First get the command group override, if any */
bool override = adminsys->GetCommandOverride(group, bool override = g_Admins.GetCommandOverride(group,
Override_CommandGroup, Override_CommandGroup,
&(pHook->admin->eflags)); &(pAdmin->eflags));
/* Next get the command override, if any */ /* Next get the command override, if any */
if (adminsys->GetCommandOverride(name, if (g_Admins.GetCommandOverride(name,
Override_Command, Override_Command,
&(pHook->admin->eflags))) &(pAdmin->eflags)))
{ {
override = true; override = true;
} }
/* Assign normal flags if there were no overrides */ /* Assign normal flags if there were no overrides */
if (!override) 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; return true;
} }
@@ -423,42 +647,63 @@ bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags); ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo) if (!pInfo)
{
return false; 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; 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()); orig = info.pInfo->pCmd->GetName();
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new PluginHookList();
pPlugin->SetProperty("CommandList", pList);
}
const char *orig = hook->info->pCmd->GetName();
/* Insert this into the help list, SORTED alphabetically. */ /* Insert this into the help list, SORTED alphabetically. */
PluginHookList::iterator iter = pList->begin();
while (iter != pList->end()) 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) if (strcmp(orig, cmd) < 0)
{ {
pList->insertBefore(iter, hook); pList->insert(iter, info);
return; inserted = true;
break;
} }
iter++; iter++;
} }
pList->append(hook); if (!inserted)
{
pList->push_back(info);
}
} }
void ConCmdManager::AddToCmdList(ConCmdInfo *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) void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove)
{ {
ConCmdInfo *pInfo;
if (type == Override_Command) if (type == Override_Command)
{ {
ConCmdInfo *pInfo; if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
if (!m_Cmds.retrieve(cmd, &pInfo))
return;
for (CmdHookList::iterator iter = pInfo->hooks.begin(); iter != pInfo->hooks.end(); iter++)
{ {
if (!iter->admin) return;
continue; }
if (!remove) List<CmdHook *>::iterator iter;
iter->admin->eflags = bits; CmdHook *pHook;
else
iter->admin->eflags = iter->admin->flags; for (iter=pInfo->conhooks.begin(); iter!=pInfo->conhooks.end(); iter++)
pInfo->eflags = iter->admin->eflags; {
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) else if (type == Override_CommandGroup)
{ {
GroupMap::Result r = m_CmdGrps.find(cmd); void *object;
if (!r.found()) if (!sm_trie_retrieve(m_pCmdGrps, cmd, &object))
return;
Ref<CommandGroup> group(r->value);
for (PluginHookList::iterator iter = group->hooks.begin(); iter != group->hooks.end(); iter++)
{ {
CmdHook *hook = *iter; return;
if (remove) }
hook->admin->eflags = bits; int grpid = (int)object;
else
hook->admin->eflags = hook->admin->flags; /* This is bad :( loop through all commands */
hook->info->eflags = hook->admin->eflags; 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) void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_read_safe, bool untrack)
{ {
/* Remove from the trie */ /* Remove from the trie */
m_Cmds.remove(name); sm_trie_delete(m_pCmds, name);
/* Remove console-specific information /* Remove console-specific information
* This should always be true as of right now * 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) if (is_read_safe)
{ {
/* Remove the external hook */ /* 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) if (untrack)
{ {
@@ -575,26 +844,33 @@ void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_rea
bool ConCmdManager::LookForSourceModCommand(const char *cmd) bool ConCmdManager::LookForSourceModCommand(const char *cmd)
{ {
ConCmdInfo *pInfo; 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) bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
{ {
ConCmdInfo *pInfo; 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; return true;
} }
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags) ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
{ {
ConCmdInfo *pInfo; ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(name, &pInfo)) if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
{ {
ConCmdList::iterator item = FindInList(name); ConCmdList::iterator item = FindInList(name);
if (item != m_CmdList.end()) if (item != m_CmdList.end())
@@ -621,12 +897,12 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
else else
{ {
TrackConCommandBase(pCmd, this); 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; pInfo->pCmd = pCmd;
m_Cmds.insert(name, pInfo); sm_trie_insert(m_pCmds, name, pInfo);
AddToCmdList(pInfo); AddToCmdList(pInfo);
} }
@@ -639,7 +915,7 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
{ {
const char *text = command.Arg(2); const char *text = command.Arg(2);
IPlugin *pPlugin = scripts->FindPluginByConsoleArg(text); CPlugin *pPlugin = g_PluginSys.FindPluginByConsoleArg(text);
if (!pPlugin) if (!pPlugin)
{ {
@@ -650,36 +926,46 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo(); const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo();
const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename(); const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename();
PluginHookList *pList; CmdList *pList;
if (!pPlugin->GetProperty("CommandList", (void **)&pList)) if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{ {
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname); g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
return; return;
} }
if (pList->empty()) if (!pList->size())
{ {
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname); g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
return; return;
} }
CmdList::iterator iter;
const char *type = NULL; const char *type = NULL;
const char *name; const char *name;
const char *help; 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]"); 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; PlCmdInfo &cmd = (*iter);
if (hook->type == CmdHook::Server) if (cmd.type == Cmd_Server)
{
type = "server"; type = "server";
else }
type = hook->info->eflags == 0 ? "console" : "admin"; else if (cmd.type == Cmd_Admin)
{
name = hook->info->pCmd->GetName(); type = (cmd.pInfo->admin.eflags == 0)?"console":"admin";
if (hook->helptext.length()) }
help = hook->helptext.chars(); name = cmd.pInfo->pCmd->GetName();
if (cmd.pHook->helptext.size())
{
help = cmd.pHook->helptext.c_str();
}
else else
help = hook->info->pCmd->GetHelpText(); {
help = cmd.pInfo->pCmd->GetHelpText();
}
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help); 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,77 +34,60 @@
#include "sm_globals.h" #include "sm_globals.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <IForwardSys.h> #include "ForwardSys.h"
#include "sm_trie.h"
#include "sm_memtable.h"
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.h> #include <sh_string.h>
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include <IAdminSystem.h> #include <IAdminSystem.h>
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include <sm_stringhashmap.h>
#include <am-utility.h>
#include <am-inlinelist.h>
#include <am-linkedlist.h>
#include <am-refcounting.h>
using namespace SourceHook; using namespace SourceHook;
struct CmdHook; enum CmdType
struct ConCmdInfo;
struct CommandGroup : public ke::Refcounted<CommandGroup>
{ {
ke::LinkedList<CmdHook *> hooks; Cmd_Server,
Cmd_Admin,
}; };
struct AdminCmdInfo struct AdminCmdInfo
{ {
AdminCmdInfo(const ke::Ref<CommandGroup> &group, FlagBits flags) AdminCmdInfo()
: group(group),
flags(flags),
eflags(0)
{ {
cmdGrpId = -1;
flags = 0;
eflags = 0;
} }
ke::Ref<CommandGroup> group; int cmdGrpId; /* index into cmdgroup string table */
FlagBits flags; /* default flags */ FlagBits flags; /* default flags */
FlagBits eflags; /* effective flags */ FlagBits eflags; /* effective flags */
}; };
struct CmdHook : public ke::InlineListNode<CmdHook> struct CmdHook
{ {
enum Type { CmdHook()
Server,
Client
};
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description)
: type(type),
info(cmd),
pf(fun),
helptext(description)
{ {
pf = NULL;
pAdmin = NULL;
} }
IPluginFunction *pf; /* function hook */
Type type; String helptext; /* help text */
ConCmdInfo *info; AdminCmdInfo *pAdmin; /* admin requirements, if any */
IPluginFunction *pf; /* function hook */
ke::AString helptext; /* help text */
ke::AutoPtr<AdminCmdInfo> admin; /* admin requirements, if any */
}; };
typedef ke::InlineList<CmdHook> CmdHookList;
struct ConCmdInfo struct ConCmdInfo
{ {
ConCmdInfo() ConCmdInfo()
{ {
sourceMod = false; sourceMod = false;
pCmd = NULL; pCmd = NULL;
eflags = 0;
} }
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */ bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
ConCommand *pCmd; /**< Pointer to the command itself */ ConCommand *pCmd; /**< Pointer to the command itself */
CmdHookList hooks; /**< Hook list */ List<CmdHook *> srvhooks; /**< Hooks as a server command */
FlagBits eflags; /**< Effective admin flags */ List<CmdHook *> conhooks; /**< Hooks as a console command */
AdminCmdInfo admin; /**< Admin info, if any */
}; };
typedef List<ConCmdInfo *> ConCmdList; typedef List<ConCmdInfo *> ConCmdList;
@@ -115,9 +98,7 @@ class ConCmdManager :
public IPluginsListener, public IPluginsListener,
public IConCommandTracker public IConCommandTracker
{ {
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
friend void CommandCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
friend void CommandCallback(const CCommand &command); friend void CommandCallback(const CCommand &command);
#else #else
friend void CommandCallback(); friend void CommandCallback();
@@ -146,6 +127,8 @@ public:
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove); void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool LookForSourceModCommand(const char *cmd); bool LookForSourceModCommand(const char *cmd);
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags); bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits flags);
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
private: private:
void InternalDispatch(const CCommand &command); void InternalDispatch(const CCommand &command);
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args); ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
@@ -153,6 +136,8 @@ private:
void SetCommandClient(int client); void SetCommandClient(int client);
void AddToCmdList(ConCmdInfo *info); void AddToCmdList(ConCmdInfo *info);
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack); void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack);
void RemoveConCmds(List<CmdHook *> &cmdlist);
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
// Case insensitive // Case insensitive
@@ -170,12 +155,11 @@ public:
return m_CmdList; return m_CmdList;
} }
private: private:
typedef StringHashMap<ke::Ref<CommandGroup> > GroupMap; Trie *m_pCmds; /* command lookup */
Trie *m_pCmdGrps; /* command group lookup */
StringHashMap<ConCmdInfo *> m_Cmds; /* command lookup */
GroupMap m_CmdGrps; /* command group map */
ConCmdList m_CmdList; /* command list */ ConCmdList m_CmdList; /* command list */
int m_CmdClient; /* current client */ int m_CmdClient; /* current client */
BaseStringTable m_Strings; /* string table */
}; };
extern ConCmdManager g_ConCmds; extern ConCmdManager g_ConCmds;
+56 -83
View File
@@ -29,31 +29,34 @@
#include "ConVarManager.h" #include "ConVarManager.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "PluginSys.h"
#include "ForwardSys.h"
#include "HandleSys.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include <sh_vector.h> #include <sh_vector.h>
#include <sm_namehashset.h> #include <sm_trie_tpl.h>
#include "logic_bridge.h"
ConVarManager g_ConVarManager; ConVarManager g_ConVarManager;
#if SOURCE_ENGINE <= SE_DARKMESSIAH
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
#endif
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float); SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
#else #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 #endif
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE != SE_DARKMESSIAH
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *);
#elif SOURCE_ENGINE != SE_DARKMESSIAH
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *); SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *); SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
#endif #endif
const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String}; const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
typedef List<const ConVar *> ConVarList; typedef List<const ConVar *> ConVarList;
NameHashSet<ConVarInfo *> convar_cache; KTrie<ConVarInfo *> convar_cache;
class ConVarReentrancyGuard class ConVarReentrancyGuard
{ {
@@ -107,7 +110,7 @@ void ConVarManager::OnSourceModStartup(bool late)
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER; sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
/* Create the 'ConVar' handle type */ /* Create the 'ConVar' handle type */
m_ConVarType = handlesys->CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL); m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
} }
void ConVarManager::OnSourceModAllInitialized() void ConVarManager::OnSourceModAllInitialized()
@@ -118,20 +121,16 @@ void ConVarManager::OnSourceModAllInitialized()
#if SOURCE_ENGINE == SE_EPISODEONE #if SOURCE_ENGINE == SE_EPISODEONE
if (g_SMAPI->GetGameDLLVersion() >= 6) if (g_SMAPI->GetGameDLLVersion() >= 6)
{ {
SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsDLLQueryHooked = true; m_bIsDLLQueryHooked = true;
} }
#endif #endif
g_Players.AddClientListener(this); g_Players.AddClientListener(this);
#if SOURCE_ENGINE >= SE_ORANGEBOX SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
#else
SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
#endif
scripts->AddPluginsListener(this); g_PluginSys.AddPluginsListener(this);
/* Add the 'convars' option to the 'sm' console command */ /* Add the 'convars' option to the 'sm' console command */
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this); g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
@@ -149,10 +148,10 @@ void ConVarManager::OnSourceModShutdown()
iter = m_ConVars.erase(iter); iter = m_ConVars.erase(iter);
handlesys->FreeHandle(pInfo->handle, &sec); g_HandleSys.FreeHandle(pInfo->handle, &sec);
if (pInfo->pChangeForward != NULL) if (pInfo->pChangeForward != NULL)
{ {
forwardsys->ReleaseForward(pInfo->pChangeForward); g_Forwards.ReleaseForward(pInfo->pChangeForward);
} }
if (pInfo->sourceMod) if (pInfo->sourceMod)
{ {
@@ -184,33 +183,27 @@ void ConVarManager::OnSourceModShutdown()
/* Unhook things */ /* Unhook things */
if (m_bIsDLLQueryHooked) if (m_bIsDLLQueryHooked)
{ {
SH_REMOVE_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false); SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsDLLQueryHooked = false; m_bIsDLLQueryHooked = false;
} }
else if (m_bIsVSPQueryHooked) else if (m_bIsVSPQueryHooked)
{ {
#if SOURCE_ENGINE != SE_DOTA SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
SH_REMOVE_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false);
#endif
m_bIsVSPQueryHooked = false; m_bIsVSPQueryHooked = false;
} }
#endif #endif
g_Players.RemoveClientListener(this); g_Players.RemoveClientListener(this);
#if SOURCE_ENGINE >= SE_ORANGEBOX SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false);
#else
SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false);
#endif
/* Remove the 'convars' option from the 'sm' console command */ /* Remove the 'convars' option from the 'sm' console command */
g_RootMenu.RemoveRootConsoleCommand("cvars", this); g_RootMenu.RemoveRootConsoleCommand("cvars", this);
scripts->RemovePluginsListener(this); g_PluginSys.RemovePluginsListener(this);
/* Remove the 'ConVar' handle type */ /* Remove the 'ConVar' handle type */
handlesys->RemoveType(m_ConVarType, g_pCoreIdent); g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
} }
/** /**
@@ -240,15 +233,24 @@ void ConVarManager::OnSourceModVSPReceived()
} }
#endif #endif
#if SOURCE_ENGINE != SE_DARKMESSIAH && SOURCE_ENGINE != SE_DOTA #if SOURCE_ENGINE != SE_DARKMESSIAH
SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &ConVarManager::OnQueryCvarValueFinished), false); SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
m_bIsVSPQueryHooked = true; m_bIsVSPQueryHooked = true;
#endif #endif
} }
bool convar_cache_lookup(const char *name, ConVarInfo **pVar) bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
{ {
return convar_cache.retrieve(name, pVar); ConVarInfo **pLookup = convar_cache.retrieve(name);
if (pLookup != NULL)
{
*pVar = *pLookup;
return true;
}
else
{
return false;
}
} }
void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
@@ -267,7 +269,7 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
convar_cache.remove(name); convar_cache.remove(name);
/* Now make sure no plugins are referring to this pointer */ /* Now make sure no plugins are referring to this pointer */
IPluginIterator *pl_iter = scripts->GetPluginIterator(); IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
while (pl_iter->MorePlugins()) while (pl_iter->MorePlugins())
{ {
IPlugin *pl = pl_iter->GetPlugin(); IPlugin *pl = pl_iter->GetPlugin();
@@ -283,7 +285,7 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
} }
/* Free resources */ /* Free resources */
handlesys->FreeHandle(pInfo->handle, &sec); g_HandleSys.FreeHandle(pInfo->handle, &sec);
delete pInfo; delete pInfo;
} }
@@ -298,19 +300,14 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
delete pConVarList; delete pConVarList;
} }
const IPluginRuntime * pRuntime = plugin->GetRuntime();
/* Remove convar queries for this plugin that haven't returned results yet */ /* 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); ConVarQuery &query = (*iter);
if (query.pCallback->GetParentRuntime() == pRuntime) if (query.pCallback->GetParentRuntime() == plugin->GetRuntime())
{ {
iter = m_ConVarQueries.erase(iter); m_ConVarQueries.erase(iter);
continue;
} }
++iter;
} }
} }
@@ -356,7 +353,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
} }
/* Get plugin object */ /* Get plugin object */
IPlugin *plugin = scripts->FindPluginByConsoleArg(arg); CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
if (!plugin) if (!plugin)
{ {
@@ -437,7 +434,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
pInfo->pVar = pConVar; pInfo->pVar = pConVar;
/* If we don't, then create a new handle from the convar */ /* If we don't, then create a new handle from the convar */
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE) if (hndl == BAD_HANDLE)
{ {
delete pInfo; delete pInfo;
@@ -468,7 +465,7 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
pInfo->pChangeForward = NULL; pInfo->pChangeForward = NULL;
/* Create a handle from the new convar */ /* Create a handle from the new convar */
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE) if (hndl == BAD_HANDLE)
{ {
delete pInfo; delete pInfo;
@@ -497,13 +494,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
ConVarInfo *pInfo; ConVarInfo *pInfo;
Handle_t hndl; Handle_t hndl;
/* Check convar cache to find out if we already have a handle */ /* Search for convar */
if (convar_cache_lookup(name, &pInfo))
{
return pInfo->handle;
}
/* Couldn't find it in cache, so search for it */
pConVar = icvar->FindVar(name); pConVar = icvar->FindVar(name);
/* If it doesn't exist, then return an invalid handle */ /* If it doesn't exist, then return an invalid handle */
@@ -512,6 +503,12 @@ Handle_t ConVarManager::FindConVar(const char *name)
return BAD_HANDLE; return BAD_HANDLE;
} }
/* At this point, the convar exists. So, find out if we already have a handle */
if (convar_cache_lookup(name, &pInfo))
{
return pInfo->handle;
}
/* Create and initialize ConVarInfo structure */ /* Create and initialize ConVarInfo structure */
pInfo = new ConVarInfo(); pInfo = new ConVarInfo();
pInfo->sourceMod = false; pInfo->sourceMod = false;
@@ -519,7 +516,7 @@ Handle_t ConVarManager::FindConVar(const char *name)
pInfo->pVar = pConVar; pInfo->pVar = pConVar;
/* If we don't have a handle, then create a new one */ /* If we don't have a handle, then create a new one */
hndl = handlesys->CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
if (hndl == BAD_HANDLE) if (hndl == BAD_HANDLE)
{ {
delete pInfo; delete pInfo;
@@ -577,7 +574,7 @@ void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction
/* If forward does not exist, create it */ /* If forward does not exist, create it */
if (!pForward) if (!pForward)
{ {
pForward = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS); pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
pInfo->pChangeForward = pForward; pInfo->pChangeForward = pForward;
} }
@@ -617,7 +614,7 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
!ConVarReentrancyGuard::IsCvarInChain(pConVar)) !ConVarReentrancyGuard::IsCvarInChain(pConVar))
{ {
/* Free this forward */ /* Free this forward */
forwardsys->ReleaseForward(pForward); g_Forwards.ReleaseForward(pForward);
pInfo->pChangeForward = NULL; 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 */ /* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
if (m_bIsDLLQueryHooked) if (m_bIsDLLQueryHooked)
{ {
#if SOURCE_ENGINE == SE_DOTA
cookie = engine->StartQueryCvarValue(CEntityIndex(IndexOfEdict(pPlayer)), name);
#else
cookie = engine->StartQueryCvarValue(pPlayer, name); cookie = engine->StartQueryCvarValue(pPlayer, name);
#endif
} }
#if SOURCE_ENGINE != SE_DOTA
else if (m_bIsVSPQueryHooked) else if (m_bIsVSPQueryHooked)
{ {
cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name); cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
} }
#endif
else else
{ {
return InvalidQueryCvarCookie; return InvalidQueryCvarCookie;
} }
if (pCallback != NULL) ConVarQuery query = {cookie, pCallback, (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 #endif
return cookie; return cookie;
@@ -665,7 +653,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
bool inserted = false; bool inserted = false;
const char *orig = pConVar->GetName(); const char *orig = pConVar->GetName();
IPlugin *plugin = scripts->FindPluginByContext(pContext->GetContext()); IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
/* Check plugin for an existing convar list */ /* Check plugin for an existing convar list */
if (!plugin->GetProperty("ConVarList", (void **)&pConVarList)) if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
@@ -750,19 +738,8 @@ bool ConVarManager::IsQueryingSupported()
} }
#if SOURCE_ENGINE != SE_DARKMESSIAH #if SOURCE_ENGINE != SE_DARKMESSIAH
#if SOURCE_ENGINE == SE_DOTA
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
#else
void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue) void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
#endif // SE_DOTA
{ {
#if SOURCE_ENGINE == SE_CSGO
if (g_Players.HandleConVarQuery(cookie, pPlayer, result, cvarName, cvarValue))
{
return;
}
#endif
IPluginFunction *pCallback = NULL; IPluginFunction *pCallback = NULL;
cell_t value = 0; cell_t value = 0;
List<ConVarQuery>::iterator iter; List<ConVarQuery>::iterator iter;
@@ -783,11 +760,7 @@ void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *
cell_t ret; cell_t ret;
pCallback->PushCell(cookie); pCallback->PushCell(cookie);
#if SOURCE_ENGINE == SE_DOTA
pCallback->PushCell(player.Get());
#else
pCallback->PushCell(IndexOfEdict(pPlayer)); pCallback->PushCell(IndexOfEdict(pPlayer));
#endif
pCallback->PushCell(result); pCallback->PushCell(result);
pCallback->PushString(cvarName); pCallback->PushString(cvarName);
@@ -813,7 +786,7 @@ HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
ConVarInfo *pInfo; ConVarInfo *pInfo;
HandleError error; HandleError error;
if ((error = handlesys->ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None) if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
{ {
return error; return error;
} }
+2 -10
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -67,11 +67,6 @@ struct ConVarInfo
IChangeableForward *pChangeForward; /**< Forward associated with convar */ IChangeableForward *pChangeForward; /**< Forward associated with convar */
ConVar *pVar; /**< The actual convar */ ConVar *pVar; /**< The actual convar */
List<IConVarChangeListener *> changeListeners; List<IConVarChangeListener *> changeListeners;
static inline bool matches(const char *name, const ConVarInfo *info)
{
return strcmp(name, info->pVar->GetName()) == 0;
}
}; };
/** /**
@@ -165,10 +160,7 @@ private:
/** /**
* Callback for when StartQueryCvarValue() has finished. * Callback for when StartQueryCvarValue() has finished.
*/ */
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE != SE_DARKMESSIAH
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, CEntityIndex player, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue);
#elif SOURCE_ENGINE != SE_DARKMESSIAH
void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result,
const char *cvarName, const char *cvarValue); const char *cvarName, const char *cvarValue);
#endif #endif
+46 -38
View File
@@ -49,8 +49,7 @@
#include "ConCmdManager.h" #include "ConCmdManager.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "ConCommandBaseIterator.h" #include "ConCommandBaseIterator.h"
#include "logic_bridge.h" #include "ShareSys.h"
#include <am-utility.h>
#if defined PLATFORM_POSIX #if defined PLATFORM_POSIX
# include <dlfcn.h> # include <dlfcn.h>
@@ -60,9 +59,7 @@
#endif #endif
#if SH_IMPL_VERSION >= 5 #if SH_IMPL_VERSION >= 5
# if SOURCE_ENGINE == SE_DOTA # if SOURCE_ENGINE >= SE_ORANGEBOX
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 &); SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
# else # else
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
@@ -134,9 +131,7 @@ class GenericCommandHooker : public IConCommandLinkListener
} }
} }
# if SOURCE_ENGINE == SE_DOTA # if SOURCE_ENGINE >= SE_ORANGEBOX
void Dispatch(const CCommandContext &context, const CCommand& args)
# elif SOURCE_ENGINE >= SE_ORANGEBOX
void Dispatch(const CCommand& args) void Dispatch(const CCommand& args)
# else # else
void Dispatch() void Dispatch()
@@ -195,7 +190,7 @@ class GenericCommandHooker : public IConCommandLinkListener
size_t index; size_t index;
if (!FindVtable(vtable, 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; return;
} }
@@ -219,7 +214,7 @@ public:
if (dispatch.thisptroffs < 0) 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; return false;
} }
@@ -228,7 +223,7 @@ public:
if (!vtables.size()) if (!vtables.size())
{ {
logger->LogError("Command filter could not find any cvars!"); g_Logger.LogError("Command filter could not find any cvars!");
return false; return false;
} }
@@ -579,21 +574,23 @@ ConsoleDetours::ConsoleDetours() : status(FeatureStatus_Unknown)
void ConsoleDetours::OnSourceModAllInitialized() 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); Param_String, Param_Cell);
sharesys->AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER); g_ShareSys.AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
} }
void ConsoleDetours::OnSourceModShutdown() void ConsoleDetours::OnSourceModShutdown()
{ {
for (StringHashMap<IChangeableForward *>::iterator iter = m_Listeners.iter(); List<Listener*>::iterator iter = m_Listeners.begin();
!iter.empty(); while (iter != m_Listeners.end())
iter.next())
{ {
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(); s_GenericHooker.Disable();
} }
@@ -622,15 +619,22 @@ bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
} }
else else
{ {
ke::AutoArray<char> str(UTIL_ToLowerCase(command)); const char *str = UTIL_ToLowerCase(command);
IChangeableForward *forward; Listener *listener;
if (!m_Listeners.retrieve(str, &forward)) Listener **plistener = m_CmdLookup.retrieve(str);
if (plistener == NULL)
{ {
forward = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell, listener = new Listener;
Param_String, Param_Cell); listener->forward = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
m_Listeners.insert(str, forward); Param_String, Param_Cell);
m_CmdLookup.insert(str, listener);
} }
forward->AddFunction(fun); else
{
listener = *plistener;
}
listener->forward->AddFunction(fun);
delete [] str;
} }
return true; return true;
@@ -644,11 +648,14 @@ bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
} }
else else
{ {
ke::AutoArray<char> str(UTIL_ToLowerCase(command)); const char *str = UTIL_ToLowerCase(command);
IChangeableForward *forward; Listener *listener;
if (!m_Listeners.retrieve(str, &forward)) Listener **plistener = m_CmdLookup.retrieve(str);
delete [] str;
if (plistener == NULL)
return false; 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) if (result >= Pl_Handled)
return result; return result;
IChangeableForward *forward; Listener **plistener = m_CmdLookup.retrieve(name);
if (!m_Listeners.retrieve(name, &forward)) if (plistener == NULL)
return result; return result;
if (forward->GetFunctionCount() == 0) Listener *listener = *plistener;
if (listener->forward->GetFunctionCount() == 0)
return result; return result;
cell_t result2 = Pl_Continue; cell_t result2 = Pl_Continue;
forward->PushCell(client); listener->forward->PushCell(client);
forward->PushString(name); listener->forward->PushString(name);
forward->PushCell(args.ArgC() - 1); listener->forward->PushCell(args.ArgC() - 1);
forward->Execute(&result2, NULL); listener->forward->Execute(&result2, NULL);
if (result2 > result) if (result2 > result)
result = result2; 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 /* 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. * 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; dummy_hook_set = true;
pBase->Dispatch(); pBase->Dispatch();
SH_REMOVE_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false); SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
} }
else else
{ {
+8 -3
View File
@@ -33,8 +33,8 @@
#include "sm_globals.h" #include "sm_globals.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <IForwardSys.h> #include "ForwardSys.h"
#include <sm_stringhashmap.h> #include <sm_trie_tpl.h>
class ConsoleDetours : class ConsoleDetours :
public SMGlobalClass, public SMGlobalClass,
@@ -43,6 +43,10 @@ class ConsoleDetours :
friend class PlayerManager; friend class PlayerManager;
friend class GenericCommandHooker; friend class GenericCommandHooker;
struct Listener
{
IChangeableForward *forward;
};
public: public:
ConsoleDetours(); ConsoleDetours();
public: //SMGlobalClass public: //SMGlobalClass
@@ -69,7 +73,8 @@ public:
private: private:
FeatureStatus status; FeatureStatus status;
IChangeableForward *m_pForward; IChangeableForward *m_pForward;
StringHashMap<IChangeableForward *> m_Listeners; KTrie<Listener*> m_CmdLookup;
List<Listener*> m_Listeners;
}; };
extern ConsoleDetours g_ConsoleDetours; 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,12 +34,13 @@
#include "sourcemod.h" #include "sourcemod.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include <sourcemod_version.h>
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "LibrarySys.h" #include "LibrarySys.h"
#include "Logger.h" #include "Logger.h"
#include "PluginSys.h"
#include "ForwardSys.h"
#include "frame_hooks.h" #include "frame_hooks.h"
#include "logic_bridge.h"
#include <sourcemod_version.h>
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file"); ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
@@ -60,10 +61,7 @@ ConVar *g_ServerCfgFile = NULL;
void CheckAndFinalizeConfigs(); void CheckAndFinalizeConfigs();
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &);
void Hook_ExecDispatchPre(const CCommandContext &context, const CCommand &cmd)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
void Hook_ExecDispatchPre(const CCommand &cmd) void Hook_ExecDispatchPre(const CCommand &cmd)
#elif SOURCE_ENGINE == SE_DARKMESSIAH #elif SOURCE_ENGINE == SE_DARKMESSIAH
@@ -91,9 +89,7 @@ void Hook_ExecDispatchPre()
} }
} }
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
void Hook_ExecDispatchPost(const CCommandContext &context, const CCommand &cmd)
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void Hook_ExecDispatchPost(const CCommand &cmd) void Hook_ExecDispatchPost(const CCommand &cmd)
#else #else
void Hook_ExecDispatchPost() void Hook_ExecDispatchPost()
@@ -118,12 +114,12 @@ void CheckAndFinalizeConfigs()
void CoreConfig::OnSourceModAllInitialized() void CoreConfig::OnSourceModAllInitialized()
{ {
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this); g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
g_pOnServerCfg = forwardsys->CreateForward("OnServerCfg", ET_Ignore, 0, NULL); g_pOnServerCfg = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
g_pOnConfigsExecuted = forwardsys->CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL); g_pOnConfigsExecuted = g_Forwards.CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
g_pOnAutoConfigsBuffered = forwardsys->CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL); g_pOnAutoConfigsBuffered = g_Forwards.CreateForward("OnAutoConfigsBuffered", ET_Ignore, 0, NULL);
} }
CoreConfig::CoreConfig() CoreConfig::CoreConfig() : m_Strings(512)
{ {
} }
@@ -134,14 +130,14 @@ CoreConfig::~CoreConfig()
void CoreConfig::OnSourceModShutdown() void CoreConfig::OnSourceModShutdown()
{ {
g_RootMenu.RemoveRootConsoleCommand("config", this); g_RootMenu.RemoveRootConsoleCommand("config", this);
forwardsys->ReleaseForward(g_pOnServerCfg); g_Forwards.ReleaseForward(g_pOnServerCfg);
forwardsys->ReleaseForward(g_pOnConfigsExecuted); g_Forwards.ReleaseForward(g_pOnConfigsExecuted);
forwardsys->ReleaseForward(g_pOnAutoConfigsBuffered); g_Forwards.ReleaseForward(g_pOnAutoConfigsBuffered);
if (g_pExecPtr != NULL) if (g_pExecPtr != NULL)
{ {
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false); SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true); SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
g_pExecPtr = NULL; g_pExecPtr = NULL;
} }
} }
@@ -166,8 +162,8 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName)
g_pExecPtr = FindCommand("exec"); g_pExecPtr = FindCommand("exec");
if (g_pExecPtr != NULL) if (g_pExecPtr != NULL)
{ {
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false); SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPre, false);
SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true); SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_pExecPtr, Hook_ExecDispatchPost, true);
} }
else else
{ {
@@ -256,13 +252,14 @@ void CoreConfig::Initialize()
/* Reset cached key values */ /* Reset cached key values */
m_KeyValues.clear(); m_KeyValues.clear();
m_Strings.Reset();
/* Parse config file */ /* Parse config file */
if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay) if ((err=textparsers->ParseFile_SMC(filePath, this, NULL)) != SMCError_Okay)
{ {
/* :TODO: This won't actually log or print anything :( - So fix that somehow */ /* :TODO: This won't actually log or print anything :( - So fix that somehow */
const char *error = textparsers->GetSMCErrorString(err); 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) if (err == ConfigResult_Reject)
{ {
/* This is a fatal error */ /* 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; return SMCResult_Continue;
@@ -295,18 +292,19 @@ ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value,
pBase = pBase->m_pGlobalClassNext; pBase = pBase->m_pGlobalClassNext;
} }
ke::AString vstr(value); m_KeyValues.replace(option, m_Strings.AddString(value));
m_KeyValues.replace(option, ke::Move(vstr));
return ConfigResult_Ignore; return ConfigResult_Ignore;
} }
const char *CoreConfig::GetCoreConfigValue(const char *key) const char *CoreConfig::GetCoreConfigValue(const char *key)
{ {
StringHashMap<ke::AString>::Result r = m_KeyValues.find(key); int *pKey = m_KeyValues.retrieve(key);
if (!r.found()) if (pKey == NULL)
{
return NULL; return NULL;
return r->value.chars(); }
return m_Strings.GetString(*pKey);
} }
bool SM_AreConfigsExecuted() bool SM_AreConfigsExecuted()
@@ -323,7 +321,7 @@ inline bool IsPathSepChar(char c)
#endif #endif
} }
bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create) bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
{ {
bool will_create = false; bool will_create = false;
@@ -469,7 +467,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create)
} }
else 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; return can_create;
} }
} }
@@ -502,10 +500,10 @@ void SM_DoSingleExecFwds(IPluginContext *ctx)
void SM_ConfigsExecuted_Plugin(unsigned int serial) void SM_ConfigsExecuted_Plugin(unsigned int serial)
{ {
IPluginIterator *iter = scripts->GetPluginIterator(); IPluginIterator *iter = g_PluginSys.GetPluginIterator();
while (iter->MorePlugins()) while (iter->MorePlugins())
{ {
IPlugin *plugin = iter->GetPlugin(); CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
if (plugin->GetSerial() == serial) if (plugin->GetSerial() == serial)
{ {
SM_DoSingleExecFwds(plugin->GetBaseContext()); SM_DoSingleExecFwds(plugin->GetBaseContext());
@@ -518,7 +516,7 @@ void SM_ConfigsExecuted_Plugin(unsigned int serial)
void SM_ExecuteForPlugin(IPluginContext *ctx) void SM_ExecuteForPlugin(IPluginContext *ctx)
{ {
SMPlugin *plugin = scripts->FindPluginByContext(ctx->GetContext()); CPlugin *plugin = (CPlugin *)g_PluginSys.GetPluginByCtx(ctx->GetContext());
unsigned int num = plugin->GetConfigCount(); unsigned int num = plugin->GetConfigCount();
if (!num) if (!num)
@@ -547,17 +545,19 @@ void SM_ExecuteAllConfigs()
engine->ServerCommand("exec sourcemod/sourcemod.cfg\n"); engine->ServerCommand("exec sourcemod/sourcemod.cfg\n");
AutoPluginList plugins(scripts); IPluginIterator *iter = g_PluginSys.GetPluginIterator();
for (size_t i = 0; i < plugins->size(); i++) while (iter->MorePlugins())
{ {
SMPlugin *plugin = plugins->at(i); CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
unsigned int num = plugin->GetConfigCount(); unsigned int num = plugin->GetConfigCount();
bool can_create = true; bool can_create = true;
for (unsigned int i=0; i<num; i++) for (unsigned int i=0; i<num; i++)
{ {
can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create); can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
} }
iter->NextPlugin();
} }
iter->Release();
g_bGotServerStart = true; g_bGotServerStart = true;
CheckAndFinalizeConfigs(); CheckAndFinalizeConfigs();
+5 -4
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -35,8 +35,8 @@
#include "sm_globals.h" #include "sm_globals.h"
#include <ITextParsers.h> #include <ITextParsers.h>
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include <am-string.h> #include <sm_trie_tpl.h>
#include <sm_stringhashmap.h> #include "sm_memtable.h"
using namespace SourceMod; using namespace SourceMod;
@@ -68,7 +68,8 @@ private:
*/ */
ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength); ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
private: private:
StringHashMap<ke::AString> m_KeyValues; BaseStringTable m_Strings;
KTrie<int> m_KeyValues;
}; };
extern bool SM_AreConfigsExecuted(); 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,10 +30,12 @@
*/ */
#include "Database.h" #include "Database.h"
#include "ISourceMod.h"
#include "HandleSys.h" #include "HandleSys.h"
#include "ShareSys.h"
#include "sourcemod.h"
#include "sm_stringutil.h"
#include "Logger.h"
#include "ExtensionSys.h" #include "ExtensionSys.h"
#include "PluginSys.h"
#include <stdlib.h> #include <stdlib.h>
#include <IThreader.h> #include <IThreader.h>
@@ -45,18 +47,10 @@ DBManager g_DBMan;
static bool s_OneTimeThreaderErrorMsg = false; static bool s_OneTimeThreaderErrorMsg = false;
DBManager::DBManager() DBManager::DBManager()
: m_Terminate(false), : m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
m_ParseLevel(0),
m_ParseState(0),
m_pDefault(NULL)
{ {
} }
static void FrameHook(bool simulating)
{
g_DBMan.RunFrame();
}
void DBManager::OnSourceModAllInitialized() void DBManager::OnSourceModAllInitialized()
{ {
HandleAccess sec; HandleAccess sec;
@@ -70,11 +64,13 @@ void DBManager::OnSourceModAllInitialized()
g_ShareSys.AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
g_pSM->BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg"); g_SourceMod.BuildPath(Path_SM, m_Filename, sizeof(m_Filename), "configs/databases.cfg");
m_pConfigLock = g_pThreader->MakeMutex();
m_pThinkLock = g_pThreader->MakeMutex();
m_pQueueLock = g_pThreader->MakeMutex();
g_PluginSys.AddPluginsListener(this); g_PluginSys.AddPluginsListener(this);
g_pSM->AddGameFrameHook(&FrameHook);
} }
void DBManager::OnSourceModLevelChange(const char *mapName) void DBManager::OnSourceModLevelChange(const char *mapName)
@@ -86,23 +82,26 @@ void DBManager::OnSourceModLevelChange(const char *mapName)
* This way the thread's search won't be searching through a * This way the thread's search won't be searching through a
* potentially empty/corrupt list, which would be very bad. * potentially empty/corrupt list, which would be very bad.
*/ */
ke::AutoLock lock(&m_ConfigLock); m_pConfigLock->Lock();
if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay) if ((err = textparsers->ParseFile_SMC(m_Filename, this, &states)) != SMCError_Okay)
{ {
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) if (err != SMCError_Custom)
{ {
const char *txt = textparsers->GetSMCErrorString(err); 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() void DBManager::OnSourceModShutdown()
{ {
g_pSM->RemoveGameFrameHook(&FrameHook);
KillWorkerThread(); KillWorkerThread();
g_PluginSys.RemovePluginsListener(this); g_PluginSys.RemovePluginsListener(this);
m_pConfigLock->DestroyThis();
m_pThinkLock->DestroyThis();
m_pQueueLock->DestroyThis();
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent); g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent); g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
ClearConfigs(); ClearConfigs();
@@ -271,7 +270,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
*pdr = NULL; *pdr = NULL;
} }
*pdb = NULL; *pdb = NULL;
g_pSM->Format(error, maxlength, "Configuration \"%s\" not found", name); UTIL_Format(error, maxlength, "Configuration \"%s\" not found", name);
return false; return false;
} }
@@ -308,7 +307,7 @@ bool DBManager::Connect(const char *name, IDBDriver **pdr, IDatabase **pdb, bool
} }
*pdb = NULL; *pdb = NULL;
g_pSM->Format(error, maxlength, "Driver \"%s\" not found", dname); UTIL_Format(error, maxlength, "Driver \"%s\" not found", dname);
return false; return false;
} }
@@ -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. /* Now that the driver is gone, we have to test the think queue.
* Whatever happens therein is up to the db op! * Whatever happens therein is up to the db op!
*/ */
@@ -490,7 +483,7 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
} }
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
g_pSM->Format(filename, sizeof(filename), "dbi.%s.ext", name); UTIL_Format(filename, sizeof(filename), "dbi.%s.ext", name);
IExtension *pExt = g_Extensions.LoadAutoExtension(filename); IExtension *pExt = g_Extensions.LoadAutoExtension(filename);
if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size) if (!pExt || !pExt->IsLoaded() || m_drivers.size() <= last_size)
@@ -511,17 +504,12 @@ IDBDriver *DBManager::FindOrLoadDriver(const char *name)
void DBManager::KillWorkerThread() void DBManager::KillWorkerThread()
{ {
if (m_Worker) if (m_pWorker)
{ {
{ m_pWorker->Stop(false);
ke::AutoLock lock(&m_QueueEvent); g_pThreader->DestroyWorker(m_pWorker);
m_Terminate = true; m_pWorker = NULL;
m_QueueEvent.Notify();
}
m_Worker->Join();
m_Worker = NULL;
s_OneTimeThreaderErrorMsg = false; s_OneTimeThreaderErrorMsg = false;
m_Terminate = false;
} }
} }
@@ -534,106 +522,99 @@ bool DBManager::AddToThreadQueue(IDBThreadOperation *op, PrioQueueLevel prio)
return false; return false;
} }
if (!m_Worker) if (!m_pWorker)
{ {
m_Worker = new ke::Thread(this, "SM SQL Worker"); m_pWorker = g_pThreader->MakeWorker(this, true);
if (!m_Worker->Succeeded()) if (!m_pWorker)
{ {
if (!s_OneTimeThreaderErrorMsg) if (!s_OneTimeThreaderErrorMsg)
{ {
logger->LogError("[SM] Unable to create db threader (error unknown)"); g_Logger.LogError("[SM] Unable to create db threader (error unknown)");
s_OneTimeThreaderErrorMsg = true; s_OneTimeThreaderErrorMsg = true;
} }
m_Worker = NULL; return false;
}
if (!m_pWorker->Start())
{
if (!s_OneTimeThreaderErrorMsg)
{
g_Logger.LogError("[SM] Unable to start db threader (error unknown)");
s_OneTimeThreaderErrorMsg = true;
}
g_pThreader->DestroyWorker(m_pWorker);
m_pWorker = NULL;
return false; return false;
} }
} }
/* Add to the queue */ /* Add to the queue */
{ {
ke::AutoLock lock(&m_QueueEvent); m_pQueueLock->Lock();
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio); Queue<IDBThreadOperation *> &queue = m_OpQueue.GetQueue(prio);
queue.push(op); queue.push(op);
m_QueueEvent.Notify(); m_pQueueLock->Unlock();
} }
/* Make the thread */
m_pWorker->MakeThread(this);
return true; return true;
} }
void DBManager::Run() void DBManager::OnWorkerStart(IThreadWorker *pWorker)
{ {
// Initialize DB threadsafety. m_drSafety.clear();
for (size_t i=0; i < m_drivers.size(); i++) for (size_t i=0; i<m_drivers.size(); i++)
{ {
if (m_drivers[i]->IsThreadSafe()) if (m_drivers[i]->IsThreadSafe())
{
m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety()); m_drSafety.push_back(m_drivers[i]->InitializeThreadSafety());
else } else {
m_drSafety.push_back(false); m_drSafety.push_back(false);
}
} }
}
// Run actual worker thread logic. void DBManager::OnWorkerStop(IThreadWorker *pWorker)
ThreadMain(); {
// Shutdown DB threadsafety.
for (size_t i=0; i<m_drivers.size(); i++) for (size_t i=0; i<m_drivers.size(); i++)
{ {
if (m_drSafety[i]) if (m_drSafety[i])
{
m_drivers[i]->ShutdownThreadSafety(); m_drivers[i]->ShutdownThreadSafety();
}
} }
m_drSafety.clear(); m_drSafety.clear();
} }
void DBManager::ThreadMain() void DBManager::RunThread(IThreadHandle *pThread)
{ {
ke::AutoLock lock(&m_QueueEvent); IDBThreadOperation *op = NULL;
while (true) { /* Get something from the queue */
// The lock has been acquired. Grab everything we can out of the {
// queue. Since we want to flush the queue even if we're terminated, m_pQueueLock->Lock();
// we process all operations we can before checking to terminate. Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue();
// There's no risk of starvation since the main thread blocks on us if (!queue.empty())
// terminating.
while (true)
{ {
Queue<IDBThreadOperation *> &queue = m_OpQueue.GetLikelyQueue(); op = queue.first();
if (queue.empty())
break;
IDBThreadOperation *op = queue.first();
queue.pop(); queue.pop();
// Unlock the queue when we run the query, so the main thread can
// keep pumping events. We re-acquire the lock to check for more
// items. It's okay if we terminate while unlocked; the main
// thread would be blocked and we'd need to flush the queue
// anyway, so after we've depleted the queue here, we'll just
// reach the terminate at the top of the loop.
{
ke::AutoUnlock unlock(&m_QueueEvent);
op->RunThreadPart();
ke::AutoLock lock(&m_ThinkLock);
m_ThinkQueue.push(op);
}
if (!m_Terminate)
{
ke::AutoUnlock unlock(&m_QueueEvent);
#ifdef _WIN32
Sleep(20);
#else
usleep(20000);
#endif
}
} }
m_pQueueLock->Unlock();
if (m_Terminate)
return;
// Release the lock and wait for a signal.
m_QueueEvent.Wait();
} }
/* whoa. hi. did we get something? we should have. */
if (!op)
{
/* wtf? */
return;
}
op->RunThreadPart();
m_pThinkLock->Lock();
m_ThinkQueue.push(op);
m_pThinkLock->Unlock();
} }
void DBManager::RunFrame() void DBManager::RunFrame()
@@ -645,16 +626,19 @@ void DBManager::RunFrame()
} }
/* Dump one thing per-frame so the server stays sane. */ /* Dump one thing per-frame so the server stays sane. */
IDBThreadOperation *op; m_pThinkLock->Lock();
{ IDBThreadOperation *op = m_ThinkQueue.first();
ke::AutoLock lock(&m_ThinkLock); m_ThinkQueue.pop();
op = m_ThinkQueue.first(); m_pThinkLock->Unlock();
m_ThinkQueue.pop();
}
op->RunThinkPart(); op->RunThinkPart();
op->Destroy(); op->Destroy();
} }
void DBManager::OnTerminate(IThreadHandle *pThread, bool cancel)
{
/* Do nothing */
}
void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken) void DBManager::OnSourceModIdentityDropped(IdentityToken_t *pToken)
{ {
s_pAddBlock = pToken; s_pAddBlock = pToken;
@@ -730,12 +714,12 @@ void DBManager::OnPluginUnloaded(IPlugin *plugin)
void DBManager::LockConfig() void DBManager::LockConfig()
{ {
m_ConfigLock.Lock(); m_pConfigLock->Lock();
} }
void DBManager::UnlockConfig() void DBManager::UnlockConfig()
{ {
m_ConfigLock.Unlock(); m_pConfigLock->Unlock();
} }
const char *DBManager::GetDefaultDriverName() const char *DBManager::GetDefaultDriverName()
+17 -14
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -33,15 +33,15 @@
#define _INCLUDE_DATABASE_MANAGER_H_ #define _INCLUDE_DATABASE_MANAGER_H_
#include <IDBDriver.h> #include <IDBDriver.h>
#include "common_logic.h" #include "sm_globals.h"
#include <sh_vector.h> #include <sh_vector.h>
#include <sh_string.h> #include <sh_string.h>
#include <sh_list.h> #include <sh_list.h>
#include <ITextParsers.h> #include <ITextParsers.h>
#include "sm_memtable.h"
#include <IThreader.h> #include <IThreader.h>
#include <IPluginSys.h>
#include <am-thread-utils.h>
#include "sm_simple_prioqueue.h" #include "sm_simple_prioqueue.h"
#include "PluginSys.h"
using namespace SourceHook; using namespace SourceHook;
@@ -65,8 +65,9 @@ class DBManager :
public SMGlobalClass, public SMGlobalClass,
public IHandleTypeDispatch, public IHandleTypeDispatch,
public ITextListener_SMC, public ITextListener_SMC,
public IPluginsListener, public IThread,
public ke::IRunnable public IThreadWorkerCallbacks,
public IPluginsListener
{ {
public: public:
DBManager(); DBManager();
@@ -97,9 +98,12 @@ public: //ITextListener_SMC
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states); SMCResult ReadSMC_LeavingSection(const SMCStates *states);
void ReadSMC_ParseEnd(bool halted, bool failed); void ReadSMC_ParseEnd(bool halted, bool failed);
public: //ke::IRunnable public: //IThread
void Run(); void RunThread(IThreadHandle *pThread);
void ThreadMain(); void OnTerminate(IThreadHandle *pThread, bool cancel);
public: //IThreadWorkerCallbacks
void OnWorkerStart(IThreadWorker *pWorker);
void OnWorkerStop(IThreadWorker *pWorker);
public: //IPluginsListener public: //IPluginsListener
void OnPluginUnloaded(IPlugin *plugin); void OnPluginUnloaded(IPlugin *plugin);
public: public:
@@ -125,11 +129,10 @@ private:
PrioQueue<IDBThreadOperation *> m_OpQueue; PrioQueue<IDBThreadOperation *> m_OpQueue;
Queue<IDBThreadOperation *> m_ThinkQueue; Queue<IDBThreadOperation *> m_ThinkQueue;
CVector<bool> m_drSafety; /* which drivers are safe? */ CVector<bool> m_drSafety; /* which drivers are safe? */
ke::AutoPtr<ke::Thread> m_Worker; IThreadWorker *m_pWorker; /* Worker thread object */
ke::ConditionVariable m_QueueEvent; IMutex *m_pConfigLock; /* Configuration lock */
ke::Mutex m_ConfigLock; IMutex *m_pQueueLock; /* Queue safety lock */
ke::Mutex m_ThinkLock; IMutex *m_pThinkLock; /* Think-queue lock */
bool m_Terminate;
List<ConfDbInfo *> m_confs; List<ConfDbInfo *> m_confs;
HandleType_t m_DriverType; HandleType_t m_DriverType;
@@ -29,10 +29,10 @@
* Version: $Id$ * Version: $Id$
*/ */
#include <IPluginSys.h>
#include <stdarg.h>
#include "DebugReporter.h" #include "DebugReporter.h"
#include "Logger.h" #include "Logger.h"
#include "PluginSys.h"
#include "sm_stringutil.h"
DebugReport g_DbgReporter; DebugReport g_DbgReporter;
@@ -47,7 +47,7 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
char buffer[512]; char buffer[512];
va_start(ap, msg); va_start(ap, msg);
smcore.FormatArgs(buffer, sizeof(buffer), msg, ap); UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
va_end(ap); va_end(ap);
g_Logger.LogMessage("[SM] %s", buffer); 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) void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap)
{ {
char buffer[512]; 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); const char *error = g_pSourcePawn2->GetErrorString(err);
if (error) if (error)
@@ -99,10 +99,10 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
char buffer[512]; char buffer[512];
va_start(ap, message); va_start(ap, message);
smcore.FormatArgs(buffer, sizeof(buffer), message, ap); UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
va_end(ap); va_end(ap);
const char *plname = pluginsys->FindPluginByContext(pContext->GetContext())->GetFilename(); const char *plname = g_PluginSys.FindPluginByContext(pContext->GetContext())->GetFilename();
const char *error = g_pSourcePawn2->GetErrorString(err); const char *error = g_pSourcePawn2->GetErrorString(err);
if (error) if (error)
@@ -135,7 +135,7 @@ void DebugReport::GenerateCodeError(IPluginContext *pContext, uint32_t code_addr
void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error) void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *error)
{ {
const char *lastname; const char *lastname;
const char *plname = pluginsys->FindPluginByContext(ctx->GetContext())->GetFilename(); const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
int n_err = error->GetErrorCode(); int n_err = error->GetErrorCode();
if (n_err != SP_ERROR_NATIVE) if (n_err != SP_ERROR_NATIVE)
@@ -180,7 +180,7 @@ void DebugReport::OnContextExecuteError(IPluginContext *ctx, IContextTrace *erro
int DebugReport::_GetPluginIndex(IPluginContext *ctx) int DebugReport::_GetPluginIndex(IPluginContext *ctx)
{ {
int id = 1; int id = 1;
IPluginIterator *iter = pluginsys->GetPluginIterator(); IPluginIterator *iter = g_PluginSys.GetPluginIterator();
for (; iter->MorePlugins(); iter->NextPlugin(), id++) for (; iter->MorePlugins(); iter->NextPlugin(), id++)
{ {
@@ -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. */ /* 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_ #define _INCLUDE_SOURCEMOD_CDBGREPORTER_H_
#include "sp_vm_api.h" #include "sp_vm_api.h"
#include "common_logic.h" #include "sm_globals.h"
class DebugReport : class DebugReport :
public SMGlobalClass, public SMGlobalClass,
+39 -29
View File
@@ -30,8 +30,10 @@
*/ */
#include "EventManager.h" #include "EventManager.h"
#include "ForwardSys.h"
#include "HandleSys.h"
#include "PluginSys.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "logic_bridge.h"
EventManager g_EventManager; EventManager g_EventManager;
@@ -56,10 +58,14 @@ public:
EventManager::EventManager() : m_EventType(0) EventManager::EventManager() : m_EventType(0)
{ {
/* Create an event lookup trie */
m_EventHooks = sm_trie_create();
} }
EventManager::~EventManager() EventManager::~EventManager()
{ {
sm_trie_destroy(m_EventHooks);
/* Free memory used by EventInfo structs if any */ /* Free memory used by EventInfo structs if any */
CStack<EventInfo *>::iterator iter; CStack<EventInfo *>::iterator iter;
for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++) for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++)
@@ -73,8 +79,8 @@ EventManager::~EventManager()
void EventManager::OnSourceModAllInitialized() void EventManager::OnSourceModAllInitialized()
{ {
/* Add a hook for IGameEventManager2::FireEvent() */ /* Add a hook for IGameEventManager2::FireEvent() */
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false); SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true); SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
HandleAccess sec; HandleAccess sec;
@@ -84,17 +90,17 @@ void EventManager::OnSourceModAllInitialized()
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER; sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
/* Create the 'GameEvent' handle type */ /* Create the 'GameEvent' handle type */
m_EventType = handlesys->CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL); m_EventType = g_HandleSys.CreateType("GameEvent", this, 0, NULL, &sec, g_pCoreIdent, NULL);
} }
void EventManager::OnSourceModShutdown() void EventManager::OnSourceModShutdown()
{ {
/* Remove hook for IGameEventManager2::FireEvent() */ /* Remove hook for IGameEventManager2::FireEvent() */
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false); SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent, false);
SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true); SH_REMOVE_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &EventManager::OnFireEvent_Post, true);
/* Remove the 'GameEvent' handle type */ /* Remove the 'GameEvent' handle type */
handlesys->RemoveType(m_EventType, g_pCoreIdent); g_HandleSys.RemoveType(m_EventType, g_pCoreIdent);
/* Remove ourselves as listener for events */ /* Remove ourselves as listener for events */
gameevents->RemoveListener(this); gameevents->RemoveListener(this);
@@ -132,12 +138,12 @@ void EventManager::OnPluginUnloaded(IPlugin *plugin)
{ {
if (pHook->pPreHook) if (pHook->pPreHook)
{ {
forwardsys->ReleaseForward(pHook->pPreHook); g_Forwards.ReleaseForward(pHook->pPreHook);
} }
if (pHook->pPostHook) if (pHook->pPostHook)
{ {
forwardsys->ReleaseForward(pHook->pPostHook); g_Forwards.ReleaseForward(pHook->pPostHook);
} }
delete pHook; delete pHook;
@@ -155,7 +161,7 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */ Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
} }
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA #if SOURCE_ENGINE >= SE_LEFT4DEAD
int EventManager::GetEventDebugID() int EventManager::GetEventDebugID()
{ {
return EVENT_DEBUG_ID_INIT; 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 a hook structure does not exist... */
if (!m_EventHooks.retrieve(name, &pHook)) if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
{ {
EventHookList *pHookList; EventHookList *pHookList;
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext()); IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Check plugin for an existing EventHook list */ /* Check plugin for an existing EventHook list */
if (!plugin->GetProperty("EventHooks", (void **)&pHookList)) if (!plugin->GetProperty("EventHooks", (void **)&pHookList))
@@ -196,12 +202,12 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
if (mode == EventHookMode_Pre) if (mode == EventHookMode_Pre)
{ {
/* Create forward for a pre hook */ /* Create forward for a pre hook */
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS); pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, GAMEEVENT_PARAMS);
/* Add to forward list */ /* Add to forward list */
pHook->pPreHook->AddFunction(pFunction); pHook->pPreHook->AddFunction(pFunction);
} else { } else {
/* Create forward for a post hook */ /* Create forward for a post hook */
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS); pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
/* Should we copy data from a pre hook to the post hook? */ /* Should we copy data from a pre hook to the post hook? */
pHook->postCopy = (mode == EventHookMode_Post); pHook->postCopy = (mode == EventHookMode_Post);
/* Add to forward list */ /* Add to forward list */
@@ -209,14 +215,14 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
} }
/* Cache the name for post hooks */ /* Cache the name for post hooks */
pHook->name = name; pHook->name = sm_strdup(name);
/* Increase reference count */ /* Increase reference count */
pHook->refCount++; pHook->refCount++;
/* Add hook structure to hook lists */ /* Add hook structure to hook lists */
pHookList->push_back(pHook); pHookList->push_back(pHook);
m_EventHooks.insert(name, pHook); sm_trie_insert(m_EventHooks, name, pHook);
return EventHookErr_Okay; return EventHookErr_Okay;
} }
@@ -228,7 +234,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
/* Create pre hook forward if necessary */ /* Create pre hook forward if necessary */
if (!pHook->pPreHook) if (!pHook->pPreHook)
{ {
pHook->pPreHook = forwardsys->CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS); pHook->pPreHook = g_Forwards.CreateForwardEx(NULL, ET_Event, 3, GAMEEVENT_PARAMS);
} }
/* Add plugin function to forward list */ /* Add plugin function to forward list */
@@ -237,7 +243,7 @@ EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunct
/* Create post hook forward if necessary */ /* Create post hook forward if necessary */
if (!pHook->pPostHook) if (!pHook->pPostHook)
{ {
pHook->pPostHook = forwardsys->CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS); pHook->pPostHook = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, GAMEEVENT_PARAMS);
} }
/* If postCopy is false, then we may want to set it to true */ /* If postCopy is false, then we may want to set it to true */
@@ -262,7 +268,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
IChangeableForward **pEventForward; IChangeableForward **pEventForward;
/* If hook does not exist at all */ /* If hook does not exist at all */
if (!m_EventHooks.retrieve(name, &pHook)) if (!sm_trie_retrieve(m_EventHooks, name, (void **)&pHook))
{ {
return EventHookErr_NotActive; return EventHookErr_NotActive;
} }
@@ -284,7 +290,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
/* If forward's list contains 0 functions now, free it */ /* If forward's list contains 0 functions now, free it */
if ((*pEventForward)->GetFunctionCount() == 0) if ((*pEventForward)->GetFunctionCount() == 0)
{ {
forwardsys->ReleaseForward(*pEventForward); g_Forwards.ReleaseForward(*pEventForward);
*pEventForward = NULL; *pEventForward = NULL;
} }
@@ -294,7 +300,7 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
/* If reference count is now 0, free hook structure */ /* If reference count is now 0, free hook structure */
EventHookList *pHookList; EventHookList *pHookList;
IPlugin *plugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext()); IPlugin *plugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
/* Get plugin's event hook list */ /* Get plugin's event hook list */
if (!plugin->GetProperty("EventHooks", (void**)&pHookList)) if (!plugin->GetProperty("EventHooks", (void**)&pHookList))
@@ -312,7 +318,10 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun
pHookList->remove(pHook); pHookList->remove(pHook);
/* Delete entry in trie */ /* Delete entry in trie */
m_EventHooks.remove(name); sm_trie_delete(m_EventHooks, name);
/* Free the cached name */
delete pHook->name;
/* And finally free structure memory */ /* And finally free structure memory */
delete pHook; delete pHook;
@@ -388,7 +397,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
name = pEvent->GetName(); 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 /* 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. * 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); EventInfo info(pEvent, NULL);
HandleSecurity sec(NULL, g_pCoreIdent); 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; info.bDontBroadcast = bDontBroadcast;
@@ -415,7 +424,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
broadcast = info.bDontBroadcast; broadcast = info.bDontBroadcast;
handlesys->FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
} }
if (pHook->postCopy) if (pHook->postCopy)
@@ -467,14 +476,14 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
info.bDontBroadcast = bDontBroadcast; info.bDontBroadcast = bDontBroadcast;
info.pEvent = m_EventCopies.front(); info.pEvent = m_EventCopies.front();
info.pOwner = NULL; 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); pForward->PushCell(hndl);
} else { } else {
pForward->PushCell(BAD_HANDLE); pForward->PushCell(BAD_HANDLE);
} }
pForward->PushString(pHook->name.chars()); pForward->PushString(pHook->name);
pForward->PushCell(bDontBroadcast); pForward->PushCell(bDontBroadcast);
pForward->Execute(NULL); pForward->Execute(NULL);
@@ -482,7 +491,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{ {
/* Free handle */ /* Free handle */
HandleSecurity sec(NULL, g_pCoreIdent); HandleSecurity sec(NULL, g_pCoreIdent);
handlesys->FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
/* Free event structure */ /* Free event structure */
gameevents->FreeEvent(info.pEvent); gameevents->FreeEvent(info.pEvent);
@@ -495,7 +504,8 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{ {
assert(pHook->pPostHook == NULL); assert(pHook->pPostHook == NULL);
assert(pHook->pPreHook == NULL); assert(pHook->pPreHook == NULL);
m_EventHooks.remove(pHook->name.chars()); sm_trie_delete(m_EventHooks, pHook->name);
delete pHook->name;
delete pHook; delete pHook;
} }
} }
+5 -10
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -34,7 +34,7 @@
#include "sm_globals.h" #include "sm_globals.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <sm_namehashset.h> #include "sm_trie.h"
#include <sh_list.h> #include <sh_list.h>
#include <sh_stack.h> #include <sh_stack.h>
#include <IHandleSys.h> #include <IHandleSys.h>
@@ -69,12 +69,7 @@ struct EventHook
IChangeableForward *pPostHook; IChangeableForward *pPostHook;
bool postCopy; bool postCopy;
unsigned int refCount; unsigned int refCount;
ke::AString name; char *name;
static inline bool matches(const char *name, const EventHook *hook)
{
return strcmp(name, hook->name.chars()) == 0;
}
}; };
enum EventHookMode enum EventHookMode
@@ -110,7 +105,7 @@ public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin); void OnPluginUnloaded(IPlugin *plugin);
public: // IGameEventListener2 public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent); void FireGameEvent(IGameEvent *pEvent);
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA #if SOURCE_ENGINE >= SE_LEFT4DEAD
int GetEventDebugID(); int GetEventDebugID();
#endif #endif
public: public:
@@ -132,7 +127,7 @@ private: // IGameEventManager2 hooks
bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast); bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast);
private: private:
HandleType_t m_EventType; HandleType_t m_EventType;
NameHashSet<EventHook *> m_EventHooks; Trie *m_EventHooks;
CStack<EventInfo *> m_FreeEvents; CStack<EventInfo *> m_FreeEvents;
CStack<EventHook *> m_EventStack; CStack<EventHook *> m_EventStack;
CStack<IGameEvent *> m_EventCopies; CStack<IGameEvent *> m_EventCopies;
@@ -31,11 +31,13 @@
#include <stdlib.h> #include <stdlib.h>
#include "ExtensionSys.h" #include "ExtensionSys.h"
#include <ILibrarySys.h> #include "LibrarySys.h"
#include <ISourceMod.h> #include "ShareSys.h"
#include "common_logic.h" #include "Logger.h"
#include "PluginSys.h" #include "sourcemm_api.h"
#include <am-utility.h> #include "sm_srvcmds.h"
#include "sm_stringutil.h"
#include "PlayerManager.h"
CExtensionManager g_Extensions; CExtensionManager g_Extensions;
IdentityType_t g_ExtType; IdentityType_t g_ExtType;
@@ -49,7 +51,7 @@ void CExtension::Initialize(const char *filename, const char *path)
m_File.assign(filename); m_File.assign(filename);
m_Path.assign(path); m_Path.assign(path);
char real_name[PLATFORM_MAX_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); m_RealFile.assign(real_name);
} }
@@ -59,6 +61,42 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena
m_pAPI = pAPI; 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) CLocalExtension::CLocalExtension(const char *filename)
{ {
m_PlId = 0; 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. */ /* Zeroth, see if there is an engine specific build in the new place. */
g_pSM->BuildPath(Path_SM, g_SourceMod.BuildPath(Path_SM,
path, path,
PLATFORM_MAX_PATH, PLATFORM_MAX_PATH,
"extensions/%s.%s." PLATFORM_LIB_EXT, "extensions/%s." GAMEFIX "." PLATFORM_LIB_EXT,
filename, filename);
smcore.gamesuffix);
if (libsys->IsPathFile(path)) if (g_LibSys.IsPathFile(path))
{ {
goto found; 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 */ /* 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 g_SourceMod.BuildPath(Path_SM,
|| strcmp(smcore.gamesuffix, "2.dods") == 0 path,
|| strcmp(smcore.gamesuffix, "2.hl2dm") == 0 PLATFORM_MAX_PATH,
) "extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
{ filename);
g_pSM->BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
if (libsys->IsPathFile(path)) if (g_LibSys.IsPathFile(path))
{
goto found;
}
}
else if (strcmp(smcore.gamesuffix, "2.nd") == 0)
{ {
g_pSM->BuildPath(Path_SM, goto found;
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
if (libsys->IsPathFile(path))
{
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! */ /* First see if there is an engine specific build! */
g_pSM->BuildPath(Path_SM, g_SourceMod.BuildPath(Path_SM,
path, path,
PLATFORM_MAX_PATH, PLATFORM_MAX_PATH,
"extensions/auto.%s/%s." PLATFORM_LIB_EXT, "extensions/auto." GAMEFIX "/%s." PLATFORM_LIB_EXT,
filename, filename);
smcore.gamesuffix);
/* Try the "normal" version */ /* Try the "normal" version */
if (!libsys->IsPathFile(path)) if (!g_LibSys.IsPathFile(path))
{ {
normal: normal:
g_pSM->BuildPath(Path_SM, g_SourceMod.BuildPath(Path_SM,
path, path,
PLATFORM_MAX_PATH, PLATFORM_MAX_PATH,
"extensions/%s." PLATFORM_LIB_EXT, "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) 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) if (m_pLib == NULL)
{ {
@@ -190,10 +220,24 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
/* Load as MM:S */ /* Load as MM:S */
if (m_pAPI->IsMetamodExtension()) if (m_pAPI->IsMetamodExtension())
{ {
bool ok; bool already;
m_PlId = smcore.LoadMMSPlugin(m_Path.c_str(), &ok, error, maxlength); 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->CloseLibrary();
m_pLib = NULL; m_pLib = NULL;
@@ -208,7 +252,8 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
{ {
if (m_PlId) if (m_PlId)
{ {
smcore.UnloadMMSPlugin(m_PlId); char dummy[255];
g_pMMPlugins->Unload(m_PlId, true, dummy, sizeof(dummy));
m_PlId = 0; m_PlId = 0;
} }
} }
@@ -229,7 +274,8 @@ void CLocalExtension::Unload()
{ {
if (m_pAPI != NULL && m_PlId) 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; m_PlId = 0;
} }
@@ -292,7 +338,7 @@ bool CExtension::PerformAPICheck(char *error, size_t maxlength)
bool CExtension::Load(char *error, size_t maxlength) bool CExtension::Load(char *error, size_t maxlength)
{ {
CreateIdentity(); 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(); DestroyIdentity();
return false; return false;
@@ -300,7 +346,7 @@ bool CExtension::Load(char *error, size_t maxlength)
else else
{ {
/* Check if we're past load time */ /* Check if we're past load time */
if (!smcore.IsMapLoading()) if (!g_SourceMod.IsMapLoading())
{ {
m_pAPI->OnExtensionsAllLoaded(); m_pAPI->OnExtensionsAllLoaded();
} }
@@ -343,7 +389,7 @@ void CExtension::MarkAllLoaded()
void CExtension::AddPlugin(CPlugin *pPlugin) void CExtension::AddPlugin(CPlugin *pPlugin)
{ {
/* Unfortunately we have to do this :( */ /* 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); m_Dependents.push_back(pPlugin);
} }
@@ -510,15 +556,14 @@ void CExtension::AddLibrary(const char *library)
void CExtensionManager::OnSourceModAllInitialized() void CExtensionManager::OnSourceModAllInitialized()
{ {
g_ExtType = g_ShareSys.CreateIdentType("EXTENSION"); g_ExtType = g_ShareSys.CreateIdentType("EXTENSION");
pluginsys->AddPluginsListener(this); g_PluginSys.AddPluginsListener(this);
rootmenu->AddRootConsoleCommand("exts", "Manage extensions", this); g_RootMenu.AddRootConsoleCommand("exts", "Manage extensions", this);
g_ShareSys.AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
void CExtensionManager::OnSourceModShutdown() void CExtensionManager::OnSourceModShutdown()
{ {
rootmenu->RemoveRootConsoleCommand("exts", this); g_RootMenu.RemoveRootConsoleCommand("exts", this);
pluginsys->RemovePluginsListener(this);
g_ShareSys.DestroyIdentType(g_ExtType); g_ShareSys.DestroyIdentType(g_ExtType);
} }
@@ -536,11 +581,13 @@ void CExtensionManager::TryAutoload()
{ {
char path[PLATFORM_MAX_PATH]; 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) if (!pDir)
{
return; return;
}
const char *lfile; const char *lfile;
size_t len; size_t len;
@@ -567,7 +614,7 @@ void CExtensionManager::TryAutoload()
} }
char file[PLATFORM_MAX_PATH]; 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"); strcpy(&file[len - 9], ".ext");
LoadAutoExtension(file); LoadAutoExtension(file);
@@ -579,11 +626,11 @@ void CExtensionManager::TryAutoload()
IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOnMissing) IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOnMissing)
{ {
/* Remove platform extension if it's there. Compat hack. */ /* 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) if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{ {
char path2[PLATFORM_MAX_PATH]; 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'; path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadAutoExtension(path2, bErrorOnMissing); 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 (!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); p->SetError(error);
} }
@@ -622,7 +669,7 @@ IExtension *CExtensionManager::FindExtensionByFile(const char *file)
/* Chomp off the path */ /* Chomp off the path */
char lookup[PLATFORM_MAX_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++) 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) IExtension *CExtensionManager::LoadExtension(const char *file, char *error, size_t maxlength)
{ {
/* Remove platform extension if it's there. Compat hack. */ /* 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) if (strcmp(ext, PLATFORM_LIB_EXT) == 0)
{ {
char path2[PLATFORM_MAX_PATH]; 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'; path2[strlen(file) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadExtension(path2, error, maxlength); return LoadExtension(path2, error, maxlength);
} }
@@ -737,11 +784,11 @@ void CExtensionManager::AddInterface(IExtension *pOwner, SMInterface *pInterface
pExt->AddInterface(pInterface); pExt->AddInterface(pInterface);
} }
void CExtensionManager::BindChildPlugin(IExtension *pParent, SMPlugin *pPlugin) void CExtensionManager::BindChildPlugin( IExtension *pParent, CPlugin *pPlugin )
{ {
CExtension *pExt = (CExtension *)pParent; CExtension *pExt = (CExtension *)pParent;
pExt->AddPlugin(static_cast<CPlugin *>(pPlugin)); pExt->AddPlugin(pPlugin);
} }
void CExtensionManager::OnPluginDestroyed(IPlugin *plugin) void CExtensionManager::OnPluginDestroyed(IPlugin *plugin)
@@ -750,7 +797,7 @@ void CExtensionManager::OnPluginDestroyed(IPlugin *plugin)
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) 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) bool CExtensionManager::UnloadExtension(IExtension *_pExt)
{ {
if (!_pExt) if (!_pExt)
{
return false; return false;
}
CExtension *pExt = (CExtension *)_pExt; CExtension *pExt = (CExtension *)_pExt;
if (m_Libs.find(pExt) == m_Libs.end()) if (m_Libs.find(pExt) == m_Libs.end())
{
return false; return false;
}
/* Tell it to unload */ /* Tell it to unload */
if (pExt->IsLoaded()) if (pExt->IsLoaded())
pExt->GetAPI()->OnExtensionUnload(); {
IExtensionInterface *pAPI = pExt->GetAPI();
pAPI->OnExtensionUnload();
}
// Remove us from internal lists. Note that because we do this, it's /* First remove us from internal lists */
// 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.
g_ShareSys.RemoveInterfaces(_pExt); g_ShareSys.RemoveInterfaces(_pExt);
m_Libs.remove(pExt); m_Libs.remove(pExt);
@@ -806,7 +857,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
while (p_iter != pExt->m_Dependents.end()) while (p_iter != pExt->m_Dependents.end())
{ {
/* We have to manually unlink ourselves here, since we're no longer being managed */ /* 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); 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 != pExt->m_Libraries.end();
s_iter++) 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 */ /* Notify and/or unload all dependencies */
@@ -826,9 +877,13 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
{ {
pDep = (*c_iter); pDep = (*c_iter);
if ((pAPI=pDep->GetAPI()) == NULL) if ((pAPI=pDep->GetAPI()) == NULL)
{
continue; continue;
}
if (pDep == pExt) if (pDep == pExt)
{
continue; continue;
}
/* Now, get its dependency list */ /* Now, get its dependency list */
bool dropped = false; bool dropped = false;
List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin(); 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()) while (i_iter != pDep->m_ChildDeps.end())
{ {
if ((*i_iter).owner == pExt) if ((*i_iter).owner == pExt)
{
i_iter = pDep->m_ChildDeps.erase(i_iter); i_iter = pDep->m_ChildDeps.erase(i_iter);
}
else else
{
i_iter++; 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(); pExt->Unload();
delete pExt; delete pExt;
@@ -930,10 +984,10 @@ void CExtensionManager::AddDependency(IExtension *pSource, const char *file, boo
void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command) void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
{ {
int argcount = smcore.Argc(command); int argcount = command.ArgC();
if (argcount >= 3) if (argcount >= 3)
{ {
const char *cmd = smcore.Arg(command, 2); const char *cmd = command.Arg(2);
if (strcmp(cmd, "list") == 0) if (strcmp(cmd, "list") == 0)
{ {
List<CExtension *>::iterator iter; List<CExtension *>::iterator iter;
@@ -943,17 +997,17 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{ {
case 1: case 1:
{ {
rootmenu->ConsolePrint("[SM] Displaying 1 extension:"); g_RootMenu.ConsolePrint("[SM] Displaying 1 extension:");
break; break;
} }
case 0: case 0:
{ {
rootmenu->ConsolePrint("[SM] No extensions are loaded."); g_RootMenu.ConsolePrint("[SM] No extensions are loaded.");
break; break;
} }
default: default:
{ {
rootmenu->ConsolePrint("[SM] Displaying %d extensions:", m_Libs.size()); g_RootMenu.ConsolePrint("[SM] Displaying %d extensions:", m_Libs.size());
break; break;
} }
} }
@@ -965,7 +1019,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
char error[255]; char error[255];
if (!pExt->IsRunning(error, sizeof(error))) 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 else
{ {
@@ -973,10 +1027,10 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
const char *name = pAPI->GetExtensionName(); const char *name = pAPI->GetExtensionName();
const char *version = pAPI->GetExtensionVerString(); const char *version = pAPI->GetExtensionVerString();
const char *descr = pAPI->GetExtensionDescription(); 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 { } 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; return;
@@ -985,29 +1039,29 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{ {
if (argcount < 4) if (argcount < 4)
{ {
rootmenu->ConsolePrint("[SM] Usage: sm exts load <file>"); g_RootMenu.ConsolePrint("[SM] Usage: sm exts load <file>");
return; return;
} }
const char *filename = smcore.Arg(command, 3); const char *filename = command.Arg(3);
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
char error[256]; 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 : ""); !strstr(filename, "." PLATFORM_LIB_EXT) ? "." PLATFORM_LIB_EXT : "");
if (FindExtensionByFile(path) != NULL) if (FindExtensionByFile(path) != NULL)
{ {
rootmenu->ConsolePrint("[SM] Extension %s is already loaded.", path); g_RootMenu.ConsolePrint("[SM] Extension %s is already loaded.", path);
return; return;
} }
if (LoadExtension(path, error, sizeof(error))) if (LoadExtension(path, error, sizeof(error)))
{ {
rootmenu->ConsolePrint("[SM] Loaded extension %s successfully.", path); g_RootMenu.ConsolePrint("[SM] Loaded extension %s successfully.", path);
} else } 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; return;
@@ -1016,27 +1070,27 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{ {
if (argcount < 4) if (argcount < 4)
{ {
rootmenu->ConsolePrint("[SM] Usage: sm exts info <#>"); g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
return; return;
} }
const char *sId = smcore.Arg(command, 3); const char *sId = command.Arg(3);
unsigned int id = atoi(sId); unsigned int id = atoi(sId);
if (id <= 0) if (id <= 0)
{ {
rootmenu->ConsolePrint("[SM] Usage: sm exts info <#>"); g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>");
return; return;
} }
if (m_Libs.size() == 0) if (m_Libs.size() == 0)
{ {
rootmenu->ConsolePrint("[SM] No extensions are loaded."); g_RootMenu.ConsolePrint("[SM] No extensions are loaded.");
return; return;
} }
if (id > m_Libs.size()) 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; return;
} }
@@ -1054,44 +1108,44 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
/* This should never happen */ /* This should never happen */
if (!pExt) 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; return;
} }
if (!pExt->IsLoaded()) if (!pExt->IsLoaded())
{ {
rootmenu->ConsolePrint(" File: %s", pExt->GetFilename()); g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename());
rootmenu->ConsolePrint(" Loaded: No (%s)", pExt->m_Error.c_str()); g_RootMenu.ConsolePrint(" Loaded: No (%s)", pExt->m_Error.c_str());
} }
else else
{ {
char error[255]; char error[255];
if (!pExt->IsRunning(error, sizeof(error))) if (!pExt->IsRunning(error, sizeof(error)))
{ {
rootmenu->ConsolePrint(" File: %s", pExt->GetFilename()); g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename());
rootmenu->ConsolePrint(" Loaded: Yes"); g_RootMenu.ConsolePrint(" Loaded: Yes");
rootmenu->ConsolePrint(" Running: No (%s)", error); g_RootMenu.ConsolePrint(" Running: No (%s)", error);
} }
else else
{ {
IExtensionInterface *pAPI = pExt->GetAPI(); IExtensionInterface *pAPI = pExt->GetAPI();
rootmenu->ConsolePrint(" File: %s", pExt->GetFilename()); g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename());
rootmenu->ConsolePrint(" Loaded: Yes (version %s)", pAPI->GetExtensionVerString()); g_RootMenu.ConsolePrint(" Loaded: Yes (version %s)", pAPI->GetExtensionVerString());
rootmenu->ConsolePrint(" Name: %s (%s)", pAPI->GetExtensionName(), pAPI->GetExtensionDescription()); g_RootMenu.ConsolePrint(" Name: %s (%s)", pAPI->GetExtensionName(), pAPI->GetExtensionDescription());
rootmenu->ConsolePrint(" Author: %s (%s)", pAPI->GetExtensionAuthor(), pAPI->GetExtensionURL()); g_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(" Binary info: API version %d (compiled %s)", pAPI->GetExtensionVersion(), pAPI->GetExtensionDateString());
if (pExt->IsExternal()) 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()) 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 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) if (argcount < 4)
{ {
rootmenu->ConsolePrint("[SM] Usage: sm exts unload <#> [code]"); g_RootMenu.ConsolePrint("[SM] Usage: sm exts unload <#> [code]");
return; return;
} }
const char *arg = smcore.Arg(command, 3); const char *arg = command.Arg(3);
unsigned int num = atoi(arg); unsigned int num = atoi(arg);
CExtension *pExt = FindByOrder(num); CExtension *pExt = FindByOrder(num);
if (!pExt) if (!pExt)
{ {
rootmenu->ConsolePrint("[SM] Extension number %d was not found.", num); g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
return; return;
} }
if (argcount > 4 && pExt->unload_code) 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)) if (pExt->unload_code == (unsigned)atoi(unload))
{ {
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename()); snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
UnloadExtension(pExt); UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename); g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
} }
else 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; return;
} }
@@ -1138,7 +1192,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
char filename[PLATFORM_MAX_PATH]; char filename[PLATFORM_MAX_PATH];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename()); snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
UnloadExtension(pExt); UnloadExtension(pExt);
rootmenu->ConsolePrint("[SM] Extension %s is now unloaded.", filename); g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
return; return;
} }
else else
@@ -1146,7 +1200,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
List<CPlugin *> plugins; List<CPlugin *> plugins;
if (pExt->m_ChildDeps.size()) 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; List<CExtension *>::iterator iter;
CExtension *pOther; CExtension *pOther;
/* Get list of all extensions */ /* Get list of all extensions */
@@ -1171,7 +1225,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
/* Will our dependent care? */ /* Will our dependent care? */
if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface)) if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface))
{ {
rootmenu->ConsolePrint(" -> %s", pExt->GetFilename()); g_RootMenu.ConsolePrint(" -> %s", pExt->GetFilename());
/* Add to plugin unload list */ /* Add to plugin unload list */
List<CPlugin *>::iterator p_iter; List<CPlugin *>::iterator p_iter;
for (p_iter=pOther->m_Dependents.begin(); for (p_iter=pOther->m_Dependents.begin();
@@ -1189,7 +1243,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
} }
if (pExt->m_Dependents.size()) 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; List<CPlugin *>::iterator iter;
CPlugin *pPlugin; CPlugin *pPlugin;
for (iter = pExt->m_Dependents.begin(); iter != pExt->m_Dependents.end(); iter++) 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++) for (iter = plugins.begin(); iter != plugins.end(); iter++)
{ {
pPlugin = (*iter); pPlugin = (*iter);
rootmenu->ConsolePrint(" -> %s", pPlugin->GetFilename()); g_RootMenu.ConsolePrint(" -> %s", pPlugin->GetFilename());
} }
} }
srand(static_cast<int>(time(NULL))); srand(static_cast<int>(time(NULL)));
pExt->unload_code = (rand() % 877) + 123; //123 to 999 pExt->unload_code = (rand() % 877) + 123; //123 to 999
rootmenu->ConsolePrint("[SM] To verify unloading %s, please use the following: ", pExt->GetFilename()); g_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] sm exts unload %d %d", num, pExt->unload_code);
return; return;
} }
@@ -1218,17 +1272,17 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{ {
if (argcount < 4) if (argcount < 4)
{ {
rootmenu->ConsolePrint("[SM] Usage: sm exts reload <#>"); g_RootMenu.ConsolePrint("[SM] Usage: sm exts reload <#>");
return; return;
} }
const char *arg = smcore.Arg(command, 3); const char *arg = command.Arg(3);
unsigned int num = atoi(arg); unsigned int num = atoi(arg);
CExtension *pExt = FindByOrder(num); CExtension *pExt = FindByOrder(num);
if (!pExt) if (!pExt)
{ {
rootmenu->ConsolePrint("[SM] Extension number %d was not found.", num); g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
return; return;
} }
@@ -1241,18 +1295,18 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
if (pExt->Reload(error, sizeof(error))) 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 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; return;
} }
else else
{ {
rootmenu->ConsolePrint("[SM] Extension %s is not loaded.", pExt->GetFilename()); g_RootMenu.ConsolePrint("[SM] Extension %s is not loaded.", pExt->GetFilename());
return; return;
} }
@@ -1260,12 +1314,100 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
} }
} }
rootmenu->ConsolePrint("SourceMod Extensions Menu:"); g_RootMenu.ConsolePrint("SourceMod Extensions Menu:");
rootmenu->DrawGenericOption("info", "Extra extension information"); g_RootMenu.DrawGenericOption("info", "Extra extension information");
rootmenu->DrawGenericOption("list", "List extensions"); g_RootMenu.DrawGenericOption("list", "List extensions");
rootmenu->DrawGenericOption("load", "Load an extension"); g_RootMenu.DrawGenericOption("load", "Load an extension");
rootmenu->DrawGenericOption("reload", "Reload an extension"); g_RootMenu.DrawGenericOption("reload", "Reload an extension");
rootmenu->DrawGenericOption("unload", "Unload 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) CExtension *CExtensionManager::GetExtensionFromIdent(IdentityToken_t *ptr)
@@ -1290,7 +1432,7 @@ void CExtensionManager::AddLibrary(IExtension *pSource, const char *library)
{ {
CExtension *pExt = (CExtension *)pSource; CExtension *pExt = (CExtension *)pSource;
pExt->AddLibrary(library); pExt->AddLibrary(library);
scripts->OnLibraryAction(library, LibraryAction_Added); g_PluginSys.OnLibraryAction(library, LibraryAction_Added);
} }
bool CExtensionManager::LibraryExists(const char *library) 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) bool CLocalExtension::IsSameFile(const char *file)
{ {
/* Only care about the shortened name. */ /* Only care about the shortened name. */
@@ -36,11 +36,14 @@
#include <ILibrarySys.h> #include <ILibrarySys.h>
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.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 <IPluginSys.h>
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include "PluginSys.h"
#include "NativeOwner.h" #include "NativeOwner.h"
#include "ShareSys.h"
class CPlayer; class CPlayer;
@@ -117,7 +120,7 @@ public:
bool IsExternal(); bool IsExternal();
bool IsSameFile(const char *file); bool IsSameFile(const char *file);
private: private:
int m_PlId; PluginId m_PlId;
ILibrary *m_pLib; ILibrary *m_pLib;
}; };
@@ -135,7 +138,7 @@ public:
}; };
class CExtensionManager : class CExtensionManager :
public IExtensionSys, public IExtensionManager,
public SMGlobalClass, public SMGlobalClass,
public IPluginsListener, public IPluginsListener,
public IRootConsoleCommand public IRootConsoleCommand
@@ -166,17 +169,16 @@ public:
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true); IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true);
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo); void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
void AddInterface(IExtension *pOwner, SMInterface *pInterface); void AddInterface(IExtension *pOwner, SMInterface *pInterface);
void BindChildPlugin(IExtension *pParent, SMPlugin *pPlugin); void BindChildPlugin(IExtension *pParent, CPlugin *pPlugin);
void MarkAllLoaded(); void MarkAllLoaded();
void AddDependency(IExtension *pSource, const char *file, bool required, bool autoload); void AddDependency(IExtension *pSource, const char *file, bool required, bool autoload);
void TryAutoload(); void TryAutoload();
void AddLibrary(IExtension *pSource, const char *library); void AddLibrary(IExtension *pSource, const char *library);
bool LibraryExists(const char *library); bool LibraryExists(const char *library);
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax); void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
void CallOnCoreMapEnd();
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface); void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
const CVector<IExtension *> *ListExtensions(); public:
void FreeExtensionList(const CVector<IExtension *> *list); void ListExtensionsToClient(CPlayer *player, const CCommand &args);
public: public:
CExtension *GetExtensionFromIdent(IdentityToken_t *ptr); CExtension *GetExtensionFromIdent(IdentityToken_t *ptr);
void Shutdown(); void Shutdown();
@@ -33,8 +33,9 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include "ForwardSys.h" #include "ForwardSys.h"
#include "PluginSys.h"
#include "ShareSys.h"
#include "DebugReporter.h" #include "DebugReporter.h"
#include "common_logic.h"
CForwardManager g_Forwards; CForwardManager g_Forwards;
@@ -62,8 +63,8 @@ CForwardManager::~CForwardManager()
void CForwardManager::OnSourceModAllInitialized() void CForwardManager::OnSourceModAllInitialized()
{ {
scripts->AddPluginsListener(this); g_PluginSys.AddPluginsListener(this);
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...) 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) if (fwd)
{ {
scripts->AddFunctionsToForward(name, fwd); g_PluginSys.AddFunctionsToForward(name, fwd);
m_managed.push_back(fwd); m_managed.push_back(fwd);
} }
@@ -210,23 +211,7 @@ CForward *CForwardManager::ForwardMake()
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused) void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
{ {
if(paused) /* No longer used */
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);
}
}
} }
/************************************* /*************************************
@@ -699,7 +684,7 @@ bool CForward::RemoveFunction(IPluginFunction *func)
lst = &m_paused; lst = &m_paused;
} }
for (iter=lst->begin(); iter!=lst->end(); iter++) for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
{ {
if ((*iter) == func) if ((*iter) == func)
{ {
@@ -757,28 +742,6 @@ bool CForward::AddFunction(IPluginFunction *func)
return true; 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() const char *CForward::GetForwardName()
{ {
return m_name; return m_name;
+25 -3
View File
@@ -34,10 +34,10 @@
#include <IForwardSys.h> #include <IForwardSys.h>
#include <IPluginSys.h> #include <IPluginSys.h>
#include "common_logic.h" #include "sm_globals.h"
#include <sh_list.h> #include <sh_list.h>
#include <sh_stack.h> #include <sh_stack.h>
#include "ISourceMod.h" #include "sourcemod.h"
using namespace SourceHook; 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 */ /* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */
#define FORWARDS_NAME_MAX 64 #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 class FuncIteratorGuard
{ {
bool triggered; bool triggered;
@@ -118,7 +141,6 @@ public:
unsigned int num_params, unsigned int num_params,
const ParamType *types, const ParamType *types,
va_list ap); va_list ap);
bool IsFunctionRegistered(IPluginFunction *func);
private: private:
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags); 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); 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -42,24 +42,21 @@
#include "logic_bridge.h" #include "logic_bridge.h"
#include <tier0/mem.h> #include <tier0/mem.h>
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
#include <game/shared/protobuf/usermessages.pb.h>
#elif SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessages.pb.h> #include <cstrike15_usermessages.pb.h>
#endif #endif
typedef ICommandLine *(*FakeGetCommandLine)(); typedef ICommandLine *(*FakeGetCommandLine)();
#if defined _WIN32 #if defined _WIN32
#define TIER0_NAME "tier0.dll" #define TIER0_NAME "tier0.dll"
#define VSTDLIB_NAME "vstdlib.dll" #define VSTDLIB_NAME "vstdlib.dll"
#elif defined __APPLE__ #elif defined __APPLE__
#define TIER0_NAME "libtier0.dylib" #define TIER0_NAME "libtier0.dylib"
#define VSTDLIB_NAME "libvstdlib.dylib" #define VSTDLIB_NAME "libvstdlib.dylib"
#elif defined __linux__ #elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \ #if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_LEFT4DEAD2
|| SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_LEFT4DEAD2 || SOURCE_ENGINE == SE_NUCLEARDAWN
#define TIER0_NAME "libtier0_srv.so" #define TIER0_NAME "libtier0_srv.so"
#define VSTDLIB_NAME "libvstdlib_srv.so" #define VSTDLIB_NAME "libvstdlib_srv.so"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD #elif SOURCE_ENGINE >= SE_LEFT4DEAD
@@ -68,7 +65,7 @@ typedef ICommandLine *(*FakeGetCommandLine)();
#else #else
#define TIER0_NAME "tier0_i486.so" #define TIER0_NAME "tier0_i486.so"
#define VSTDLIB_NAME "vstdlib_i486.so" #define VSTDLIB_NAME "vstdlib_i486.so"
#endif #endif
#endif #endif
CHalfLife2 g_HL2; CHalfLife2 g_HL2;
@@ -92,20 +89,51 @@ static CEntInfo *EntInfoArray()
return NULL; 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() CHalfLife2::CHalfLife2()
{ {
m_Maps.init(); m_pClasses = sm_trie_create();
m_pGetCommandLine = NULL;
} }
CHalfLife2::~CHalfLife2() CHalfLife2::~CHalfLife2()
{ {
for (NameHashSet<DataTableInfo *>::iterator iter = m_Classes.iter(); !iter.empty(); iter.next()) sm_trie_destroy(m_pClasses);
delete *iter;
for (DataTableMap::iterator iter = m_Maps.iter(); !iter.empty(); iter.next()) List<DataTableInfo *>::iterator iter;
delete iter->value; 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 #if SOURCE_ENGINE != SE_DARKMESSIAH
@@ -142,7 +170,7 @@ void CHalfLife2::OnSourceModAllInitialized()
m_HinTextMsg = g_UserMsgs.GetMessageIndex("HintText"); m_HinTextMsg = g_UserMsgs.GetMessageIndex("HintText");
m_SayTextMsg = g_UserMsgs.GetMessageIndex("SayText"); m_SayTextMsg = g_UserMsgs.GetMessageIndex("SayText");
m_VGUIMenu = g_UserMsgs.GetMessageIndex("VGUIMenu"); m_VGUIMenu = g_UserMsgs.GetMessageIndex("VGUIMenu");
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
void CHalfLife2::OnSourceModAllInitialized_Post() void CHalfLife2::OnSourceModAllInitialized_Post()
@@ -153,18 +181,6 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
void CHalfLife2::InitLogicalEntData() 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; char *addr = NULL;
/* /*
@@ -174,24 +190,21 @@ void CHalfLife2::InitLogicalEntData()
* If symbols aren't present (Windows or stripped Linux/Mac), * If symbols aren't present (Windows or stripped Linux/Mac),
* attempt find via LevelShutdown + offset * 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 // Key exists so notify if lookup fails, but try other method.
if (!addr) g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
{
// 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
} }
else
{
#endif
g_EntList = reinterpret_cast<void *>(addr);
#if !defined PLATFORM_WINDOWS
}
#endif
} }
if (!g_EntList) if (!g_EntList)
@@ -201,7 +214,7 @@ void CHalfLife2::InitLogicalEntData()
int offset; int offset;
if (!g_pGameConf->GetOffset("gEntList", &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; 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 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)) 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; g_EntList = NULL;
return; return;
} }
@@ -226,48 +239,58 @@ void CHalfLife2::InitLogicalEntData()
if (!g_EntList && !g_pEntInfoList) 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; return;
} }
} }
void CHalfLife2::InitCommandLine() void CHalfLife2::InitCommandLine()
{ {
char path[PLATFORM_MAX_PATH];
char error[256]; 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 #if SOURCE_ENGINE != SE_DARKMESSIAH
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
{ {
#if SOURCE_ENGINE == SE_DOTA
return engine->GetChangeAccessor( IndexOfEdict((const edict_t *)this) );
#else
return engine->GetChangeAccessor( (const edict_t *)this ); return engine->GetChangeAccessor( (const edict_t *)this );
#endif
} }
#endif #endif
@@ -332,11 +351,16 @@ bool UTIL_FindInSendTable(SendTable *pTable,
return false; 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) while (pMap)
{ {
for (int i = 0; i < pMap->dataNumFields; ++i) for (int i=0; i<pMap->dataNumFields; i++)
{ {
if (pMap->dataDesc[i].fieldName == NULL) 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) if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
{ {
pDataTable->prop = &(pMap->dataDesc[i]); return &(pMap->dataDesc[i]);
pDataTable->actual_offset = GetTypeDescOffs(pDataTable->prop);
return true;
} }
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; pMap = pMap->baseMap;
} }
return false; return NULL;
} }
ServerClass *CHalfLife2::FindServerClass(const char *classname) ServerClass *CHalfLife2::FindServerClass(const char *classname)
@@ -368,7 +401,9 @@ ServerClass *CHalfLife2::FindServerClass(const char *classname)
DataTableInfo *pInfo = _FindServerClass(classname); DataTableInfo *pInfo = _FindServerClass(classname);
if (!pInfo) if (!pInfo)
{
return NULL; return NULL;
}
return pInfo->sc; return pInfo->sc;
} }
@@ -376,21 +411,26 @@ ServerClass *CHalfLife2::FindServerClass(const char *classname)
DataTableInfo *CHalfLife2::_FindServerClass(const char *classname) DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
{ {
DataTableInfo *pInfo = NULL; DataTableInfo *pInfo = NULL;
if (!m_Classes.retrieve(classname, &pInfo))
if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
{ {
ServerClass *sc = gamedll->GetAllServerClasses(); ServerClass *sc = gamedll->GetAllServerClasses();
while (sc) while (sc)
{ {
if (strcmp(classname, sc->GetName()) == 0) if (strcmp(classname, sc->GetName()) == 0)
{ {
pInfo = new DataTableInfo(sc); pInfo = new DataTableInfo;
m_Classes.insert(classname, pInfo); pInfo->sc = sc;
sm_trie_insert(m_pClasses, classname, pInfo);
m_Tables.push_back(pInfo);
break; break;
} }
sc = sc->m_pNext; sc = sc->m_pNext;
} }
if (!pInfo) if (!pInfo)
{
return NULL; return NULL;
}
} }
return pInfo; 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) bool CHalfLife2::FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info)
{ {
DataTableInfo *pInfo; DataTableInfo *pInfo;
sm_sendprop_info_t *prop;
if ((pInfo = _FindServerClass(classname)) == NULL) if ((pInfo = _FindServerClass(classname)) == NULL)
{ {
return false; return false;
} }
if (!pInfo->lookup.retrieve(offset, info)) if ((prop = pInfo->lookup.retrieve(offset)) == NULL)
{ {
sm_sendprop_info_t temp_info; 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); pInfo->lookup.insert(offset, temp_info);
*info = temp_info; *info = temp_info;
} }
else
{
*info = *prop;
}
return true; 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) typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
{ {
sm_datatable_info_t dt_info; return this->FindInDataMap(pMap, offset, NULL);
if (!(this->FindDataMapInfo(pMap, offset, &dt_info)))
{
return NULL;
}
return dt_info.prop;
} }
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); typedescription_t *td = NULL;
if (!i.found()) DataMapTrie &val = m_Maps[pMap];
m_Maps.add(i, pMap, new DataMapCache());
DataMapCache *cache = i->value; if (!val.trie)
if (!cache->retrieve(offset, pDataTable))
{ {
if (!UTIL_FindDataMapInfo(pMap, offset, pDataTable)) val.trie = sm_trie_create();
return false; }
cache->insert(offset, *pDataTable); 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) 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) bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
{ {
#ifndef USE_PROTOBUF_USERMESSAGES #if SOURCE_ENGINE != SE_CSGO
bf_write *pBitBuf = NULL; bf_write *pBitBuf = NULL;
#endif #endif
cell_t players[] = {client}; cell_t players[] = {client};
@@ -501,17 +541,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
char buffer[192]; char buffer[192];
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg); UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
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
CCSUsrMsg_SayText *pMsg; CCSUsrMsg_SayText *pMsg;
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL) 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 #if SOURCE_ENGINE == SE_CSGO
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
CCSUsrMsg_TextMsg *pMsg; CCSUsrMsg_TextMsg *pMsg;
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL) 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}; cell_t players[] = {client};
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
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
CCSUsrMsg_HintText *pMsg; CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL) 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) bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
{ {
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
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
CCSUsrMsg_HintText *pMsg; CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL) 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; int count = 0;
cell_t players[] = {client}; cell_t players[] = {client};
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
CUserMsg_VGUIMenu *pMsg;
if ((pMsg = (CUserMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
#elif SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_VGUIMenu *pMsg; CCSUsrMsg_VGUIMenu *pMsg;
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL) 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(); SubKey = data->GetFirstSubKey();
} }
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
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
pMsg->set_name(name); pMsg->set_name(name);
pMsg->set_show(show); pMsg->set_show(show);
@@ -759,11 +747,7 @@ void CHalfLife2::ProcessFakeCliCmdQueue()
if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client) if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
{ {
CPlayer *pPlayer = g_Players.GetPlayerByIndex(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()); serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
#endif
} }
m_CmdQueue.pop(); m_CmdQueue.pop();
@@ -1185,22 +1169,9 @@ const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity)
static int offset = -1; static int offset = -1;
if (offset == -1) if (offset == -1)
{ {
CBaseEntity *pGetterEnt = ReferenceToEntity(0); datamap_t *pMap = GetDataMap(pEntity);
if (pGetterEnt == NULL) typedescription_t *pDesc = FindInDataMap(pMap, "m_iClassname");
{ offset = GetTypeDescOffs(pDesc);
// 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;
} }
return *(const char **)(((unsigned char *)pEntity) + offset); 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -35,10 +35,8 @@
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.h> #include <sh_string.h>
#include <sh_tinyhash.h> #include <sh_tinyhash.h>
#include <am-utility.h> #include <sm_trie_tpl.h>
#include <am-hashmap.h> #include "sm_trie.h"
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
#include "sm_globals.h" #include "sm_globals.h"
#include "sm_queue.h" #include "sm_queue.h"
#include <IGameHelpers.h> #include <IGameHelpers.h>
@@ -61,38 +59,16 @@ using namespace SourceMod;
struct DataTableInfo struct DataTableInfo
{ {
struct SendPropPolicy
{
static inline bool matches(const char *name, const sm_sendprop_info_t &info)
{
return strcmp(name, info.prop->GetName()) == 0;
}
};
static inline bool matches(const char *name, const DataTableInfo *info)
{
return strcmp(name, info->sc->GetName()) == 0;
}
DataTableInfo(ServerClass *sc)
: sc(sc)
{
}
ServerClass *sc; ServerClass *sc;
NameHashSet<sm_sendprop_info_t, SendPropPolicy> lookup; KTrie<sm_sendprop_info_t> lookup;
}; };
struct DataMapCachePolicy struct DataMapTrie
{ {
static inline bool matches(const char *name, const sm_datatable_info_t &info) DataMapTrie() : trie(NULL) {}
{ Trie *trie;
return strcmp(name, info.prop->fieldName) == 0;
}
}; };
typedef NameHashSet<sm_datatable_info_t, DataMapCachePolicy> DataMapCache;
struct DelayedFakeCliCmd struct DelayedFakeCliCmd
{ {
String cmd; String cmd;
@@ -123,7 +99,7 @@ public:
int m_SerialNumber; int m_SerialNumber;
CEntInfo *m_pPrev; CEntInfo *m_pPrev;
CEntInfo *m_pNext; CEntInfo *m_pNext;
#if (SOURCE_ENGINE >= SE_PORTAL2) && (SOURCE_ENGINE != SE_DOTA) #if SOURCE_ENGINE >= SE_PORTAL2
string_t m_iName; string_t m_iName;
string_t m_iClassName; string_t m_iClassName;
#endif #endif
@@ -147,7 +123,7 @@ public: //IGameHelpers
datamap_t *GetDataMap(CBaseEntity *pEntity); datamap_t *GetDataMap(CBaseEntity *pEntity);
ServerClass *FindServerClass(const char *classname); ServerClass *FindServerClass(const char *classname);
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset); typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable); typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested);
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset); void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
bool TextMsg(int client, int dest, const char *msg); bool TextMsg(int client, int dest, const char *msg);
bool HintTextMsg(int client, const char *msg); bool HintTextMsg(int client, const char *msg);
@@ -193,10 +169,9 @@ private:
void InitLogicalEntData(); void InitLogicalEntData();
void InitCommandLine(); void InitCommandLine();
private: private:
typedef ke::HashMap<datamap_t *, DataMapCache *, ke::PointerPolicy<datamap_t> > DataTableMap; Trie *m_pClasses;
List<DataTableInfo *> m_Tables;
NameHashSet<DataTableInfo *> m_Classes; THash<datamap_t *, DataMapTrie> m_Maps;
DataTableMap m_Maps;
int m_MsgTextMsg; int m_MsgTextMsg;
int m_HinTextMsg; int m_HinTextMsg;
int m_SayTextMsg; 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,12 +30,13 @@
*/ */
#include "HandleSys.h" #include "HandleSys.h"
#include "ShareSys.h"
#include "PluginSys.h"
#include "ExtensionSys.h"
#include "Logger.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "common_logic.h" #include "sm_stringutil.h"
#include "ShareSys.h"
#include "ExtensionSys.h"
#include "PluginSys.h"
HandleSystem g_HandleSys; HandleSystem g_HandleSys;
@@ -59,6 +60,9 @@ HandleSystem::HandleSystem()
m_Types = new QHandleType[HANDLESYS_TYPEARRAY_SIZE]; m_Types = new QHandleType[HANDLESYS_TYPEARRAY_SIZE];
memset(m_Types, 0, sizeof(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; m_TypeTail = 0;
} }
@@ -66,6 +70,8 @@ HandleSystem::~HandleSystem()
{ {
delete [] m_Handles; delete [] m_Handles;
delete [] m_Types; 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 (name && name[0] != '\0')
{ {
if (m_TypeLookup.contains(name)) if (sm_trie_retrieve(m_TypeLookup, name, NULL))
{ {
if (err) if (err)
{
*err = HandleError_Parameter; *err = HandleError_Parameter;
}
return 0; return 0;
} }
} }
@@ -204,8 +212,10 @@ HandleType_t HandleSystem::CreateType(const char *name,
pType->dispatch = dispatch; pType->dispatch = dispatch;
if (name && name[0] != '\0') if (name && name[0] != '\0')
{ {
pType->name = new ke::AString(name); pType->nameIdx = m_strtab->AddString(name);
m_TypeLookup.insert(name, pType); sm_trie_insert(m_TypeLookup, name, (void *)pType);
} else {
pType->nameIdx = -1;
} }
pType->opened = 0; pType->opened = 0;
@@ -233,14 +243,21 @@ HandleType_t HandleSystem::CreateType(const char *name,
return index; return index;
} }
bool HandleSystem::FindHandleType(const char *name, HandleType_t *aResult) bool HandleSystem::FindHandleType(const char *name, HandleType_t *type)
{ {
QHandleType *type; QHandleType *_type;
if (!m_TypeLookup.retrieve(name, &type))
return false;
if (aResult) if (!sm_trie_retrieve(m_TypeLookup, name, (void **)&_type))
*aResult = type - m_Types; {
return false;
}
unsigned int offset = _type - m_Types;
if (type)
{
*type = offset;
}
return true; return true;
} }
@@ -643,13 +660,13 @@ void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigne
HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index) HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
{ {
if (pHandle->is_destroying) if (pHandle->is_destroying)
{ {
/* Someone tried to free this recursively. /* Someone tried to free this recursively.
* We'll just ignore this safely. * We'll just ignore this safely.
*/ */
return HandleError_None; return HandleError_None;
} }
QHandleType *pType = &m_Types[pHandle->type]; 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... */ /* Type should be the same but do this anyway... */
pType = &m_Types[pMaster->type]; pType = &m_Types[pMaster->type];
pMaster->is_destroying = true; pMaster->is_destroying = true;
if (pMaster->object) if (pMaster->object)
{ {
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object); pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
} }
ReleasePrimHandle(master); ReleasePrimHandle(master);
} }
@@ -691,9 +708,9 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
if (--pHandle->refcount == 0) if (--pHandle->refcount == 0)
{ {
pHandle->is_destroying = true; pHandle->is_destroying = true;
if (pHandle->object) if (pHandle->object)
{ {
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object); pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
} }
ReleasePrimHandle(index); ReleasePrimHandle(index);
} else { } else {
@@ -897,6 +914,10 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
m_Types[++m_FreeTypes].freeID = type; m_Types[++m_FreeTypes].freeID = type;
} }
/* Invalidate the type now */
IHandleTypeDispatch *dispatch = pType->dispatch;
pType->dispatch = NULL;
/* Make sure nothing is using this type. */ /* Make sure nothing is using this type. */
if (pType->opened) 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. */ /* Remove it from the type cache. */
if (pType->name) if (pType->nameIdx != -1)
m_TypeLookup.remove(pType->name->chars()); {
const char *typeName;
typeName = m_strtab->GetString(pType->nameIdx);
sm_trie_delete(m_TypeLookup, typeName);
}
return true; return true;
} }
@@ -957,8 +980,8 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
} }
#define HANDLE_LOG_VERY_BAD(message, ...) \ #define HANDLE_LOG_VERY_BAD(message, ...) \
logger->LogFatal(message, ##__VA_ARGS__); \ g_Logger.LogFatal(message, ##__VA_ARGS__); \
logger->LogError(message, ##__VA_ARGS__); g_Logger.LogError(message, ##__VA_ARGS__);
bool HandleSystem::TryAndFreeSomeHandles() 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] 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] 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("[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"); 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) void HandleSystem::Dump(HANDLE_REPORTER rep)
@@ -1086,20 +1056,20 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
{ {
owner = "CORE"; owner = "CORE";
} }
else if (pOwner == scripts->GetIdentity()) else if (pOwner == g_PluginSys.GetIdentity())
{ {
owner = "PLUGINSYS"; owner = "PLUGINSYS";
} }
else else
{ {
IExtension *ext = g_Extensions.GetExtensionFromIdent(pOwner); CExtension *ext = g_Extensions.GetExtensionFromIdent(pOwner);
if (ext) if (ext)
{ {
owner = ext->GetFilename(); owner = ext->GetFilename();
} }
else else
{ {
SMPlugin *pPlugin = scripts->FindPluginByIdentity(pOwner); CPlugin *pPlugin = g_PluginSys.GetPluginFromIdentity(pOwner);
if (pPlugin) if (pPlugin)
{ {
owner = pPlugin->GetFilename(); owner = pPlugin->GetFilename();
@@ -1116,24 +1086,26 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
unsigned int size = 0; unsigned int size = 0;
unsigned int parentIdx; unsigned int parentIdx;
bool bresult; bool bresult;
if (pType->name) if (pType->nameIdx != -1)
type = pType->name->chars();
if ((parentIdx = m_Handles[i].clone) != 0)
{ {
if (m_Handles[parentIdx].refcount > 0) type = m_strtab->GetString(pType->nameIdx);
{
size = 0;
bresult = true;
}
else
{
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[parentIdx].type, m_Handles[parentIdx].object, &size);
}
} }
else
{ if ((parentIdx = m_Handles[i].clone) != 0)
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size); {
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 if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
@@ -1144,7 +1116,7 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
else else
{ {
char buffer[32]; 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); rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, buffer);
total_size += size; 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,11 +34,12 @@
#include <IHandleSys.h> #include <IHandleSys.h>
#include <stdio.h> #include <stdio.h>
#include <sm_namehashset.h> #include "sm_globals.h"
#include <am-string.h> #include "sm_trie.h"
#include "common_logic.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_TYPES (1<<9)
#define HANDLESYS_MAX_SUBTYPES 0xF #define HANDLESYS_MAX_SUBTYPES 0xF
#define HANDLESYS_SUBTYPE_MASK 0xF #define HANDLESYS_SUBTYPE_MASK 0xF
@@ -103,12 +104,7 @@ struct QHandleType
TypeAccess typeSec; TypeAccess typeSec;
HandleAccess hndlSec; HandleAccess hndlSec;
unsigned int opened; unsigned int opened;
ke::AutoPtr<ke::AString> name; int nameIdx;
static inline bool matches(const char *key, const QHandleType *type)
{
return type->name && type->name->compare(key) == 0;
}
}; };
typedef void (HANDLE_REPORTER)(const char *str, ...); typedef void (HANDLE_REPORTER)(const char *str, ...);
@@ -221,12 +217,13 @@ protected:
private: private:
QHandle *m_Handles; QHandle *m_Handles;
QHandleType *m_Types; QHandleType *m_Types;
NameHashSet<QHandleType *> m_TypeLookup; Trie *m_TypeLookup;
unsigned int m_TypeTail; unsigned int m_TypeTail;
unsigned int m_FreeTypes; unsigned int m_FreeTypes;
unsigned int m_HandleTail; unsigned int m_HandleTail;
unsigned int m_FreeHandles; unsigned int m_FreeHandles;
unsigned int m_HSerial; unsigned int m_HSerial;
BaseStringTable *m_strtab;
}; };
extern HandleSystem g_HandleSys; extern HandleSystem g_HandleSys;
+511 -25
View File
@@ -36,35 +36,521 @@
#include "Logger.h" #include "Logger.h"
#include "LibrarySys.h" #include "LibrarySys.h"
#include "TimerSys.h" #include "TimerSys.h"
#include "logic_bridge.h"
#include <sourcemod_version.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; 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) void Engine_LogPrintWrapper(const char *msg)
{ {
if (g_in_game_log_hook) if (g_in_game_log_hook)
+61 -1
View File
@@ -38,13 +38,73 @@
using namespace SourceHook; 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 public: //SMGlobalClass
ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength);
void OnSourceModStartup(bool late); void OnSourceModStartup(bool late);
void OnSourceModAllShutdown(); 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); void Engine_LogPrintWrapper(const char *msg);
extern bool g_in_game_log_hook;
extern Logger g_Logger;
#endif // _INCLUDE_SOURCEMOD_CLOGGER_H_ #endif // _INCLUDE_SOURCEMOD_CLOGGER_H_
+12 -10
View File
@@ -38,6 +38,8 @@
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "MenuStyle_Valve.h" #include "MenuStyle_Valve.h"
#include "ShareSys.h"
#include "HandleSys.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "logic_bridge.h" #include "logic_bridge.h"
@@ -54,24 +56,24 @@ MenuManager::MenuManager()
void MenuManager::OnSourceModAllInitialized() void MenuManager::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
HandleAccess access; HandleAccess access;
handlesys->InitAccessDefaults(NULL, &access); g_HandleSys.InitAccessDefaults(NULL, &access);
/* Deny cloning to menus */ /* Deny cloning to menus */
access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY; access.access[HandleAccess_Clone] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
m_MenuType = handlesys->CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL); m_MenuType = g_HandleSys.CreateType("IBaseMenu", this, 0, NULL, &access, g_pCoreIdent, NULL);
/* Also deny deletion to styles */ /* Also deny deletion to styles */
access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY; access.access[HandleAccess_Delete] = HANDLE_RESTRICT_OWNER|HANDLE_RESTRICT_IDENTITY;
m_StyleType = handlesys->CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL); m_StyleType = g_HandleSys.CreateType("IMenuStyle", this, 0, NULL, &access, g_pCoreIdent, NULL);
} }
void MenuManager::OnSourceModAllShutdown() void MenuManager::OnSourceModAllShutdown()
{ {
handlesys->RemoveType(m_MenuType, g_pCoreIdent); g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
handlesys->RemoveType(m_StyleType, g_pCoreIdent); g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
} }
void MenuManager::OnHandleDestroy(HandleType_t type, void *object) void MenuManager::OnHandleDestroy(HandleType_t type, void *object)
@@ -110,7 +112,7 @@ Handle_t MenuManager::CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner)
return BAD_HANDLE; return BAD_HANDLE;
} }
return handlesys->CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL); return g_HandleSys.CreateHandle(m_MenuType, menu, pOwner, g_pCoreIdent, NULL);
} }
Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style) Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
@@ -120,7 +122,7 @@ Handle_t MenuManager::CreateStyleHandle(IMenuStyle *style)
return BAD_HANDLE; return BAD_HANDLE;
} }
return handlesys->CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL); return g_HandleSys.CreateHandle(m_StyleType, style, g_pCoreIdent, g_pCoreIdent, NULL);
} }
HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu) HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
@@ -130,7 +132,7 @@ HandleError MenuManager::ReadMenuHandle(Handle_t handle, IBaseMenu **menu)
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
sec.pOwner = NULL; sec.pOwner = NULL;
return handlesys->ReadHandle(handle, m_MenuType, &sec, (void **)menu); return g_HandleSys.ReadHandle(handle, m_MenuType, &sec, (void **)menu);
} }
HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style) HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
@@ -140,7 +142,7 @@ HandleError MenuManager::ReadStyleHandle(Handle_t handle, IMenuStyle **style)
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
sec.pOwner = g_pCoreIdent; sec.pOwner = g_pCoreIdent;
return handlesys->ReadHandle(handle, m_StyleType, &sec, (void **)style); return g_HandleSys.ReadHandle(handle, m_StyleType, &sec, (void **)style);
} }
bool MenuManager::SetDefaultStyle(IMenuStyle *style) bool MenuManager::SetDefaultStyle(IMenuStyle *style)
+1
View File
@@ -37,6 +37,7 @@
#include <sh_stack.h> #include <sh_stack.h>
#include <sh_list.h> #include <sh_list.h>
#include <sh_string.h> #include <sh_string.h>
#include "sm_memtable.h"
#include "sm_globals.h" #include "sm_globals.h"
using namespace SourceMod; using namespace SourceMod;
+46 -25
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,12 +34,11 @@
#include "MenuStyle_Base.h" #include "MenuStyle_Base.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "MenuManager.h" #include "MenuManager.h"
#include "HandleSys.h"
#include "CellRecipientFilter.h" #include "CellRecipientFilter.h"
#if defined MENU_DEBUG #if defined MENU_DEBUG
#include "Logger.h" #include "Logger.h"
#endif #endif
#include "logic_bridge.h"
#include "AutoHandleRooter.h"
BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE) BaseMenuStyle::BaseMenuStyle() : m_WatchList(256), m_hHandle(BAD_HANDLE)
{ {
@@ -338,7 +337,7 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
#endif #endif
0, 0,
PITCH_NORM, PITCH_NORM,
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2 #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2
0, 0,
#endif #endif
&pos); &pos);
@@ -604,7 +603,7 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
} }
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) : CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
m_pStyle(pStyle), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false), m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_bShouldDelete(false), m_bCancelling(false),
m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false), m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bDeleting(false), m_bWillFreeHandle(false),
m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT) m_hHandle(BAD_HANDLE), m_pHandler(pHandler), m_nFlags(MENUFLAG_BUTTON_EXIT)
{ {
@@ -627,74 +626,94 @@ Handle_t CBaseMenu::GetHandle()
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw) bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
{ {
if (m_Pagination == (unsigned)MENU_NO_PAGINATION if (m_Pagination == (unsigned)MENU_NO_PAGINATION
&& m_items.length() >= m_pStyle->GetMaxPageItems()) && m_items.size() >= m_pStyle->GetMaxPageItems())
{ {
return false; return false;
} }
CItem item; CItem item;
item.info = info; item.infoString = m_Strings.AddString(info);
if (draw.display) if (draw.display)
item.display = new ke::AString(draw.display); {
item.displayString = m_Strings.AddString(draw.display);
}
item.style = draw.style; item.style = draw.style;
m_items.append(ke::Move(item)); m_items.push_back(item);
return true; return true;
} }
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw) bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
{ {
if (m_Pagination == (unsigned)MENU_NO_PAGINATION && if (m_Pagination == (unsigned)MENU_NO_PAGINATION
m_items.length() >= m_pStyle->GetMaxPageItems()) && m_items.size() >= m_pStyle->GetMaxPageItems())
{ {
return false; return false;
} }
if (position >= m_items.length()) if (position >= m_items.size())
{
return false; return false;
}
CItem item; CItem item;
item.info = info; item.infoString = m_Strings.AddString(info);
if (draw.display) if (draw.display)
item.display = new ke::AString(draw.display); {
item.displayString = m_Strings.AddString(draw.display);
}
item.style = draw.style; item.style = draw.style;
m_items.insert(position, ke::Move(item)); CVector<CItem>::iterator iter = m_items.iterAt(position);
m_items.insert(iter, item);
return true; return true;
} }
bool CBaseMenu::RemoveItem(unsigned int position) bool CBaseMenu::RemoveItem(unsigned int position)
{ {
if (position >= m_items.length()) if (position >= m_items.size())
{
return false; return false;
}
m_items.erase(m_items.iterAt(position));
if (m_items.size() == 0)
{
m_Strings.Reset();
}
m_items.remove(position);
return true; return true;
} }
void CBaseMenu::RemoveAllItems() void CBaseMenu::RemoveAllItems()
{ {
m_items.clear(); m_items.clear();
m_Strings.Reset();
} }
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */) const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
{ {
if (position >= m_items.length()) if (position >= m_items.size())
{
return NULL; return NULL;
}
if (draw) if (draw)
{ {
draw->display = m_items[position].display->chars(); draw->display = m_Strings.GetString(m_items[position].displayString);
draw->style = m_items[position].style; draw->style = m_items[position].style;
} }
return m_items[position].info.chars(); return m_Strings.GetString(m_items[position].infoString);
} }
unsigned int CBaseMenu::GetItemCount() unsigned int CBaseMenu::GetItemCount()
{ {
return m_items.length(); return m_items.size();
} }
bool CBaseMenu::SetPagination(unsigned int itemsPerPage) bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
@@ -727,12 +746,12 @@ IMenuStyle *CBaseMenu::GetDrawStyle()
void CBaseMenu::SetDefaultTitle(const char *message) void CBaseMenu::SetDefaultTitle(const char *message)
{ {
m_Title = message; m_Title.assign(message);
} }
const char *CBaseMenu::GetDefaultTitle() const char *CBaseMenu::GetDefaultTitle()
{ {
return m_Title.chars(); return m_Title.c_str();
} }
void CBaseMenu::Cancel() void CBaseMenu::Cancel()
@@ -799,7 +818,7 @@ void CBaseMenu::InternalDelete()
m_hHandle = BAD_HANDLE; m_hHandle = BAD_HANDLE;
m_bDeleting = true; m_bDeleting = true;
handlesys->FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
} }
m_pHandler->OnMenuDestroy(this); m_pHandler->OnMenuDestroy(this);
@@ -824,5 +843,7 @@ IMenuHandler *CBaseMenu::GetHandler()
unsigned int CBaseMenu::GetBaseMemUsage() unsigned int CBaseMenu::GetBaseMemUsage()
{ {
return m_Title.length() + (m_items.length() * sizeof(CItem)); return m_Title.size()
+ m_Strings.GetMemTable()->GetMemUsage()
+ (m_items.size() * sizeof(CItem));
} }
+12 -27
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,45 +34,29 @@
#include <IMenuManager.h> #include <IMenuManager.h>
#include <IPlayerHelpers.h> #include <IPlayerHelpers.h>
#include <am-string.h> #include <sh_string.h>
#include <am-vector.h> #include <sh_vector.h>
#include "sm_memtable.h"
#include "sm_fastlink.h" #include "sm_fastlink.h"
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook;
class CItem class CItem
{ {
public: public:
CItem() CItem()
{ {
infoString = -1;
displayString = -1;
style = 0; style = 0;
access = 0; access = 0;
} }
CItem(ke::Moveable<CItem> other)
: info(ke::Move(other->info)),
display(ke::Move(other->display))
{
style = other->style;
access = other->access;
}
CItem & operator =(ke::Moveable<CItem> other)
{
info = ke::Move(other->info);
display = ke::Move(other->display);
style = other->style;
access = other->access;
return *this;
}
public: public:
ke::AString info; int infoString;
ke::AutoPtr<ke::AString> display; int displayString;
unsigned int style; unsigned int style;
unsigned int access; unsigned int access;
private:
CItem(const CItem &other) KE_DELETE;
CItem &operator =(const CItem &other) KE_DELETE;
}; };
class CBaseMenuPlayer class CBaseMenuPlayer
@@ -155,10 +139,11 @@ public:
private: private:
void InternalDelete(); void InternalDelete();
protected: protected:
ke::AString m_Title; String m_Title;
IMenuStyle *m_pStyle; IMenuStyle *m_pStyle;
BaseStringTable m_Strings;
unsigned int m_Pagination; unsigned int m_Pagination;
ke::Vector<CItem> m_items; CVector<CItem> m_items;
bool m_bShouldDelete; bool m_bShouldDelete;
bool m_bCancelling; bool m_bCancelling;
IdentityToken_t *m_pOwner; IdentityToken_t *m_pOwner;
+13 -17
View File
@@ -83,10 +83,6 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
} }
g_bRadioInit = true; 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"); const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
if (!msg || msg[0] == '\0') if (!msg || msg[0] == '\0')
{ {
@@ -122,6 +118,7 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
} }
} }
g_Menus.AddStyle(this);
g_Menus.SetDefaultStyle(this); g_Menus.SetDefaultStyle(this);
g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false); g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
@@ -141,11 +138,7 @@ void CRadioStyle::OnSourceModShutdown()
bool CRadioStyle::IsSupported() bool CRadioStyle::IsSupported()
{ {
#if SOURCE_ENGINE == SE_DOTA
return false;
#else
return (g_ShowMenuId != -1); return (g_ShowMenuId != -1);
#endif
} }
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd) bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
@@ -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) void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
#endif #endif
{ {
#if SOURCE_ENGINE != SE_DOTA
int count = pFilter->GetRecipientCount(); int count = pFilter->GetRecipientCount();
#ifdef USE_PROTOBUF_USERMESSAGES #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); g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
} }
#endif
} }
void CRadioStyle::OnUserMessageSent(int msg_id) void CRadioStyle::OnUserMessageSent(int msg_id)
@@ -264,6 +255,15 @@ CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
return display; 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) void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
{ {
m_FreeDisplays.push(display); m_FreeDisplays.push(display);
@@ -330,12 +330,11 @@ void CRadioDisplay::Reset()
keys = 0; keys = 0;
} }
bool CRadioDisplay::DirectSet(const char *str) void CRadioDisplay::DirectSet(const char *str, int keymap)
{ {
m_Title.clear(); m_Title.clear();
m_BufferText.assign(str); m_BufferText.assign(str);
keys = keymap;
return true;
} }
unsigned int CRadioDisplay::GetCurrentKey() unsigned int CRadioDisplay::GetCurrentKey()
@@ -474,8 +473,7 @@ void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
void CRadioMenuPlayer::Radio_Refresh() void CRadioMenuPlayer::Radio_Refresh()
{ {
#if SOURCE_ENGINE != SE_DOTA cell_t players[1] = {m_index};
cell_t players[1] = { (cell_t)m_index };
char *ptr = display_pkt; char *ptr = display_pkt;
char save = 0; char save = 0;
size_t len = display_len; size_t len = display_len;
@@ -528,7 +526,6 @@ void CRadioMenuPlayer::Radio_Refresh()
#endif #endif
display_last_refresh = gpGlobals->curtime; display_last_refresh = gpGlobals->curtime;
#endif // !DOTA
} }
int CRadioDisplay::GetAmountRemaining() int CRadioDisplay::GetAmountRemaining()
@@ -596,7 +593,6 @@ bool CRadioMenu::DisplayAtItem(int client,
return false; return false;
} }
AutoHandleRooter ahr(this->GetHandle());
return g_RadioMenuStyle.DoClientMenu(client, return g_RadioMenuStyle.DoClientMenu(client,
this, this,
start_item, start_item,
+3 -3
View File
@@ -41,8 +41,6 @@
#include "sm_fastlink.h" #include "sm_fastlink.h"
#include <sh_stack.h> #include <sh_stack.h>
#include <compat_wrappers.h> #include <compat_wrappers.h>
#include "logic/common_logic.h"
#include "AutoHandleRooter.h"
using namespace SourceMod; using namespace SourceMod;
@@ -103,6 +101,7 @@ public:
CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL); CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL);
void FreeRadioDisplay(CRadioDisplay *display); void FreeRadioDisplay(CRadioDisplay *display);
CRadioMenuPlayer *GetRadioMenuPlayer(int client); CRadioMenuPlayer *GetRadioMenuPlayer(int client);
IMenuPanel *MakeRadioDisplay(const char *str, int keys);
private: private:
CRadioMenuPlayer *m_players; CRadioMenuPlayer *m_players;
CStack<CRadioDisplay *> m_FreeDisplays; CStack<CRadioDisplay *> m_FreeDisplays;
@@ -130,7 +129,8 @@ public: //IMenuPanel
bool SetCurrentKey(unsigned int key); bool SetCurrentKey(unsigned int key);
int GetAmountRemaining(); int GetAmountRemaining();
unsigned int GetApproxMemUsage(); unsigned int GetApproxMemUsage();
bool DirectSet(const char *str); public:
void DirectSet(const char *str, int keymap);
private: private:
String m_BufferText; String m_BufferText;
String m_Title; String m_Title;
+2 -7
View File
@@ -65,20 +65,16 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom
void ValveMenuStyle::OnSourceModAllInitialized() void ValveMenuStyle::OnSourceModAllInitialized()
{ {
#if SOURCE_ENGINE != SE_DOTA
g_Players.AddClientListener(this); g_Players.AddClientListener(this);
SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false); SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers); g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
#endif
} }
void ValveMenuStyle::OnSourceModShutdown() void ValveMenuStyle::OnSourceModShutdown()
{ {
#if SOURCE_ENGINE != SE_DOTA
SH_RELEASE_CALLCLASS(g_pSPHCC); SH_RELEASE_CALLCLASS(g_pSPHCC);
SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false); SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
g_Players.RemoveClientListener(this); g_Players.RemoveClientListener(this);
#endif
} }
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict, void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
@@ -408,7 +404,6 @@ bool CValveMenu::DisplayAtItem(int client,
return false; return false;
} }
AutoHandleRooter ahr(this->GetHandle());
return g_ValveMenuStyle.DoClientMenu(client, this, start_item, alt_handler ? alt_handler : m_pHandler, time); 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 "KeyValues.h"
#include "sm_fastlink.h" #include "sm_fastlink.h"
#include <compat_wrappers.h> #include <compat_wrappers.h>
#include "logic/common_logic.h"
#include "AutoHandleRooter.h"
using namespace SourceMod; using namespace SourceMod;
@@ -77,7 +75,6 @@ public: //IMenuStyle
IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner); IBaseMenu *CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner);
unsigned int GetMaxPageItems(); unsigned int GetMaxPageItems();
unsigned int GetApproxMemUsage(); unsigned int GetApproxMemUsage();
bool IsSupported() { return true; }
private: private:
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin); void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
private: private:
@@ -108,7 +105,6 @@ public:
bool SetCurrentKey(unsigned int key); bool SetCurrentKey(unsigned int key);
int GetAmountRemaining(); int GetAmountRemaining();
unsigned int GetApproxMemUsage(); unsigned int GetApproxMemUsage();
bool DirectSet(const char *str) { return false; }
private: private:
KeyValues *m_pKv; KeyValues *m_pKv;
unsigned int m_NextPos; unsigned int m_NextPos;
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourcePawn * SourcePawn
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
@@ -54,7 +54,7 @@ unsigned int NativeInterface::GetInterfaceVersion()
void NativeInterface::OnSourceModAllInitialized() void NativeInterface::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, &g_NInvoke); g_ShareSys.AddInterface(NULL, &g_NInvoke);
} }
IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes) IPluginRuntime *NativeInterface::CreateRuntime(const char *name, size_t bytes)
@@ -69,15 +69,30 @@ INativeInvoker *NativeInterface::CreateInvoker()
bool NativeInvoker::Start(IPluginContext *pContext, const char *name) bool NativeInvoker::Start(IPluginContext *pContext, const char *name)
{ {
ke::Ref<Native> entry = g_ShareSys.FindNative(name); NativeEntry *entry;
if (!entry)
entry = g_ShareSys.FindNative(name);
if (entry == NULL)
{
return false; 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; return false;
}
native_ = entry->func(); this->pContext = pContext;
context_ = pContext;
m_curparam = 0; m_curparam = 0;
m_errorstate = SP_ERROR_NONE; 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() void NativeInvoker::Cancel()
{ {
if (context_ == NULL) if (pContext == NULL)
{
return; return;
}
m_errorstate = SP_ERROR_NONE; m_errorstate = SP_ERROR_NONE;
m_curparam = 0; m_curparam = 0;
context_ = NULL; pContext = NULL;
native_ = NULL; native = NULL;
} }
int NativeInvoker::SetError(int err) int NativeInvoker::SetError(int err)
@@ -188,8 +205,10 @@ int NativeInvoker::Invoke(cell_t *result)
{ {
int err = SP_ERROR_NONE; int err = SP_ERROR_NONE;
if (context_ == NULL) if (pContext == NULL)
{
return SP_ERROR_INVALID_NATIVE; return SP_ERROR_INVALID_NATIVE;
}
if (m_errorstate != SP_ERROR_NONE) if (m_errorstate != SP_ERROR_NONE)
{ {
@@ -206,7 +225,7 @@ int NativeInvoker::Invoke(cell_t *result)
} }
//This is for re-entrancy! //This is for re-entrancy!
IPluginContext *ctx = context_; IPluginContext *ctx = pContext;
cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1]; cell_t _temp_params[SP_MAX_EXEC_PARAMS + 1];
cell_t *temp_params = &_temp_params[1]; cell_t *temp_params = &_temp_params[1];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS]; 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)); memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
} }
m_curparam = 0; m_curparam = 0;
context_ = NULL; pContext = NULL;
/* Initialize 0th parameter */ /* Initialize 0th parameter */
_temp_params[0] = numparams; _temp_params[0] = numparams;
@@ -305,7 +324,7 @@ int NativeInvoker::Invoke(cell_t *result)
/* Make the call if we can */ /* Make the call if we can */
if (err == SP_ERROR_NONE) if (err == SP_ERROR_NONE)
{ {
*result = native_(ctx, _temp_params); *result = native(ctx, _temp_params);
if (ctx->GetLastNativeError() != SP_ERROR_NONE) if (ctx->GetLastNativeError() != SP_ERROR_NONE)
{ {
docopies = false; docopies = false;
@@ -32,12 +32,8 @@
#ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_ #ifndef _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_ #define _INCLUDE_SOURCEMOD_NATIVE_INVOKER_H_
#include <sp_vm_api.h> #include "sm_globals.h"
#include <INativeInvoker.h> #include <INativeInvoker.h>
#include "common_logic.h"
using namespace SourceMod;
using namespace SourcePawn;
struct ParamInfo struct ParamInfo
{ {
@@ -75,8 +71,8 @@ private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len); int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err); int SetError(int err);
private: private:
IPluginContext *context_; IPluginContext *pContext;
SPVM_NATIVE_FUNC native_; SPVM_NATIVE_FUNC native;
cell_t m_params[SP_MAX_EXEC_PARAMS]; cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS]; ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam; 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 "sm_stringutil.h"
#include "sourcehook.h" #include "sourcehook.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include "logic_bridge.h"
NextMapManager g_NextMap; 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); SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool);
#endif #endif
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
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 &); SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
#elif SOURCE_ENGINE == SE_DARKMESSIAH #elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
@@ -72,13 +69,13 @@ void NextMapManager::OnSourceModAllInitialized_Post()
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false); SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
#else #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 #endif
ConCommand *pCmd = FindCommand("changelevel"); ConCommand *pCmd = FindCommand("changelevel");
if (pCmd != NULL) if (pCmd != NULL)
{ {
SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdChangeLevelCallback), false); SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdChangeLevelCallback, false);
changeLevelCmd = pCmd; changeLevelCmd = pCmd;
} }
} }
@@ -88,12 +85,12 @@ void NextMapManager::OnSourceModShutdown()
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false); SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false);
#else #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 #endif
if (changeLevelCmd != NULL) 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; SourceHook::List<MapChangeData *>::iterator iter;
@@ -131,7 +128,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
{ {
if (g_forcedChange) if (g_forcedChange)
{ {
logger->LogMessage("[SM] Changed map to \"%s\"", map); g_Logger.LogMessage("[SM] Changed map to \"%s\"", map);
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@@ -142,7 +139,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
RETURN_META(MRES_IGNORED); 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_mapName, sizeof(m_tempChangeInfo.m_mapName), newmap);
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change"); 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 *>(); m_mapHistory = SourceHook::List<MapChangeData *>();
} }
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command)
{
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command) void CmdChangeLevelCallback(const CCommand &command)
{ {
#else #else
+2 -6
View File
@@ -58,9 +58,7 @@ struct MapChangeData
time_t startTime; time_t startTime;
}; };
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void CmdChangeLevelCallback(const CCommand &command); void CmdChangeLevelCallback(const CCommand &command);
#else #else
void CmdChangeLevelCallback(); void CmdChangeLevelCallback();
@@ -71,9 +69,7 @@ class NextMapManager : public SMGlobalClass
public: public:
NextMapManager(); NextMapManager();
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
friend void CmdChangeLevelCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
friend void CmdChangeLevelCallback(const CCommand &command); friend void CmdChangeLevelCallback(const CCommand &command);
#else #else
friend void CmdChangeLevelCallback(); 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_string.h>
#include <sh_list.h> #include <sh_list.h>
#include <sh_vector.h> #include <sh_vector.h>
#include <am-string.h>
#include "ConVarManager.h" #include "ConVarManager.h"
#include <steam/steamclientpublic.h>
using namespace SourceHook; using namespace SourceHook;
#define PLAYER_LIFE_UNKNOWN 0 #define PLAYER_LIFE_UNKNOWN 0
@@ -74,10 +71,6 @@ public:
const char *GetIPAddress(); const char *GetIPAddress();
const char *GetAuthString(bool validated = true); const char *GetAuthString(bool validated = true);
unsigned int GetSteamAccountID(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(); edict_t *GetEdict();
bool IsInGame(); bool IsInGame();
bool WasCountedAsInGame(); bool WasCountedAsInGame();
@@ -97,9 +90,6 @@ public:
bool RunAdminCacheChecks(); bool RunAdminCacheChecks();
void NotifyPostAdminChecks(); void NotifyPostAdminChecks();
unsigned int GetSerial(); unsigned int GetSerial();
int GetIndex() const;
void PrintToConsole(const char *pMsg);
void ClearAdmin();
public: public:
void DoBasicAdminChecks(); void DoBasicAdminChecks();
void MarkAsBeingKicked(); void MarkAsBeingKicked();
@@ -110,7 +100,7 @@ private:
void Disconnect(); void Disconnect();
void SetName(const char *name); void SetName(const char *name);
void DumpAdmin(bool deleting); void DumpAdmin(bool deleting);
void UpdateAuthIds(); void SetAuthString(const char *auth);
void Authorize(); void Authorize();
void Authorize_Post(); void Authorize_Post();
void DoPostConnectAuthorization(); void DoPostConnectAuthorization();
@@ -123,9 +113,7 @@ private:
String m_Name; String m_Name;
String m_Ip; String m_Ip;
String m_IpNoPort; String m_IpNoPort;
ke::AString m_AuthID; String m_AuthID;
ke::AString m_Steam2Id;
ke::AString m_Steam3Id;
AdminId m_Admin; AdminId m_Admin;
bool m_TempAdmin; bool m_TempAdmin;
edict_t *m_pEdict; edict_t *m_pEdict;
@@ -139,10 +127,7 @@ private:
bool m_bIsSourceTV; bool m_bIsSourceTV;
bool m_bIsReplay; bool m_bIsReplay;
serial_t m_Serial; serial_t m_Serial;
CSteamID m_SteamId; unsigned int m_SteamAccountID;
#if SOURCE_ENGINE == SE_CSGO
QueryCvarCookie_t m_LanguageCookie;
#endif
}; };
class PlayerManager : class PlayerManager :
@@ -162,17 +147,9 @@ public: //SMGlobalClass
public: public:
CPlayer *GetPlayerByIndex(int client) const; CPlayer *GetPlayerByIndex(int client) const;
void RunAuthChecks(); void RunAuthChecks();
void ClearAdminId(AdminId id);
void ClearAllAdmins();
public: public:
#if SOURCE_ENGINE == SE_DOTA
bool OnClientConnect(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
bool OnClientConnect_Post(CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
void OnClientPutInServer(CEntityIndex index, char const *playername);
void OnClientDisconnect(CEntityIndex index, int reason);
void OnClientDisconnect_Post(CEntityIndex index, int reason);
void OnClientCommand(CEntityIndex index, const CCommand &args);
void OnClientSettingsChanged(CEntityIndex index);
//void OnClientSettingsChanged_Pre(CEntityIndex client);
#else
bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
void OnClientPutInServer(edict_t *pEntity, char const *playername); void OnClientPutInServer(edict_t *pEntity, char const *playername);
@@ -185,8 +162,6 @@ public:
#endif #endif
void OnClientSettingsChanged(edict_t *pEntity); void OnClientSettingsChanged(edict_t *pEntity);
//void OnClientSettingsChanged_Pre(edict_t *pEntity); //void OnClientSettingsChanged_Pre(edict_t *pEntity);
#endif
void OnServerHibernationUpdate(bool bHibernating);
public: //IPlayerManager public: //IPlayerManager
void AddClientListener(IClientListener *listener); void AddClientListener(IClientListener *listener);
void RemoveClientListener(IClientListener *listener); void RemoveClientListener(IClientListener *listener);
@@ -202,8 +177,6 @@ public: //IPlayerManager
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler); void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
void ProcessCommandTarget(cmd_target_info_t *info); void ProcessCommandTarget(cmd_target_info_t *info);
int GetClientFromSerial(unsigned int serial); int GetClientFromSerial(unsigned int serial);
void ClearAdminId(AdminId id);
void RecheckAnyAdmins();
public: public:
inline int MaxClients() inline int MaxClients()
{ {
@@ -220,18 +193,12 @@ public:
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id); bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id); bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
const char *GetPassInfoVar(); const char *GetPassInfoVar();
void RecheckAnyAdmins();
unsigned int GetReplyTo(); unsigned int GetReplyTo();
unsigned int SetReplyTo(unsigned int reply); unsigned int SetReplyTo(unsigned int reply);
void MaxPlayersChanged(int newvalue = -1); void MaxPlayersChanged(int newvalue = -1);
#if SOURCE_ENGINE == SE_CSGO
bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
#endif
private: private:
#if SOURCE_ENGINE == SE_DOTA
void OnServerActivate();
#else
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax); void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
#endif
void InvalidatePlayer(CPlayer *pPlayer); void InvalidatePlayer(CPlayer *pPlayer);
private: private:
List<IClientListener *> m_hooks; List<IClientListener *> m_hooks;
@@ -263,9 +230,7 @@ private:
int m_ReplayUserId; int m_ReplayUserId;
}; };
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE >= SE_ORANGEBOX
void CmdMaxplayersCallback(const CCommandContext &context, const CCommand &command);
#elif SOURCE_ENGINE >= SE_ORANGEBOX
void CmdMaxplayersCallback(const CCommand &command); void CmdMaxplayersCallback(const CCommand &command);
#else #else
void CmdMaxplayersCallback(); 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 * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -42,10 +42,20 @@
#include <sh_stack.h> #include <sh_stack.h>
#include <sh_vector.h> #include <sh_vector.h>
#include <sh_string.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 <IRootConsoleMenu.h>
#include <sm_stringhashmap.h> #if SOURCE_ENGINE >= SE_ALIENSWARM
#include <sm_namehashset.h> #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 "ITranslator.h"
#include "IGameConfigs.h" #include "IGameConfigs.h"
#include "NativeOwner.h" #include "NativeOwner.h"
@@ -121,8 +131,23 @@ enum APLRes
APLRes_SilentFailure APLRes_SilentFailure
}; };
enum LibraryAction
{
LibraryAction_Removed,
LibraryAction_Added
};
struct AutoConfig
{
String autocfg;
String folder;
bool create;
};
class CPlugin;
class CPlugin : class CPlugin :
public SMPlugin, public IPlugin,
public CNativeOwner public CNativeOwner
{ {
friend class CPluginManager; friend class CPluginManager;
@@ -149,9 +174,6 @@ public:
bool GetProperty(const char *prop, void **ptr, bool remove=false); bool GetProperty(const char *prop, void **ptr, bool remove=false);
void DropEverything(); void DropEverything();
SourcePawn::IPluginRuntime *GetRuntime(); SourcePawn::IPluginRuntime *GetRuntime();
CNativeOwner *ToNativeOwner() {
return this;
}
public: public:
/** /**
* Creates a plugin object with default values. * Creates a plugin object with default values.
@@ -161,11 +183,6 @@ public:
* a valid (but error-stated) CPlugin will be returned. * a valid (but error-stated) CPlugin will be returned.
*/ */
static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength); 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: public:
/** /**
@@ -204,11 +221,6 @@ public:
*/ */
void Call_OnAllPluginsLoaded(); void Call_OnAllPluginsLoaded();
/**
* Calls the OnLibraryAdded function.
*/
void Call_OnLibraryAdded(const char *lib);
/** /**
* Returns true if a plugin is usable. * Returns true if a plugin is usable.
*/ */
@@ -238,8 +250,8 @@ public:
bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func); bool AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
void AddConfig(bool autoCreate, const char *cfg, const char *folder); void AddConfig(bool autoCreate, const char *cfg, const char *folder);
size_t GetConfigCount(); unsigned int GetConfigCount();
AutoConfig *GetConfig(size_t i); AutoConfig *GetConfig(unsigned int i);
inline void AddLibrary(const char *name) inline void AddLibrary(const char *name)
{ {
m_Libraries.push_back(name); m_Libraries.push_back(name);
@@ -265,7 +277,7 @@ private:
IPhraseCollection *m_pPhrases; IPhraseCollection *m_pPhrases;
List<String> m_RequiredLibs; List<String> m_RequiredLibs;
List<String> m_Libraries; List<String> m_Libraries;
StringHashMap<void *> m_Props; Trie *m_pProps;
bool m_FakeNativesMissing; bool m_FakeNativesMissing;
bool m_LibraryMissing; bool m_LibraryMissing;
CVector<AutoConfig *> m_configs; CVector<AutoConfig *> m_configs;
@@ -278,7 +290,7 @@ private:
}; };
class CPluginManager : class CPluginManager :
public IScriptManager, public IPluginManager,
public SMGlobalClass, public SMGlobalClass,
public IHandleTypeDispatch, public IHandleTypeDispatch,
public IRootConsoleCommand public IRootConsoleCommand
@@ -305,7 +317,7 @@ public:
List<CPlugin *>::iterator current; List<CPlugin *>::iterator current;
}; };
friend class CPluginManager::CPluginIterator; friend class CPluginManager::CPluginIterator;
public: //IScriptManager public: //IPluginManager
IPlugin *LoadPlugin(const char *path, IPlugin *LoadPlugin(const char *path,
bool debug, bool debug,
PluginType type, PluginType type,
@@ -318,26 +330,6 @@ public: //IScriptManager
IPluginIterator *GetPluginIterator(); IPluginIterator *GetPluginIterator();
void AddPluginsListener(IPluginsListener *listener); void AddPluginsListener(IPluginsListener *listener);
void RemovePluginsListener(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 public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown(); void OnSourceModShutdown();
@@ -397,6 +389,11 @@ public:
*/ */
const char *GetStatusText(PluginStatus status); const char *GetStatusText(PluginStatus status);
/**
* Reload or update plugins on level shutdown.
*/
void ReloadOrUnloadPlugins();
/** /**
* Add public functions from all running or paused * Add public functions from all running or paused
* plugins to the specified forward if the names match. * plugins to the specified forward if the names match.
@@ -420,6 +417,8 @@ public:
void UnloadAll(); void UnloadAll();
CPlugin *FindPluginByConsoleArg(const char *arg);
void SyncMaxClients(int max_clients); void SyncMaxClients(int max_clients);
void ListPluginsToClient(CPlayer *player, const CCommand &args); void ListPluginsToClient(CPlayer *player, const CCommand &args);
@@ -464,14 +463,14 @@ public:
{ {
return m_MyIdent; return m_MyIdent;
} }
IPluginManager *GetOldAPI();
private: private:
void TryRefreshDependencies(CPlugin *pOther); void TryRefreshDependencies(CPlugin *pOther);
private: private:
List<IPluginsListener *> m_listeners; List<IPluginsListener *> m_listeners;
List<CPlugin *> m_plugins; List<CPlugin *> m_plugins;
CStack<CPluginManager::CPluginIterator *> m_iters; CStack<CPluginManager::CPluginIterator *> m_iters;
NameHashSet<CPlugin *> m_LoadLookup; CPluginInfoDatabase m_PluginInfo;
Trie *m_LoadLookup;
bool m_AllPluginsLoaded; bool m_AllPluginsLoaded;
IdentityToken_t *m_MyIdent; 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -30,14 +30,11 @@
*/ */
#include "ShareSys.h" #include "ShareSys.h"
#include "ExtensionSys.h"
#include <ILibrarySys.h>
#include "common_logic.h"
#include "PluginSys.h"
#include "HandleSys.h" #include "HandleSys.h"
#include <assert.h> #include "ExtensionSys.h"
#include "LibrarySys.h"
using namespace ke; #include "PluginSys.h"
#include "sm_stringutil.h"
ShareSystem g_ShareSys; ShareSystem g_ShareSys;
static unsigned int g_mark_serial = 0; static unsigned int g_mark_serial = 0;
@@ -64,36 +61,36 @@ void ShareSystem::Initialize()
{ {
TypeAccess sec; TypeAccess sec;
handlesys->InitAccessDefaults(&sec, NULL); g_HandleSys.InitAccessDefaults(&sec, NULL);
sec.ident = GetIdentRoot(); sec.ident = GetIdentRoot();
m_TypeRoot = handlesys->CreateType("Identity", this, 0, &sec, NULL, NULL, NULL); m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
m_IfaceType = handlesys->CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL); m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
/* Initialize our static identity handle */ /* 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 */ /* Add the Handle System and others... they are too innocent and pure to do it themselves */
AddInterface(NULL, handlesys); AddInterface(NULL, &g_HandleSys);
AddInterface(NULL, libsys); AddInterface(NULL, &g_LibSys);
} }
void ShareSystem::OnSourceModShutdown() void ShareSystem::OnSourceModShutdown()
{ {
if (m_CoreType) if (m_CoreType)
{ {
handlesys->RemoveType(m_CoreType, GetIdentRoot()); g_HandleSys.RemoveType(m_CoreType, GetIdentRoot());
} }
handlesys->RemoveType(m_IfaceType, GetIdentRoot()); g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot());
handlesys->RemoveType(m_TypeRoot, GetIdentRoot()); g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot());
} }
IdentityType_t ShareSystem::FindIdentType(const char *name) IdentityType_t ShareSystem::FindIdentType(const char *name)
{ {
HandleType_t type; HandleType_t type;
if (handlesys->FindHandleType(name, &type)) if (g_HandleSys.FindHandleType(name, &type))
{ {
if (g_HandleSys.TypeCheck(type, m_TypeRoot)) if (g_HandleSys.TypeCheck(type, m_TypeRoot))
{ {
@@ -111,7 +108,7 @@ IdentityType_t ShareSystem::CreateIdentType(const char *name)
return 0; 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) void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
@@ -220,13 +217,13 @@ void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
sec.pOwner = GetIdentRoot(); sec.pOwner = GetIdentRoot();
sec.pIdentity = GetIdentRoot(); sec.pIdentity = GetIdentRoot();
handlesys->FreeHandle(identity->ident, &sec); g_HandleSys.FreeHandle(identity->ident, &sec);
delete identity; delete identity;
} }
void ShareSystem::DestroyIdentType(IdentityType_t type) void ShareSystem::DestroyIdentType(IdentityType_t type)
{ {
handlesys->RemoveType(type, GetIdentRoot()); g_HandleSys.RemoveType(type, GetIdentRoot());
} }
void ShareSystem::RemoveInterfaces(IExtension *pExtension) 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) 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); NativeEntry **ppEntry;
if (!r.found())
if ((ppEntry = m_NtvCache.retrieve(name)) == NULL)
{
return NULL; return NULL;
return *r; }
return *ppEntry;
} }
void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly) void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
{ {
NativeEntry *pEntry;
sp_native_t *native; sp_native_t *native;
uint32_t i, native_count; uint32_t i, native_count;
IPluginContext *pContext; IPluginContext *pContext;
@@ -279,152 +308,230 @@ void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly)
/* Generate a new serial ID, mark our dependencies with it. */ /* Generate a new serial ID, mark our dependencies with it. */
g_mark_serial++; g_mark_serial++;
pPlugin->PropagateMarkSerial(g_mark_serial); pPlugin->PropogateMarkSerial(g_mark_serial);
native_count = pContext->GetNativesNum(); native_count = pContext->GetNativesNum();
for (i = 0; i < native_count; i++) for (i = 0; i < native_count; i++)
{ {
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE) if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
{
continue; 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) 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. */ /* Otherwise, the native must be in our cache. */
Ref<Native> pEntry = FindNative(native->name); else if ((pEntry = FindNative(native->name)) == NULL)
if (!pEntry) {
continue; continue;
}
if (bCoreOnly && pEntry->owner != &g_CoreNatives) if (bCoreOnly && pEntry->owner != g_pCoreNatives)
{
continue; continue;
}
BindNativeToPlugin(pPlugin, native, i, pEntry); 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; uint32_t i;
if (pContext->FindNativeByName(entry->name(), &i) != SP_ERROR_NONE)
return;
sp_native_t *native; 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; return;
}
if (pContext->GetNativeByIndex(i, &native) != SP_ERROR_NONE)
{
return;
}
if (native->status == SP_NATIVE_BOUND) if (native->status == SP_NATIVE_BOUND)
{
return; return;
}
BindNativeToPlugin(pPlugin, native, i, entry); BindNativeToPlugin(pPlugin, native, i, pEntry);
} }
void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, sp_native_t *native, uint32_t index, void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin,
const Ref<Native> &pEntry) sp_native_t *native,
uint32_t index,
NativeEntry *pEntry)
{ {
/* Mark as bound... we do the rest next. */ /* Mark as bound... we do the rest next. */
native->status = SP_NATIVE_BOUND; 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 /* Perform a replacement bind. */
* that its address is long-lived. */ native->pfn = pEntry->replacement.func;
native->flags |= SP_NTVFLAG_EPHEMERAL; pEntry->replacement.owner->AddWeakRef(WeakNative(pPlugin, index, pEntry));
} }
else
/* We don't bother with dependency crap if the owner is Core. */
if (pEntry->owner != &g_CoreNatives)
{ {
/* The native is optional, this is a special case */ /* Perform a normal bind. */
if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL) 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. */ /* The native is optional, this is a special case */
if (pEntry->owner) if ((native->flags & SP_NTVFLAG_OPTIONAL) == SP_NTVFLAG_OPTIONAL)
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)
{ {
/* This has not been marked as a dependency yet */ /* Only add if there is a valid owner. */
//pPlugin->AddDependency(pEntry->owner); if (pEntry->owner != NULL)
pEntry->owner->AddDependent(pPlugin); {
pEntry->owner->SetMarkSerial(g_mark_serial); 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); NativeEntry *pEntry;
if (i.found())
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; return NULL;
}
Ref<Native> entry = new Native(pOwner, ntv); pEntry->owner = pOwner;
m_NtvCache.insert(ntv->name, entry); pEntry->func = ntv->func;
return entry; pEntry->name = ntv->name;
}
FakeNative::~FakeNative() return pEntry;
{
g_pSourcePawn2->DestroyFakeNative(gate);
} }
void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name) void ShareSystem::ClearNativeFromCache(CNativeOwner *pOwner, const char *name)
{ {
NativeCache::Result r = m_NtvCache.find(name); NativeEntry *pEntry;
if (!r.found())
if ((pEntry = FindNative(name)) == NULL)
{
return; return;
}
Ref<Native> entry(*r); if (pEntry->owner != pOwner)
if (entry->owner != pOwner) {
return; return;
}
// Clear out the owner bit as a sanity measure. if (pEntry->fake != NULL)
entry->owner = 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)); FakeNative *pFake;
if (entry) NativeEntry *pEntry;
SPVM_NATIVE_FUNC gate;
if ((pEntry = FindNative(name)) != NULL && pEntry->owner != NULL)
{
return NULL; return NULL;
}
AutoPtr<FakeNative> fake(new FakeNative(name, pFunc)); pFake = new FakeNative;
fake->gate = g_pSourcePawn2->CreateFakeNative(func, fake); if ((gate = g_pSourcePawn2->CreateFakeNative(func, pFake)) == NULL)
if (!fake->gate) {
delete pFake;
return NULL; 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()); pFake->call = pFunc;
m_NtvCache.insert(name, entry); 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, void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name) const char *name)
{ {
if (m_caps.contains(name)) if (m_caps.retrieve(name) != NULL)
return; return;
Capability cap; Capability cap;
@@ -437,13 +544,14 @@ void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *pr
void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider, void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name) const char *name)
{ {
StringHashMap<Capability>::Result r = m_caps.find(name); Capability *pCap = m_caps.retrieve(name);
if (!r.found()) if (pCap == NULL)
return;
if (r->value.ext != myself || r->value.provider != provider)
return; return;
m_caps.remove(r); if (pCap->ext != myself || pCap->provider != provider)
return;
m_caps.remove(name);
} }
FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature, FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature,
@@ -478,18 +586,26 @@ FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name
} }
} }
Ref<Native> entry = FindNative(name); NativeEntry *entry = FindNative(name);
if (!entry) if (entry == NULL)
return FeatureStatus_Unknown; 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) FeatureStatus ShareSystem::TestCap(const char *name)
{ {
StringHashMap<Capability>::Result r = m_caps.find(name); Capability *cap = m_caps.retrieve(name);
if (!r.found()) if (cap == NULL)
return FeatureStatus_Unknown; 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -34,14 +34,10 @@
#include <IShareSys.h> #include <IShareSys.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <am-string.h>
#include <am-utility.h>
#include <am-refcounting.h>
#include <sh_list.h> #include <sh_list.h>
#include <sm_stringhashmap.h> #include <sm_trie_tpl.h>
#include <sm_namehashset.h> #include "sm_globals.h"
#include "common_logic.h" #include "sourcemod.h"
#include "Native.h"
using namespace SourceHook; using namespace SourceHook;
@@ -67,6 +63,29 @@ struct IfaceInfo
class CNativeOwner; class CNativeOwner;
class CPlugin; 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 struct Capability
{ {
@@ -120,23 +139,24 @@ public:
} }
public: public:
void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly); void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly);
void BindNativeToPlugin(CPlugin *pPlugin, const ke::Ref<Native> &pEntry); void BindNativeToPlugin(CPlugin *pPlugin, NativeEntry *pEntry);
ke::PassRef<Native> AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func); NativeEntry *AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func);
ke::PassRef<Native> FindNative(const char *name); NativeEntry *FindNative(const char *name);
private: 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 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: private:
typedef NameHashSet<ke::Ref<Native>, Native> NativeCache;
List<IfaceInfo> m_Interfaces; List<IfaceInfo> m_Interfaces;
HandleType_t m_TypeRoot; HandleType_t m_TypeRoot;
IdentityToken_t m_IdentRoot; IdentityToken_t m_IdentRoot;
HandleType_t m_IfaceType; HandleType_t m_IfaceType;
IdentityType_t m_CoreType; IdentityType_t m_CoreType;
NativeCache m_NtvCache; KTrie<NativeEntry *> m_NtvCache;
StringHashMap<Capability> m_caps; KTrie<Capability> m_caps;
}; };
extern ShareSystem g_ShareSys; extern ShareSystem g_ShareSys;
+6 -6
View File
@@ -31,10 +31,10 @@
#include <time.h> #include <time.h>
#include "TimerSys.h" #include "TimerSys.h"
#include "ForwardSys.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "frame_hooks.h" #include "frame_hooks.h"
#include "ConVarManager.h" #include "ConVarManager.h"
#include "logic_bridge.h"
#define TIMER_MIN_ACCURACY 0.1 #define TIMER_MIN_ACCURACY 0.1
@@ -180,9 +180,9 @@ TimerSystem::~TimerSystem()
void TimerSystem::OnSourceModAllInitialized() void TimerSystem::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
m_pOnGameFrame = forwardsys->CreateForward("OnGameFrame", ET_Ignore, 0, NULL); m_pOnGameFrame = g_Forwards.CreateForward("OnGameFrame", ET_Ignore, 0, NULL);
m_pOnMapTimeLeftChanged = forwardsys->CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL); m_pOnMapTimeLeftChanged = g_Forwards.CreateForward("OnMapTimeLeftChanged", ET_Ignore, 0, NULL);
} }
void TimerSystem::OnSourceModGameInitialized() void TimerSystem::OnSourceModGameInitialized()
@@ -198,8 +198,8 @@ void TimerSystem::OnSourceModGameInitialized()
void TimerSystem::OnSourceModShutdown() void TimerSystem::OnSourceModShutdown()
{ {
SetMapTimer(NULL); SetMapTimer(NULL);
forwardsys->ReleaseForward(m_pOnGameFrame); g_Forwards.ReleaseForward(m_pOnGameFrame);
forwardsys->ReleaseForward(m_pOnMapTimeLeftChanged); g_Forwards.ReleaseForward(m_pOnMapTimeLeftChanged);
} }
void TimerSystem::OnSourceModLevelEnd() void TimerSystem::OnSourceModLevelEnd()
+1 -1
View File
@@ -32,11 +32,11 @@
#ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_ #ifndef _INCLUDE_SOURCEMOD_CTIMERSYS_H_
#define _INCLUDE_SOURCEMOD_CTIMERSYS_H_ #define _INCLUDE_SOURCEMOD_CTIMERSYS_H_
#include "ShareSys.h"
#include <ITimerSystem.h> #include <ITimerSystem.h>
#include <sh_stack.h> #include <sh_stack.h>
#include <sh_list.h> #include <sh_list.h>
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_globals.h"
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
+16 -103
View File
@@ -56,15 +56,6 @@
return false; \ 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() \ #define CHECK_FIELD_REPEATED() \
if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED) \ if (field->label() != protobuf::FieldDescriptor::LABEL_REPEATED) \
{ \ { \
@@ -102,7 +93,7 @@ public:
Handle_t &hndl = (*iter); Handle_t &hndl = (*iter);
HandleSecurity sec; HandleSecurity sec;
sec.pIdentity = g_pCoreIdent; sec.pIdentity = g_pCoreIdent;
handlesys->FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
iter = childHandles.erase(iter); iter = childHandles.erase(iter);
} }
} }
@@ -325,114 +316,74 @@ public:
return true; return true;
} }
inline bool GetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 *out) inline bool GetInt32OrUnsigned(const char *pszFieldName, int32 *out)
{ {
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM); CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_NOT_REPEATED(); CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32) if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
*out = (int32)msg->GetReflection()->GetUInt32(*msg, field); *out = (int32)msg->GetReflection()->GetUInt32(*msg, field);
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32) else
*out = msg->GetReflection()->GetInt32(*msg, field); *out = msg->GetReflection()->GetInt32(*msg, field);
else // CPPTYPE_ENUM
*out = msg->GetReflection()->GetEnum(*msg, field)->number();
return true; return true;
} }
inline bool SetInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value) inline bool SetInt32OrUnsigned(const char *pszFieldName, int32 value)
{ {
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM); CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_NOT_REPEATED(); CHECK_FIELD_NOT_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32) if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
{
msg->GetReflection()->SetUInt32(msg, field, (uint32)value); msg->GetReflection()->SetUInt32(msg, field, (uint32)value);
} else
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
{
msg->GetReflection()->SetInt32(msg, field, value); 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; return true;
} }
inline bool GetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 *out) inline bool GetRepeatedInt32OrUnsigned(const char *pszFieldName, int index, int32 *out)
{ {
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM); CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_REPEATED(); CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index); CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32) if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
*out = (int32)msg->GetReflection()->GetRepeatedUInt32(*msg, field, index); *out = (int32)msg->GetReflection()->GetRepeatedUInt32(*msg, field, index);
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32) else
*out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index); *out = msg->GetReflection()->GetRepeatedInt32(*msg, field, index);
else // CPPTYPE_ENUM
*out = msg->GetReflection()->GetRepeatedEnum(*msg, field, index)->number();
return true; return true;
} }
inline bool SetRepeatedInt32OrUnsignedOrEnum(const char *pszFieldName, int index, int32 value) inline bool SetRepeatedInt32OrUnsigned(const char *pszFieldName, int index, int32 value)
{ {
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM); CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_REPEATED(); CHECK_FIELD_REPEATED();
CHECK_REPEATED_ELEMENT(index); CHECK_REPEATED_ELEMENT(index);
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32) if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
{
msg->GetReflection()->SetRepeatedUInt32(msg, field, index, (uint32)value); msg->GetReflection()->SetRepeatedUInt32(msg, field, index, (uint32)value);
} else
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
{
msg->GetReflection()->SetRepeatedInt32(msg, field, index, value); 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; return true;
} }
inline bool AddInt32OrUnsignedOrEnum(const char *pszFieldName, int32 value) inline bool AddInt32OrUnsigned(const char *pszFieldName, int32 value)
{ {
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE3(INT32, UINT32, ENUM); CHECK_FIELD_TYPE2(INT32, UINT32);
CHECK_FIELD_REPEATED(); CHECK_FIELD_REPEATED();
if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32) if (fieldType == protobuf::FieldDescriptor::CPPTYPE_UINT32)
{
msg->GetReflection()->AddUInt32(msg, field, (uint32)value); msg->GetReflection()->AddUInt32(msg, field, (uint32)value);
} else
else if (fieldType == protobuf::FieldDescriptor::CPPTYPE_INT32)
{
msg->GetReflection()->AddInt32(msg, field, value); 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; return true;
} }
@@ -724,9 +675,6 @@ public:
inline bool GetColor(const char *pszFieldName, Color *out) inline bool GetColor(const char *pszFieldName, Color *out)
{ {
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE); CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_NOT_REPEATED(); CHECK_FIELD_NOT_REPEATED();
@@ -740,14 +688,10 @@ public:
); );
return true; return true;
#endif
} }
inline bool SetColor(const char *pszFieldName, const Color &value) inline bool SetColor(const char *pszFieldName, const Color &value)
{ {
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE); CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_NOT_REPEATED(); CHECK_FIELD_NOT_REPEATED();
@@ -759,14 +703,10 @@ public:
msgRGBA->set_a(value.a()); msgRGBA->set_a(value.a());
return true; return true;
#endif
} }
inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out) inline bool GetRepeatedColor(const char *pszFieldName, int index, Color *out)
{ {
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE); CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_REPEATED(); CHECK_FIELD_REPEATED();
@@ -781,14 +721,10 @@ public:
); );
return true; return true;
#endif
} }
inline bool SetRepeatedColor(const char *pszFieldName, int index, const Color &value) inline bool SetRepeatedColor(const char *pszFieldName, int index, const Color &value)
{ {
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE); CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_REPEATED(); CHECK_FIELD_REPEATED();
@@ -801,14 +737,10 @@ public:
msgRGBA->set_a(value.a()); msgRGBA->set_a(value.a());
return true; return true;
#endif
} }
inline bool AddColor(const char *pszFieldName, const Color &value) inline bool AddColor(const char *pszFieldName, const Color &value)
{ {
#if SOURCE_ENGINE != SE_CSGO
return false;
#else
GETCHECK_FIELD(); GETCHECK_FIELD();
CHECK_FIELD_TYPE(MESSAGE); CHECK_FIELD_TYPE(MESSAGE);
CHECK_FIELD_REPEATED(); CHECK_FIELD_REPEATED();
@@ -820,7 +752,6 @@ public:
msgRGBA->set_a(value.a()); msgRGBA->set_a(value.a());
return true; return true;
#endif
} }
inline bool GetVector2D(const char *pszFieldName, Vector2D *out) inline bool GetVector2D(const char *pszFieldName, Vector2D *out)
@@ -1093,24 +1024,6 @@ public:
return msg->GetReflection()->FieldSize(*msg, field); 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: private:
protobuf::Message *msg; protobuf::Message *msg;
PBHandleList childHandles; PBHandleList childHandles;
+52 -76
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -31,17 +31,14 @@
#include "UserMessages.h" #include "UserMessages.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "logic_bridge.h"
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
#include <dota_usermessage_helpers.h>
#elif SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessage_helpers.h> #include <cstrike15_usermessage_helpers.h>
#endif #endif
UserMessages g_UserMsgs; 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 &); SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
#else #else
#if SOURCE_ENGINE >= SE_LEFT4DEAD #if SOURCE_ENGINE >= SE_LEFT4DEAD
@@ -56,6 +53,7 @@ UserMessages::UserMessages()
#ifndef USE_PROTOBUF_USERMESSAGES #ifndef USE_PROTOBUF_USERMESSAGES
: m_InterceptBuffer(m_pBase, 2500) : m_InterceptBuffer(m_pBase, 2500)
{ {
m_Names = sm_trie_create();
#else #else
: m_InterceptBuffer(NULL) : m_InterceptBuffer(NULL)
{ {
@@ -69,6 +67,10 @@ UserMessages::UserMessages()
UserMessages::~UserMessages() UserMessages::~UserMessages()
{ {
#ifndef USE_PROTOBUF_USERMESSAGES
sm_trie_destroy(m_Names);
#endif
CStack<ListenerInfo *>::iterator iter; CStack<ListenerInfo *>::iterator iter;
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++) for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
{ {
@@ -87,21 +89,21 @@ void UserMessages::OnSourceModStartup(bool late)
void UserMessages::OnSourceModAllInitialized() void UserMessages::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
void UserMessages::OnSourceModAllShutdown() void UserMessages::OnSourceModAllShutdown()
{ {
if (m_HookCount) if (m_HookCount)
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else #else
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif #endif
} }
m_HookCount = 0; m_HookCount = 0;
@@ -109,16 +111,13 @@ void UserMessages::OnSourceModAllShutdown()
int UserMessages::GetMessageIndex(const char *msg) int UserMessages::GetMessageIndex(const char *msg)
{ {
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
// Can split this per engine and/or game later
return g_DotaUsermessageHelpers.GetIndex(msg);
#elif SOURCE_ENGINE == SE_CSGO
// Can split this per engine and/or game later // Can split this per engine and/or game later
return g_Cstrike15UsermessageHelpers.GetIndex(msg); return g_Cstrike15UsermessageHelpers.GetIndex(msg);
#else #else
int msgid; int msgid;
if (!m_Names.retrieve(msg, &msgid))
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
{ {
if (m_FallbackSearch) if (m_FallbackSearch)
{ {
@@ -130,7 +129,7 @@ int UserMessages::GetMessageIndex(const char *msg)
{ {
if (strcmp(msgbuf, msg) == 0) if (strcmp(msgbuf, msg) == 0)
{ {
m_Names.insert(msg, msgid); sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
return msgid; return msgid;
} }
msgid++; msgid++;
@@ -140,7 +139,9 @@ int UserMessages::GetMessageIndex(const char *msg)
msgid = g_SMAPI->FindUserMessage(msg); msgid = g_SMAPI->FindUserMessage(msg);
if (msgid != INVALID_MESSAGE_ID) if (msgid != INVALID_MESSAGE_ID)
m_Names.insert(msg, msgid); {
sm_trie_insert(m_Names, msg, reinterpret_cast<void *>(msgid));
}
} }
return msgid; return msgid;
@@ -149,12 +150,8 @@ int UserMessages::GetMessageIndex(const char *msg)
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
{ {
#ifdef USE_PROTOBUF_USERMESSAGES #if SOURCE_ENGINE == SE_CSGO
#if SOURCE_ENGINE == SE_DOTA
const char *pszName = g_DotaUsermessageHelpers.GetName(msgid);
#elif SOURCE_ENGINE == SE_CSGO
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid); const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
#endif
if (!pszName) if (!pszName)
return false; return false;
@@ -262,7 +259,7 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const
if (m_CurFlags & USERMSG_BLOCKHOOKS) if (m_CurFlags & USERMSG_BLOCKHOOKS)
{ {
// direct message creation, return buffer "from engine". keep track // 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; buffer = m_FakeEngineBuffer;
} else { } else {
char messageName[32]; char messageName[32];
@@ -277,12 +274,12 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const
{ {
case MRES_IGNORED: case MRES_IGNORED:
case MRES_HANDLED: case MRES_HANDLED:
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New(); m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
buffer = m_FakeEngineBuffer; buffer = m_FakeEngineBuffer;
break; break;
case MRES_OVERRIDE: case MRES_OVERRIDE:
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New(); m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
// fallthrough // fallthrough
case MRES_SUPERCEDE: case MRES_SUPERCEDE:
buffer = msg; buffer = msg;
@@ -303,7 +300,7 @@ bool UserMessages::EndMessage()
return false; return false;
} }
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
if (m_CurFlags & USERMSG_BLOCKHOOKS) if (m_CurFlags & USERMSG_BLOCKHOOKS)
{ {
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer); ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
@@ -333,7 +330,7 @@ bool UserMessages::EndMessage()
} else { } else {
engine->MessageEnd(); engine->MessageEnd();
} }
#endif // SE_CSGO || SE_DOTA #endif // SE_CSGO
m_InExec = false; m_InExec = false;
m_CurFlags = 0; m_CurFlags = 0;
@@ -418,14 +415,14 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
if (!m_HookCount++) if (!m_HookCount++)
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else #else
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false); SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true); SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false); SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true); SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif #endif
} }
@@ -439,17 +436,6 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
return true; 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 #ifdef USE_PROTOBUF_USERMESSAGES
bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew) bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
#else #else
@@ -495,26 +481,22 @@ void UserMessages::_DecRefCounter()
{ {
if (--m_HookCount == 0) if (--m_HookCount == 0)
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else #else
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Post, true);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Pre, false);
SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif #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) 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)); OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
if (m_FakeMetaRes == MRES_SUPERCEDE) if (m_FakeMetaRes == MRES_SUPERCEDE)
{ {
int size = msg.ByteSize(); int size = msg.ByteSize();
@@ -527,11 +509,7 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type,
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg); 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)); OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
#endif
OnMessageEnd_Pre(); OnMessageEnd_Pre();
if (m_FakeMetaRes == MRES_SUPERCEDE) if (m_FakeMetaRes == MRES_SUPERCEDE)
@@ -563,7 +541,7 @@ void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type
RETURN_META(res) RETURN_META(res)
#endif #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) protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD #elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name) 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 #ifdef USE_PROTOBUF_USERMESSAGES
if (m_InterceptBuffer) if (m_InterceptBuffer)
delete 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); UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
#else #else
m_InterceptBuffer.Reset(); m_InterceptBuffer.Reset();
@@ -603,7 +580,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); 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) protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD #elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name) 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 (!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); ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
#else #else
bf_write *engine_bfw; bf_write *engine_bfw;
@@ -780,16 +757,15 @@ void UserMessages::OnMessageEnd_Pre()
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten()); m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten()); engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
ENGINE_CALL(MessageEnd)(); ENGINE_CALL(MessageEnd)();
#endif // SE_CSGO || SE_DOTA #endif // SE_CSGO
} }
{ {
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
int size = m_OrigBuffer->ByteSize(); int size = m_OrigBuffer->ByteSize();
uint8 *data = (uint8 *)stackalloc(size); uint8 *data = (uint8 *)stackalloc(size);
m_OrigBuffer->SerializePartialToArray(data, size); m_OrigBuffer->SerializePartialToArray(data, size);
protobuf::Message *pTempMsg = g_Cstrike15UsermessageHelpers.GetPrototype(m_CurId)->New();
protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New();
pTempMsg->ParsePartialFromArray(data, size); pTempMsg->ParsePartialFromArray(data, size);
#else #else
bf_write *pTempMsg = m_OrigBuffer; bf_write *pTempMsg = m_OrigBuffer;
@@ -814,7 +790,7 @@ void UserMessages::OnMessageEnd_Pre()
iter++; iter++;
} }
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
delete pTempMsg; delete pTempMsg;
#endif #endif
} }
+7 -10
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
@@ -32,19 +32,17 @@
#ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_ #ifndef _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
#define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_ #define _INCLUDE_SOURCEMOD_CUSERMESSAGES_H_
#include "ShareSys.h"
#include <IUserMessages.h> #include <IUserMessages.h>
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <sm_stringhashmap.h> #include "sm_trie.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "CellRecipientFilter.h" #include "CellRecipientFilter.h"
#include "sm_globals.h"
#include <sh_list.h>
#include <sh_stack.h>
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_CSGO
#define USE_PROTOBUF_USERMESSAGES #define USE_PROTOBUF_USERMESSAGES
#endif #endif
@@ -102,12 +100,12 @@ public: //IUserMessages
bool intercept=false); bool intercept=false);
UserMessageType GetUserMessageType() const; UserMessageType GetUserMessageType() const;
public: 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_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg); void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
#endif #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_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
protobuf::Message *OnStartMessage_Post(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 #elif SOURCE_ENGINE >= SE_LEFT4DEAD
@@ -121,7 +119,6 @@ public:
void OnMessageEnd_Post(); void OnMessageEnd_Post();
private: private:
#ifdef USE_PROTOBUF_USERMESSAGES #ifdef USE_PROTOBUF_USERMESSAGES
const protobuf::Message *GetMessagePrototype(int msg_type);
bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew); bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew); bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
#else #else
@@ -153,7 +150,7 @@ private:
#ifndef USE_PROTOBUF_USERMESSAGES #ifndef USE_PROTOBUF_USERMESSAGES
bool m_FallbackSearch; bool m_FallbackSearch;
StringHashMap<int> m_Names; Trie *m_Names;
#endif #endif
CellRecipientFilter m_CellRecFilter; CellRecipientFilter m_CellRecFilter;
bool m_InExec; bool m_InExec;
+6 -6
View File
@@ -64,20 +64,20 @@ public:
void OnSourceModAllInitialized() void OnSourceModAllInitialized()
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_ADD_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false); SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_ADD_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false); SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#else #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 #endif
} }
void OnSourceModShutdown() void OnSourceModShutdown()
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_REMOVE_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false); SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_REMOVE_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false); SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#else #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 #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 ]; } FnChangeCallback_t GetChangeCallback( int slot ) const { return m_pParent->m_fnChangeCallbacks[ slot ]; }
// Retrieve value // Retrieve value
#if SOURCE_ENGINE >= SE_INSURGENCY #if SOURCE_ENGINE == SE_CSGO
virtual float GetFloat( void ) const; virtual float GetFloat( void ) const;
virtual int GetInt( void ) const; virtual int GetInt( void ) const;
#else #else
+2 -1
View File
@@ -30,6 +30,7 @@
*/ */
#include "frame_hooks.h" #include "frame_hooks.h"
#include "TimerSys.h" #include "TimerSys.h"
#include "Database.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "MenuStyle_Valve.h" #include "MenuStyle_Valve.h"
#include "MenuStyle_Radio.h" #include "MenuStyle_Radio.h"
@@ -37,7 +38,6 @@
#include "CoreConfig.h" #include "CoreConfig.h"
#include <sm_queue.h> #include <sm_queue.h>
#include <IThreader.h> #include <IThreader.h>
#include "sourcemod.h"
static IMutex *frame_mutex; static IMutex *frame_mutex;
static Queue<FrameAction> *frame_queue; static Queue<FrameAction> *frame_queue;
@@ -95,6 +95,7 @@ void RunFrameHooks(bool simulating)
} }
/* Frame based hooks */ /* Frame based hooks */
g_DBMan.RunFrame();
g_HL2.ProcessFakeCliCmdQueue(); g_HL2.ProcessFakeCliCmdQueue();
g_HL2.ProcessDelayedKicks(); g_HL2.ProcessDelayedKicks();
+1 -26
View File
@@ -19,18 +19,11 @@ if builder.target_platform == 'linux':
elif builder.target_platform == 'mac': elif builder.target_platform == 'mac':
binary.compiler.cflags += ['-Wno-deprecated-declarations'] binary.compiler.cflags += ['-Wno-deprecated-declarations']
binary.compiler.postlink += ['-framework', 'CoreServices'] binary.compiler.postlink += ['-framework', 'CoreServices']
if binary.compiler.vendor == 'gcc' or binary.compiler.vendor == 'clang':
binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.vendor == 'msvc':
binary.compiler.cxxflags += ['/GR-']
binary.sources += [ binary.sources += [
'common_logic.cpp', 'common_logic.cpp',
'smn_adt_array.cpp', 'smn_adt_array.cpp',
'smn_sorting.cpp', 'smn_sorting.cpp',
'smn_maplists.cpp', 'smn_maplists.cpp',
'ADTFactory.cpp',
'smn_adt_stack.cpp', 'smn_adt_stack.cpp',
'thread/ThreadWorker.cpp', 'thread/ThreadWorker.cpp',
'thread/BaseWorker.cpp', 'thread/BaseWorker.cpp',
@@ -39,13 +32,13 @@ binary.sources += [
'TextParsers.cpp', 'TextParsers.cpp',
'smn_textparse.cpp', 'smn_textparse.cpp',
'smn_adt_trie.cpp', 'smn_adt_trie.cpp',
'Profiler.cpp',
'smn_functions.cpp', 'smn_functions.cpp',
'smn_timers.cpp', 'smn_timers.cpp',
'smn_players.cpp', 'smn_players.cpp',
'MemoryUtils.cpp', 'MemoryUtils.cpp',
'smn_admin.cpp', 'smn_admin.cpp',
'smn_banning.cpp', 'smn_banning.cpp',
'smn_filesystem.cpp',
'stringutil.cpp', 'stringutil.cpp',
'Translator.cpp', 'Translator.cpp',
'PhraseCollection.cpp', 'PhraseCollection.cpp',
@@ -54,27 +47,9 @@ binary.sources += [
'smn_handles.cpp', 'smn_handles.cpp',
'smn_datapacks.cpp', 'smn_datapacks.cpp',
'smn_gameconfigs.cpp', 'smn_gameconfigs.cpp',
'smn_fakenatives.cpp',
'GameConfigs.cpp', 'GameConfigs.cpp',
'sm_crc32.cpp', 'sm_crc32.cpp',
'smn_profiler.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': if builder.target_platform == 'windows':
binary.sources += ['thread/WinThreads.cpp'] binary.sources += ['thread/WinThreads.cpp']
@@ -32,6 +32,7 @@
#ifndef _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_ #ifndef _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
#define _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_ #define _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
#include "common_logic.h"
#include <IHandleSys.h> #include <IHandleSys.h>
class AutoHandleRooter class AutoHandleRooter
+114 -116
View File
@@ -77,12 +77,10 @@ static const char *g_pParseEngine = NULL;
#define PLATFORM_SERVER_BINARY "server.dll" #define PLATFORM_SERVER_BINARY "server.dll"
#elif defined PLATFORM_LINUX #elif defined PLATFORM_LINUX
#define PLATFORM_NAME "linux" #define PLATFORM_NAME "linux"
#define PLATFORM_COMPAT_ALT "mac" /* Alternate platform name if game data is missing for primary one */
#define PLATFORM_SERVER_BINARY "server_i486.so" #define PLATFORM_SERVER_BINARY "server_i486.so"
#elif defined PLATFORM_APPLE #elif defined PLATFORM_APPLE
#define PLATFORM_NAME "mac" #define PLATFORM_NAME "mac"
#define PLATFORM_COMPAT_ALT "linux" #define PLATFORM_SERVER_BINARY "server.dylib"
#define PLATFORM_SERVER_BINARY "server.dylib"
#endif #endif
struct TempSigInfo struct TempSigInfo
@@ -118,33 +116,12 @@ static bool DoesEngineMatch(const char *value)
return strcmp(value, g_pParseEngine) == 0; 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) CGameConfig::CGameConfig(const char *file, const char *engine)
{ {
strncopy(m_File, file, sizeof(m_File)); strncopy(m_File, file, sizeof(m_File));
m_pAddresses = new KTrie<AddressConf>();
m_pStrings = new BaseStringTable(512);
m_RefCount = 0;
m_CustomLevel = 0; m_CustomLevel = 0;
m_CustomHandler = NULL; m_CustomHandler = NULL;
@@ -164,7 +141,8 @@ CGameConfig::CGameConfig(const char *file, const char *engine)
CGameConfig::~CGameConfig() CGameConfig::~CGameConfig()
{ {
g_GameConfigs.RemoveCachedConfig(this); delete m_pAddresses;
delete m_pStrings;
} }
SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name) 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 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_CustomLevel = 0;
m_ParseState = PSTATE_GAMEDEFS_CUSTOM; m_ParseState = PSTATE_GAMEDEFS_CUSTOM;
m_CustomHandler = *pListen;
m_CustomHandler->ReadSMC_ParseStart(); m_CustomHandler->ReadSMC_ParseStart();
break; break;
} }
@@ -254,7 +235,6 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
m_Class[0] = '\0'; m_Class[0] = '\0';
strncopy(m_offset, name, sizeof(m_offset)); strncopy(m_offset, name, sizeof(m_offset));
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET; m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
matched_platform = false;
break; break;
} }
case PSTATE_GAMEDEFS_SIGNATURES: 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)); strncopy(m_offset, name, sizeof(m_offset));
s_TempSig.Reset(); s_TempSig.Reset();
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG; m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
matched_platform = false;
break; break;
} }
case PSTATE_GAMEDEFS_CRC: case PSTATE_GAMEDEFS_CRC:
@@ -301,8 +280,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
if (error[0] != '\0') if (error[0] != '\0')
{ {
m_IgnoreLevel = 1; m_IgnoreLevel = 1;
logger->LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile); smcore.LogError("[SM] Error while parsing CRC section for \"%s\" (%s):", m_Game, m_CurFile);
logger->LogError("[SM] %s", error); smcore.LogError("[SM] %s", error);
} else { } else {
m_ParseState = PSTATE_GAMEDEFS_CRC_BINARY; 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: case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
{ {
if (DoesPlatformMatch(name)) if (strcmp(name, PLATFORM_NAME) == 0)
{ {
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ; 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) 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); smcore.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
logger->LogError("[SM] Unrecognized platform \"%s\"", name); smcore.LogError("[SM] Unrecognized platform \"%s\"", name);
} }
m_IgnoreLevel = 1; m_IgnoreLevel = 1;
} }
@@ -375,12 +354,11 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
strncopy(m_Class, value, sizeof(m_Class)); strncopy(m_Class, value, sizeof(m_Class));
} else if (strcmp(key, "prop") == 0) { } else if (strcmp(key, "prop") == 0) {
strncopy(m_Prop, value, sizeof(m_Prop)); strncopy(m_Prop, value, sizeof(m_Prop));
} else if (IsPlatformCompatible(key, &matched_platform)) { } else if (strcmp(key, PLATFORM_NAME) == 0) {
m_Offsets.replace(m_offset, atoi(value)); m_Offsets.replace(m_offset, atoi(value));
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { } else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
ke::AString vstr(value); m_Keys.replace(key, m_pStrings->AddString(value));
m_Keys.replace(key, ke::Move(vstr));
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) { } else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
if (strcmp(key, "game") == 0) if (strcmp(key, "game") == 0)
{ {
@@ -407,14 +385,14 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
} }
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) { } 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)); strncopy(s_TempSig.sig, value, sizeof(s_TempSig.sig));
} else if (strcmp(key, "library") == 0) { } else if (strcmp(key, "library") == 0) {
strncopy(s_TempSig.library, value, sizeof(s_TempSig.library)); strncopy(s_TempSig.library, value, sizeof(s_TempSig.library));
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) { } else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) {
if (DoesPlatformMatch(key) if (strcmp(key, PLATFORM_NAME) == 0
&& s_ServerBinCRC_Ok && s_ServerBinCRC_Ok
&& !bShouldBeReadingDefault) && !bShouldBeReadingDefault)
{ {
@@ -435,7 +413,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
} }
else 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) { } else if (strcmp(key, "signature") == 0) {
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature)); 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) if (((strcmp(m_Game, "*") != 0) && strcmp(m_Game, "#default") != 0)
&& (!m_Offsets.retrieve(m_offset))) && (!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_Class,
m_Prop, m_Prop,
m_CurFile, m_CurFile,
@@ -556,12 +534,10 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
void *final_addr = NULL; void *final_addr = NULL;
if (addrInBase == NULL) if (addrInBase == NULL)
{ {
logger->LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")", smcore.LogError("[SM] Unrecognized library \"%s\" (gameconf \"%s\")",
s_TempSig.library, s_TempSig.library,
m_CurFile); m_CurFile);
} } else {
else if (s_TempSig.sig[0])
{
if (s_TempSig.sig[0] == '@') if (s_TempSig.sig[0] == '@')
{ {
#if defined PLATFORM_WINDOWS #if defined PLATFORM_WINDOWS
@@ -570,7 +546,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (VirtualQuery(addrInBase, &mem, sizeof(mem))) if (VirtualQuery(addrInBase, &mem, sizeof(mem)))
final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]); final_addr = g_MemUtils.ResolveSymbol(mem.AllocationBase, &s_TempSig.sig[1]);
else 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 #elif defined PLATFORM_POSIX
Dl_info info; Dl_info info;
/* GNU only: returns 0 on error, inconsistent! >:[ */ /* 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]); final_addr = dlsym(handle, &s_TempSig.sig[1]);
dlclose(handle); dlclose(handle);
} else { } else {
logger->LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")", smcore.LogError("[SM] Unable to load library \"%s\" (gameconf \"%s\")",
s_TempSig.library, s_TempSig.library,
m_File); m_File);
} }
} else { } 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, s_TempSig.library,
m_File); m_File);
} }
#endif #endif
} }
if (final_addr)
if (!final_addr)
{ {
/* First, preprocess the signature */ goto skip_find;
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);
}
} }
/* 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; m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
break; break;
@@ -634,7 +610,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0') if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0')
{ {
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead); AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead);
m_Addresses.replace(m_Address, addrConf); m_pAddresses->replace(m_Address, addrConf);
} }
break; break;
@@ -779,10 +755,11 @@ static MasterReader master_reader;
bool CGameConfig::Reparse(char *error, size_t maxlength) bool CGameConfig::Reparse(char *error, size_t maxlength)
{ {
/* Reset cached data */ /* Reset cached data */
m_pStrings->Reset();
m_Offsets.clear(); m_Offsets.clear();
m_Props.clear(); m_Props.clear();
m_Keys.clear(); m_Keys.clear();
m_Addresses.clear(); m_pAddresses->clear();
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
@@ -792,19 +769,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
{ {
/* Nope, use the old mechanism. */ /* Nope, use the old mechanism. */
smcore.Format(path, sizeof(path), "%s.txt", m_File); smcore.Format(path, sizeof(path), "%s.txt", m_File);
if (!EnterFile(path, error, maxlength)) return 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;
} }
/* Otherwise, it's time to parse the master. */ /* 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); const char *msg = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Error parsing master gameconf file \"%s\":", path); smcore.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
logger->LogError("[SM] Error %d on line %d, col %d: %s", smcore.LogError("[SM] Error %d on line %d, col %d: %s",
err, err,
state.line, state.line,
state.col, state.col,
@@ -915,8 +880,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
{ {
const char *msg = textparsers->GetSMCErrorString(err); const char *msg = textparsers->GetSMCErrorString(err);
logger->LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile); smcore.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
logger->LogError("[SM] Error %d on line %d, col %d: %s", smcore.LogError("[SM] Error %d on line %d, col %d: %s",
err, err,
state.line, state.line,
state.col, state.col,
@@ -949,15 +914,20 @@ void CGameConfig::SetParseEngine(const char *engine)
bool CGameConfig::GetOffset(const char *key, int *value) 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) const char *CGameConfig::GetKeyValue(const char *key)
{ {
StringHashMap<ke::AString>::Result r = m_Keys.find(key); int *pkey;
if (!r.found()) if ((pkey = m_Keys.retrieve(key)) == NULL)
return NULL; return NULL;
return r->value.chars(); return m_pStrings->GetString(*pkey);
} }
//memory addresses below 0x10000 are automatically considered invalid for dereferencing //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) bool CGameConfig::GetAddress(const char *key, void **retaddr)
{ {
StringHashMap<AddressConf>::Result r = m_Addresses.find(key); AddressConf *addrConf;
if (!r.found())
addrConf = m_pAddresses->retrieve(key);
if (!addrConf)
{ {
*retaddr = NULL; *retaddr = NULL;
return false; return false;
} }
AddressConf &addrConf = r->value;
void *addr; void *addr;
if (!GetMemSig(addrConf.signatureName, &addr)) if (!GetMemSig(addrConf->signatureName, &addr))
{ {
*retaddr = NULL; *retaddr = NULL;
return false; 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 //NULLs in the middle of an indirection chain are bad, end NULL is ok
if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS) if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
@@ -1014,15 +984,32 @@ CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigne
SendProp *CGameConfig::GetSendProp(const char *key) SendProp *CGameConfig::GetSendProp(const char *key)
{ {
SendProp *prop; SendProp **pProp;
if (!m_Props.retrieve(key, &prop))
if ((pProp = m_Props.retrieve(key)) == NULL)
return NULL; return NULL;
return prop;
return *pProp;
} }
bool CGameConfig::GetMemSig(const char *key, void **addr) 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() GameConfigManager::GameConfigManager()
@@ -1073,16 +1060,17 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
#endif #endif
CGameConfig *pConfig; 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; *_pConfig = pConfig;
return true; return true;
} }
pConfig = new CGameConfig(file); pConfig = new CGameConfig(file);
pConfig->AddRef();
/* :HACKHACK: Don't parse the main config file */ /* :HACKHACK: Don't parse the main config file */
bool retval = true; bool retval = true;
@@ -1091,16 +1079,25 @@ bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pCon
retval = pConfig->Reparse(error, maxlength); retval = pConfig->Reparse(error, maxlength);
} }
m_cfgs.push_back(pConfig);
m_Lookup.insert(file, pConfig); m_Lookup.insert(file, pConfig);
pConfig->IncRefCount();
*_pConfig = pConfig; *_pConfig = pConfig;
return retval; return retval;
} }
void GameConfigManager::CloseGameConfigFile(IGameConfig *cfg) void GameConfigManager::CloseGameConfigFile(IGameConfig *cfg)
{ {
CGameConfig *pConfig = (CGameConfig *)cfg; CGameConfig *pConfig = (CGameConfig *)cfg;
pConfig->Release();
if (pConfig->DecRefCount() == 0)
{
m_Lookup.remove(pConfig->m_File);
delete pConfig;
}
} }
extern Handle_t g_GameConfigsType; extern Handle_t g_GameConfigsType;
@@ -1124,16 +1121,22 @@ void GameConfigManager::AddUserConfigHook(const char *sectionname, ITextListener
m_customHandlers.insert(sectionname, listener); 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; ITextListener_SMC **pListener = m_customHandlers.retrieve(sectionname);
if (!m_customHandlers.retrieve(sectionname, &listener))
return;
if (listener != aListener) if (pListener == NULL)
{
return; return;
}
if (*pListener != listener)
{
return;
}
m_customHandlers.remove(sectionname); m_customHandlers.remove(sectionname);
return; return;
} }
@@ -1144,8 +1147,3 @@ void GameConfigManager::AcquireLock()
void GameConfigManager::ReleaseLock() 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -35,9 +35,9 @@
#include "common_logic.h" #include "common_logic.h"
#include <IGameConfigs.h> #include <IGameConfigs.h>
#include <ITextParsers.h> #include <ITextParsers.h>
#include <am-refcounting.h> #include <sh_list.h>
#include <sm_stringhashmap.h> #include "sm_memtable.h"
#include <sm_namehashset.h> #include <sm_trie_tpl.h>
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook; using namespace SourceHook;
@@ -46,8 +46,7 @@ class SendProp;
class CGameConfig : class CGameConfig :
public ITextListener_SMC, public ITextListener_SMC,
public IGameConfig, public IGameConfig
public ke::Refcounted<CGameConfig>
{ {
friend class GameConfigManager; friend class GameConfigManager;
public: public:
@@ -68,18 +67,18 @@ public: //IGameConfig
SendProp *GetSendProp(const char *key); SendProp *GetSendProp(const char *key);
bool GetMemSig(const char *key, void **addr); bool GetMemSig(const char *key, void **addr);
bool GetAddress(const char *key, void **addr); bool GetAddress(const char *key, void **addr);
public: //NameHashSet public:
static inline bool matches(const char *key, const CGameConfig *value) void IncRefCount();
{ unsigned int DecRefCount();
return strcmp(key, value->m_File) == 0;
}
private: private:
BaseStringTable *m_pStrings;
char m_File[PLATFORM_MAX_PATH]; char m_File[PLATFORM_MAX_PATH];
char m_CurFile[PLATFORM_MAX_PATH]; char m_CurFile[PLATFORM_MAX_PATH];
StringHashMap<int> m_Offsets; KTrie<int> m_Offsets;
StringHashMap<SendProp *> m_Props; KTrie<SendProp *> m_Props;
StringHashMap<ke::AString> m_Keys; KTrie<int> m_Keys;
StringHashMap<void *> m_Sigs; KTrie<void *> m_Sigs;
unsigned int m_RefCount;
/* Parse states */ /* Parse states */
int m_ParseState; int m_ParseState;
unsigned int m_IgnoreLevel; unsigned int m_IgnoreLevel;
@@ -92,7 +91,6 @@ private:
bool matched_game; bool matched_game;
bool had_engine; bool had_engine;
bool matched_engine; bool matched_engine;
bool matched_platform;
/* Custom Sections */ /* Custom Sections */
unsigned int m_CustomLevel; unsigned int m_CustomLevel;
@@ -114,7 +112,7 @@ private:
char m_AddressSignature[64]; char m_AddressSignature[64];
int m_AddressReadCount; int m_AddressReadCount;
int m_AddressRead[8]; int m_AddressRead[8];
StringHashMap<AddressConf> m_Addresses; KTrie<AddressConf> *m_pAddresses;
const char *m_pEngine; const char *m_pEngine;
const char *m_pBaseEngine; const char *m_pBaseEngine;
}; };
@@ -140,12 +138,11 @@ public: //SMGlobalClass
void OnSourceModStartup(bool late); void OnSourceModStartup(bool late);
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModAllShutdown(); void OnSourceModAllShutdown();
public:
void RemoveCachedConfig(CGameConfig *config);
private: private:
NameHashSet<CGameConfig *> m_Lookup; List<CGameConfig *> m_cfgs;
KTrie<CGameConfig *> m_Lookup;
public: public:
StringHashMap<ITextListener_SMC *> m_customHandlers; KTrie<ITextListener_SMC *> m_customHandlers;
}; };
extern GameConfigManager g_GameConfigs; 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, NULL,
"Stream failed to open", "Stream failed to open",
"Stream returned read error", "Stream returned read error",
"Callback error", NULL,
"Un-quoted section has invalid tokens", "Un-quoted section has invalid tokens",
"Section declared without header", "Section declared without header",
"Section declared with unknown tokens", "Section declared with unknown tokens",
-39
View File
@@ -33,48 +33,9 @@
#define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H #define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
#include <IThreader.h> #include <IThreader.h>
#include <am-thread-utils.h>
#include <am-utility.h>
using namespace SourceMod; 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; extern IThreader *g_pThreader;
#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H #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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -96,11 +96,11 @@ void CPhraseFile::ParseWarning(const char *message, ...)
if (!m_FileLogged) 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; m_FileLogged = true;
} }
logger->LogError("[SM] %s", buffer); smcore.LogError("[SM] %s", buffer);
} }
void CPhraseFile::ReparseFile() void CPhraseFile::ReparseFile()
@@ -142,8 +142,8 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str(); msg = m_ParseError.c_str();
} }
logger->LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str()); smcore.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] Error (line %d, column %d): %s", states.line, states.col, msg);
} }
const char *code; const char *code;
@@ -175,10 +175,10 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str(); 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, code,
m_File.c_str()); 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.line,
states.col, states.col,
msg); msg);
@@ -210,7 +210,12 @@ SMCResult CPhraseFile::ReadSMC_NewSection(const SMCStates *states, const char *n
m_ParseState = PPS_InPhrase; m_ParseState = PPS_InPhrase;
recognized = true; recognized = true;
if (!m_PhraseLookup.retrieve(name, &m_CurPhrase)) int *pvalue;
if ((pvalue = m_PhraseLookup.retrieve(name)) != NULL)
{
m_CurPhrase = *pvalue;
}
else
{ {
phrase_t *pPhrase; phrase_t *pPhrase;
@@ -647,11 +652,11 @@ TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_i
return Trans_BadLanguage; return Trans_BadLanguage;
} }
int address; int *pvalue;
if (!m_PhraseLookup.retrieve(szPhrase, &address)) if ((pvalue = m_PhraseLookup.retrieve(szPhrase)) == NULL)
return Trans_BadPhrase; 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_t *trans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl);
trans = &trans[lang_id]; trans = &trans[lang_id];
@@ -728,7 +733,10 @@ ConfigResult Translator::OnSourceModConfigChanged(const char *key,
void Translator::OnSourceModLevelChange(const char *mapName) void Translator::OnSourceModLevelChange(const char *mapName)
{ {
RebuildLanguageDatabase(); /* Refresh language stuff */
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
RebuildLanguageDatabase(path);
} }
void Translator::OnSourceModAllInitialized() void Translator::OnSourceModAllInitialized()
@@ -754,7 +762,15 @@ void Translator::OnSourceModShutdown()
bool Translator::GetLanguageByCode(const char *code, unsigned int *index) 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) 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'; 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() unsigned int Translator::GetLanguageCount()
@@ -804,7 +828,7 @@ unsigned int Translator::FindOrAddPhraseFile(const char *phrase_file)
return idx; return idx;
} }
void Translator::RebuildLanguageDatabase() void Translator::RebuildLanguageDatabase(const char *lang_header_file)
{ {
/* Erase everything we have */ /* Erase everything we have */
m_LCodeLookup.clear(); m_LCodeLookup.clear();
@@ -818,12 +842,9 @@ void Translator::RebuildLanguageDatabase()
m_Languages.clear(); m_Languages.clear();
/* Start anew */ /* Start anew */
char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
SMCError err; SMCError err;
SMCStates states; SMCStates states;
if ((err=textparsers->ParseFile_SMC(path, this, &states)) != SMCError_Okay) if ((err=textparsers->ParseFile_SMC(lang_header_file, this, &states)) != SMCError_Okay)
{ {
const char *str_err = textparsers->GetSMCErrorString(err); const char *str_err = textparsers->GetSMCErrorString(err);
if (!str_err) if (!str_err)
@@ -831,21 +852,27 @@ void Translator::RebuildLanguageDatabase()
str_err = m_CustomError.c_str(); str_err = m_CustomError.c_str();
} }
logger->LogError("[SM] Failed to parse language header file: \"%s\"", path); smcore.LogError("[SM] Failed to parse language header file: \"%s\"", lang_header_file);
logger->LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err); 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)); smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH; m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
} }
else
{
m_ServerLang = *pServerLang;
}
if (!m_Languages.size()) 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++) 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) 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; 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) 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); AddLanguage(key, value);
return SMCResult_Continue; return SMCResult_Continue;
@@ -914,11 +933,15 @@ bool Translator::AddLanguage(const char *langcode, const char *description)
} }
lower[len] = '\0'; lower[len] = '\0';
if (m_LAliases.contains(lower)) if (m_LAliases.retrieve(lower))
return false; return false;
unsigned int idx; unsigned int idx;
if (!m_LCodeLookup.retrieve(langcode, &idx)) if (unsigned int *pIdx = m_LCodeLookup.retrieve(langcode))
{
idx = *pIdx;
}
else
{ {
Language *pLanguage = new Language; Language *pLanguage = new Language;
idx = m_Languages.size(); idx = m_Languages.size();
@@ -1033,11 +1056,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned
{ {
if (fail_phrase != NULL) 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 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; return false;
+6 -6
View File
@@ -33,7 +33,7 @@
#define _INCLUDE_SOURCEMOD_TRANSLATOR_H_ #define _INCLUDE_SOURCEMOD_TRANSLATOR_H_
#include "common_logic.h" #include "common_logic.h"
#include <sm_stringhashmap.h> #include <sm_trie_tpl.h>
#include <sh_string.h> #include <sh_string.h>
#include <sh_vector.h> #include <sh_vector.h>
#include "sm_memtable.h" #include "sm_memtable.h"
@@ -54,7 +54,7 @@ enum PhraseParseState
struct Language struct Language
{ {
char m_code2[32]; char m_code2[4];
int m_CanonicalName; int m_CanonicalName;
}; };
@@ -79,7 +79,7 @@ private:
void ParseError(const char *message, ...); void ParseError(const char *message, ...);
void ParseWarning(const char *message, ...); void ParseWarning(const char *message, ...);
private: private:
StringHashMap<int> m_PhraseLookup; KTrie<int> m_PhraseLookup;
String m_File; String m_File;
Translator *m_pTranslator; Translator *m_pTranslator;
PhraseParseState m_ParseState; PhraseParseState m_ParseState;
@@ -115,6 +115,7 @@ public: // ITextListener_SMC
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
SMCResult ReadSMC_LeavingSection(const SMCStates *states); SMCResult ReadSMC_LeavingSection(const SMCStates *states);
public: public:
void RebuildLanguageDatabase(const char *lang_header_file);
unsigned int FindOrAddPhraseFile(const char *phrase_file); unsigned int FindOrAddPhraseFile(const char *phrase_file);
BaseStringTable *GetStringTable(); BaseStringTable *GetStringTable();
unsigned int GetLanguageCount(); unsigned int GetLanguageCount();
@@ -145,15 +146,14 @@ public: //ITranslator
size_t *pOutLength, size_t *pOutLength,
const char **pFailPhrase); const char **pFailPhrase);
bool GetLanguageInfo(unsigned int number, const char **code, const char **name); bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
void RebuildLanguageDatabase();
private: private:
bool AddLanguage(const char *langcode, const char *description); bool AddLanguage(const char *langcode, const char *description);
private: private:
CVector<Language *> m_Languages; CVector<Language *> m_Languages;
CVector<CPhraseFile *> m_Files; CVector<CPhraseFile *> m_Files;
BaseStringTable *m_pStringTab; BaseStringTable *m_pStringTab;
StringHashMap<unsigned int> m_LCodeLookup; KTrie<unsigned int> m_LCodeLookup;
StringHashMap<unsigned int> m_LAliases; KTrie<unsigned int> m_LAliases;
bool m_InLanguageSection; bool m_InLanguageSection;
String m_CustomError; String m_CustomError;
unsigned int m_ServerLang; 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 * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -32,50 +32,33 @@
#include <stdlib.h> #include <stdlib.h>
#include <sm_platform.h> #include <sm_platform.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include "common_logic.h" #include "common_logic.h"
#include "TextParsers.h" #include "TextParsers.h"
#include "Profiler.h"
#include "sm_crc32.h" #include "sm_crc32.h"
#include "MemoryUtils.h" #include "MemoryUtils.h"
#include "stringutil.h" #include "stringutil.h"
#include "ThreadSupport.h" #include "ThreadSupport.h"
#include "Translator.h" #include "Translator.h"
#include "GameConfigs.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; sm_core_t smcore;
IHandleSys *handlesys = &g_HandleSys; IHandleSys *handlesys;
IdentityToken_t *g_pCoreIdent; IdentityToken_t *g_pCoreIdent;
SMGlobalClass *SMGlobalClass::head = NULL; SMGlobalClass *SMGlobalClass::head = NULL;
ISourceMod *g_pSM; ISourceMod *g_pSM;
ILibrarySys *libsys; ILibrarySys *libsys;
ITextParsers *textparser = &g_TextParser; ITextParsers *textparser = &g_TextParser;
IVEngineServer *engine; IVEngineServer *engine;
IShareSys *sharesys = &g_ShareSys; IShareSys *sharesys;
IRootConsole *rootmenu; IRootConsole *rootmenu;
IPluginManager *pluginsys = g_PluginSys.GetOldAPI(); IPluginManager *pluginsys;
IForwardManager *forwardsys = &g_Forwards; IForwardManager *forwardsys;
ITimerSystem *timersys; ITimerSystem *timersys;
ServerGlobals serverGlobals; ServerGlobals serverGlobals;
IPlayerManager *playerhelpers; IPlayerManager *playerhelpers;
IAdminSystem *adminsys = &g_Admins; IAdminSystem *adminsys;
IGameHelpers *gamehelpers; 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) static void AddCorePhraseFile(const char *filename)
{ {
@@ -87,41 +70,11 @@ static IGameConfig *GetCoreGameConfig()
return g_pGameConf; 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 = static sm_logic_t logic =
{ {
NULL, NULL,
g_pThreader, g_pThreader,
sm_profiler,
&g_Translator, &g_Translator,
stristr, stristr,
CoreTranslate, CoreTranslate,
@@ -129,23 +82,7 @@ static sm_logic_t logic =
UTIL_ReplaceAll, UTIL_ReplaceAll,
UTIL_ReplaceEx, UTIL_ReplaceEx,
UTIL_DecodeHexString, UTIL_DecodeHexString,
GetCoreGameConfig, 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
}; };
static void logic_init(const sm_core_t* core, sm_logic_t* _logic) 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(_logic, &logic, sizeof(sm_logic_t));
memcpy(&serverGlobals, core->serverGlobals, sizeof(ServerGlobals)); memcpy(&serverGlobals, core->serverGlobals, sizeof(ServerGlobals));
handlesys = core->handlesys;
libsys = core->libsys; libsys = core->libsys;
engine = core->engine; engine = core->engine;
g_pCoreIdent = core->core_ident;
g_pSM = core->sm; g_pSM = core->sm;
sharesys = core->sharesys;
rootmenu = core->rootmenu; rootmenu = core->rootmenu;
pluginsys = core->pluginsys;
forwardsys = core->forwardsys;
timersys = core->timersys; timersys = core->timersys;
playerhelpers = core->playerhelpers; playerhelpers = core->playerhelpers;
adminsys = core->adminsys;
gamehelpers = core->gamehelpers; 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() PLATFORM_EXTERN_C ITextParsers *get_textparsers()
@@ -191,7 +125,7 @@ PLATFORM_EXTERN_C LogicInitFunction logic_load(uint32_t magic)
void CoreNativesToAdd::OnSourceModAllInitialized() void CoreNativesToAdd::OnSourceModAllInitialized()
{ {
g_CoreNatives.AddNatives(m_NativeList); smcore.AddNatives(m_NativeList);
} }
/* Overload a few things to prevent libstdc++ linking */ /* Overload a few things to prevent libstdc++ linking */
-4
View File
@@ -52,10 +52,6 @@ extern ServerGlobals serverGlobals;
extern IPlayerManager *playerhelpers; extern IPlayerManager *playerhelpers;
extern IAdminSystem *adminsys; extern IAdminSystem *adminsys;
extern IGameHelpers *gamehelpers; extern IGameHelpers *gamehelpers;
extern IScriptManager *scripts;
extern IExtensionSys *extsys;
extern ILogger *logger;
extern IMenuManager *menus;
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */ #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 * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
@@ -29,30 +29,20 @@
* Version: $Id$ * Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_INTERCOM_H_
#define _INCLUDE_SOURCEMOD_INTERCOM_H_
#include <sp_vm_api.h> #include <sp_vm_api.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <IShareSys.h> #include <IShareSys.h>
#include <IPluginSys.h>
#include <IDBDriver.h> #ifndef _INCLUDE_SOURCEMOD_INTERCOM_H_
#include <sh_string.h> #define _INCLUDE_SOURCEMOD_INTERCOM_H_
#include <sp_vm_api.h>
#include <sh_vector.h>
#include <IExtensionSys.h>
#include <IForwardSys.h>
#include <IAdminSystem.h>
using namespace SourceMod; using namespace SourceMod;
using namespace SourcePawn;
using namespace SourceHook;
/** /**
* Add 1 to the RHS of this expression to bump the intercom file * Add 1 to the RHS of this expression to bump the intercom file
* This is to prevent mismatching core/logic binaries * This is to prevent mismatching core/logic binaries
*/ */
#define SM_LOGIC_MAGIC (0x0F47C0DE - 29) #define SM_LOGIC_MAGIC (0x0F47C0DE - 18)
#if defined SM_LOGIC #if defined SM_LOGIC
class IVEngineServer class IVEngineServer
@@ -62,16 +52,9 @@ class IVEngineServer_Logic
{ {
public: public:
virtual bool IsMapValid(const char *map) = 0; 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 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; typedef int FileFindHandle_t;
#if defined SM_LOGIC #if defined SM_LOGIC
@@ -83,25 +66,7 @@ class IFileSystem_Logic
public: public:
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0; virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
virtual const char *FindNext(FileFindHandle_t handle) = 0; virtual const char *FindNext(FileFindHandle_t handle) = 0;
virtual bool FindIsDirectory(FileFindHandle_t handle) = 0;
virtual void FindClose(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 namespace SourceMod
@@ -120,38 +85,11 @@ namespace SourceMod
class IPhraseCollection; class IPhraseCollection;
class ITranslator; class ITranslator;
class IGameConfig; class IGameConfig;
class IMenuManager;
} }
class IVEngineServer; class IVEngineServer;
class IFileSystem; class IFileSystem;
class ConVar; 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 struct ServerGlobals
{ {
@@ -160,148 +98,32 @@ struct ServerGlobals
float *frametime; 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 struct sm_core_t
{ {
/* Objects */ /* Objects */
IHandleSys *handlesys;
IdentityToken_t *core_ident;
ISourceMod *sm; ISourceMod *sm;
ILibrarySys *libsys; ILibrarySys *libsys;
IVEngineServer *engine; IVEngineServer *engine;
IFileSystem *filesystem; IFileSystem *filesystem;
IPlayerInfo_Logic *playerInfo; IShareSys *sharesys;
IRootConsole *rootmenu; IRootConsole *rootmenu;
IPluginManager *pluginsys;
IForwardManager *forwardsys;
ITimerSystem *timersys; ITimerSystem *timersys;
IPlayerManager *playerhelpers; IPlayerManager *playerhelpers;
IAdminSystem *adminsys;
IGameHelpers *gamehelpers; IGameHelpers *gamehelpers;
IMenuManager *menus;
ISourcePawnEngine **spe1;
ISourcePawnEngine2 **spe2;
/* Functions */ /* Functions */
void (*AddNatives)(sp_nativeinfo_t* nlist);
ConVar * (*FindConVar)(const char*); ConVar * (*FindConVar)(const char*);
unsigned int (*strncopy)(char*, const char*, size_t); unsigned int (*strncopy)(char*, const char*, size_t);
char * (*TrimWhitespace)(char *, size_t &); char * (*TrimWhitespace)(char *, size_t &);
void (*LogToGame)(const char *message); void (*LogError)(const char*, ...);
void (*ConPrint)(const char *message);
const char * (*GetCvarString)(ConVar*); const char * (*GetCvarString)(ConVar*);
bool (*GetCvarBool)(ConVar*);
size_t (*Format)(char*, size_t, const char*, ...); 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 **, bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
unsigned int, unsigned int &, size_t *, const char **); unsigned int, unsigned int &, size_t *, const char **);
size_t (*atcprintf)(char *, size_t, const char *, IPluginContext *, const cell_t *, int *); size_t (*atcprintf)(char *, size_t, const char *, IPluginContext *, const cell_t *, int *);
@@ -310,33 +132,18 @@ struct sm_core_t
const char * (*GetSourceEngineName)(); const char * (*GetSourceEngineName)();
bool (*SymbolsAreHidden)(); bool (*SymbolsAreHidden)();
const char * (*GetCoreConfigValue)(const char*); 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 */ /* Data */
ServerGlobals *serverGlobals; ServerGlobals *serverGlobals;
void * serverFactory; void * serverFactory;
void * engineFactory; void * engineFactory;
void * matchmakingDSFactory; void * matchmakingDSFactory;
SMGlobalClass * listeners;
}; };
struct sm_logic_t struct sm_logic_t
{ {
SMGlobalClass *head; SMGlobalClass *head;
IThreader *threader; IThreader *threader;
IProfiler *profiler;
ITranslator *translator; ITranslator *translator;
const char *(*stristr)(const char *, const char *); const char *(*stristr)(const char *, const char *);
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...); 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); char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
size_t (*DecodeHexString)(unsigned char *, size_t, const char *); size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
IGameConfig * (*GetCoreGameConfig)(); 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); 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)(); typedef ITextParsers *(*GetITextParsers)();
#endif /* _INCLUDE_SOURCEMOD_INTERCOM_H_ */ #endif /* _INCLUDE_SOURCEMOD_INTERCOM_H_ */
+3 -14
View File
@@ -112,19 +112,10 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\common_logic.cpp" /> <ClCompile Include="..\common_logic.cpp" />
<ClCompile Include="..\DebugReporter.cpp" />
<ClCompile Include="..\ExtensionSys.cpp" />
<ClCompile Include="..\GameConfigs.cpp" /> <ClCompile Include="..\GameConfigs.cpp" />
<ClCompile Include="..\HandleSys.cpp" />
<ClCompile Include="..\MemoryUtils.cpp" /> <ClCompile Include="..\MemoryUtils.cpp" />
<ClCompile Include="..\NativeInvoker.cpp" />
<ClCompile Include="..\NativeOwner.cpp" />
<ClCompile Include="..\PhraseCollection.cpp" /> <ClCompile Include="..\PhraseCollection.cpp" />
<ClCompile Include="..\PluginSys.cpp" />
<ClCompile Include="..\Profiler.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="..\sm_crc32.cpp" />
<ClCompile Include="..\smn_admin.cpp" /> <ClCompile Include="..\smn_admin.cpp" />
<ClCompile Include="..\smn_adt_array.cpp" /> <ClCompile Include="..\smn_adt_array.cpp" />
@@ -158,17 +149,12 @@
<ClInclude Include="..\AutoHandleRooter.h" /> <ClInclude Include="..\AutoHandleRooter.h" />
<ClInclude Include="..\CellArray.h" /> <ClInclude Include="..\CellArray.h" />
<ClInclude Include="..\common_logic.h" /> <ClInclude Include="..\common_logic.h" />
<ClInclude Include="..\ExtensionSys.h" />
<ClInclude Include="..\GameConfigs.h" /> <ClInclude Include="..\GameConfigs.h" />
<ClInclude Include="..\intercom.h" /> <ClInclude Include="..\intercom.h" />
<ClInclude Include="..\MemoryUtils.h" /> <ClInclude Include="..\MemoryUtils.h" />
<ClInclude Include="..\MersenneTwister.h" /> <ClInclude Include="..\MersenneTwister.h" />
<ClInclude Include="..\NativeInvoker.h" />
<ClInclude Include="..\NativeOwner.h" />
<ClInclude Include="..\PhraseCollection.h" /> <ClInclude Include="..\PhraseCollection.h" />
<ClInclude Include="..\PluginSys.h" />
<ClInclude Include="..\Profiler.h" /> <ClInclude Include="..\Profiler.h" />
<ClInclude Include="..\ShareSys.h" />
<ClInclude Include="..\sm_crc32.h" /> <ClInclude Include="..\sm_crc32.h" />
<ClInclude Include="..\sm_memtable.h" /> <ClInclude Include="..\sm_memtable.h" />
<ClInclude Include="..\sm_symtable.h" /> <ClInclude Include="..\sm_symtable.h" />
@@ -180,6 +166,9 @@
<ClInclude Include="..\thread\WinThreads.h" /> <ClInclude Include="..\thread\WinThreads.h" />
<ClInclude Include="..\Translator.h" /> <ClInclude Include="..\Translator.h" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>

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