Y_Less

Untitled

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