Advertisement
Guest User

y_commands with OPCR/OPCP

a guest
Aug 17th, 2011
1,226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 64.49 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. #if defined FILTERSCRIPT
  911.     #if defined _ALS_OnFilterScriptInit
  912.         #undef OnFilterScriptInit
  913.     #else
  914.         #define _ALS_OnFilterScriptInit
  915.     #endif
  916.     #define OnFilterScriptInit Command_OnScriptInit
  917. #else
  918.     #if defined _ALS_OnGameModeInit
  919.         #undef OnGameModeInit
  920.     #else
  921.         #define _ALS_OnGameModeInit
  922.     #endif
  923.     #define OnGameModeInit Command_OnScriptInit
  924. #endif
  925. forward Command_OnScriptInit();
  926.  
  927. // Forwards for initial command callbacks.
  928. forward OnPlayerCommandReceived(playerid, cmdtext[]);
  929. forward OnPlayerCommandPerformed(playerid, cmdtext[], success);
  930.  
  931. /*----------------------------------------------------------------------------*-
  932. Function:
  933.     OnScriptClose
  934. Params:
  935.     script - ID of the closing script.
  936. Return:
  937.     -
  938. Notes:
  939.     Called when a script under the control of the master system ends.
  940. -*----------------------------------------------------------------------------*/
  941.  
  942. #if YSIM_NOT_CLIENT
  943.     #if YSIM_CLOUD
  944.         public OnScriptClose(script) <>
  945.         {
  946.             if (funcidx("OnPlayerCommandPerformed") != -1)
  947.             {
  948.                 Command_DecOPCP();
  949.             }
  950.             if (funcidx("OnPlayerCommandReceived") != -1)
  951.             {
  952.                 Command_DecOPCR();
  953.             }
  954.             CallLocalFunction("Command_OnScriptClose", "i", script);
  955.         }
  956.        
  957.         public OnScriptClose(script) <_YCM:y>
  958.     #elseif YSIM_IS_STUB
  959.         #error y_commands called with YSIM_IS_STUB.
  960.     #else
  961.         public OnScriptClose(script)
  962.     #endif
  963.     {
  964.         if (funcidx("OnPlayerCommandPerformed") != -1)
  965.         {
  966.             Command_DecOPCP();
  967.         }
  968.         if (funcidx("OnPlayerCommandReceived") != -1)
  969.         {
  970.             Command_DecOPCR();
  971.         }
  972.         new
  973.             mask = ~(1 << script);
  974.         for (new i = 0; i != MAX_COMMANDS; ++i)
  975.         {
  976.             if (Command_GetPointer(i) == i && (YSI_g_sCommands[i][E_COMMANDS_MASTERS] &= mask) == 0)
  977.             {
  978.                 for (new j = 0; j != MAX_COMMANDS; ++j)
  979.                 {
  980.                     // Remove all alternate names.
  981.                     if (Command_GetPointer(j) == i)
  982.                     {
  983.                         YSI_g_sCommands[j][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  984.                         YSI_g_sCommandIndex = j;
  985.                         YSI_g_sCommands[j][E_COMMANDS_MASTERS] = 0;
  986.                         //Bintree_Delete(YSI_g_sSearchTree, j, YSI_g_sCommandCount);
  987.                         Command_RemoveFromBintree(j);
  988.                         --YSI_g_sCommandCount;
  989.                         //Bintree_Add(YSI_g_sSearchTree, YSI_g_sCommandIndex, hash, YSI_g_sCommandIndex);
  990.                     }
  991.                 }
  992.             }
  993.             /*new
  994.                 p = i;
  995.             while (YSI_g_sCommands[p][E_COMMANDS_MASTERS] == -1)
  996.             {
  997.                 p = Command_GetPointer(p);
  998.             }
  999.             if (YSI_g_sCommands[p][E_COMMANDS_FUNC_POINTER] == p && (YSI_g_sCommands[p][E_COMMANDS_MASTERS] &= mask) == 0)
  1000.             {
  1001.                 // Remove all alternate versions of commands - done backwards by
  1002.                 // an alternate command checking its parent.  Can also handle
  1003.                 // alternate versions of alternate commands (note this is the
  1004.                 // only code that can currently).
  1005.                 YSI_g_sCommands[i][E_COMMANDS_MASTERS] = 0;
  1006.                 YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  1007.                 YSI_g_sCommandIndex = i;
  1008.                 // Mark it as invalid in this instance.
  1009.                 YSI_g_sCommands[i][E_COMMANDS_MASTERS] = 0;
  1010.                 // Reduce the number of commands.
  1011.                 --YSI_g_sCommandCount;
  1012.             }*/
  1013.         }
  1014.         YSI_g_sMaster23 = getproperty(8, "x@");
  1015.         // I can add better removal code later.  Done ^
  1016.         CallLocalFunction("Command_OnScriptClose", "i", script);
  1017.     }
  1018.    
  1019.     // Don't need ALS here as we did it supporting it at the start.
  1020.     #undef OnScriptClose
  1021.     #define OnScriptClose Command_OnScriptClose
  1022.     forward Command_OnScriptClose(script);
  1023. #endif
  1024.  
  1025. /*----------------------------------------------------------------------------*-
  1026. Function:
  1027.     OnPlayerConnect
  1028. Params:
  1029.     -
  1030. Return:
  1031.     -
  1032. Notes:
  1033.     -
  1034. -*----------------------------------------------------------------------------*/
  1035.  
  1036. // TODO: Rewrite!
  1037. //RA:Command_OnPlayerConnect(playerid)
  1038.  
  1039. #if YSIM_NOT_CLIENT
  1040.     #if YSIM_CLOUD
  1041.         public OnPlayerConnect(playerid) <>
  1042.         {
  1043.             YSI_g_sPlayerProvider{playerid} = 0xFF;
  1044.             if (YSI_g_sCommandFlags & e_COMM_FLAG_OPC)
  1045.             {
  1046.                 return CallLocalFunction("Command_OnPlayerConnect", "i", playerid);
  1047.             }
  1048.             return 1;
  1049.         }
  1050.        
  1051.         public OnPlayerConnect(playerid) <_YCM:y>
  1052.     #elseif YSIM_IS_STUB
  1053.         #error y_commands called with YSIM_IS_STUB.
  1054.     #else
  1055.         public OnPlayerConnect(playerid)
  1056.     #endif
  1057.     {
  1058.         //#if YSIM_NOT_CLIENT
  1059.         //YSI_g_sCommandDialog[playerid] = -1;
  1060.         YSI_g_sPlayerProvider{playerid} = 0xFF;
  1061.         NO_GROUPS()
  1062.         {
  1063.             new
  1064.                 slot = Bit_Slot(playerid) + 1,
  1065.                 Bit:mask = Bit_Mask(playerid); //Bit:(1 << (playerid & (cellbits - 1)));
  1066.             for (new i = 0; i != MAX_COMMANDS; ++i)
  1067.             {
  1068.                 YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] |= mask;
  1069.                 //PA+(YSI_g_sCommands[i][E_COMMANDS_PLAYERS], mask);
  1070.             }
  1071.         }
  1072.         //#endif
  1073.         // Groups will ALWAYS be called after this function - so this can reset
  1074.         // player permissions however it likes with the group system then being
  1075.         // able to override anything set in here.
  1076.         if (YSI_g_sCommandFlags & e_COMM_FLAG_OPC)
  1077.         {
  1078.             return CallLocalFunction("Command_OnPlayerConnect", "i", playerid);
  1079.         }
  1080.         return 1;
  1081.         //ALS_CALL<PlayerConnect, i>(playerid)
  1082.     }
  1083.    
  1084.     #if defined _ALS_OnPlayerConnect
  1085.         #undef OnPlayerConnect
  1086.     #else
  1087.         #define _ALS_OnPlayerConnect
  1088.     #endif
  1089.     #define OnPlayerConnect Command_OnPlayerConnect
  1090.     forward Command_OnPlayerConnect(playerid);
  1091. #endif
  1092.  
  1093. /*----------------------------------------------------------------------------*-
  1094. Function:
  1095.     Command_
  1096. Params:
  1097.     command - Command to declare.
  1098. Return:
  1099.     -
  1100. Notes:
  1101.     Deprecated!
  1102. -*----------------------------------------------------------------------------*/
  1103.  
  1104. #define Command_(%1) \
  1105.     CMD:%1(playerid,params[],help)
  1106.  
  1107. /*----------------------------------------------------------------------------*-
  1108. Function:
  1109.     ycmd
  1110. Params:
  1111.     command[] - Command to register.
  1112. Return:
  1113.     -
  1114. Notes:
  1115.     Deprecated!
  1116. -*----------------------------------------------------------------------------*/
  1117.  
  1118. #define ycmd(%1);
  1119.  
  1120. /*----------------------------------------------------------------------------*-
  1121. Function:
  1122.     Command_FindFast
  1123. Params:
  1124.     data[] - Function name to find.
  1125.     value - Hash of function name.
  1126. Return:
  1127.     Position in functions array or COMMAND_NOT_FOUND.
  1128. Notes:
  1129.     -
  1130. -*----------------------------------------------------------------------------*/
  1131.  
  1132. static stock Command_FindFast(data[], value, provider = 0xFF)
  1133. {
  1134.     new
  1135.         leaf,
  1136.         pointer;
  1137.     P:5("Command_FindFast: Searching for %s", data);
  1138.     while ((pointer = Bintree_FindValue(YSI_g_sSearchTree, value, leaf)) != BINTREE_NOT_FOUND)
  1139.     {
  1140.         new
  1141.             p = YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER];
  1142.         if (Command_HasMultipleProviders() && (p & 0xFF000000 != 0xFF000000) && (p >>> 24 != provider)) continue;
  1143.         // Don't do an strcmp if there are no collisions.
  1144.         if (!Command_HasCollisions()) return pointer;
  1145.         //if (!strcmp(YSI_g_sCommands[i][E_COMMANDS_FUNCTION][1], funcname) &&
  1146.         if (!strcmp(Command_Name(pointer), data)) return pointer;
  1147.         //if (!strcmp(Command_Name(pointer), data) && (Command_GetProvider(pointer) == 0xFF || Command_GetProvider(pointer) == provider)) return pointer;
  1148.     }
  1149.     P:5("Command_FindFast: Not found");
  1150.     return COMMAND_NOT_FOUND;
  1151. }
  1152.  
  1153. static stock Command_FindFastStrict(data[], value, provider)
  1154. {
  1155.     new
  1156.         leaf,
  1157.         pointer;
  1158.     P:5("Command_FindFast: Searching for %s", data);
  1159.     while ((pointer = Bintree_FindValue(YSI_g_sSearchTree, value, leaf)) != BINTREE_NOT_FOUND)
  1160.     {
  1161.         if (Command_HasMultipleProviders() && (YSI_g_sCommands[pointer][E_COMMANDS_FUNC_POINTER] >>> 24 != provider)) continue;
  1162.         // Don't do an strcmp if there are no collisions.
  1163.         if (!Command_HasCollisions()) return pointer;
  1164.         if (!strcmp(Command_Name(pointer), data)) return pointer;
  1165.     }
  1166.     P:5("Command_FindFast: Not found");
  1167.     return COMMAND_NOT_FOUND;
  1168. }
  1169.  
  1170. /*----------------------------------------------------------------------------*-
  1171. Function:
  1172.     Command_FindSlow
  1173. Params:
  1174.     funcname[] - Function to find.
  1175. Return:
  1176.     -
  1177. Notes:
  1178.     Searches through the array for function linearly - used to set altnames
  1179.     before the data has been sorted.
  1180. -*----------------------------------------------------------------------------*/
  1181.  
  1182. static stock Command_FindSlow(funcname[], provider = 0xFF)
  1183. {
  1184.     for (new i = 0; i != MAX_COMMANDS; ++i)
  1185.     {
  1186.         new
  1187.             p = YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER];
  1188.         if (((p & 0x00FFFFFF == i) || (YSI_g_sCommands[i][E_COMMANDS_MASTERS] == -1)) &&
  1189.             (!Command_HasMultipleProviders() || (p & 0xFF000000 == 0xFF000000) || (p >>> 24 == provider)) &&
  1190.             !strcmp(Command_Name(i), funcname))
  1191.         {
  1192.             return i;
  1193.         }
  1194.     }
  1195.     return COMMAND_NOT_FOUND;
  1196. }
  1197.  
  1198. /*----------------------------------------------------------------------------*-
  1199. Function:
  1200.     Command_FindSlowStrict
  1201. Params:
  1202.     funcname[] - Function to find.
  1203. Return:
  1204.     -
  1205. Notes:
  1206.     Searches through the array for function linearly - used to set altnames
  1207.     before the data has been sorted.
  1208. -*----------------------------------------------------------------------------*/
  1209.  
  1210. static stock Command_FindSlowStrict(funcname[], provider)
  1211. {
  1212.     for (new i = 0; i != MAX_COMMANDS; ++i)
  1213.     {
  1214.         new
  1215.             p = YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER];
  1216.         // This needs additional checks that the item is valid.
  1217.         if (((p & 0x00FFFFFF == i) || (YSI_g_sCommands[i][E_COMMANDS_MASTERS] == -1)) &&
  1218.             (!Command_HasMultipleProviders() || (p >>> 24 == provider)) &&
  1219.             !strcmp(Command_Name(i), funcname))
  1220.         {
  1221.             return i;
  1222.         }
  1223.     }
  1224.     return COMMAND_NOT_FOUND;
  1225. }
  1226.  
  1227. /*----------------------------------------------------------------------------*-
  1228. Function:
  1229.     Command_AddHash
  1230. Params:
  1231.     command[] - Command text to hash.
  1232.     dest[] - Array to copy to.
  1233.     idx - Point to start copying from.
  1234. Return:
  1235.     hash value.
  1236. Notes:
  1237.     Hashes a string and copies it to a destination at the same time.
  1238. -*----------------------------------------------------------------------------*/
  1239.  
  1240. static stock Command_AddHash(command[], dest[], idx)
  1241. {
  1242.     // Skip the function name prefix.
  1243.     new
  1244.         hash = -1,
  1245.         ch,
  1246.         dx = 1,
  1247.         end = idx + 28;
  1248.     // Copy and hash at the same time.
  1249.     do
  1250.     {
  1251.         /*ch = TOLOWER(command[idx++]);
  1252.         // Always NULL terminate.
  1253.         if ((dest[dx] = ch << 24) == COMMAND_END_CMP << 24)
  1254.         {
  1255.             // Fixes a bug with commands multiples of 4 chars long.
  1256.             dest[dx] = 0;
  1257.             break;
  1258.         }*/
  1259.         ch = TOLOWER(command[idx++]);
  1260.         if (ch == COMMAND_END_CMP) break;
  1261.         dest[dx] = ch << 24;
  1262.         hash = hash * 33 + ch; //Command_ToUpper(ch);
  1263.         ch = TOLOWER(command[idx++]);
  1264.         if (ch == COMMAND_END_CMP) break;
  1265.         dest[dx] |= ch << 16;
  1266.         hash = hash * 33 + ch; //Command_ToUpper(ch);
  1267.         ch = TOLOWER(command[idx++]);
  1268.         if (ch == COMMAND_END_CMP) break;
  1269.         dest[dx] |= ch << 8;
  1270.         hash = hash * 33 + ch; //Command_ToUpper(ch);
  1271.         ch = TOLOWER(command[idx++]);
  1272.         if (ch == COMMAND_END_CMP) break;
  1273.         dest[dx] |= ch << 0;
  1274.         hash = hash * 33 + ch; //Command_ToUpper(ch);
  1275.         ++dx;
  1276.     }
  1277.     while (idx < end);
  1278.     return hash;
  1279. }
  1280.  
  1281. /*----------------------------------------------------------------------------*-
  1282. Function:
  1283.     Command_FastHash
  1284. Params:
  1285.     command[] - Command text to hash.
  1286. Return:
  1287.     hash value.
  1288. Notes:
  1289.     Just hashes the passed string.
  1290. -*----------------------------------------------------------------------------*/
  1291.  
  1292. static stock Command_FastHash(command[])
  1293. {
  1294.     new
  1295.         index = 0,
  1296.         hash = -1,
  1297.         ch;
  1298.     while ((ch = command[index++])) hash = hash * 33 + TOLOWER(ch);
  1299.     return hash;
  1300. }
  1301.  
  1302. /*----------------------------------------------------------------------------*-
  1303. Function:
  1304.     Command_PackHash
  1305. Params:
  1306.     command[] - Command text to hash.
  1307. Return:
  1308.     hash value.
  1309. Notes:
  1310.     Hashes packed strings.
  1311. -*----------------------------------------------------------------------------*/
  1312.  
  1313. static stock Command_PackHash(command[])
  1314. {
  1315.     new
  1316.         index = 0,
  1317.         hash = -1,
  1318.         ch;
  1319.     while ((ch = command[index++]))
  1320.     {
  1321.         P:4("Commands_PackHash: ch = 0x%04x%04x", ch >>> 16, ch & 0xFFFF);
  1322.         if (ch & 0xFF000000)
  1323.         {
  1324.             hash = hash * 33 + TOLOWER(ch >>> 24);
  1325.             P:5("Command_PackHash: Hash1 = %d", hash);
  1326.         }
  1327.         else
  1328.         {
  1329.             break;
  1330.         }
  1331.         if (ch & 0x00FF0000)
  1332.         {
  1333.             hash = hash * 33 + TOLOWER(ch >> 16 & 0xFF);
  1334.             P:5("Command_PackHash: Hash2 = %d", hash);
  1335.         }
  1336.         else
  1337.         {
  1338.             break;
  1339.         }
  1340.         if (ch & 0x0000FF00)
  1341.         {
  1342.             hash = hash * 33 + TOLOWER(ch >> 8 & 0xFF);
  1343.             P:5("Command_PackHash: Hash3 = %d", hash);
  1344.         }
  1345.         else
  1346.         {
  1347.             break;
  1348.         }
  1349.         if (ch & 0x000000FF)
  1350.         {
  1351.             hash = hash * 33 + TOLOWER(ch & 0xFF);
  1352.             P:5("Command_PackHash: Hash4 = %d", hash);
  1353.         }
  1354.         else
  1355.         {
  1356.             break;
  1357.         }
  1358.     }
  1359.     return hash;
  1360. }
  1361.  
  1362. /*----------------------------------------------------------------------------*-
  1363. Function:
  1364.     Command_Hash
  1365. Params:
  1366.     command[] - Command text to hash.
  1367.     &index - Start point and variable to store end point to.
  1368.     &length - Length of the hashed word.
  1369. Return:
  1370.     hash value.
  1371. Notes:
  1372.     Hashes a string using space delimiters and returns information such as the
  1373.     length of the string hased and the start point of the next word.
  1374. -*----------------------------------------------------------------------------*/
  1375.  
  1376. static stock Command_Hash(command[], &index, &length)
  1377. {
  1378.     new
  1379.         hash = -1,
  1380.         ch;
  1381.     length = index;
  1382.     while ((ch = command[index++]) > ' ') hash = hash * 33 + TOLOWER(ch);
  1383.     length = index - length - 1;
  1384.     while (ch)
  1385.     {
  1386.         if (ch > ' ')
  1387.         {
  1388.             break;
  1389.         }
  1390.         ch = command[index++];
  1391.     }
  1392.     --index;
  1393.     return hash;
  1394. }
  1395.  
  1396. /*----------------------------------------------------------------------------*-
  1397. Function:
  1398.     Command_Find
  1399. Params:
  1400.     function[] - Function name to find.
  1401. Return:
  1402.     Position in functions array or COMMAND_NOT_FOUND.
  1403. Notes:
  1404.     Used by API functions to avoid repeated sorting checks.
  1405. -*----------------------------------------------------------------------------*/
  1406.  
  1407. static stock Command_Find(function[], provider = -1)
  1408. {
  1409.     if (provider == -1)
  1410.     {
  1411.         provider = _:Command_DefaultProvider();
  1412.         // Find the ID of the command.
  1413.         if (Command_IsSorted())
  1414.         {
  1415.             return Command_FindFast(function, Command_FastHash(function), provider);
  1416.         }
  1417.         else
  1418.         {
  1419.             return Command_FindSlow(function, provider);
  1420.         }
  1421.     }
  1422.     else
  1423.     {
  1424.         provider &= 0xFF;
  1425.         // Find the ID of the command.
  1426.         if (Command_IsSorted())
  1427.         {
  1428.             return Command_FindFastStrict(function, Command_FastHash(function), provider);
  1429.         }
  1430.         else
  1431.         {
  1432.             return Command_FindSlowStrict(function, provider);
  1433.         }
  1434.     }
  1435. }
  1436.  
  1437. /*----------------------------------------------------------------------------*-
  1438. Function:
  1439.     Command_GetID
  1440. Params:
  1441.     function[] - Function name to find.
  1442. Return:
  1443.     The ID of the passed function.
  1444. Notes:
  1445.     -
  1446.  
  1447. native Command_GetID(function[])
  1448.  
  1449. -*----------------------------------------------------------------------------*/
  1450.  
  1451. RF@p:Command_GetID[s](function[])<function>
  1452. {
  1453.     return Command_Find(function);
  1454. }
  1455.  
  1456. /*----------------------------------------------------------------------------*-
  1457. Function:
  1458.     Command_SetPlayer
  1459. Params:
  1460.     command - Command to set for.
  1461.     playerid - Player to set.
  1462.     bool:set - Wether or not this player can use this command.
  1463. Return:
  1464.     -
  1465. Notes:
  1466.     -
  1467.  
  1468. native bool:Command_SetPlayer(command, playerid, bool:set);
  1469.  
  1470. -*----------------------------------------------------------------------------*/
  1471.  
  1472. RF@pv:Command_SetPlayer[iii](c,p,bool:s)<c,p,s>
  1473. {
  1474. //  if (c < 0 || c >= YSI_g_sCommandIndex)
  1475.     if (0 <= c < MAX_COMMANDS)
  1476.     {
  1477.         //Bit_Set(YSI_g_sCommands[c][E_COMMANDS_PLAYERS], p, s, bits<MAX_PLAYERS>);
  1478.         if (s) PA+(YSI_g_sCommands[c][E_COMMANDS_PLAYERS], p);
  1479.         else PA-(YSI_g_sCommands[c][E_COMMANDS_PLAYERS], p);
  1480.         // Not in range,
  1481. //      return false;
  1482.     }
  1483. //  return s;
  1484. }
  1485.  
  1486. /*----------------------------------------------------------------------------*-
  1487. Function:
  1488.     Command_SetPlayerNamed
  1489. Params:
  1490.     funcname[] - Command to set for.
  1491.     playerid - Player to set.
  1492.     set - Wether or not this player can use this command.
  1493. Return:
  1494.     -
  1495. Notes:
  1496.     Like Command_SetPlayer but for a function name.
  1497.  
  1498. native bool:Command_SetPlayerNamed(funcname[], playerid, bool:set);
  1499.  
  1500. -*----------------------------------------------------------------------------*/
  1501.  
  1502. RF@pv:Command_SetPlayerNamed[sii](f[],p,bool:s)<f,p,s>
  1503. {
  1504.     Command_SetPlayer(Command_Find(f), p, s);
  1505. }
  1506.  
  1507. /*----------------------------------------------------------------------------*-
  1508. Function:
  1509.     Command_GetPlayer
  1510. Params:
  1511.     command - Command to get for.
  1512.     playerid - Player to get.
  1513. Return:
  1514.     Wether this player can use this command.
  1515. Notes:
  1516.     -
  1517.  
  1518. native bool:Command_GetPlayer(command, playerid);
  1519.  
  1520. -*----------------------------------------------------------------------------*/
  1521.  
  1522. RF@t:bool:Command_GetPlayer[ii](command, playerid)
  1523. {
  1524.     if (0 <= command < MAX_COMMANDS)
  1525.     {
  1526.         return bool:Command_CheckPlayer(command, playerid);
  1527.     }
  1528.     // Not in range,
  1529.     return false;
  1530. }
  1531.  
  1532. /*----------------------------------------------------------------------------*-
  1533. Function:
  1534.     Command_GetPlayerNamed
  1535. Params:
  1536.     funcname[] - Command to get for.
  1537.     playerid - Player to get.
  1538. Return:
  1539.     -
  1540. Notes:
  1541.     Like Command_GetPlayer but for a function name.
  1542.  
  1543. native bool:Command_GetPlayerNamed(funcname[], playerid);
  1544.  
  1545. -*----------------------------------------------------------------------------*/
  1546.  
  1547. RF@pt:bool:Command_GetPlayerNamed[si](func[], playerid)<func, playerid>
  1548. {
  1549.     return Command_GetPlayer(Command_Find(func), playerid);
  1550. }
  1551.  
  1552. /*----------------------------------------------------------------------------*-
  1553. Function:
  1554.     Command_Remove
  1555. Params:
  1556.     func - The slot of the command to remove.
  1557. Return:
  1558.     -
  1559. Notes:
  1560.  
  1561. native Command_Remove(func);
  1562.  
  1563. -*----------------------------------------------------------------------------*/
  1564.  
  1565. static stock Command_RemoveFromBintree(func)
  1566. {
  1567.     if (!Command_IsSorted()) return;
  1568.     // This function has to find the right index in the binary tree, as that's
  1569.     // not in the same order at all.
  1570.     new
  1571.         leaf,
  1572.         hash = Command_PackHash(Command_Name(func));
  1573.     // Find where in the binary tree this is referenced from.
  1574.     while (Bintree_FindValue(YSI_g_sSearchTree, hash, _, leaf) != BINTREE_NOT_FOUND)
  1575.     {
  1576.         if (YSI_g_sSearchTree[leaf][E_BINTREE_TREE_POINTER] == func)
  1577.         {
  1578.             P:2("Command_RemoveFromBintree: Delete branch");
  1579.             Bintree_Delete(YSI_g_sSearchTree, leaf, YSI_g_sCommandCount);
  1580.             return;
  1581.         }
  1582.     }
  1583. }
  1584.  
  1585. RF:Command_Remove[i](func)
  1586. {
  1587.     P:2("Command_Remove called (%d)", func);
  1588.     if (0 <= func < MAX_COMMANDS)
  1589.     {
  1590.         if (Command_GetPointer(func) == func)
  1591.         {
  1592.             for (new i = 0; i != MAX_COMMANDS; ++i)
  1593.             {
  1594.                 // Remove all alternate names.
  1595.                 if (Command_GetPointer(i) == func)
  1596.                 {
  1597.                     // Add this to the list of unused functions.
  1598.                     YSI_g_sCommands[i][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  1599.                     YSI_g_sCommandIndex = i;
  1600.                     // Mark it as invalid in this instance.
  1601.                     YSI_g_sCommands[i][E_COMMANDS_MASTERS] = 0;
  1602.                     // Reduce the number of commands.
  1603.                     //Bintree_Delete(YSI_g_sSearchTree, i, YSI_g_sCommandCount);
  1604.                     Command_RemoveFromBintree(i);
  1605.                     --YSI_g_sCommandCount;
  1606.                 }
  1607.             }
  1608.         }
  1609.         else if (YSI_g_sCommands[func][E_COMMANDS_MASTERS] == -1)
  1610.         {
  1611.             // Remove a single alternate name.
  1612.             YSI_g_sCommands[func][E_COMMANDS_FUNC_POINTER] = YSI_g_sCommandIndex;
  1613.             YSI_g_sCommandIndex = func;
  1614.             YSI_g_sCommands[func][E_COMMANDS_MASTERS] = 0;
  1615.             //Bintree_Delete(YSI_g_sSearchTree, func, YSI_g_sCommandCount);
  1616.             Command_RemoveFromBintree(func);
  1617.             --YSI_g_sCommandCount;
  1618.         }
  1619.         return 1;
  1620.     }
  1621.     return 0;
  1622. }
  1623.  
  1624. RF@p:Command_RemoveNamed[s](func[])<func>
  1625. {
  1626.     P:2("Command_RemoveNamed called (%s)", func);
  1627.     return Command_Remove(Command_Find(func));
  1628. }
  1629.  
  1630. /*----------------------------------------------------------------------------*-
  1631. Function:
  1632.     Command_Add
  1633. Params:
  1634.     funcname[] - The function to add to the array.
  1635.     script - The script ID with the function.
  1636. Return:
  1637.     -
  1638. Notes:
  1639.     If the list of commands have already been sorted into the binary tree the
  1640.     new commands will be appended, otherwise they will just be added to the
  1641.     array.
  1642.  
  1643. native Command_Add(funcname[], script);
  1644.  
  1645. -*----------------------------------------------------------------------------*/
  1646.  
  1647. RF@pv:Command_Add[si](f[],s)<f,s>
  1648. {
  1649.     P:2("Command_Add called");
  1650.     if (YSI_g_sCommandCount < MAX_COMMANDS && YSI_g_sCommandIndex != -1)
  1651.     {
  1652.         new
  1653.             hash = Command_AddHash(f, YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION], 4),
  1654.             provider = _:Command_DefaultProvider();
  1655.         if (Command_IsSorted())
  1656.         {
  1657.             new
  1658.                 idx = Command_FindFastStrict(f[4], hash, provider);
  1659.             if (idx != COMMAND_NOT_FOUND)
  1660.             {
  1661.                 YSI_g_sCommands[idx][E_COMMANDS_MASTERS] |= 1 << s;
  1662.                 return;
  1663.             }
  1664.             if (!Command_HasCollisions())
  1665.             {
  1666.                 // Check for an existing command with this hash.
  1667.                 if (Bintree_FindValue(YSI_g_sSearchTree, hash) != BINTREE_NOT_FOUND)
  1668.                 {
  1669.                     Command_SetCollisions();
  1670.                 }
  1671.             }
  1672.             // Command doesn't exist already - good!
  1673.             Bintree_Add(YSI_g_sSearchTree, YSI_g_sCommandIndex, hash, YSI_g_sCommandIndex);
  1674.         }
  1675.         else
  1676.         {
  1677.             new
  1678.                 idx = Command_FindSlowStrict(f[4], provider);
  1679.             if (idx != COMMAND_NOT_FOUND)
  1680.             {
  1681.                 YSI_g_sCommands[idx][E_COMMANDS_MASTERS] |= 1 << s;
  1682.                 return;
  1683.             }
  1684.         }
  1685.         YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][0] = COMMAND_FUNCTION_PREFIX;
  1686.         //Bit_SetAll(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true, bits<MAX_PLAYERS>);
  1687.         //Command_InitialiseFromGroups(YSI_g_sCommandIndex);
  1688.         NO_GROUPS(YSI_g_sCommandIndex)
  1689.         {
  1690.             PA_Init(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true);
  1691.         }
  1692.         // Swap these.
  1693.         YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_MASTERS] = 1 << s;
  1694.         hash = YSI_g_sCommandIndex;
  1695.         // Set this command as usable in any script.
  1696.         YSI_g_sCommandIndex = YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER];
  1697.         YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER] = hash | (provider << 24);
  1698.         // Now some complex debug rubbish.
  1699.         P:2("Command_Add: Command added in %d", YSI_g_sCommandIndex);
  1700.         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]);
  1701.         C:4(new str[32];strpack(str, f);printf("Command_Add: %08x%08x%08x%08x", str[0], str[1], str[2], str[3]););
  1702.         ++YSI_g_sCommandCount;
  1703.     }
  1704.     /*else
  1705.     {
  1706.         // Not all hope is lost - check if this command name already exists.
  1707.         if (Command_IsSorted())
  1708.         {
  1709.             new
  1710.                 pos = Command_FindFast(funcname[4], Command_FastHash(funcname[4]));
  1711.             if (pos != COMMAND_NOT_FOUND)
  1712.             {
  1713.                 // Found it already in the array.
  1714.                 return pos;
  1715.             }
  1716.         }
  1717.         else
  1718.         {
  1719.             new
  1720.                 pos = Command_FindSlow(funcname[4]);
  1721.             if (pos != COMMAND_NOT_FOUND)
  1722.             {
  1723.                 // Command already exists.
  1724.                 return pos;
  1725.             }
  1726.         }
  1727.     }
  1728.     return COMMAND_NOT_FOUND;*/
  1729. }
  1730.  
  1731. /*----------------------------------------------------------------------------*-
  1732. Function:
  1733.     Command_AddAlt
  1734. Params:
  1735.     funcidx - The function this is an alternate to.
  1736.     altname[] - The new name.
  1737. Return:
  1738.     -
  1739. Notes:
  1740.     If the list of commands have already been sorted into the binary tree the
  1741.     new commands will be appended, otherwise they will just be added to the
  1742.     array.
  1743.  
  1744. native Command_AddAlt(funcidx, altname[]);
  1745.  
  1746. -*----------------------------------------------------------------------------*/
  1747.  
  1748. RF@p:Command_AddAlt[is](oidx, altname[])<oidx, altname>
  1749. {
  1750.     if (!Command_IsValid(oidx))
  1751.     {
  1752.         return COMMAND_NOT_FOUND;
  1753.     }
  1754.     new
  1755.         provider = _:Command_DefaultProvider();
  1756.     if (YSI_g_sCommandCount < MAX_COMMANDS && YSI_g_sCommandIndex != -1)
  1757.     {
  1758.         new
  1759.             hash = Command_AddHash(altname, YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION], 0);
  1760.         if (Command_IsSorted())
  1761.         {
  1762.             // Find the function this mirrors.
  1763.             //oidx = Command_FindFast(function, Command_FastHash(function));
  1764.             new
  1765.                 pos = Command_FindFastStrict(altname, hash, provider);
  1766.             if (pos != COMMAND_NOT_FOUND)
  1767.             {
  1768.                 if (Command_GetPointer(pos) != oidx)
  1769.                 {
  1770.                     // Same altname, different function.
  1771.                     return COMMAND_NOT_FOUND;
  1772.                 }
  1773.                 return pos;
  1774.             }
  1775.             // Command doesn't exist already - good!
  1776.             Bintree_Add(YSI_g_sSearchTree, YSI_g_sCommandIndex, hash, YSI_g_sCommandIndex);
  1777.         }
  1778.         else
  1779.         {
  1780.             new
  1781.                 pos = Command_FindSlowStrict(altname, provider);
  1782.             if (pos != COMMAND_NOT_FOUND)
  1783.             {
  1784.                 if (Command_GetPointer(pos) != oidx)
  1785.                 {
  1786.                     // Same altname, different function.
  1787.                     return COMMAND_NOT_FOUND;
  1788.                 }
  1789.                 // Command already exists.
  1790.                 return pos;
  1791.             }
  1792.         }
  1793.         YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_FUNCTION][0] = COMMAND_FUNCTION_PREFIX;
  1794.         //Bit_SetAll(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true, bits<MAX_PLAYERS>);
  1795.         //Command_InitialiseFromGroups(YSI_g_sCommandIndex);
  1796.         NO_GROUPS(YSI_g_sCommandIndex)
  1797.         {
  1798.             PA_Init(YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_PLAYERS], true);
  1799.         }
  1800.         ++YSI_g_sCommandCount;
  1801.         // This doesn't have real masters.
  1802.         YSI_g_sCommands[YSI_g_sCommandIndex][E_COMMANDS_MASTERS] = -1;
  1803.         hash = YSI_g_sCommandIndex;
  1804.         YSI_g_sCommandIndex = YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER];
  1805.         YSI_g_sCommands[hash][E_COMMANDS_FUNC_POINTER] = oidx | (provider << 24);
  1806.         return hash;
  1807.     }
  1808.     else
  1809.     {
  1810.         // Not all hope is lost - check if this command name already exists.
  1811.         new
  1812.             pos;
  1813.         if (Command_IsSorted())
  1814.         {
  1815.             pos = Command_FindFastStrict(altname, Command_FastHash(altname), provider);
  1816.         }
  1817.         else
  1818.         {
  1819.             pos = Command_FindSlowStrict(altname, provider);
  1820.         }
  1821.         if (pos != COMMAND_NOT_FOUND)
  1822.         {
  1823.             // Found it already in the array.  Check if the element it points to
  1824.             // has the correct name so we know this is the correct pair, not
  1825.             // just the correct single element.  I.e. check that this is the
  1826.             // correct original/altname combo, not the right altname on a
  1827.             // different original name.
  1828.             if (oidx == Command_GetPointer(pos))
  1829.             {
  1830.                 return pos;
  1831.             }
  1832.         }
  1833.     }
  1834.     return COMMAND_NOT_FOUND;
  1835. }
  1836.  
  1837. /*----------------------------------------------------------------------------*-
  1838. Function:
  1839.     Command_AddAltNamed
  1840. Params:
  1841.     function[] - The function this is an alternate to.
  1842.     altname[] - The new name.
  1843. Return:
  1844.     -
  1845. Notes:
  1846.     Add an alternate command for an existing command.
  1847.  
  1848. native Command_AddAltNamed(function[], altname[]);
  1849.  
  1850. -*----------------------------------------------------------------------------*/
  1851.  
  1852. RF@p:Command_AddAltNamed[ss](function[], altname[])<function, altname>
  1853. {
  1854.     return Command_AddAlt(Command_Find(function), altname);
  1855. }
  1856.  
  1857. /*----------------------------------------------------------------------------*-
  1858. Function:
  1859.     Command_Debug
  1860. Params:
  1861.     -
  1862. Return:
  1863.     -
  1864. Notes:
  1865.     Print some random information about commands if _DEBUG is set.
  1866. -*----------------------------------------------------------------------------*/
  1867.  
  1868. stock Command_Debug()
  1869. {
  1870.     #if _DEBUG > 0
  1871.         printf("Command_Debug: Start");
  1872.         for (new i = 0; i != MAX_COMMANDS; ++i)
  1873.         {
  1874.             if (Command_IsValid(i))
  1875.             {
  1876.                 printf("Command_Debug: Loop start %d", i);
  1877.                 new buffer[MAX_COMMAND_LENGTH];
  1878.                 strunpack(buffer, Command_Name(i));
  1879.                 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]);
  1880.                 new pointer = Command_GetPointer(i);
  1881.                 printf("Command %d:", i);
  1882.                 printf("\t%s", buffer);
  1883.                 printf("\t%d", pointer);
  1884.                 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]);
  1885.                 CallLocalFunction(Command_GetFunction(Command_GetPointer(i)), "isi", 0, "hi", 0);
  1886.                 printf("Command_Debug: Loop end");
  1887.             }
  1888.         }
  1889.         printf("Command_Debug: End");
  1890.     #endif
  1891. }
  1892.  
  1893. /*----------------------------------------------------------------------------*-
  1894. Function:
  1895.     OnPlayerCommandText
  1896. Params:
  1897.     playerid - Player who entered the command.
  1898.     cmdtext[] - Text entered.
  1899. Return:
  1900.     true - success or hidden fail, false - fail.
  1901. Notes:
  1902.     Calls the Command_Process function if this is not a client.
  1903. -*----------------------------------------------------------------------------*/
  1904.  
  1905. #if YSIM_NOT_CLIENT
  1906.     #if YSIM_CLOUD
  1907.         public OnPlayerCommandText(playerid, cmdtext[]) <>
  1908.         {
  1909.             if (YSI_g_sCommandFlags & e_COMM_FLAG_OPCT)
  1910.             {
  1911.                 return CallLocalFunction("Command_OnPlayerCommandText", "is", playerid, cmdtext);
  1912.             }
  1913.             return 0;
  1914.         }
  1915.        
  1916.         public OnPlayerCommandText(playerid, cmdtext[]) <_YCM:y>
  1917.     #elseif YSIM_IS_STUB
  1918.         #error y_commands called with YSIM_IS_STUB.
  1919.     #else
  1920.         public OnPlayerCommandText(playerid, cmdtext[])
  1921.     #endif
  1922.     {
  1923.         /*if (Command_Process(playerid, cmdtext, 0))
  1924.         {
  1925.             return 1;
  1926.         }
  1927.         if (YSI_g_sCommandFlags & e_COMM_FLAG_OPCT)
  1928.         {
  1929.             return CallLocalFunction("Command_OnPlayerCommandText", "is", playerid, cmdtext);
  1930.         }
  1931.         return 0;*/
  1932.         if (YSI_g_sCommandFlags & e_COMM_FLAG_OPCR)
  1933.         {
  1934.             switch (CallRemoteFunction("OnPlayerCommandReceived", "is", playerid, cmdtext))
  1935.             {
  1936.                 case 0:
  1937.                     // Handle normally, as in ZCMD.
  1938.                     return 1;
  1939.                 case -1:
  1940.                     // Allow them to stop processing but return 0.
  1941.                     return 0;
  1942.                 // Do nothing on 1.
  1943.             }
  1944.         }
  1945.         if (YSI_g_sCommandFlags & e_COMM_FLAG_OPCP)
  1946.         {
  1947.             switch (CallRemoteFunction("OnPlayerCommandPerformed", "isi", playerid, cmdtext, Command_Process(playerid, cmdtext, 0)))
  1948.             {
  1949.                 case 0:
  1950.                     return 0;
  1951.                 case 1:
  1952.                     return 1;
  1953.                 // Do nothing on -1.
  1954.             }
  1955.         }
  1956.         else
  1957.         {
  1958.             switch (Command_Process(playerid, cmdtext, 0))
  1959.             {
  1960.                 case 1:
  1961.                     // Found the command, processed.
  1962.                     return 1;
  1963.                 case -1:
  1964.                     // Found the command, but want to return 0 anyway.
  1965.                     return 0;
  1966.                 // Do nothing on 0.
  1967.             }
  1968.         }
  1969.         // Call the regular OnPlayerCommandText.
  1970.         if (YSI_g_sCommandFlags & e_COMM_FLAG_OPCT)
  1971.         {
  1972.             return CallLocalFunction("Command_OnPlayerCommandText", "is", playerid, cmdtext);
  1973.         }
  1974.         return 0;
  1975.     }
  1976.    
  1977.     #if defined _ALS_OnPlayerCommandText
  1978.         #undef OnPlayerCommandText
  1979.     #else
  1980.         #define _ALS_OnPlayerCommandText
  1981.     #endif
  1982.     #define OnPlayerCommandText Command_OnPlayerCommandText
  1983.     forward Command_OnPlayerCommandText(playerid, cmdtext[]);
  1984. #endif
  1985.  
  1986. /*----------------------------------------------------------------------------*-
  1987. Function:
  1988.     Command_ReProcess
  1989. Params:
  1990.     playerid - Player who entered the command.
  1991.     cmdtext[] - Text entered.
  1992.     help - Called from the help commmand or OnPlayerCommandText.
  1993. Return:
  1994.     true - success or hidden fail, false - fail.
  1995. Notes:
  1996.     -
  1997. -*----------------------------------------------------------------------------*/
  1998.  
  1999. RF@p:Command_ReProcess[isi](p,c[],h)<p,c,h>
  2000. {
  2001.     return Command_Process(p,c,h);
  2002. }
  2003.  
  2004. /*----------------------------------------------------------------------------*-
  2005. Function:
  2006.     Command_Process
  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. #define Command_CallR(%1,%2) \
  2018.     CallRemoteFunction(Command_GetFunction((%1)), "isii", playerid, %2, help, master)
  2019.  
  2020. #define Command_CallL(%1,%2) \
  2021.     CallLocalFunction(Command_GetFunction((%1)), "isi", playerid, %2, help)
  2022.  
  2023. static stock Command_Process(playerid, cmdtext[], help)
  2024. {
  2025.     // Support for very old problems!
  2026.     // TODO: Add back.
  2027.     P:2("Command_Process called: %d %s", playerid, cmdtext);
  2028.     #if !_DEBUG && !defined _YSI_SPECIAL_DEBUG
  2029.         // For testing purposes.
  2030.         if (!IsPlayerConnected(playerid))
  2031.         {
  2032.             return Command_DisconnectReturn();
  2033.         }
  2034.     #endif
  2035.     P:4("Command_Process: Connected");
  2036.     new
  2037.         idx,
  2038.         prelen = help ? 0 : 1,
  2039.         index = prelen;
  2040.     /*// Shortcuts.
  2041.     if (cmdtext[2] <= ' ')
  2042.     {
  2043.         // Get a player's shortcut information for this letter.
  2044.     }
  2045.     else*/
  2046.     {
  2047.         // No more faffing about with random alternate code - it's all done in
  2048.         // one nice function instead of having to handle both separately.
  2049.         new
  2050.             length,
  2051.             hash = Command_Hash(cmdtext, index, length);
  2052.         P:3("Command_Process: Hash = %d, Length = %d", hash, length);
  2053.         // NOTE: No prefix support here.
  2054.         cmdtext[length + prelen] = '\0';
  2055.         P:3("Command_Process: Provider: %d", YSI_g_sPlayerProvider{playerid});
  2056.         idx = Command_FindFast(cmdtext[prelen], hash, YSI_g_sPlayerProvider{playerid});
  2057.         // TODO: Replace!
  2058.         //idx = Command_FindSlow(cmdtext[prelen]);//, hash);
  2059.     }
  2060.     P:3("Command_Process: Index = %d", idx);
  2061.     if (idx != COMMAND_NOT_FOUND)
  2062.     {
  2063.         // Get the master data for the underlying command, not the possibly
  2064.         // changed name.
  2065.         new
  2066.             pointer = Command_GetPointer(idx),
  2067.             master = YSI_g_sCommands[pointer][E_COMMANDS_MASTERS];
  2068.         if (!master)
  2069.         {
  2070.             // No scripts can serve the code.
  2071.             return Command_UnknownReturn();
  2072.         }
  2073.         P:4("Command_Process: Found %d", idx);
  2074.         // Found a command with this name - check the permissions.
  2075.         //if (Bit_Get(YSI_g_sCommands[idx][E_COMMANDS_PLAYERS], playerid))
  2076.         if (Command_CheckPlayer(idx, playerid))
  2077.         {
  2078.             P:4("Command_Process: Allowed");
  2079.             // Allowed to use the command, get the real function.  Note that
  2080.             // this may well be the same as "idx", but we loose no time.
  2081.             #if YSIM_HAS_MASTER
  2082.                 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]);
  2083.                 if (master & 1 << YSI_g_sMaster23)
  2084.                 {
  2085.                     master = YSI_g_sMaster23;
  2086.                 }
  2087.                 else
  2088.                 {
  2089.                     // Find the lowest set bit.
  2090.                     static const
  2091.                         scDeBruijn[] =
  2092.                             {
  2093.                                 0,  1,  28, 2,  29, 14, 24, 3,  30, 22, 20, 15, 25, 17, 4,  8,
  2094.                                 31, 27, 13, 23, 21, 19, 16, 7,  26, 12, 18, 6,  11, 5,  10, 9
  2095.                             };
  2096.                     // http://supertech.csail.mit.edu/papers/debruijn.pdf
  2097.                     master = scDeBruijn[((master & -master) * 0x077CB531) >>> 27];
  2098.                 }
  2099.                 P:3("Command_Process: master = %d", master);
  2100.                 if (cmdtext[index])
  2101.                 {
  2102.                     // Call it!
  2103.                     Command_CallR(pointer, cmdtext[index]);
  2104.                 }
  2105.                 else
  2106.                 {
  2107.                     Command_CallR(pointer, NULL);
  2108.                 }
  2109.                 // Get the real return.
  2110.                 P:1("Command_Process: return: %d", getproperty(8, YSIM_RETURN));
  2111.                 return getproperty(8, YSIM_RETURN);
  2112.             #else
  2113.                 if (cmdtext[index])
  2114.                 {
  2115.                     // Call it!
  2116.                     return Command_CallL(pointer, cmdtext[index]);
  2117.                 }
  2118.                 else
  2119.                 {
  2120.                     return Command_CallL(pointer, NULL);
  2121.                 }
  2122.             #endif
  2123.         }
  2124.         else
  2125.         {
  2126.             return Command_DeniedReturn();
  2127.         }
  2128.     }
  2129.     P:5("Command_Process: Not found");
  2130.     return Command_UnknownReturn();
  2131. }
  2132.  
  2133. /*----------------------------------------------------------------------------*-
  2134. Function:
  2135.     Command_GetName
  2136. Params:
  2137.     funcid - Command to get the name of.
  2138. Return:
  2139.     -
  2140. Notes:
  2141.  
  2142. native Command_GetName(funcid);
  2143.  
  2144. -*----------------------------------------------------------------------------*/
  2145.  
  2146. RS:Command_GetName[i](funcid)
  2147. {
  2148.     new
  2149.         buffer[YSI_MAX_STRING] = "";
  2150.     if (Command_IsValid(funcid))
  2151.     {
  2152.         strunpack(buffer, Command_Name(funcid));
  2153.     }
  2154.     return buffer;
  2155. }
  2156.  
  2157. /*----------------------------------------------------------------------------*-
  2158. Function:
  2159.     Command_GetDisplay
  2160. Params:
  2161.     f - Command to get the real name of.
  2162.     p - Player to get the name for.
  2163. Return:
  2164.     The name of a command for a single player.
  2165. Notes:
  2166.     -
  2167.  
  2168. native Command_GetDisplay(funcid, playerid);
  2169.  
  2170. -*----------------------------------------------------------------------------*/
  2171.  
  2172. RS:Command_GetDisplay[ii](funcid, playerid)
  2173. {
  2174.     new
  2175.         buffer[YSI_MAX_STRING] = "";
  2176.     if (Command_IsValid(funcid))
  2177.     {
  2178.         // Don't recalculate this every loop.
  2179.         new
  2180.             slot = Bit_Slot(playerid) + 1,
  2181.             Bit:mask = Bit_Mask(playerid);
  2182.         // Check if they can use the original version.
  2183.         if (YSI_g_sCommands[funcid][E_COMMANDS_PLAYERS][slot] & mask)
  2184.         {
  2185.             //setproperty(8, "", YSIM_STRING, Command_Name(f));
  2186.             strunpack(buffer, Command_Name(funcid));
  2187.             return buffer;
  2188.             //return 1;
  2189.         }
  2190.         // Search for a command pointing to that command which the player can use.
  2191.         for (new i = 0; i != MAX_COMMANDS; ++i)
  2192.         {
  2193.             if (Command_GetPointer(i) == funcid && (YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask))
  2194.             {
  2195.                 //setproperty(8, "", YSIM_STRING, Command_Name(i));
  2196.                 strunpack(buffer, Command_Name(i));
  2197.                 return buffer;
  2198.             }
  2199.         }
  2200.     }
  2201.     return buffer;
  2202. }
  2203.  
  2204. /*----------------------------------------------------------------------------*-
  2205. Function:
  2206.     Command_GetDisplayNamed
  2207. Params:
  2208.     f[] - Command to get the real name of.
  2209.     p - Player to get the name for.
  2210. Return:
  2211.     The name of a named function for one player.
  2212. Notes:
  2213.     Remote function call for Command_GetDisplayNameNamed - avoids needing to
  2214.     expose users to the master system's odd way of returning strings.  This is
  2215.     the only part I've not yet fixed up to be nice and hidden.
  2216.  
  2217. native Command_GetDisplayNamed(funcid[], playerid);
  2218.  
  2219. -*----------------------------------------------------------------------------*/
  2220.  
  2221. RS@p:Command_GetDisplayNamed[si](func[], playerid)<func, playerid>
  2222. {
  2223.     P:1("Command_GetDisplayNamed called %d", _@);
  2224.     new
  2225.         pointer = Command_Find(func),
  2226.         buffer[YSI_MAX_STRING] = "";
  2227.     if (pointer != COMMAND_NOT_FOUND)
  2228.     {
  2229.         // Don't recalculate this every loop.
  2230.         new
  2231.             slot = Bit_Slot(playerid) + 1, //playerid >>> CELLSHIFT) + 1,
  2232.             Bit:mask = Bit_Mask(playerid); //Bit:(1 << (playerid & (cellbits - 1)));
  2233.         // Check if they can use the original version.
  2234.         if (YSI_g_sCommands[pointer][E_COMMANDS_PLAYERS][slot] & mask)
  2235.         {
  2236.             //setproperty(8, "", YSIM_STRING, Command_Name(pointer));
  2237.             strunpack(buffer, Command_Name(pointer));
  2238.             return buffer;
  2239.         }
  2240.         // Search for a command pointing to that command which the player can use.
  2241.         for (new i = 0; i != MAX_COMMANDS; ++i)
  2242.         {
  2243.             if (Command_GetPointer(i) == pointer && (YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask))
  2244.             {
  2245.                 //setproperty(8, "", YSIM_STRING, Command_Name(i));
  2246.                 strunpack(buffer, Command_Name(i));
  2247.                 return buffer;
  2248.             }
  2249.         }
  2250.     }
  2251.     return buffer;
  2252. }
  2253.  
  2254. /*----------------------------------------------------------------------------*-
  2255. Function:
  2256.     Command_GetPlayerCommandCount
  2257. Params:
  2258.     playerid - Player to count for.
  2259. Return:
  2260.     -
  2261. Notes:
  2262.     Gets the number of comamnds this player can use.
  2263.  
  2264. native Command_GetPlayerCommandCount(playerid);
  2265.  
  2266. -*----------------------------------------------------------------------------*/
  2267.  
  2268. RF:Command_GetPlayerCommandCount[i](playerid)
  2269. {
  2270.     new
  2271.         slot = Bit_Slot(playerid) + 1,
  2272.         Bit:mask = Bit_Mask(playerid),
  2273.         count = 0;
  2274.     for (new i = 0; i != MAX_COMMANDS; ++i)
  2275.     {
  2276.         if (_Command_IsValid(i) && YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask)
  2277.         {
  2278.             ++count;
  2279.         }
  2280.     }
  2281.     return count;
  2282. }
  2283.  
  2284. /*----------------------------------------------------------------------------*-
  2285. Function:
  2286.     Command_GetNext
  2287. Params:
  2288.     index - Index of the next command for this player.
  2289.     playerid - Player to get the name for.
  2290. Return:
  2291.     The name of a command for a single player.
  2292. Notes:
  2293.     -
  2294.  
  2295. native Command_GetNext(index, playerid);
  2296.  
  2297. -*----------------------------------------------------------------------------*/
  2298.  
  2299. RS:Command_GetNext[ii](index, playerid)
  2300. {
  2301.     new
  2302.         buffer[YSI_MAX_STRING] = "";
  2303.     if (0 <= index < MAX_COMMANDS)
  2304.     {
  2305.         // Don't recalculate this every loop.
  2306.         new
  2307.             slot = Bit_Slot(playerid) + 1,
  2308.             Bit:mask = Bit_Mask(playerid);
  2309.         for (new i = 0; i != MAX_COMMANDS; ++i)
  2310.         {
  2311.             if (_Command_IsValid(i) && YSI_g_sCommands[i][E_COMMANDS_PLAYERS][slot] & mask)
  2312.             {
  2313.                 // Skip already displayed ones.
  2314.                 if (index)
  2315.                 {
  2316.                     --index;
  2317.                 }
  2318.                 else
  2319.                 {
  2320.                     strunpack(buffer, Command_Name(i));
  2321.                     return buffer;
  2322.                 }
  2323.             }
  2324.         }
  2325.     }
  2326.     return buffer;
  2327. }
  2328.  
  2329. //#tryinclude <YSI\y_groups>
  2330.  
  2331. //#undef _YCM
  2332.  
  2333. #if defined _YSIM_MANUAL_SET
  2334.     // This is to allow callback chaining.  When the user includes y_groups and
  2335.     // other libraries, the function names will be reset to their custom ones
  2336.     // after every inclusion, however if you then include another YSI library
  2337.     // you need to revert to the previous library names to get the chaining to
  2338.     // work.
  2339.     #define YSI_GROUPS_LAST 25
  2340.     #include <YSI\internal\y_grouprevert>
  2341. #else
  2342.     // Define a numbered master to use for user commands, without them needing
  2343.     // to know about the master system.  This should default to cloud mode,
  2344.     // unless global settings have been applied.
  2345.     #define MASTER 23
  2346.     #include <YSI\y_master>
  2347.     //#define _YSIM_FAKE_MANUAL_SET
  2348. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement