y_commands.inc 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760
  1. /**--------------------------------------------------------------------------**\
  2. ================================
  3. Y Sever Includes - Commands Core
  4. ================================
  5. Description:
  6. Runs commands registered with the system and calls the required functions.
  7. Also handles alternate names and prefixes. Based very loosely on dcmd.
  8. Legal:
  9. Version: MPL 1.1
  10. The contents of this file are subject to the Mozilla Public License Version
  11. 1.1 (the "License"); you may not use this file except in compliance with
  12. the License. You may obtain a copy of the License at
  13. http://www.mozilla.org/MPL/
  14. Software distributed under the License is distributed on an "AS IS" basis,
  15. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  16. for the specific language governing rights and limitations under the
  17. License.
  18. The Original Code is the YSI commands include.
  19. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  20. Portions created by the Initial Developer are Copyright (C) 2011
  21. the Initial Developer. All Rights Reserved.
  22. Contributors:
  23. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  24. Thanks:
  25. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  26. ZeeX - Very productive conversations.
  27. koolk - IsPlayerinAreaEx code.
  28. TheAlpha - Danish translation.
  29. breadfish - German translation.
  30. Fireburn - Dutch translation.
  31. yom - French translation.
  32. 50p - Polish translation.
  33. Zamaroht - Spanish translation.
  34. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  35. for me to strive to better.
  36. Pixels^ - Running XScripters where the idea was born.
  37. Matite - Pestering me to release it and using it.
  38. Very special thanks to:
  39. Thiadmer - PAWN, whose limits continue to amaze me!
  40. Kye/Kalcor - SA:MP.
  41. SA:MP Team past, present and future - SA:MP.
  42. Version:
  43. 0.1.4
  44. Changelog:
  45. 20/10/10:
  46. Fixed a bug with insensitive commands - my fault for not testing.
  47. 06/01/08:
  48. Improved master and /help support.
  49. 04/01/08:
  50. Fixed bad element in Command_SetDeniedReturn.
  51. 12/08/07:
  52. Added master support.
  53. 24/06/07:
  54. Modifed a few functions to use Bit_GetBit for speed.
  55. 04/05/07:
  56. Completed command use support.
  57. Added invalid character protection.
  58. 02/05/07:
  59. Added YSI_ prefix to all globals.
  60. 14/04/07:
  61. Updated header documentation with more than changelog/functions.
  62. Added function name requesting.
  63. 13/04/07:
  64. Added function documentation.
  65. Added wrapped functions for e_COMM_FLAG values missing them.
  66. Added header function list.
  67. 12/04/07:
  68. Added command removal.
  69. 11/04/07:
  70. Changed system slightly to handle names and alt names separately. Still
  71. need a better way of ignoring names when alt names are used.
  72. 10/04/07:
  73. First version.
  74. Functions:
  75. Public:
  76. Command_Add - Adds a command to the array for processing.
  77. Command_Remove - Removes a command.
  78. Command_Name - Gets the name of a command in a property.
  79. Core:
  80. Command_Process - Called from OnPlayerCommandText to process entered commands.
  81. Command_Parse - Sorts added commands into a binary tree.
  82. Command_Hash - Hashes a word for command hashing.
  83. Command_ProcRem - Processes a help command in the master script.
  84. Stock:
  85. Command_SetDisconnectReturn - Sets the return value for unconnected players.
  86. Command_UseShortCuts - Toggles use of per-player command shortcuts.
  87. Command_SetDeniedReturn - Sets the return value for denied use commands.
  88. Command_UseDeniedMessage - Toggles the use of an error message for denied.
  89. Command_SetIllegalReturn - Sets the return value for illegal characters.
  90. Command_UseAltNames - Toggles the use of ini defined alternate names.
  91. Command_UsePrefix - Toggles the use of a global prefix.
  92. Command_UseSpace - Toggles the use of a space between prefix and command.
  93. Command_SetAltName - Sets the alternate name of a function.
  94. Command_SetPrefix - Sets the pfexix to be typed.
  95. Comamnd_SetPlayerUse - Sets wether or not a player can use a command.
  96. Comamnd_SetPlayerUseByID - Sets wether or not a player can use a command.
  97. Command_FindByName - Finds a command in a possibly sorted list.
  98. Static:
  99. Command_FindFast - Finds a function by binary search of function name.
  100. Command_FindAlt - Finds a function by binary search of alternate name.
  101. Command_SetSorted - Marks the binary tree as sorted.
  102. Command_FindSlow - Finds a function by linear search of function name.
  103. Command_Find - Finds a function from entered text.
  104. Command_Prefix - Checks the entered prefix.
  105. Command_ReturnName - Returns the name of a function.
  106. Command_GetPlayerCount - Gets the number of commands a player can use.
  107. Inline:
  108. Command_Command - Not used, constructor.
  109. Command_IsCleared - Checks a player is cleared to use a command.
  110. Command_DisconnectReturn - Gets the return value for disconnected players.
  111. Command_UsingShortCuts - Checks if short cuts are being used.
  112. Command_DeniedReturn - Gets the return value for prohibited commands.
  113. Command_IllegalReturn - Gets the return value for invalid characters.
  114. Command_DeniedMessage - Checks if a level error message should be sent.
  115. Command_IsSorted - Checks if the binary tree has been initialised.
  116. Command_UsingAltNames - Checks if alt names are being used.
  117. Command_UsingPrefix - Checks if the prefix is being used.
  118. Command_UsingSpace - Checks if the space option is being used.
  119. Command_CallFunction - Calls the required function.
  120. ycmd - Adds a command to the system.
  121. API:
  122. -
  123. Callbacks:
  124. -
  125. Definitions:
  126. MAX_COMMAND_LENGTH - The maximum length of a command string.
  127. COMMAND_NOT_FOUND - Indicates that a searched for string is not a function.
  128. Enums:
  129. e_COMM_FLAG - Bit mappings for command options.
  130. E_COMMANDS - Structure of the array holding the string data.
  131. Macros:
  132. Command_(%1) - Forwards and declares a standard command for calling.
  133. ycmd(%1) - Adds a command to the array (wrapper for Command_Add).
  134. Tags:
  135. e_COMM_FLAG - Flag type.
  136. Variables:
  137. Global:
  138. -
  139. Static:
  140. YSI_g_sCommands - Holds all the textual data of the commands.
  141. YSI_g_sSearchTree - Tree of hashes for function names.
  142. YSI_g_sAltTree - Tree of hashes for alternate names.
  143. YSI_g_sPrefix - The command prefix.
  144. YSI_g_sPrefixLength - Length of the prefix.
  145. YSI_g_sCommandIndex - Pointer to the next free index in the function array.
  146. YSI_g_sAltCount - The number of commands with altnames.
  147. YSI_g_sCommandFlags - Bit array of command options.
  148. Commands:
  149. commands - Lists all commands available to you.
  150. Compile options:
  151. COMMAND_SENSITIVE - Make commands case sensitive.
  152. COMMAND_ACCURATE - Can use '@' in command names.
  153. MAX_COMMANDS - The maximum number of commands which can be used.
  154. </remarks>
  155. \**--------------------------------------------------------------------------**/
  156. #if defined _INC_y_text
  157. #error y_commands must be included before y_text
  158. #endif
  159. #include "internal\y_version"
  160. #if !defined MAX_COMMANDS
  161. #define MAX_COMMANDS (1024)
  162. #endif
  163. #define _GROUP_MAKE_NAME_CMD<%0...%1> %0Command%1
  164. #define _GROUP_MAKE_LIMIT_CMD MAX_COMMANDS
  165. #define YSIM_U_DISABLE
  166. #include "y_master"
  167. #include "y_groups"
  168. #include "y_debug"
  169. #include "y_hooks"
  170. #include "y_bintree"
  171. #include "y_amx"
  172. #include "y_playerarray"
  173. #include "y_utils"
  174. #include "internal\y_natives"
  175. // Define the CMD: macro. This uses the prefix "@yC_" as it's 32 bits so allows
  176. // for fast command string searching in the publics table and makes the commands
  177. // public without the need for the public keyword.
  178. /*#if YSIM_HAS_MASTER
  179. #if _YSIM_IS_CLIENT
  180. #define YCMD:%1(%2) static stock @_yC%1(%2)
  181. #else
  182. #if _YSIM_IS_SERVER
  183. #define YCMD:%1(%2) @yC_%1(a,b[],c);@yC_%1(a,b[],c)U@(8,YSIM_RETURN,@_yC%1(a,b,c));static @_yC%1(%2)
  184. #else
  185. #define YCMD:%1(%2) @yC_%1(a,b[],c);@yC_%1(a,b[],c)<>{}@yC_%1(a,b[],c)<_YCM:y>U@(8,YSIM_RETURN,@_yC%1(a,b,c));static @_yC%1(%2)
  186. #endif
  187. #endif
  188. #else
  189. #define YCMD:%1(%2) @yC_%1(%2);@yC_%1(%2)
  190. #endif*/
  191. //#define YCMD:%0(%1) RC:%0(%1)
  192. #define _YCMD_0:_YCMD_1:_YCMD_2:%0(%1[]%2) RC:%0(%1[]%2)
  193. #define _YCMD_1:_YCMD_2:%0, Command_GetID(#%0),
  194. #define _YCMD_2:%0) Command_GetID(#%0))
  195. #define @YCMD:%0; Command_TouchNamed(#%0);
  196. #define YCMD: _YCMD_0:_YCMD_1:_YCMD_2:
  197. // ZCMD compatibility.
  198. #define CMD:%0(%1) RC:%0(%1,__help)if(__help)return 0;else
  199. #define COMMAND CMD
  200. // This is opposite AMX_FastString as that's in C, not packed, order.
  201. #define Command_FastString(%1,%2,%3,%4) \
  202. (((%1)<<24)|((%2)<<16)|((%3)<<8)|((%4)<<0))
  203. #define MAX_COMMAND_LENGTH (32)
  204. #define COMMAND_NOT_FOUND (-1)
  205. #if defined COMMAND_SENSITIVE
  206. #define TOLOWER(%0) (%0)
  207. #define COMMAND_END_CMP (0)
  208. #else
  209. //#if defined COMMAND_ACCURATE
  210. // #define TOLOWER(%0) ((%0) | 0x20)
  211. // #define COMMAND_END_CMP (0x20)
  212. //#else
  213. #define TOLOWER(%0) tolower(%0)
  214. #define COMMAND_END_CMP (0)
  215. //#endif
  216. #endif
  217. // Don't forget the AMX_FastString below if you change this.
  218. #define COMMAND_FUNCTION_PREFIX (Command_FastString('@', 'y', 'C', '_'))
  219. // Reset both of these when you remove a command.
  220. #define _Command_IsValid(%0) ((Command_GetPointer(%0)==(%0))||(YSI_g_sCommands[(%0)][E_COMMANDS_MASTERS]==-1))
  221. #define Command_IsValid(%0) ((0<=(%0)<MAX_COMMANDS)&&_Command_IsValid(%0))
  222. enum e_COMM_FLAG (<<= 1)
  223. {
  224. e_COMM_FLAG_PROVIDER = 0x000000FF,
  225. e_COMM_FLAG_SORTED = 0x00000100,
  226. e_COMM_FLAG_PERMISSION_WARN,
  227. e_COMM_FLAG_USE_ALTNAMES,
  228. e_COMM_FLAG_PERMISSION_RET,
  229. e_COMM_FLAG_USE_PREFIX,
  230. e_COMM_FLAG_USE_SPACE,
  231. e_COMM_FLAG_USE_SHORTCUTS,
  232. e_COMM_FLAG_DISCONNECT,
  233. e_COMM_FLAG_ILLEGAL,
  234. e_COMM_FLAG_COLLISION,
  235. e_COMM_FLAG_UNKNOWN,
  236. e_COMM_FLAG_MULPRO,
  237. // Can't easilly add more flags now...
  238. e_COMM_FLAG_OPCP = 0x07C00000, // 0b00000111110..0
  239. e_COMM_FLAG_OPCP_ADD = 0x00400000, // Low bit of above flag.
  240. e_COMM_FLAG_OPCR = 0xF8000000, // 0b11111000000..0
  241. e_COMM_FLAG_OPCR_ADD = 0x08000000 // Low bit of above flag.
  242. }
  243. enum E_COMMANDS
  244. {
  245. E_COMMANDS_FUNCTION[MAX_COMMAND_LENGTH char],
  246. PlayerArray:E_COMMANDS_PLAYERS<MAX_PLAYERS>,
  247. #if YSIM_HAS_MASTER
  248. E_COMMANDS_MASTERS,
  249. #endif
  250. E_COMMANDS_FUNC_POINTER
  251. //E_COMMANDS_AMX_ADDRESS,
  252. }
  253. static stock
  254. #if YSIM_HAS_MASTER
  255. YSI_g_sPlayerProvider[MAX_PLAYERS char] = {-1, ...},
  256. #endif
  257. YSI_g_sCommands[MAX_COMMANDS][E_COMMANDS],
  258. BinaryTree:YSI_g_sSearchTree<MAX_COMMANDS>,
  259. e_COMM_FLAG:YSI_g_sCommandFlags = e_COMM_FLAG:0xFF,
  260. YSI_g_sCommandIndex,
  261. YSI_g_sCommandCount;
  262. /**--------------------------------------------------------------------------**\
  263. <summary>Command_Name</summary>
  264. <param name="index">Index of the command to operate on.</param>
  265. <returns>
  266. -
  267. </returns>
  268. <remarks>
  269. Gets the name of a function from the array.
  270. </remarks>
  271. \**--------------------------------------------------------------------------**/
  272. #define Command_Name(%1) \
  273. (YSI_g_sCommands[(%1)][E_COMMANDS_FUNCTION][1])
  274. /**--------------------------------------------------------------------------**\
  275. <summary>Command_GetFuncName</summary>
  276. <param name="index">Index of the command to operate on.</param>
  277. <returns>
  278. -
  279. </returns>
  280. <remarks>
  281. Gets the full function name for a slot - note that this may not be the right
  282. function if this slot points to another one.
  283. </remarks>
  284. \**--------------------------------------------------------------------------**/
  285. #define Command_GetFuncName(%1) \
  286. (YSI_g_sCommands[(%1)][E_COMMANDS_FUNCTION])
  287. /**--------------------------------------------------------------------------**\
  288. <summary>Command_GetPointer</summary>
  289. <param name="index">Index of the command to operate on.</param>
  290. <returns>
  291. -
  292. </returns>
  293. <remarks>
  294. Gets the pointer for a function from the array.
  295. </remarks>
  296. \**--------------------------------------------------------------------------**/
  297. #if YSIM_HAS_MASTER
  298. #define Command_GetPointer(%1) \
  299. (YSI_g_sCommands[(%1)][E_COMMANDS_FUNC_POINTER]&0x00FFFFFF)
  300. #else
  301. #define Command_GetPointer(%1) \
  302. (YSI_g_sCommands[(%1)][E_COMMANDS_FUNC_POINTER])
  303. #endif
  304. /**--------------------------------------------------------------------------**\
  305. <summary>Command_GetProvider</summary>
  306. <param name="index">Index of the command to operate on.</param>
  307. <returns>
  308. -
  309. </returns>
  310. <remarks>
  311. Gets the unique script in which this version of the command is.
  312. </remarks>
  313. \**--------------------------------------------------------------------------**/
  314. #if YSIM_HAS_MASTER
  315. #define Command_Provider(%1) \
  316. (YSI_g_sCommands[(%1)][E_COMMANDS_FUNC_POINTER]>>>24)
  317. #endif
  318. /**--------------------------------------------------------------------------**\
  319. <summary>Command_GetProvider</summary>
  320. <param name="index">Index of the command to operate on.</param>
  321. <returns>
  322. -
  323. </returns>
  324. <remarks>
  325. Gets the unique script in which this version of the command is.
  326. </remarks>
  327. \**--------------------------------------------------------------------------**/
  328. #if YSIM_HAS_MASTER
  329. #define Command_DefaultProvider() \
  330. (YSI_g_sCommandFlags & e_COMM_FLAG_PROVIDER)
  331. #endif
  332. /**--------------------------------------------------------------------------**\
  333. <summary>Command_GetFunction</summary>
  334. <param name="index">Index of the command to operate on.</param>
  335. <returns>
  336. -
  337. </returns>
  338. <remarks>
  339. Gets the real function for this slot.
  340. </remarks>
  341. \**--------------------------------------------------------------------------**/
  342. #define Command_GetFunction(%1) \
  343. (Command_GetFuncName(Command_GetPointer((%1))))
  344. /**--------------------------------------------------------------------------**\
  345. <summary>Command_CheckPlayer</summary>
  346. <param name="index">Index of the command to operate on.</param>
  347. <param name="playerid">The player to check for.</param>
  348. <returns>
  349. -
  350. </returns>
  351. <remarks>
  352. Gets wether a player can use a command.
  353. </remarks>
  354. \**--------------------------------------------------------------------------**/
  355. #define Command_CheckPlayer(%1,%2) \
  356. (YSI_g_sCommands[(%1)][E_COMMANDS_PLAYERS][Bit_Slot(%2)+1]&Bit_Mask(%2))
  357. //(PA=([E_COMMANDS_PLAYERS], (%2)))
  358. //(Bit_Get(YSI_g_sCommands[(%1)][E_COMMANDS_PLAYERS], (%2)))
  359. /**--------------------------------------------------------------------------**\
  360. <summary>Command_DeniedReturn</summary>
  361. <returns>
  362. e_COMM_FLAG_PERMISSION_RET
  363. </returns>
  364. <remarks>
  365. -
  366. </remarks>
  367. \**--------------------------------------------------------------------------**/
  368. #define Command_DeniedReturn() \
  369. (YSI_g_sCommandFlags & e_COMM_FLAG_PERMISSION_RET)
  370. /**--------------------------------------------------------------------------**\
  371. <summary>Command_SetDeniedReturn</summary>
  372. <returns>
  373. -
  374. </returns>
  375. <remarks>
  376. -
  377. </remarks>
  378. \**--------------------------------------------------------------------------**/
  379. foreign void:Command_SetDeniedReturn(bool:set);
  380. global void:Command_SetDeniedReturn(bool:set)
  381. {
  382. P:2("Command_SetDeniedReturn called: %i", bool:set);
  383. if (set)
  384. {
  385. YSI_g_sCommandFlags |= e_COMM_FLAG_PERMISSION_RET;
  386. }
  387. else
  388. {
  389. YSI_g_sCommandFlags &= ~e_COMM_FLAG_PERMISSION_RET;
  390. }
  391. //return 1;
  392. }
  393. /**--------------------------------------------------------------------------**\
  394. <summary>Command_SetProvider</summary>
  395. <param name="p">Script.</param>
  396. <returns>
  397. -
  398. </returns>
  399. <remarks>
  400. Set the current provider to use for all commands being added. Basically
  401. allows us to have the same command name in different scripts and have them
  402. do different things, with different players targetting different ones.
  403. </remarks>
  404. \**--------------------------------------------------------------------------**/
  405. #if YSIM_HAS_MASTER
  406. foreign void:Command_SetProvider(p);
  407. global void:Command_SetProvider(p)
  408. {
  409. P:2("Command_SetProvider called: %i", p);
  410. YSI_g_sCommandFlags = (YSI_g_sCommandFlags & ~e_COMM_FLAG_PROVIDER) | (e_COMM_FLAG:p & e_COMM_FLAG_PROVIDER) | e_COMM_FLAG_MULPRO;
  411. //return 1;
  412. }
  413. foreign Command_GetProvider();
  414. global Command_GetProvider()
  415. {
  416. P:2("Command_GetProvider called");
  417. /*YSI_g_sCommandFlags = (YSI_g_sCommandFlags & ~e_COMM_FLAG_PROVIDER) | (e_COMM_FLAG:p & e_COMM_FLAG_PROVIDER)
  418. if (YSI_g_sCommandFlags & e_COMM_FLAG_MULPRO)
  419. {
  420. return _:(YSI_g_sCommandFlags & (YSI_g_sCommandFlags & ~e_COMM_FLAG_PROVIDER));
  421. }
  422. else
  423. {
  424. }*/
  425. // Poorely named, gets the current provider.
  426. return _:Command_DefaultProvider();
  427. }
  428. foreign void:Command_SetPlayerProvider(playerid,p);
  429. global void:Command_SetPlayerProvider(playerid,p)
  430. {
  431. P:2("Command_SetPlayerProvider called: %i, %i", playerid, p);
  432. if (0 <= playerid < MAX_PLAYERS)
  433. {
  434. YSI_g_sPlayerProvider{playerid} = p & 0xFF;
  435. }
  436. //return 1;
  437. }
  438. foreign Command_GetPlayerProvider(playerid);
  439. global Command_GetPlayerProvider(playerid)
  440. {
  441. P:2("Command_GetPlayerProvider called: %i", playerid);
  442. return YSI_g_sPlayerProvider{playerid};
  443. }
  444. #endif
  445. /**--------------------------------------------------------------------------**\
  446. <summary>Command_GetDeniedReturn</summary>
  447. <returns>
  448. -
  449. </returns>
  450. <remarks>
  451. -
  452. </remarks>
  453. \**--------------------------------------------------------------------------**/
  454. foreign bool:Command_GetDeniedReturn();
  455. global bool:Command_GetDeniedReturn()
  456. {
  457. P:2("bool:Command_GetDeniedReturn called");
  458. return bool:Command_DeniedReturn();
  459. }
  460. /**--------------------------------------------------------------------------**\
  461. <summary>Command_HasCollisions</summary>
  462. <returns>
  463. e_COMM_FLAG_COLLISION
  464. </returns>
  465. <remarks>
  466. -
  467. </remarks>
  468. \**--------------------------------------------------------------------------**/
  469. #define Command_HasCollisions() \
  470. (YSI_g_sCommandFlags & e_COMM_FLAG_COLLISION)
  471. /**--------------------------------------------------------------------------**\
  472. <summary>Command_HasCollisions</summary>
  473. <returns>
  474. e_COMM_FLAG_MULPRO
  475. </returns>
  476. <remarks>
  477. -
  478. </remarks>
  479. \**--------------------------------------------------------------------------**/
  480. #if YSIM_HAS_MASTER
  481. #define Command_HasMultipleProviders() \
  482. (YSI_g_sCommandFlags & e_COMM_FLAG_MULPRO)
  483. #endif
  484. /**--------------------------------------------------------------------------**\
  485. <summary>Command_SetCollisions</summary>
  486. <returns>
  487. -
  488. </returns>
  489. <remarks>
  490. -
  491. </remarks>
  492. \**--------------------------------------------------------------------------**/
  493. #define Command_SetCollisions() \
  494. YSI_g_sCommandFlags |= e_COMM_FLAG_COLLISION
  495. /**--------------------------------------------------------------------------**\
  496. <summary>Command_IllegalReturn</summary>
  497. <returns>
  498. e_COMM_FLAG_ILLEGAL
  499. </returns>
  500. <remarks>
  501. -
  502. </remarks>
  503. \**--------------------------------------------------------------------------**/
  504. #define Command_IllegalReturn() \
  505. (YSI_g_sCommandFlags & e_COMM_FLAG_ILLEGAL)
  506. /**--------------------------------------------------------------------------**\
  507. <summary>Command_SetIllegalReturn</summary>
  508. <returns>
  509. -
  510. </returns>
  511. <remarks>
  512. -
  513. </remarks>
  514. \**--------------------------------------------------------------------------**/
  515. foreign void:Command_SetIllegalReturn(bool:set);
  516. global void:Command_SetIllegalReturn(bool:set)
  517. {
  518. P:2("Command_SetIllegalReturn called: %i", bool:set);
  519. if (set)
  520. {
  521. YSI_g_sCommandFlags |= e_COMM_FLAG_ILLEGAL;
  522. }
  523. else
  524. {
  525. YSI_g_sCommandFlags &= ~e_COMM_FLAG_ILLEGAL;
  526. }
  527. //return 1;
  528. }
  529. /**--------------------------------------------------------------------------**\
  530. <summary>Command_GetIllegalReturn</summary>
  531. <returns>
  532. -
  533. </returns>
  534. <remarks>
  535. -
  536. </remarks>
  537. \**--------------------------------------------------------------------------**/
  538. foreign bool:Command_GetIllegalReturn();
  539. global bool:Command_GetIllegalReturn()
  540. {
  541. P:2("bool:Command_GetIllegalReturn called");
  542. return bool:Command_IllegalReturn();
  543. }
  544. /**--------------------------------------------------------------------------**\
  545. <summary>Command_IllegalReturn</summary>
  546. <returns>
  547. e_COMM_FLAG_ILLEGAL
  548. </returns>
  549. <remarks>
  550. -
  551. </remarks>
  552. \**--------------------------------------------------------------------------**/
  553. #define Command_UnknownReturn() \
  554. (YSI_g_sCommandFlags & e_COMM_FLAG_UNKNOWN)
  555. /**--------------------------------------------------------------------------**\
  556. <summary>Command_SetIllegalReturn</summary>
  557. <returns>
  558. -
  559. </returns>
  560. <remarks>
  561. -
  562. </remarks>
  563. \**--------------------------------------------------------------------------**/
  564. foreign void:Command_SetUnknownReturn(bool:set);
  565. global void:Command_SetUnknownReturn(bool:set)
  566. {
  567. P:2("Command_SetUnknownReturn called: %i", bool:set);
  568. if (set)
  569. {
  570. YSI_g_sCommandFlags |= e_COMM_FLAG_UNKNOWN;
  571. }
  572. else
  573. {
  574. YSI_g_sCommandFlags &= ~e_COMM_FLAG_UNKNOWN;
  575. }
  576. //return 1;
  577. }
  578. /**--------------------------------------------------------------------------**\
  579. <summary>Command_GetIllegalReturn</summary>
  580. <returns>
  581. -
  582. </returns>
  583. <remarks>
  584. -
  585. </remarks>
  586. \**--------------------------------------------------------------------------**/
  587. foreign bool:Command_GetUnknownReturn();
  588. global bool:Command_GetUnknownReturn()
  589. {
  590. P:2("bool:Command_GetUnknownReturn called");
  591. return bool:Command_UnknownReturn();
  592. }
  593. /**--------------------------------------------------------------------------**\
  594. <summary>Command_DisconnectReturn</summary>
  595. <returns>
  596. e_COMM_FLAG_DISCONNECT
  597. </returns>
  598. <remarks>
  599. -
  600. </remarks>
  601. \**--------------------------------------------------------------------------**/
  602. #define Command_DisconnectReturn() \
  603. (YSI_g_sCommandFlags & e_COMM_FLAG_DISCONNECT)
  604. /**--------------------------------------------------------------------------**\
  605. <summary>Command_SetDisconnectReturn</summary>
  606. <returns>
  607. -
  608. </returns>
  609. <remarks>
  610. -
  611. </remarks>
  612. \**--------------------------------------------------------------------------**/
  613. foreign void:Command_SetDisconnectReturn(bool:set);
  614. global void:Command_SetDisconnectReturn(bool:set)
  615. {
  616. P:2("Command_SetDisconnectReturn called: %i", bool:set);
  617. if (set)
  618. {
  619. YSI_g_sCommandFlags |= e_COMM_FLAG_DISCONNECT;
  620. }
  621. else
  622. {
  623. YSI_g_sCommandFlags &= ~e_COMM_FLAG_DISCONNECT;
  624. }
  625. //return 1;
  626. }
  627. /**--------------------------------------------------------------------------**\
  628. <summary>Command_GetDisconnectReturn</summary>
  629. <returns>
  630. -
  631. </returns>
  632. <remarks>
  633. -
  634. </remarks>
  635. \**--------------------------------------------------------------------------**/
  636. foreign bool:Command_GetDisconnectReturn();
  637. global bool:Command_GetDisconnectReturn()
  638. {
  639. P:2("bool:Command_GetDisconnectReturn called");
  640. return bool:Command_DisconnectReturn();
  641. }
  642. /**--------------------------------------------------------------------------**\
  643. <summary>Command_DeniedDisplay</summary>
  644. <returns>
  645. e_COMM_FLAG_PERMISSION_WARN
  646. </returns>
  647. <remarks>
  648. -
  649. </remarks>
  650. \**--------------------------------------------------------------------------**/
  651. #define Command_DeniedDisplay() \
  652. (YSI_g_sCommandFlags & e_COMM_FLAG_PERMISSION_WARN)
  653. /**--------------------------------------------------------------------------**\
  654. <summary>Command_SetDeniedDisplay</summary>
  655. <returns>
  656. -
  657. </returns>
  658. <remarks>
  659. -
  660. </remarks>
  661. \**--------------------------------------------------------------------------**/
  662. foreign void:Command_SetDeniedDisplay(bool:set);
  663. global void:Command_SetDeniedDisplay(bool:set)
  664. {
  665. P:2("Command_SetDeniedDisplay called: %i", bool:set);
  666. if (set)
  667. {
  668. YSI_g_sCommandFlags |= e_COMM_FLAG_PERMISSION_WARN;
  669. }
  670. else
  671. {
  672. YSI_g_sCommandFlags &= ~e_COMM_FLAG_PERMISSION_WARN;
  673. }
  674. //return 1;
  675. }
  676. /**--------------------------------------------------------------------------**\
  677. <summary>Command_GetDeniedDisplay</summary>
  678. <returns>
  679. -
  680. </returns>
  681. <remarks>
  682. -
  683. </remarks>
  684. \**--------------------------------------------------------------------------**/
  685. foreign bool:Command_GetDeniedDisplay();
  686. global bool:Command_GetDeniedDisplay()
  687. {
  688. P:2("bool:Command_GetDeniedDisplay called");
  689. return bool:Command_DeniedDisplay();
  690. }
  691. /**--------------------------------------------------------------------------**\
  692. <summary>Command_GetNameInt</summary>
  693. <param name="f">Command to get the name of.</param>
  694. <returns>
  695. -
  696. </returns>
  697. <remarks>
  698. -
  699. </remarks>
  700. \**--------------------------------------------------------------------------**/
  701. /*RF:Command_GetNameInt[i](f)
  702. {
  703. P:2("Command_GetNameInt called: %i", f);
  704. if (f >= 0 && f < YSI_g_sCommandIndex)
  705. {
  706. setproperty(8, "", YSIM_STRING, Command_Name(f));
  707. return 1;
  708. }
  709. return 0;
  710. }*/
  711. /**--------------------------------------------------------------------------**\
  712. <summary>Command_GetName</summary>
  713. <param name="funcid">Command to get the name of.</param>
  714. <returns>
  715. -
  716. </returns>
  717. <remarks>
  718. native Command_GetName(funcid);
  719. </remarks>
  720. \**--------------------------------------------------------------------------**/
  721. /*stock Command_GetName(funcid)
  722. {
  723. P:3("Command_GetName called: %i", funcid);
  724. new
  725. buffer[32] = "";
  726. if (Command_GetNameInt(funcid))
  727. {
  728. getproperty(8, "", YSIM_STRING, buffer);
  729. strunpack(buffer, buffer);
  730. }
  731. return buffer;
  732. }*/
  733. /**--------------------------------------------------------------------------**\
  734. <summary>Command_IsSorted</summary>
  735. <returns>
  736. e_COMM_FLAG_SORTED
  737. </returns>
  738. <remarks>
  739. -
  740. </remarks>
  741. \**--------------------------------------------------------------------------**/
  742. #define Command_IsSorted() \
  743. (YSI_g_sCommandFlags & e_COMM_FLAG_SORTED)
  744. /**--------------------------------------------------------------------------**\
  745. <summary>Command_Generate</summary>
  746. <returns>
  747. -
  748. </returns>
  749. <remarks>
  750. -
  751. </remarks>
  752. \**--------------------------------------------------------------------------**/
  753. foreign void:Command_Generate();
  754. global void:Command_Generate()
  755. {
  756. P:2("Command_Generate called");
  757. P:2("Command_Generate called");
  758. if (!Command_IsSorted())
  759. {
  760. P:2("Command_Generate: Count = %d", YSI_g_sCommandCount);
  761. new
  762. data[MAX_COMMANDS][E_BINTREE_INPUT];
  763. // This is only called once, so we know YSI_g_sCommandCount will be
  764. // accurate WRT the locations of commands.
  765. for (new i = 0; i != YSI_g_sCommandCount; ++i)
  766. {
  767. data[i][E_BINTREE_INPUT_POINTER] = i;
  768. new
  769. hash = Command_PackHash(Command_Name(i));
  770. // Check for an existing command with this hash.
  771. if (!Command_HasCollisions())
  772. {
  773. for (new j = 0; j != i; ++j)
  774. {
  775. if (hash == data[j][E_BINTREE_INPUT_VALUE])
  776. {
  777. Command_SetCollisions();
  778. break;
  779. }
  780. }
  781. }
  782. C:3(else printf("Command_Generate: Hash = %d", hash););
  783. P:2("Command_Generate: Hash = %d", hash);
  784. data[i][E_BINTREE_INPUT_VALUE] = hash;
  785. }
  786. // WHY THE HECK did I change "Bintree_Generate" to "Bintree_Fill"? That
  787. // skips the whole sorting code before adding things to the binary tree!
  788. if (YSI_g_sCommandCount)
  789. {
  790. //Bintree_Fill(YSI_g_sSearchTree, data, YSI_g_sCommandCount);
  791. Bintree_Generate(YSI_g_sSearchTree, data, YSI_g_sCommandCount);
  792. //Bintree_Fill(YSI_g_sSearchTree, data, YSI_g_sCommandCount);
  793. }
  794. P:4("Command_Generate: %d %d %d %d %d", YSI_g_sSearchTree[0][E_BINTREE_TREE_VALUE], YSI_g_sSearchTree[0][E_BINTREE_TREE_LEFT], YSI_g_sSearchTree[0][E_BINTREE_TREE_RIGHT], YSI_g_sSearchTree[0][E_BINTREE_TREE_PARENT], YSI_g_sSearchTree[0][E_BINTREE_TREE_POINTER]);
  795. // Set sorted to true.
  796. YSI_g_sCommandFlags |= e_COMM_FLAG_SORTED;
  797. }
  798. //return 1;
  799. }
  800. foreign void:Command_IncOPCR();
  801. global void:Command_IncOPCR()
  802. {
  803. P:2("Command_IncOPCR called");
  804. YSI_g_sCommandFlags += e_COMM_FLAG_OPCR_ADD;
  805. //return 1;
  806. }
  807. foreign void:Command_DecOPCR();
  808. global void:Command_DecOPCR()
  809. {
  810. P:2("Command_DecOPCR called");
  811. YSI_g_sCommandFlags -= e_COMM_FLAG_OPCR_ADD;
  812. //return 1;
  813. }
  814. foreign void:Command_IncOPCP();
  815. global void:Command_IncOPCP()
  816. {
  817. P:2("Command_IncOPCP called");
  818. YSI_g_sCommandFlags += e_COMM_FLAG_OPCP_ADD;
  819. //return 1;
  820. }
  821. foreign void:Command_DecOPCP();
  822. global void:Command_DecOPCP()
  823. {
  824. P:2("Command_DecOPCP called");
  825. YSI_g_sCommandFlags -= e_COMM_FLAG_OPCP_ADD;
  826. //return 1;
  827. }
  828. /**--------------------------------------------------------------------------**\
  829. <summary>OnScriptInit</summary>
  830. <returns>
  831. -
  832. </returns>
  833. <remarks>
  834. -
  835. </remarks>
  836. \**--------------------------------------------------------------------------**/
  837. hook OnScriptInit()
  838. {
  839. // Set the default provider as any script.
  840. //YSI_g_sCommandFlags = 0xFF;
  841. P:1("Command_OnScriptInit called");
  842. // Initialise the tree.
  843. #if YSIM_NOT_CLIENT
  844. Bintree_Reset(YSI_g_sSearchTree);
  845. //YSI_g_sMaster23 = getproperty(8, "x@");
  846. #endif
  847. // Make a list of unused commands.
  848. for (new i = 0; i != MAX_COMMANDS - 1; ++i)
  849. {
  850. YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER] = i + 1;
  851. }
  852. YSI_g_sCommands[MAX_COMMANDS - 1][E_COMMANDS_FUNC_POINTER] = -1;
  853. // Loop through all the possible commands. Note that this may need to add
  854. // commands to the remote command system if this is not the master system.
  855. // The way the master system is designed means that we will know if we are
  856. // master or not by the time this function is called.
  857. new
  858. buffer[32],
  859. idx;
  860. // This is the only place where AMX_FastString is used instead of
  861. // Commands_FastString as the strings in the AMX are not the same as packed
  862. // strings - they are in different memory orders.
  863. while ((idx = AMX_GetPublicNamePrefix(idx, buffer, _A<@yC_>)))
  864. {
  865. Command_Add(buffer, _@);
  866. //Command_Add(unpack(buffer), _@);
  867. //Command_Add(unpack(buffer), _@);
  868. P:2("Command_OnScriptInit: Adding %s", unpack(buffer));
  869. }
  870. Command_Generate();
  871. // Now that all commands have been added to the array, sort it.
  872. // Now call the next constructor.
  873. if (funcidx("OnPlayerCommandPerformed") != -1)
  874. {
  875. Command_IncOPCP();
  876. }
  877. if (funcidx("OnPlayerCommandReceived") != -1)
  878. {
  879. Command_IncOPCR();
  880. }
  881. }
  882. // Forwards for initial command callbacks.
  883. forward OnPlayerCommandReceived(playerid, cmdtext[]);
  884. forward OnPlayerCommandPerformed(playerid, cmdtext[], success);
  885. hook OnScriptExit()
  886. {
  887. P:1("Commands_OnScriptExit called");
  888. if (funcidx("OnPlayerCommandPerformed") != -1)
  889. {
  890. Command_DecOPCP();
  891. }
  892. if (funcidx("OnPlayerCommandReceived") != -1)
  893. {
  894. Command_DecOPCR();
  895. }
  896. return 1;
  897. }
  898. /**--------------------------------------------------------------------------**\
  899. <summary>OnScriptClose</summary>
  900. <param name="script">ID of the closing script.</param>
  901. <returns>
  902. -
  903. </returns>
  904. <remarks>
  905. Called when a script under the control of the master system ends.
  906. </remarks>
  907. \**--------------------------------------------------------------------------**/
  908. #if YSIM_HAS_MASTER && YSIM_NOT_CLIENT
  909. #if _YSIM_IS_CLOUD
  910. public OnScriptClose(script) <>
  911. {
  912. #if defined Command_OnScriptClose
  913. Command_OnScriptClose(script);
  914. #endif
  915. }
  916. public OnScriptClose(script) <_YCM:y>
  917. #elseif _YSIM_IS_STUB
  918. #error y_commands called with _YSIM_IS_STUB.
  919. #else
  920. public OnScriptClose(script)
  921. #endif
  922. {
  923. new
  924. mask = ~(1 << script);
  925. for (new i = 0; i != MAX_COMMANDS; ++i)
  926. {
  927. if (Command_GetPointer(i) == i && (YSI_g_sCommands[i][E_COMMANDS_MASTERS] &= mask) == 0)
  928. {
  929. for (new j = 0; j != MAX_COMMANDS; ++j)
  930. {
  931. // Remove all alternate names.
  932. if (Command_GetPointer(j) == i)
  933. {
  934. YSI_g_sCommands[j][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  935. YSI_g_sCommandIndex = j;
  936. YSI_g_sCommands[j][E_COMMANDS_MASTERS] = 0;
  937. //Bintree_Delete(YSI_g_sSearchTree, j, YSI_g_sCommandCount);
  938. Command_RemoveFromBintree(j);
  939. --YSI_g_sCommandCount;
  940. //Bintree_Add(YSI_g_sSearchTree, YSI_g_sCommandIndex, hash, YSI_g_sCommandIndex);
  941. }
  942. }
  943. }
  944. /*new
  945. p = i;
  946. while (YSI_g_sCommands[p][E_COMMANDS_MASTERS] == -1)
  947. {
  948. p = Command_GetPointer(p);
  949. }
  950. if (YSI_g_sCommands[p][E_COMMANDS_FUNC_POINTER] == p && (YSI_g_sCommands[p][E_COMMANDS_MASTERS] &= mask) == 0)
  951. {
  952. // Remove all alternate versions of commands - done backwards by
  953. // an alternate command checking its parent. Can also handle
  954. // alternate versions of alternate commands (note this is the
  955. // only code that can currently).
  956. YSI_g_sCommands[i][E_COMMANDS_MASTERS] = 0;
  957. YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  958. YSI_g_sCommandIndex = i;
  959. // Mark it as invalid in this instance.
  960. YSI_g_sCommands[i][E_COMMANDS_MASTERS] = 0;
  961. // Reduce the number of commands.
  962. --YSI_g_sCommandCount;
  963. }*/
  964. }
  965. //YSI_g_sMaster23 = getproperty(8, "x@");
  966. // I can add better removal code later. Done ^
  967. #if defined Command_OnScriptClose
  968. Command_OnScriptClose(script);
  969. #endif
  970. }
  971. // Don't need ALS here as we did it supporting it at the start.
  972. #undef OnScriptClose
  973. #define OnScriptClose Command_OnScriptClose
  974. #if defined Command_OnScriptClose
  975. forward Command_OnScriptClose(script);
  976. #endif
  977. #endif
  978. /**--------------------------------------------------------------------------**\
  979. <summary>Command_TouchNamed</summary>
  980. <param name="string:command[]">Command to "touch".</param>
  981. <returns>
  982. -
  983. </returns>
  984. <remarks>
  985. Used within "GROUP_ADD" to quickly assign a load of commands to just one
  986. group.
  987. </remarks>
  988. \**--------------------------------------------------------------------------**/
  989. foreign void:Command_TouchNamed(string:command[]);
  990. global void:Command_TouchNamed(string:command[])
  991. {
  992. new
  993. id = Command_Find(command);
  994. if (id != COMMAND_NOT_FOUND)
  995. {
  996. NO_GROUPS(id)
  997. {
  998. return; //0;
  999. }
  1000. }
  1001. }
  1002. /**--------------------------------------------------------------------------**\
  1003. <summary>Command_Touch</summary>
  1004. <param name="string:command[]">Command to "touch".</param>
  1005. <returns>
  1006. -
  1007. </returns>
  1008. <remarks>
  1009. Used within "GROUP_ADD" to quickly assign a load of commands to just one
  1010. group.
  1011. </remarks>
  1012. \**--------------------------------------------------------------------------**/
  1013. foreign void:Command_Touch(command);
  1014. global void:Command_Touch(command)
  1015. {
  1016. if (Command_IsValid(command))
  1017. {
  1018. NO_GROUPS(command)
  1019. {
  1020. return; //0;
  1021. }
  1022. //return 1;
  1023. }
  1024. //return 0;
  1025. }
  1026. /**--------------------------------------------------------------------------**\
  1027. <summary>OnPlayerConnect</summary>
  1028. <returns>
  1029. -
  1030. </returns>
  1031. <remarks>
  1032. -
  1033. </remarks>
  1034. \**--------------------------------------------------------------------------**/
  1035. // TODO: Rewrite!
  1036. //RA:Command_OnPlayerConnect(playerid)
  1037. #if YSIM_NOT_CLIENT
  1038. mhook OnPlayerConnect(playerid)
  1039. {
  1040. //#if YSIM_NOT_CLIENT
  1041. //YSI_g_sCommandDialog[playerid] = -1;
  1042. #if YSIM_HAS_MASTER
  1043. YSI_g_sPlayerProvider{playerid} = 0xFF;
  1044. #endif
  1045. NO_GROUPS()
  1046. {
  1047. new
  1048. slot = Bit_Slot(playerid) + 1,
  1049. Bit:mask = Bit_Mask(playerid); //Bit:(1 << (playerid & (cellbits - 1)));
  1050. for (new i = 0; i != MAX_COMMANDS; ++i)
  1051. {
  1052. YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] |= mask;
  1053. //PA+(YSI_g_sCommands[i][E_COMMANDS_PLAYERS], mask);
  1054. }
  1055. }
  1056. //#endif
  1057. // Groups will ALWAYS be called after this function - so this can reset
  1058. // player permissions however it likes with the group system then being
  1059. // able to override anything set in here.
  1060. return 1;
  1061. //ALS_CALL<PlayerConnect, i>(playerid)
  1062. }
  1063. #endif
  1064. /**--------------------------------------------------------------------------**\
  1065. <summary>Command_</summary>
  1066. <param name="command">Command to declare.</param>
  1067. <returns>
  1068. -
  1069. </returns>
  1070. <remarks>
  1071. Deprecated!
  1072. </remarks>
  1073. \**--------------------------------------------------------------------------**/
  1074. #define Command_(%1) \
  1075. CMD:%1(playerid,params[],help)
  1076. /**--------------------------------------------------------------------------**\
  1077. <summary>ycmd</summary>
  1078. <param name="command[]">Command to register.</param>
  1079. <returns>
  1080. -
  1081. </returns>
  1082. <remarks>
  1083. Deprecated!
  1084. </remarks>
  1085. \**--------------------------------------------------------------------------**/
  1086. #define ycmd(%1);
  1087. /**--------------------------------------------------------------------------**\
  1088. <summary>Command_FindFast</summary>
  1089. <param name="data[]">Function name to find.</param>
  1090. <param name="value">Hash of function name.</param>
  1091. <returns>
  1092. Position in functions array or COMMAND_NOT_FOUND.
  1093. </returns>
  1094. <remarks>
  1095. -
  1096. </remarks>
  1097. \**--------------------------------------------------------------------------**/
  1098. #if YSIM_HAS_MASTER
  1099. static stock Command_FindFast(data[], value, provider = 0xFF)
  1100. #else
  1101. static stock Command_FindFast(data[], value)
  1102. #endif
  1103. {
  1104. new
  1105. leaf,
  1106. pointer;
  1107. #if YSIM_HAS_MASTER
  1108. P:4("Command_FindFast called: \"%s\", %i, %i", data, value, provider);
  1109. provider <<= 24;
  1110. P:5("Command_FindFast: Searching for %s", data);
  1111. if (Command_HasMultipleProviders())
  1112. {
  1113. /*if (provider == 0xFF)
  1114. {
  1115. while ((pointer = Bintree_FindValue(YSI_g_sSearchTree, value, leaf)) != BINTREE_NOT_FOUND)
  1116. {
  1117. //new
  1118. // p = YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER] & 0xFF000000;
  1119. //P:7("Command_FindFast: providers %d %d %d", Command_HasMultipleProviders(), (p & 0xFF000000 != 0xFF000000), (p >>> 24 != provider));
  1120. // Any script will do.
  1121. //if ((YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER] & 0xFF000000) != 0xFF000000) continue;
  1122. //if (p != 0xFF000000 && p != provider) continue;
  1123. // Don't do an strcmp if there are no collisions.
  1124. P:7("Command_FindFast: collisions %d", !Command_HasCollisions());
  1125. if (!Command_HasCollisions()) return pointer;
  1126. //if (!strcmp(YSI_g_sCommands[i][E_COMMANDS_FUNCTION][1], funcname) &&
  1127. P:7("Command_FindFast: strcmp %d", !strcmp(Command_Name(pointer), data));
  1128. if (!strcmp(Command_Name(pointer), data)) return pointer;
  1129. //if (!strcmp(Command_Name(pointer), data) && (Command_GetProvider(pointer) == 0xFF || Command_GetProvider(pointer) == provider)) return pointer;
  1130. }
  1131. }
  1132. else
  1133. {*/
  1134. while ((pointer = Bintree_FindValue(YSI_g_sSearchTree, value, leaf)) != BINTREE_NOT_FOUND)
  1135. {
  1136. //new
  1137. // p = YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER] & 0xFF000000;
  1138. //P:7("Command_FindFast: providers %d %d %d", Command_HasMultipleProviders(), (p & 0xFF000000 != 0xFF000000), (p >>> 24 != provider));
  1139. //if (p != provider && p != 0xFF000000) continue;
  1140. // Only one provider will do.
  1141. if ((YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER] & 0xFF000000) != provider) continue;
  1142. // Don't do an strcmp if there are no collisions.
  1143. P:7("Command_FindFast: collisions %d", Command_HasCollisions());
  1144. if (!Command_HasCollisions()) return pointer;
  1145. //if (!strcmp(YSI_g_sCommands[i][E_COMMANDS_FUNCTION][1], funcname) &&
  1146. P:7("Command_FindFast: strcmp %d", !strcmp(Command_Name(pointer), data));
  1147. if (!strcmp(Command_Name(pointer), data)) return pointer;
  1148. //if (!strcmp(Command_Name(pointer), data) && (Command_GetProvider(pointer) == 0xFF || Command_GetProvider(pointer) == provider)) return pointer;
  1149. }
  1150. //}
  1151. }
  1152. else
  1153. {
  1154. #endif
  1155. while ((pointer = Bintree_FindValue(YSI_g_sSearchTree, value, leaf)) != BINTREE_NOT_FOUND)
  1156. {
  1157. //new
  1158. // p = YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER] & 0xFF000000;
  1159. //P:7("Command_FindFast: providers %d %d %d", Command_HasMultipleProviders(), (p & 0xFF000000 != 0xFF000000), (p >>> 24 != provider));
  1160. //if (Command_HasMultipleProviders() && (p != 0xFF000000) && (p != provider)) continue;
  1161. // Don't do an strcmp if there are no collisions.
  1162. P:7("Command_FindFast: collisions %d", Command_HasCollisions());
  1163. if (!Command_HasCollisions()) return pointer;
  1164. //if (!strcmp(YSI_g_sCommands[i][E_COMMANDS_FUNCTION][1], funcname) &&
  1165. P:7("Command_FindFast: strcmp %d", !strcmp(Command_Name(pointer), data));
  1166. if (!strcmp(Command_Name(pointer), data)) return pointer;
  1167. //if (!strcmp(Command_Name(pointer), data) && (Command_GetProvider(pointer) == 0xFF || Command_GetProvider(pointer) == provider)) return pointer;
  1168. }
  1169. #if YSIM_HAS_MASTER
  1170. }
  1171. #endif
  1172. P:5("Command_FindFast: Not found");
  1173. return COMMAND_NOT_FOUND;
  1174. }
  1175. static stock Command_FindFastStrict(data[], value, provider)
  1176. {
  1177. #if YSIM_HAS_MASTER
  1178. P:4("Command_FindFastStrict called: \"%s\", %i, %i", data, value, provider);
  1179. #else
  1180. #pragma unused provider
  1181. #endif
  1182. new
  1183. leaf,
  1184. pointer;
  1185. P:5("Command_FindFast: Searching for %s", data);
  1186. while ((pointer = Bintree_FindValue(YSI_g_sSearchTree, value, leaf)) != BINTREE_NOT_FOUND)
  1187. {
  1188. #if YSIM_HAS_MASTER
  1189. if (Command_HasMultipleProviders() && (YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER] >>> 24 != provider)) continue;
  1190. #endif
  1191. // Don't do an strcmp if there are no collisions.
  1192. if (!Command_HasCollisions()) return pointer;
  1193. if (!strcmp(Command_Name(pointer), data)) return pointer;
  1194. }
  1195. P:5("Command_FindFast: Not found");
  1196. return COMMAND_NOT_FOUND;
  1197. }
  1198. /**--------------------------------------------------------------------------**\
  1199. <summary>Command_FindSlow</summary>
  1200. <param name="funcname[]">Function to find.</param>
  1201. <returns>
  1202. -
  1203. </returns>
  1204. <remarks>
  1205. Searches through the array for function linearly - used to set altnames
  1206. before the data has been sorted.
  1207. </remarks>
  1208. \**--------------------------------------------------------------------------**/
  1209. #if YSIM_HAS_MASTER
  1210. static stock Command_FindSlow(funcname[], provider = 0xFF)
  1211. #else
  1212. static stock Command_FindSlow(funcname[])
  1213. #endif
  1214. {
  1215. #if YSIM_HAS_MASTER
  1216. P:4("Command_FindSlow called: \"%s\", %i", funcname, provider);
  1217. #endif
  1218. for (new i = 0; i != MAX_COMMANDS; ++i)
  1219. {
  1220. #if YSIM_HAS_MASTER
  1221. new
  1222. p = YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER];
  1223. if (((p & 0x00FFFFFF == i) || (YSI_g_sCommands[i][E_COMMANDS_MASTERS] == -1)) &&
  1224. (!Command_HasMultipleProviders() || (p & 0xFF000000 == 0xFF000000) || (p >>> 24 == provider)) &&
  1225. !strcmp(Command_Name(i), funcname))
  1226. #else
  1227. if (YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER] == i && !strcmp(Command_Name(i), funcname))
  1228. #endif
  1229. {
  1230. return i;
  1231. }
  1232. }
  1233. return COMMAND_NOT_FOUND;
  1234. }
  1235. /**--------------------------------------------------------------------------**\
  1236. <summary>Command_FindSlowStrict</summary>
  1237. <param name="funcname[]">Function to find.</param>
  1238. <returns>
  1239. -
  1240. </returns>
  1241. <remarks>
  1242. Searches through the array for function linearly - used to set altnames
  1243. before the data has been sorted.
  1244. </remarks>
  1245. \**--------------------------------------------------------------------------**/
  1246. static stock Command_FindSlowStrict(funcname[], provider)
  1247. {
  1248. #if YSIM_HAS_MASTER
  1249. P:4("Command_FindSlowStrict called: \"%s\", %i", funcname, provider);
  1250. #else
  1251. #pragma unused provider
  1252. #endif
  1253. P:2("Command_FindSlowStrict: Searching for %s", unpack(funcname));
  1254. for (new i = 0; i != MAX_COMMANDS; ++i)
  1255. {
  1256. #if YSIM_HAS_MASTER
  1257. new
  1258. p = YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER];
  1259. P:6("Command_FindSlowStrict: %s %08x %d %d", unpack(funcname), Command_Name(i), p & 0xFFFFFF, i);
  1260. // This needs additional checks that the item is valid.
  1261. if (((p & 0x00FFFFFF == i) || (YSI_g_sCommands[i][E_COMMANDS_MASTERS] == -1)) &&
  1262. (!Command_HasMultipleProviders() || (p >>> 24 == provider)) &&
  1263. !strcmp(Command_Name(i), funcname))
  1264. #else
  1265. if (YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER] == i && !strcmp(Command_Name(i), funcname))
  1266. #endif
  1267. {
  1268. return i;
  1269. }
  1270. }
  1271. return COMMAND_NOT_FOUND;
  1272. }
  1273. /**--------------------------------------------------------------------------**\
  1274. <summary>Command_AddHash</summary>
  1275. <param name="command[]">Command text to hash.</param>
  1276. <param name="dest[]">Array to copy to.</param>
  1277. <param name="idx">Point to start copying from.</param>
  1278. <returns>
  1279. hash value.
  1280. </returns>
  1281. <remarks>
  1282. Hashes a string and copies it to a destination at the same time.
  1283. </remarks>
  1284. \**--------------------------------------------------------------------------**/
  1285. static stock Command_AddHash(command[], dest[], idx)
  1286. {
  1287. P:4("Command_AddHash called: \"%s\", %i, %i", command, dest, idx);
  1288. // Skip the function name prefix.
  1289. new
  1290. hash = -1,
  1291. ch,
  1292. dx = 1,
  1293. end = idx + 28;
  1294. // Copy and hash at the same time.
  1295. do
  1296. {
  1297. /*ch = TOLOWER(command[idx++]);
  1298. // Always NULL terminate.
  1299. if ((dest[dx] = ch << 24) == COMMAND_END_CMP << 24)
  1300. {
  1301. // Fixes a bug with commands multiples of 4 chars long.
  1302. dest[dx] = 0;
  1303. break;
  1304. }*/
  1305. ch = TOLOWER(command[idx++]);
  1306. if (ch == COMMAND_END_CMP) break;
  1307. dest[dx] = ch << 24;
  1308. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1309. ch = TOLOWER(command[idx++]);
  1310. if (ch == COMMAND_END_CMP) break;
  1311. dest[dx] |= ch << 16;
  1312. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1313. ch = TOLOWER(command[idx++]);
  1314. if (ch == COMMAND_END_CMP) break;
  1315. dest[dx] |= ch << 8;
  1316. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1317. ch = TOLOWER(command[idx++]);
  1318. if (ch == COMMAND_END_CMP) break;
  1319. dest[dx] |= ch << 0;
  1320. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1321. ++dx;
  1322. }
  1323. while (idx < end);
  1324. return hash;
  1325. }
  1326. /**--------------------------------------------------------------------------**\
  1327. <summary>Command_AddHashPacked</summary>
  1328. <param name="command[]">Packed command text to hash.</param>
  1329. <param name="dest[]">Array to copy to.</param>
  1330. <param name="idx">Point to start copying from.</param>
  1331. <returns>
  1332. hash value.
  1333. </returns>
  1334. <remarks>
  1335. Hashes a string and copies it to a destination at the same time.
  1336. </remarks>
  1337. \**--------------------------------------------------------------------------**/
  1338. static stock Command_AddHashPacked(command[], dest[], idx)
  1339. {
  1340. P:4("Command_AddHashPacked called: \"%s\", %i, %i", command, dest, idx);
  1341. // Skip the function name prefix.
  1342. new
  1343. hash = -1,
  1344. ch,
  1345. dx = 1,
  1346. end = idx + 28;
  1347. // Copy and hash at the same time.
  1348. do
  1349. {
  1350. /*ch = TOLOWER(command[idx++]);
  1351. // Always NULL terminate.
  1352. if ((dest[dx] = ch << 24) == COMMAND_END_CMP << 24)
  1353. {
  1354. // Fixes a bug with commands multiples of 4 chars long.
  1355. dest[dx] = 0;
  1356. break;
  1357. }*/
  1358. ch = TOLOWER(command{idx++});
  1359. if (ch == COMMAND_END_CMP) break;
  1360. dest[dx] = ch << 24;
  1361. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1362. ch = TOLOWER(command{idx++});
  1363. if (ch == COMMAND_END_CMP) break;
  1364. dest[dx] |= ch << 16;
  1365. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1366. ch = TOLOWER(command{idx++});
  1367. if (ch == COMMAND_END_CMP) break;
  1368. dest[dx] |= ch << 8;
  1369. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1370. ch = TOLOWER(command{idx++});
  1371. if (ch == COMMAND_END_CMP) break;
  1372. dest[dx] |= ch << 0;
  1373. hash = hash * 33 + ch; //Command_ToUpper(ch);
  1374. ++dx;
  1375. }
  1376. while (idx < end);
  1377. return hash;
  1378. }
  1379. /**--------------------------------------------------------------------------**\
  1380. <summary>Command_FastHash</summary>
  1381. <param name="command[]">Command text to hash.</param>
  1382. <returns>
  1383. hash value.
  1384. </returns>
  1385. <remarks>
  1386. Just hashes the passed string.
  1387. </remarks>
  1388. \**--------------------------------------------------------------------------**/
  1389. static stock Command_FastHash(command[])
  1390. {
  1391. P:4("Command_FastHash called: \"%s\"", command);
  1392. new
  1393. index = 0,
  1394. hash = -1,
  1395. ch;
  1396. while ((ch = command[index++])) hash = hash * 33 + TOLOWER(ch);
  1397. return hash;
  1398. }
  1399. /**--------------------------------------------------------------------------**\
  1400. <summary>Command_PackHash</summary>
  1401. <param name="command[]">Command text to hash.</param>
  1402. <returns>
  1403. hash value.
  1404. </returns>
  1405. <remarks>
  1406. Hashes packed strings.
  1407. </remarks>
  1408. \**--------------------------------------------------------------------------**/
  1409. static stock Command_PackHash(command[])
  1410. {
  1411. P:4("Command_PackHash called: \"%s\"", command);
  1412. new
  1413. index = 0,
  1414. hash = -1,
  1415. ch;
  1416. while ((ch = command[index++]))
  1417. {
  1418. P:4("Commands_PackHash: ch = 0x%04x%04x", ch >>> 16, ch & 0xFFFF);
  1419. if (ch & 0xFF000000)
  1420. {
  1421. hash = hash * 33 + TOLOWER(ch >>> 24);
  1422. P:5("Command_PackHash: Hash1 = %d", hash);
  1423. }
  1424. else
  1425. {
  1426. break;
  1427. }
  1428. if (ch & 0x00FF0000)
  1429. {
  1430. hash = hash * 33 + TOLOWER(ch >> 16 & 0xFF);
  1431. P:5("Command_PackHash: Hash2 = %d", hash);
  1432. }
  1433. else
  1434. {
  1435. break;
  1436. }
  1437. if (ch & 0x0000FF00)
  1438. {
  1439. hash = hash * 33 + TOLOWER(ch >> 8 & 0xFF);
  1440. P:5("Command_PackHash: Hash3 = %d", hash);
  1441. }
  1442. else
  1443. {
  1444. break;
  1445. }
  1446. if (ch & 0x000000FF)
  1447. {
  1448. hash = hash * 33 + TOLOWER(ch & 0xFF);
  1449. P:5("Command_PackHash: Hash4 = %d", hash);
  1450. }
  1451. else
  1452. {
  1453. break;
  1454. }
  1455. }
  1456. return hash;
  1457. }
  1458. /**--------------------------------------------------------------------------**\
  1459. <summary>Command_Hash</summary>
  1460. <param name="command[]">Command text to hash.</param>
  1461. <param name="&index">Start point and variable to store end point to.</param>
  1462. <param name="&length">Length of the hashed word.</param>
  1463. <returns>
  1464. hash value.
  1465. </returns>
  1466. <remarks>
  1467. Hashes a string using space delimiters and returns information such as the
  1468. length of the string hased and the start point of the next word.
  1469. </remarks>
  1470. \**--------------------------------------------------------------------------**/
  1471. static stock Command_Hash(command[], &index, &length)
  1472. {
  1473. P:4("Command_Hash called: \"%s\", %i, %i", command, index, length);
  1474. new
  1475. hash = -1,
  1476. ch;
  1477. length = index;
  1478. while ((ch = command[index++]) > ' ') hash = hash * 33 + TOLOWER(ch);
  1479. length = index - length - 1;
  1480. while (ch)
  1481. {
  1482. if (ch > ' ')
  1483. {
  1484. break;
  1485. }
  1486. ch = command[index++];
  1487. }
  1488. --index;
  1489. return hash;
  1490. }
  1491. /**--------------------------------------------------------------------------**\
  1492. <summary>Command_Find</summary>
  1493. <param name="function[]">Function name to find.</param>
  1494. <returns>
  1495. Position in functions array or COMMAND_NOT_FOUND.
  1496. </returns>
  1497. <remarks>
  1498. Used by API functions to avoid repeated sorting checks.
  1499. </remarks>
  1500. \**--------------------------------------------------------------------------**/
  1501. #if YSIM_HAS_MASTER
  1502. static stock Command_Find(function[], provider = -1)
  1503. #else
  1504. static stock Command_Find(function[])
  1505. #endif
  1506. {
  1507. #if YSIM_HAS_MASTER
  1508. P:4("Command_Find called: \"%s\", %i", function, provider);
  1509. if (provider == -1)
  1510. {
  1511. provider = _:Command_DefaultProvider();
  1512. // Find the ID of the command.
  1513. if (Command_IsSorted())
  1514. {
  1515. return Command_FindFast(function, Command_FastHash(function), provider);
  1516. }
  1517. else
  1518. {
  1519. return Command_FindSlow(function, provider);
  1520. }
  1521. }
  1522. else
  1523. {
  1524. provider &= 0xFF;
  1525. // Find the ID of the command.
  1526. if (Command_IsSorted())
  1527. {
  1528. return Command_FindFastStrict(function, Command_FastHash(function), provider);
  1529. }
  1530. else
  1531. {
  1532. return Command_FindSlowStrict(function, provider);
  1533. }
  1534. }
  1535. #else
  1536. if (Command_IsSorted())
  1537. {
  1538. return Command_FindFast(function, Command_FastHash(function));
  1539. }
  1540. else
  1541. {
  1542. return Command_FindSlow(function);
  1543. }
  1544. #endif
  1545. }
  1546. /**--------------------------------------------------------------------------**\
  1547. <summary>Command_GetID</summary>
  1548. <param name="function[]">Function name to find.</param>
  1549. <returns>
  1550. The ID of the passed function.
  1551. </returns>
  1552. <remarks>
  1553. -
  1554. native Command_GetID(function[])
  1555. </remarks>
  1556. \**--------------------------------------------------------------------------**/
  1557. foreign Command_GetID(string:function[]);
  1558. global Command_GetID(string:function[])
  1559. {
  1560. P:2("Command_GetID called: \"%s\"", function);
  1561. return Command_Find(function);
  1562. }
  1563. /**--------------------------------------------------------------------------**\
  1564. <summary>Command_SetPlayer</summary>
  1565. <param name="command">Command to set for.</param>
  1566. <param name="playerid">Player to set.</param>
  1567. <param name="bool:set">Wether or not this player can use this command.</param>
  1568. <returns>
  1569. -
  1570. </returns>
  1571. <remarks>
  1572. -
  1573. native bool:Command_SetPlayer(command, playerid, bool:set);
  1574. </remarks>
  1575. \**--------------------------------------------------------------------------**/
  1576. foreign void:Command_SetPlayer(c,p,bool:s);
  1577. global void:Command_SetPlayer(c,p,bool:s)
  1578. {
  1579. P:2("Command_SetPlayer called: %i, %i, %i", c, p, s);
  1580. // if (c < 0 || c >= YSI_g_sCommandIndex)
  1581. if (0 <= c < MAX_COMMANDS)
  1582. {
  1583. //Bit_Set(YSI_g_sCommands[c][E_COMMANDS_PLAYERS], p, s, bits<MAX_PLAYERS>);
  1584. //if (s) PA+(YSI_g_sCommands[c][E_COMMANDS_PLAYERS], p);
  1585. //else PA-(YSI_g_sCommands[c][E_COMMANDS_PLAYERS], p);
  1586. PA_Set(YSI_g_sCommands[c][E_COMMANDS_PLAYERS], p, s);
  1587. // Not in range,
  1588. // return false;
  1589. }
  1590. //return 1;
  1591. // return s;
  1592. }
  1593. /**--------------------------------------------------------------------------**\
  1594. <summary>Command_SetPlayerNamed</summary>
  1595. <param name="funcname[]">Command to set for.</param>
  1596. <param name="playerid">Player to set.</param>
  1597. <param name="set">Wether or not this player can use this command.</param>
  1598. <returns>
  1599. -
  1600. </returns>
  1601. <remarks>
  1602. Like Command_SetPlayer but for a function name.
  1603. native bool:Command_SetPlayerNamed(funcname[], playerid, bool:set);
  1604. </remarks>
  1605. \**--------------------------------------------------------------------------**/
  1606. foreign void:Command_SetPlayerNamed(string:f[],p,bool:s);
  1607. global void:Command_SetPlayerNamed(string:f[],p,bool:s)
  1608. {
  1609. P:2("Command_SetPlayerNamed called: \"%s\", %i, %i", f, p, s);
  1610. Command_SetPlayer(Command_Find(f), p, s);
  1611. //return 1;
  1612. }
  1613. /**--------------------------------------------------------------------------**\
  1614. <summary>Command_GetPlayer</summary>
  1615. <param name="command">Command to get for.</param>
  1616. <param name="playerid">Player to get.</param>
  1617. <returns>
  1618. Wether this player can use this command.
  1619. </returns>
  1620. <remarks>
  1621. -
  1622. native bool:Command_GetPlayer(command, playerid);
  1623. </remarks>
  1624. \**--------------------------------------------------------------------------**/
  1625. foreign bool:Command_GetPlayer(command, playerid);
  1626. global bool:Command_GetPlayer(command, playerid)
  1627. {
  1628. P:2("bool:Command_GetPlayer called: %i, %i", command, playerid);
  1629. if (0 <= command < MAX_COMMANDS)
  1630. {
  1631. return bool:Command_CheckPlayer(command, playerid);
  1632. }
  1633. // Not in range,
  1634. return false;
  1635. }
  1636. /**--------------------------------------------------------------------------**\
  1637. <summary>Command_GetPlayerNamed</summary>
  1638. <param name="funcname[]">Command to get for.</param>
  1639. <param name="playerid">Player to get.</param>
  1640. <returns>
  1641. -
  1642. </returns>
  1643. <remarks>
  1644. Like Command_GetPlayer but for a function name.
  1645. native bool:Command_GetPlayerNamed(funcname[], playerid);
  1646. </remarks>
  1647. \**--------------------------------------------------------------------------**/
  1648. foreign bool:Command_GetPlayerNamed(string:func[], playerid);
  1649. global bool:Command_GetPlayerNamed(string:func[], playerid)
  1650. {
  1651. P:2("bool:Command_GetPlayerNamed called: \"%s\", %i", func, playerid);
  1652. return Command_GetPlayer(Command_Find(func), playerid);
  1653. }
  1654. /**--------------------------------------------------------------------------**\
  1655. <summary>Command_Remove</summary>
  1656. <param name="func">The slot of the command to remove.</param>
  1657. <returns>
  1658. -
  1659. </returns>
  1660. <remarks>
  1661. native Command_Remove(func);
  1662. </remarks>
  1663. \**--------------------------------------------------------------------------**/
  1664. static stock Command_RemoveFromBintree(func)
  1665. {
  1666. P:4("Command_RemoveFromBintree called: %i", func);
  1667. if (!Command_IsSorted()) return;
  1668. // This function has to find the right index in the binary tree, as that's
  1669. // not in the same order at all.
  1670. new
  1671. leaf,
  1672. hash = Command_PackHash(Command_Name(func));
  1673. // Find where in the binary tree this is referenced from.
  1674. while (Bintree_FindValue(YSI_g_sSearchTree, hash, _, leaf) != BINTREE_NOT_FOUND)
  1675. {
  1676. if (YSI_g_sSearchTree[leaf][E_BINTREE_TREE_POINTER] == func)
  1677. {
  1678. P:2("Command_RemoveFromBintree: Delete branch");
  1679. Bintree_Delete(YSI_g_sSearchTree, leaf, YSI_g_sCommandCount);
  1680. return;
  1681. }
  1682. }
  1683. }
  1684. foreign void:Command_Remove(func);
  1685. global void:Command_Remove(func)
  1686. {
  1687. P:2("Command_Remove called: %i", func);
  1688. if (0 <= func < MAX_COMMANDS)
  1689. {
  1690. if (Command_GetPointer(func) == func)
  1691. {
  1692. for (new i = 0; i != MAX_COMMANDS; ++i)
  1693. {
  1694. // Remove all alternate names.
  1695. if (Command_GetPointer(i) == func)
  1696. {
  1697. // Add this to the list of unused functions.
  1698. YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  1699. YSI_g_sCommandIndex = i;
  1700. // Mark it as invalid in this instance.
  1701. #if YSIM_HAS_MASTER
  1702. YSI_g_sCommands[i][E_COMMANDS_MASTERS] = 0;
  1703. #endif
  1704. // Reduce the number of commands.
  1705. //Bintree_Delete(YSI_g_sSearchTree, i, YSI_g_sCommandCount);
  1706. Command_RemoveFromBintree(i);
  1707. --YSI_g_sCommandCount;
  1708. }
  1709. }
  1710. }
  1711. // Remove a single alternate name.
  1712. YSI_g_sCommands[func][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  1713. YSI_g_sCommandIndex = func;
  1714. #if YSIM_HAS_MASTER
  1715. YSI_g_sCommands[func][E_COMMANDS_MASTERS] = 0;
  1716. #endif
  1717. //Bintree_Delete(YSI_g_sSearchTree, func, YSI_g_sCommandCount);
  1718. Command_RemoveFromBintree(func);
  1719. --YSI_g_sCommandCount;
  1720. //return 1;
  1721. }
  1722. //return 0;
  1723. }
  1724. foreign void:Command_RemoveNamed(string:func[]);
  1725. global void:Command_RemoveNamed(string:func[])
  1726. {
  1727. P:2("Command_RemoveNamed called: \"%s\"", func);
  1728. Command_Remove(Command_Find(func));
  1729. }
  1730. /**--------------------------------------------------------------------------**\
  1731. <summary>Command_Add</summary>
  1732. <param name="funcname[]">The function to add to the array.</param>
  1733. <param name="script">The script ID with the function.</param>
  1734. <returns>
  1735. -
  1736. </returns>
  1737. <remarks>
  1738. If the list of commands have already been sorted into the binary tree the
  1739. new commands will be appended, otherwise they will just be added to the
  1740. array.
  1741. native Command_Add(funcname[], script);
  1742. </remarks>
  1743. \**--------------------------------------------------------------------------**/
  1744. foreign void:Command_Add(string:f[],s);
  1745. global void:Command_Add(string:f[],s)
  1746. {
  1747. #if !YSIM_HAS_MASTER
  1748. #pragma unused s
  1749. #endif
  1750. P:2("Command_Add called: \"%s\", %i", f, s);
  1751. if (YSI_g_sCommandCount < MAX_COMMANDS && YSI_g_sCommandIndex != -1)
  1752. {
  1753. #if !YSIM_HAS_MASTER
  1754. static
  1755. provider = -1;
  1756. #endif
  1757. new
  1758. #if YSIM_HAS_MASTER
  1759. provider = _:Command_DefaultProvider(),
  1760. #endif
  1761. //hash = Command_AddHashPacked(f, YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION], 4),
  1762. // Because of the way the master system works, packed strings are
  1763. // unpacked when they are passed remotely, but not when they are
  1764. // passed locally. The unpacking is done by "CallRemoteFunction",
  1765. // not anything we outselves do...
  1766. offset = f[0] == '@' ? 4 : 1,
  1767. hash = f[0] == '@' ?
  1768. Command_AddHash(f, YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION], 4) :
  1769. Command_AddHashPacked(f, YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION], 4);
  1770. //printf("%s", unpack(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][1]));
  1771. if (Command_IsSorted())
  1772. {
  1773. new
  1774. idx = Command_FindFastStrict(f[offset], hash, provider);
  1775. if (idx != COMMAND_NOT_FOUND)
  1776. {
  1777. P:4("Command_Add: Command exists");
  1778. #if YSIM_HAS_MASTER
  1779. YSI_g_sCommands[idx][E_COMMANDS_MASTERS] |= 1 << s;
  1780. #endif
  1781. return; //0;
  1782. }
  1783. if (!Command_HasCollisions())
  1784. {
  1785. // Check for an existing command with this hash.
  1786. if (Bintree_FindValue(YSI_g_sSearchTree, hash) != BINTREE_NOT_FOUND)
  1787. {
  1788. Command_SetCollisions();
  1789. }
  1790. }
  1791. // Command doesn't exist already - good!
  1792. Bintree_Add(YSI_g_sSearchTree, YSI_g_sCommandIndex, hash, YSI_g_sCommandIndex);
  1793. }
  1794. else
  1795. {
  1796. new
  1797. idx = Command_FindSlowStrict(f[offset], provider);
  1798. if (idx != COMMAND_NOT_FOUND)
  1799. {
  1800. P:4("Command_Add: Command exists");
  1801. #if YSIM_HAS_MASTER
  1802. YSI_g_sCommands[idx][E_COMMANDS_MASTERS] |= 1 << s;
  1803. #endif
  1804. return; //0;
  1805. }
  1806. }
  1807. YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][0] = COMMAND_FUNCTION_PREFIX;
  1808. //Bit_SetAll(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true, bits<MAX_PLAYERS>);
  1809. //Command_InitialiseFromGroups(YSI_g_sCommandIndex);
  1810. PA_FastInit(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS]);
  1811. NO_GROUPS(YSI_g_sCommandIndex)
  1812. {
  1813. PA_Init(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true);
  1814. }
  1815. // Swap these.
  1816. #if YSIM_HAS_MASTER
  1817. YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_MASTERS] = 1 << s;
  1818. #endif
  1819. P:2("Command_Add: Command added in %d (%d)", YSI_g_sCommandIndex, hash);
  1820. hash = YSI_g_sCommandIndex;
  1821. // Set this command as usable in any script.
  1822. P:4("Command_Add: %08x%08x%08x%08x", YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][0], YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][1], YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][2], YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][3]);
  1823. YSI_g_sCommandIndex = YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER];
  1824. #if YSIM_HAS_MASTER
  1825. YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER] = hash | (provider << 24);
  1826. #else
  1827. YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER] = hash;
  1828. #endif
  1829. /*#if YSIM_HAS_MASTER
  1830. if (s == _@)
  1831. #endif
  1832. {
  1833. new
  1834. addr = funcidx(f) * 8 + AMX_HEADER_PUBLICS;
  1835. #emit LREF.S.pri addr
  1836. #emit STOR.S.pri addr
  1837. YSI_g_sCommands[hash][E_COMMANDS_AMX_ADDRESS] = addr;
  1838. }
  1839. #pragma tabsize 4*/
  1840. // Now some complex debug rubbish.
  1841. C:4(new str[32];strpack(str, f);printf("Command_Add: %08x%08x%08x%08x", str[0], str[1], str[2], str[3]););
  1842. ++YSI_g_sCommandCount;
  1843. }
  1844. //return 1;
  1845. /*else
  1846. {
  1847. // Not all hope is lost - check if this command name already exists.
  1848. if (Command_IsSorted())
  1849. {
  1850. new
  1851. pos = Command_FindFast(funcname[4], Command_FastHash(funcname[4]));
  1852. if (pos != COMMAND_NOT_FOUND)
  1853. {
  1854. // Found it already in the array.
  1855. return pos;
  1856. }
  1857. }
  1858. else
  1859. {
  1860. new
  1861. pos = Command_FindSlow(funcname[4]);
  1862. if (pos != COMMAND_NOT_FOUND)
  1863. {
  1864. // Command already exists.
  1865. return pos;
  1866. }
  1867. }
  1868. }
  1869. return COMMAND_NOT_FOUND;*/
  1870. }
  1871. /**--------------------------------------------------------------------------**\
  1872. <summary>Command_AddAlt</summary>
  1873. <param name="funcidx">The function this is an alternate to.</param>
  1874. <param name="altname[]">The new name.</param>
  1875. <returns>
  1876. -
  1877. </returns>
  1878. <remarks>
  1879. If the list of commands have already been sorted into the binary tree the
  1880. new commands will be appended, otherwise they will just be added to the
  1881. array.
  1882. native Command_AddAlt(funcidx, altname[]);
  1883. </remarks>
  1884. \**--------------------------------------------------------------------------**/
  1885. foreign Command_AddAlt(oidx, string:altname[]);
  1886. global Command_AddAlt(oidx, string:altname[])
  1887. {
  1888. P:2("Command_AddAlt called: %i, \"%s\"", oidx, altname);
  1889. if (!Command_IsValid(oidx))
  1890. {
  1891. return COMMAND_NOT_FOUND;
  1892. }
  1893. #if YSIM_HAS_MASTER
  1894. new
  1895. provider = _:Command_DefaultProvider();
  1896. #else
  1897. static
  1898. provider = -1;
  1899. #endif
  1900. if (YSI_g_sCommandCount < MAX_COMMANDS && YSI_g_sCommandIndex != -1)
  1901. {
  1902. new
  1903. hash = Command_AddHash(altname, YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION], 0);
  1904. if (Command_IsSorted())
  1905. {
  1906. // Find the function this mirrors.
  1907. //oidx = Command_FindFast(function, Command_FastHash(function));
  1908. new
  1909. pos = Command_FindFastStrict(altname, hash, provider);
  1910. if (pos != COMMAND_NOT_FOUND)
  1911. {
  1912. if (Command_GetPointer(pos) != oidx)
  1913. {
  1914. // Same altname, different function.
  1915. return COMMAND_NOT_FOUND;
  1916. }
  1917. return pos;
  1918. }
  1919. if (!Command_HasCollisions())
  1920. {
  1921. // Check for an existing command with this hash.
  1922. //if (Bintree_FindValue(YSI_g_sSearchTree, hash) != BINTREE_NOT_FOUND)
  1923. //{
  1924. // Command_SetCollisions();
  1925. //}
  1926. new
  1927. leaf;
  1928. while ((pos = Bintree_FindValue(YSI_g_sSearchTree, hash, leaf)) != BINTREE_NOT_FOUND)
  1929. {
  1930. // Don't have collisions if the providers are different.
  1931. if ((YSI_g_sCommands[pos][E_COMMANDS_FUNC_POINTER] >>> 24) != provider) continue;
  1932. Command_SetCollisions();
  1933. }
  1934. }
  1935. // Command doesn't exist already - good!
  1936. Bintree_Add(YSI_g_sSearchTree, YSI_g_sCommandIndex, hash, YSI_g_sCommandIndex);
  1937. }
  1938. else
  1939. {
  1940. new
  1941. pos = Command_FindSlowStrict(altname, provider);
  1942. if (pos != COMMAND_NOT_FOUND)
  1943. {
  1944. if (Command_GetPointer(pos) != oidx)
  1945. {
  1946. // Same altname, different function.
  1947. return COMMAND_NOT_FOUND;
  1948. }
  1949. // Command already exists.
  1950. return pos;
  1951. }
  1952. }
  1953. YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][0] = COMMAND_FUNCTION_PREFIX;
  1954. //Bit_SetAll(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true, bits<MAX_PLAYERS>);
  1955. //Command_InitialiseFromGroups(YSI_g_sCommandIndex);
  1956. PA_FastInit(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS]);
  1957. NO_GROUPS(YSI_g_sCommandIndex)
  1958. {
  1959. PA_Init(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true);
  1960. }
  1961. ++YSI_g_sCommandCount;
  1962. #if YSIM_HAS_MASTER
  1963. // This doesn't have real masters.
  1964. YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_MASTERS] = -1;
  1965. #endif
  1966. P:2("Command_AddAlt: Command added in %d as %d", YSI_g_sCommandIndex, oidx);
  1967. hash = YSI_g_sCommandIndex;
  1968. YSI_g_sCommandIndex = YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER];
  1969. #if YSIM_HAS_MASTER
  1970. YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER] = oidx | (provider << 24);
  1971. #else
  1972. YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER] = oidx;
  1973. #endif
  1974. return hash;
  1975. }
  1976. else
  1977. {
  1978. // Not all hope is lost - check if this command name already exists.
  1979. new
  1980. pos;
  1981. if (Command_IsSorted())
  1982. {
  1983. pos = Command_FindFastStrict(altname, Command_FastHash(altname), provider);
  1984. }
  1985. else
  1986. {
  1987. pos = Command_FindSlowStrict(altname, provider);
  1988. }
  1989. if (pos != COMMAND_NOT_FOUND)
  1990. {
  1991. // Found it already in the array. Check if the element it points to
  1992. // has the correct name so we know this is the correct pair, not
  1993. // just the correct single element. I.e. check that this is the
  1994. // correct original/altname combo, not the right altname on a
  1995. // different original name.
  1996. if (oidx == Command_GetPointer(pos))
  1997. {
  1998. return pos;
  1999. }
  2000. }
  2001. }
  2002. return COMMAND_NOT_FOUND;
  2003. }
  2004. /**--------------------------------------------------------------------------**\
  2005. <summary>Command_AddAltNamed</summary>
  2006. <param name="function[]">The function this is an alternate to.</param>
  2007. <param name="altname[]">The new name.</param>
  2008. <returns>
  2009. -
  2010. </returns>
  2011. <remarks>
  2012. Add an alternate command for an existing command.
  2013. native Command_AddAltNamed(function[], altname[]);
  2014. </remarks>
  2015. \**--------------------------------------------------------------------------**/
  2016. foreign Command_AddAltNamed(string:function[], string:altname[]);
  2017. global Command_AddAltNamed(string:function[], string:altname[])
  2018. {
  2019. P:2("Command_AddAltNamed called: \"%s\", \"%s\"", function, altname);
  2020. return Command_AddAlt(Command_Find(function), altname);
  2021. }
  2022. /**--------------------------------------------------------------------------**\
  2023. <summary>Command_Debug</summary>
  2024. <returns>
  2025. -
  2026. </returns>
  2027. <remarks>
  2028. Print some random information about commands if _DEBUG is set.
  2029. </remarks>
  2030. \**--------------------------------------------------------------------------**/
  2031. stock Command_Debug()
  2032. {
  2033. P:3("Command_Debug called: %i");
  2034. #if _DEBUG > 0
  2035. printf("Command_Debug: Start");
  2036. for (new i = 0; i != MAX_COMMANDS; ++i)
  2037. {
  2038. if (Command_IsValid(i))
  2039. {
  2040. printf("Command_Debug: Loop start %d", i);
  2041. new buffer[MAX_COMMAND_LENGTH];
  2042. strunpack(buffer, Command_Name(i));
  2043. printf("%08x%08x%08x", YSI_g_sCommands[i][E_COMMANDS_FUNCTION][0], YSI_g_sCommands[i][E_COMMANDS_FUNCTION][1], YSI_g_sCommands[i][E_COMMANDS_FUNCTION][2]);
  2044. new pointer = Command_GetPointer(i);
  2045. printf("Command %d:", i);
  2046. printf("\t%s", buffer);
  2047. printf("\t%d", pointer);
  2048. printf("\t%d %d %d", YSI_g_sSearchTree[i][E_BINTREE_TREE_LEFT], YSI_g_sSearchTree[i][E_BINTREE_TREE_RIGHT], YSI_g_sSearchTree[i][E_BINTREE_TREE_VALUE]);
  2049. CallLocalFunction(Command_GetFunction(Command_GetPointer(i)), "isi", 0, "hi", 0);
  2050. printf("Command_Debug: Loop end");
  2051. }
  2052. }
  2053. printf("Command_Debug: End");
  2054. #endif
  2055. }
  2056. /**--------------------------------------------------------------------------**\
  2057. <summary>OnPlayerCommandText</summary>
  2058. <param name="playerid">Player who entered the command.</param>
  2059. <param name="cmdtext[]">Text entered.</param>
  2060. <returns>
  2061. true - success or hidden fail.
  2062. false - fail.
  2063. </returns>
  2064. <remarks>
  2065. Calls the Command_Process function if this is not a client.
  2066. </remarks>
  2067. \**--------------------------------------------------------------------------**/
  2068. #if YSIM_NOT_CLIENT
  2069. mhook OnPlayerCommandText(playerid, cmdtext[])
  2070. {
  2071. P:1("Commands_OnPlayerCommandText");
  2072. if (isnull(cmdtext)) return Command_UnknownReturn();
  2073. if (YSI_g_sCommandFlags & e_COMM_FLAG_OPCR)
  2074. {
  2075. switch (CallRemoteFunction("OnPlayerCommandReceived", "is", playerid, cmdtext))
  2076. {
  2077. case 0:
  2078. // Handle normally, as in ZCMD.
  2079. return 1;
  2080. case -1:
  2081. // Allow them to stop processing but return 0.
  2082. return 0;
  2083. // Do nothing on 1.
  2084. }
  2085. }
  2086. if (YSI_g_sCommandFlags & e_COMM_FLAG_OPCP)
  2087. {
  2088. new
  2089. ret = Command_Process(playerid, cmdtext, 0);
  2090. switch (CallRemoteFunction("OnPlayerCommandPerformed", "isi", playerid, cmdtext, ret))
  2091. {
  2092. case 0:
  2093. return 0;
  2094. case 1:
  2095. return 1;
  2096. //default:
  2097. // Return the original return on -1.
  2098. }
  2099. return ret;
  2100. }
  2101. else
  2102. {
  2103. /*switch (Command_Process(playerid, cmdtext, 0))
  2104. {
  2105. case 1:
  2106. // Found the command, processed.
  2107. return 1;
  2108. case -1:
  2109. // Found the command, but want to return 0 anyway.
  2110. return 0;
  2111. // Do nothing on 0.
  2112. }*/
  2113. return Command_Process(playerid, cmdtext, 0);
  2114. }
  2115. // This can never actually be reached!
  2116. //return 0;
  2117. }
  2118. #endif
  2119. /**--------------------------------------------------------------------------**\
  2120. <summary>Command_ReProcess</summary>
  2121. <param name="playerid">Player who entered the command.</param>
  2122. <param name="cmdtext[]">Text entered.</param>
  2123. <param name="help">Called from the help commmand or OnPlayerCommandText.</param>
  2124. <returns>
  2125. true - success or hidden fail.
  2126. false - fail.
  2127. </returns>
  2128. <remarks>
  2129. -
  2130. </remarks>
  2131. \**--------------------------------------------------------------------------**/
  2132. foreign Command_ReProcess(p,string:c[],h);
  2133. global Command_ReProcess(p,string:c[],h)
  2134. {
  2135. P:2("Command_ReProcess called: %i, \"%s\", %i", p, c, h);
  2136. return Command_Process(p,c,h);
  2137. }
  2138. /**--------------------------------------------------------------------------**\
  2139. <summary>Command_Process</summary>
  2140. <param name="playerid">Player who entered the command.</param>
  2141. <param name="cmdtext[]">Text entered.</param>
  2142. <param name="help">Called from the help commmand or OnPlayerCommandText.</param>
  2143. <returns>
  2144. true - success or hidden fail.
  2145. false - fail.
  2146. </returns>
  2147. <remarks>
  2148. -
  2149. </remarks>
  2150. \**--------------------------------------------------------------------------**/
  2151. #define Command_CallR(%1,%2) \
  2152. CallRemoteFunction(Command_GetFuncName((%1)), "isii", playerid, %2, help, script)
  2153. #define Command_CallL(%1,%2) \
  2154. CallLocalFunction(Command_GetFuncName((%1)), "isi", playerid, %2, help)
  2155. static stock Command_Process(playerid, cmdtext[], help)
  2156. {
  2157. P:4("Command_Process FS called: %i, \"%s\", %i", playerid, cmdtext, help);
  2158. // Support for very old problems!
  2159. // TODO: Add back.
  2160. P:2("Command_Process called: %d %s", playerid, cmdtext);
  2161. /*#if !_DEBUG && !defined _YSI_SPECIAL_DEBUG
  2162. // For testing purposes.
  2163. if (!IsPlayerConnected(playerid))
  2164. {
  2165. return Command_DisconnectReturn();
  2166. }
  2167. #endif*/
  2168. P:4("Command_Process: Connected");
  2169. new
  2170. idx,
  2171. prelen = help ? 0 : 1,
  2172. index = prelen;
  2173. /*// Shortcuts.
  2174. if (cmdtext[2] <= ' ')
  2175. {
  2176. // Get a player's shortcut information for this letter.
  2177. }
  2178. else*/
  2179. {
  2180. // No more faffing about with random alternate code - it's all done in
  2181. // one nice function instead of having to handle both separately.
  2182. new
  2183. length,
  2184. hash = Command_Hash(cmdtext, index, length);
  2185. P:2("Command_Process: Hash = %d, Length = %d", hash, length);
  2186. // NOTE: No prefix support here.
  2187. cmdtext[length + prelen] = '\0';
  2188. #if YSIM_HAS_MASTER
  2189. length = YSI_g_sPlayerProvider{playerid};
  2190. P:2("Command_Process: Provider: %d", length);
  2191. idx = Command_FindFast(cmdtext[prelen], hash, length);
  2192. if (idx == COMMAND_NOT_FOUND && length != 0xFF)
  2193. {
  2194. // Check default commands if no specialised commands were found.
  2195. idx = Command_FindFast(cmdtext[prelen], hash);
  2196. }
  2197. #else
  2198. idx = Command_FindFast(cmdtext[prelen], hash);
  2199. #endif
  2200. // TODO: Replace!
  2201. //idx = Command_FindSlow(cmdtext[prelen]);//, hash);
  2202. }
  2203. P:2("Command_Process: Index = %d", idx);
  2204. if (idx != COMMAND_NOT_FOUND)
  2205. {
  2206. // Get the master data for the underlying command, not the possibly
  2207. // changed name.
  2208. new
  2209. pointer = Command_GetPointer(idx);
  2210. P:4("Command_Process: Found %d, %d", idx, pointer);
  2211. // Found a command with this name - check the permissions.
  2212. //if (Bit_Get(YSI_g_sCommands[idx][E_COMMANDS_PLAYERS], playerid))
  2213. if (Command_CheckPlayer(idx, playerid))
  2214. {
  2215. P:4("Command_Process: Allowed");
  2216. // Allowed to use the command, get the real function. Note that
  2217. // this may well be the same as "idx", but we loose no time.
  2218. #if YSIM_HAS_MASTER
  2219. P:4("Command_Process: %08x%08x%08x%08x", YSI_g_sCommands[idx][E_COMMANDS_FUNCTION][0], YSI_g_sCommands[idx][E_COMMANDS_FUNCTION][1], YSI_g_sCommands[idx][E_COMMANDS_FUNCTION][2], YSI_g_sCommands[idx][E_COMMANDS_FUNCTION][3]);
  2220. //if (master & 1 << YSI_g_sMaster23)
  2221. //{
  2222. // master = YSI_g_sMaster23;
  2223. //}
  2224. //else
  2225. //{
  2226. new
  2227. script = Command_Provider(idx);
  2228. if (script == 0xFF)
  2229. {
  2230. script = YSI_g_sCommands[pointer][E_COMMANDS_MASTERS];
  2231. if (!script)
  2232. {
  2233. // No scripts can serve the code.
  2234. return Command_UnknownReturn();
  2235. }
  2236. // Find the lowest set bit. We use this to broadcastfunc the
  2237. // command. If it uses MASTER 23, this will select only
  2238. // one script to use. If it doesn't use MASTER 23, this is
  2239. // ignored as a parameter and _YCM is used instead.
  2240. static const
  2241. scDeBruijn[] =
  2242. {
  2243. 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  2244. 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
  2245. };
  2246. // http://supertech.csail.mit.edu/papers/debruijn.pdf
  2247. script = scDeBruijn[((script & -script) * 0x077CB531) >>> 27];
  2248. }
  2249. //}
  2250. P:2("Command_Process: script = %d", script);
  2251. //if (master == _@)
  2252. //{
  2253. /*#endif
  2254. // This script has it!
  2255. addr = YSI_g_sCommands[pointer][E_COMMANDS_AMX_ADDRESS];
  2256. P:4("Command_Process: %04x%04x", addr >>> 16, addr & 0xFFFF);
  2257. // Make sure all the "#emits" are together as they don't
  2258. // seem to be affected by pre-processor directives.
  2259. #emit PUSH.S master
  2260. #emit PUSH.S help
  2261. #emit LOAD.S.alt cmdtext
  2262. #emit LOAD.S.pri index
  2263. #emit SMUL.C 4
  2264. #emit ADD
  2265. #emit PUSH.pri
  2266. #emit PUSH.S playerid
  2267. #emit PUSH.C 16
  2268. #emit LCTRL 6
  2269. #emit ADD.C 28
  2270. #emit PUSH.pri
  2271. #emit LOAD.S.pri addr
  2272. #emit SCTRL 6
  2273. #emit STOR.S.pri addr
  2274. #if YSIM_HAS_MASTER*/
  2275. //}
  2276. //else
  2277. //{
  2278. #pragma tabsize 4
  2279. P:2("Command_Process: call %s (%d, %d)", unpack(Command_GetFuncName(pointer)), pointer, script);
  2280. if (cmdtext[index])
  2281. {
  2282. // Call it!
  2283. Command_CallR(pointer, cmdtext[index]);
  2284. }
  2285. else
  2286. {
  2287. Command_CallR(pointer, NULL);
  2288. }
  2289. #pragma tabsize 4
  2290. //}
  2291. // Get the real return.
  2292. P:1("Command_Process: return: %d", getproperty(8, YSIM_RETURN));
  2293. return getproperty(8, YSIM_RETURN);
  2294. #else
  2295. if (cmdtext[index])
  2296. {
  2297. // Call it!
  2298. return Command_CallL(pointer, cmdtext[index]);
  2299. }
  2300. else
  2301. {
  2302. return Command_CallL(pointer, NULL);
  2303. }
  2304. //return addr;
  2305. #endif
  2306. }
  2307. else
  2308. {
  2309. return Command_DeniedReturn();
  2310. }
  2311. }
  2312. P:5("Command_Process: Not found");
  2313. #pragma tabsize 4
  2314. return Command_UnknownReturn();
  2315. }
  2316. /**--------------------------------------------------------------------------**\
  2317. <summary>Command_GetName</summary>
  2318. <param name="funcid">Command to get the name of.</param>
  2319. <returns>
  2320. -
  2321. </returns>
  2322. <remarks>
  2323. -
  2324. native Command_GetName(funcid);
  2325. </remarks>
  2326. \**--------------------------------------------------------------------------**/
  2327. foreign string:Command_GetName(funcid);
  2328. global string:Command_GetName(funcid)
  2329. {
  2330. P:2("Command_GetName called: %i", funcid);
  2331. new
  2332. buffer[YSI_MAX_STRING] = "";
  2333. if (Command_IsValid(funcid))
  2334. {
  2335. strunpack(buffer, Command_Name(funcid));
  2336. }
  2337. return buffer;
  2338. }
  2339. /**--------------------------------------------------------------------------**\
  2340. <summary>Command_GetDisplay</summary>
  2341. <param name="f">Command to get the real name of.</param>
  2342. <param name="p">Player to get the name for.</param>
  2343. <returns>
  2344. The name of a command for a single player.
  2345. </returns>
  2346. <remarks>
  2347. -
  2348. native Command_GetDisplay(funcid, playerid);
  2349. </remarks>
  2350. \**--------------------------------------------------------------------------**/
  2351. foreign string:Command_GetDisplay(funcid, playerid);
  2352. global string:Command_GetDisplay(funcid, playerid)
  2353. {
  2354. P:2("Command_GetDisplay called: %i, %i", funcid, playerid);
  2355. new
  2356. buffer[YSI_MAX_STRING] = "";
  2357. if (Command_IsValid(funcid))
  2358. {
  2359. // Don't recalculate this every loop.
  2360. new
  2361. slot = Bit_Slot(playerid) + 1,
  2362. Bit:mask = Bit_Mask(playerid);
  2363. // Check if they can use the original version.
  2364. if (YSI_g_sCommands[funcid][E_COMMANDS_PLAYERS][slot] & mask)
  2365. {
  2366. //setproperty(8, "", YSIM_STRING, Command_Name(f));
  2367. strunpack(buffer, Command_Name(funcid));
  2368. return buffer;
  2369. //return 1;
  2370. }
  2371. // Search for a command pointing to that command which the player can use.
  2372. for (new i = 0; i != MAX_COMMANDS; ++i)
  2373. {
  2374. if (Command_GetPointer(i) == funcid && (YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask))
  2375. {
  2376. //setproperty(8, "", YSIM_STRING, Command_Name(i));
  2377. strunpack(buffer, Command_Name(i));
  2378. return buffer;
  2379. }
  2380. }
  2381. }
  2382. return buffer;
  2383. }
  2384. /**--------------------------------------------------------------------------**\
  2385. <summary>Command_GetDisplayNamed</summary>
  2386. <param name="f[]">Command to get the real name of.</param>
  2387. <param name="p">Player to get the name for.</param>
  2388. <returns>
  2389. The name of a named function for one player.
  2390. </returns>
  2391. <remarks>
  2392. Remote function call for Command_GetDisplayNameNamed - avoids needing to
  2393. expose users to the master system's odd way of returning strings. This is
  2394. the only part I've not yet fixed up to be nice and hidden.
  2395. native string:Command_GetDisplayNamed(string:funcid[], playerid);
  2396. </remarks>
  2397. \**--------------------------------------------------------------------------**/
  2398. foreign string:Command_GetDisplayNamed(string:func[], playerid);
  2399. global string:Command_GetDisplayNamed(string:func[], playerid)
  2400. {
  2401. P:1("Command_GetDisplayNamed called: \"%s\", %i", func, playerid);
  2402. new
  2403. pointer = Command_Find(func),
  2404. buffer[YSI_MAX_STRING] = "";
  2405. if (pointer != COMMAND_NOT_FOUND)
  2406. {
  2407. // Don't recalculate this every loop.
  2408. new
  2409. slot = Bit_Slot(playerid) + 1, //playerid >>> CELLSHIFT) + 1,
  2410. Bit:mask = Bit_Mask(playerid); //Bit:(1 << (playerid & (cellbits - 1)));
  2411. // Check if they can use the original version.
  2412. if (YSI_g_sCommands[pointer][E_COMMANDS_PLAYERS][slot] & mask)
  2413. {
  2414. //setproperty(8, "", YSIM_STRING, Command_Name(pointer));
  2415. strunpack(buffer, Command_Name(pointer));
  2416. return buffer;
  2417. }
  2418. // Search for a command pointing to that command which the player can use.
  2419. for (new i = 0; i != MAX_COMMANDS; ++i)
  2420. {
  2421. if (Command_GetPointer(i) == pointer && (YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask))
  2422. {
  2423. //setproperty(8, "", YSIM_STRING, Command_Name(i));
  2424. strunpack(buffer, Command_Name(i));
  2425. return buffer;
  2426. }
  2427. }
  2428. }
  2429. return buffer;
  2430. }
  2431. /**--------------------------------------------------------------------------**\
  2432. <summary>Command_GetPlayerCommandCount</summary>
  2433. <param name="playerid">Player to count for.</param>
  2434. <returns>
  2435. -
  2436. </returns>
  2437. <remarks>
  2438. Gets the number of comamnds this player can use.
  2439. native Command_GetPlayerCommandCount(playerid);
  2440. </remarks>
  2441. \**--------------------------------------------------------------------------**/
  2442. foreign Command_GetPlayerCommandCount(playerid);
  2443. global Command_GetPlayerCommandCount(playerid)
  2444. {
  2445. P:2("Command_GetPlayerCommandCount called: %i", playerid);
  2446. new
  2447. slot = Bit_Slot(playerid) + 1,
  2448. Bit:mask = Bit_Mask(playerid),
  2449. count = 0;
  2450. for (new i = 0; i != MAX_COMMANDS; ++i)
  2451. {
  2452. if (_Command_IsValid(i) && YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask)
  2453. {
  2454. ++count;
  2455. }
  2456. }
  2457. return count;
  2458. }
  2459. /**--------------------------------------------------------------------------**\
  2460. <summary>Command_GetNext</summary>
  2461. <param name="index">Index of the next command for this player.</param>
  2462. <param name="playerid">Player to get the name for.</param>
  2463. <returns>
  2464. The name of a command for a single player.
  2465. </returns>
  2466. <remarks>
  2467. -
  2468. native Command_GetNext(index, playerid);
  2469. </remarks>
  2470. \**--------------------------------------------------------------------------**/
  2471. foreign string:Command_GetNext(index, playerid);
  2472. global string:Command_GetNext(index, playerid)
  2473. {
  2474. P:2("Command_GetNext called: %i, %i", index, playerid);
  2475. new
  2476. buffer[YSI_MAX_STRING] = "";
  2477. if (0 <= index < MAX_COMMANDS)
  2478. {
  2479. // Don't recalculate this every loop.
  2480. new
  2481. slot = Bit_Slot(playerid) + 1,
  2482. Bit:mask = Bit_Mask(playerid);
  2483. for (new i = 0; i != MAX_COMMANDS; ++i)
  2484. {
  2485. if (_Command_IsValid(i) && YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask)
  2486. {
  2487. // Skip already displayed ones.
  2488. if (index)
  2489. {
  2490. --index;
  2491. }
  2492. else
  2493. {
  2494. strunpack(buffer, Command_Name(i));
  2495. return buffer;
  2496. }
  2497. }
  2498. }
  2499. }
  2500. return buffer;
  2501. }
  2502. //#tryinclude <YSI\y_groups>
  2503. //#undef _YCM
  2504. // This is to allow callback chaining. When the user includes y_groups and
  2505. // other libraries, the function names will be reset to their custom ones after
  2506. // every inclusion, however if you then include another YSI library you need to
  2507. // revert to the previous library names to get the chaining to work. However I
  2508. // think this is completely pointless now thanks to "y_hooks".
  2509. //#define YSI_SET_LAST_GROUP 25
  2510. #include "internal\y_grouprevert"
  2511. // So we can use custom syntax on these two functions and allow command names to
  2512. // be sort of used...
  2513. //#define Group_SetCommand(%0,YCMD:%2,%3) Group_SetCommand(%0,Command_GetID(#%2),%3)
  2514. //#define Group_SetGlobalCommand(YCMD:%2,%3) Group_SetGlobalCommand(Command_GetID(#%2),%3)