[Include] [I-ZCMD]Improved ZCMD - Fastest Command Processor
#1

Improved ZCMD
Latest Version:0.2.3.0 (August 2016)

NOTE: Please do not credit me for the include. The original concept is from ZCMD. This is just a useless optimized (practically insignificant) cleaner version of ZCMD with one bug fixed.

ZCMD hasn't been updated in the last 6 years. We (the SAMP community) have advanced a lot in these years and these advancements haven't been implemented in ZCMD. I just re-wrote ZCMD 0.3.1 include and updated it. This is now a lot faster (still negligible) than ZCMD which makes this the fastest 'PAWN code' based Command Processor at the moment. The speed test results are given at the end of this thread. iZCMD also addresses few issues/bugs with ZCMD and also adds some new features (Case-sensitivity can be turned on/off using a define).

The great improvement in efficiency can be observed when you have small commands(commands which do not take a lot of CPU). If you have just one format function call in your command, I-ZCMD will be almost 2x faster than ZCMD. If you have 10 format calls in your command, I-ZCMD will be 1.5x faster than ZCMD.The main reason why I-ZCMD is amazingly fast when compared to ZCMD is because I-ZCMD gets rid of two CallLocalFunction(very slow function) calls. However, this improvement is negligible compared to the overall performance of your server which means don't expect your server to show measurable improvements after installing iZCMD. Anyway, its always advisable to use updated includes.

Changes from ZCMD:
  • OnPlayerCommandReceived & OnPlayerCommandPerformed are now called directly instead of using CallLocalFunction
  • Removed the OnGameModeInit/OnFilterscriptInit Hooks
  • Minor optimizations
  • Case Sensitivity now toggled on/off using a define
  • Addresses few ZCMD bugs
How to install?
For those who are already using ZCMD, you just need to replace ZCMD include with IZCMD include.There is no change in functionality (by default), all the changes affect the speed and efficiency of the script. The only new feature in I-ZCMD is that now case-sensitivity can be turned on/off by defining IZCMD_ENABLE_CASE_SENSITIVITY before including IZCMD. To maximize compatibility, iZCMD is not case-sensitive by default (ZCMD is not case-sensitive).

For those who are not using ZCMD, you need to download I-ZCMD include and paste it in your include folder. Any ZCMD tutorial will do for I-ZCMD since the syntax and functionality are the same in both.

How to use?
To create a command, all you need to do is create a public function using any of the given formats.

Code:
COMMAND:yourcommand(playerid,params[])
{
     return CMD_SUCCESS;
}
CMD:yourcommand(playerid,params[])
{
     return CMD_SUCCESS;
}
command(yourcommand,playerid,params[])
{
     return CMD_SUCCESS;
}
cmd(yourcommand,playerid,params[])
{
     return CMD_SUCCESS;
}
When a player types "/yourcommand parameters", the public function will be called.The playerid parameter will have the id of the player who used the command and the params[] parameter will have the text which the player typed after typing the command (for the given example, params[] will have "parameters").

The "params" parameter will never be empty. If the player did give any parameters then params[0] will be '\1'.

You must return CMD_SUCCESS if the command was executed successfully (return CMD_FAILURE if you wish the server to send the "Unknown Command" message). This result will be passed on to OnPlayerCommandPerformed.

You can also use the ZCMD style of returning, i.e: 1 for success and any other value for failure.

You cannot use OnPlayerCommandText once you include this include. It won't be called if you still have it in your code. There are two new callbacks instead.

OnPlayerCommandReceived
This callback is called before the actual command function is called.

Parameters:
  • playerid is the ID of the player who used the command
  • cmdtext is text which the player typed
Return Values:
1 - command function will be called
0 - the command function won't be called.

Code:
public OnPlayerCommandReceived(playerid,cmdtext[])
{
	return 1;
}
OnPlayerCommandPerformed
This callback is called after the command function is executed.

Parameters:
  • playerid is the ID of the player who used the command
  • cmdtext is text which the player typed
  • success is what the command function returned (CMD_SUCCESS or CMD_FAILURE)
Return Values:
0 or CMD_FAILURE - Player will see the Error Message, i.e "Unknown command"
1 or CMD_SUCCESS - The error message won't be sent

Code:
public OnPlayerCommandPerformed(playerid,cmdtext[], success)
{
	return success;
}
If you are not using OnPlayerCommandPerformed then what you return in your command function will decide if the Error Message will be sent or not.

Returning 0 or CMD_FAILURE in the command function means the error message will be sent.
Returning 1 or CMD_SUCCESS in the command function means the error message won't be sent.

Case-Sensitivity
Case Sensitivity is disabled by default which means that "/pm" and "/PM" will be treated to be the same. Case-sensitivity can be enabled by defining IZCMD_ENABLE_CASE_SENSITIVITY before you include izcmd to your script.

Tips & Tricks

1. Calling command functions manually
You can call a command function using the following code.

Code:
cmd_yourcommand(playerid,params);
You need to prefix "cmd_" to your command to call the command function.

2. Shortcut Commands
You can make shortcut commands using the idea given below.

Code:
COMMAND:arrest(playerid,params[])
{
     //your arrest code
     return CMD_SUCCESS; 
}
COMMAND:ar(playerid,params[])
{
     return cmd_arrest(playerid,params);
}
3. Disable Commands if player is not logged in
You can disable commands for a player who hasn't logged in using the following idea.

Code:
public OnPlayerCommandReceived(playerid,cmdtext[])
{
        if(!PlayerLoggedIn[playerid]) 
        {
               SendClientMessage(playerid,-1,"You need to log in to use commands");
               return 0;
        }
	return 1;
}
4. I-ZCMD with sscanf is the fastest way to process commands

Code:
COMMAND:setskin(playerid,params[])
{
      new skinid;
      if(sscanf(params,"i",skinid)) SendClientMessage(playerid,-1,"Usage:/setskin [skinid]");
      else SetPlayerSkin(playerid, skin);
      return CMD_SUCCESS;
}
More Examples
Code:
COMMAND:getvid(playerid,params[])
{
		new id,string[144],vid;
		if(sscanf(params,"u",id))
		{
			if(IsPlayerInAnyVehicle(playerid))
			{
			    vid = GetPlayerVehicleID(playerid);
			    format(string,sizeof(string),"The vehicle ID of your vehicle is %d.Use/getvid [Name/ID] to get vehicle ID of other player's vehicle.",vid);
				return SendClientMessage(playerid,-1,string);
		 	}
			return SendClientMessage(playerid,-1,"Your not in a vehicle nor you have specified any player from which to get the vehicle id.Use /getvid [Name/ID] to get the vehicle ID of their vehicle.");
	 	}
		if(IsPlayerConnected(id))
		{
		    if(IsPlayerInAnyVehicle(id))
		    {
                        new pName[MAX_PLAYER_NAME];
                        GetPlayerName(playerid,pName,MAX_PLAYER_NAME);
		        vid = GetPlayerVehicleID(id);
		        format(string,sizeof(string),"The vehicle ID of the vehicle which %s(%d) is using is %d.",pName,id,vid);
				SendClientMessage(playerid,-1,string);
			}
		    else
		    {
		        SendClientMessage(playerid,-1,"The given player is not using any vehicle.");
		    }
		}
		else { return SendClientMessage(playerid,-1,"Usage:/getvid:Invalid Player ID"); }
	}
	return CMD_SUCCESS;
}
Speed Tests
The test code approximately has 250 test commands out of which 6 valid commands are called and one invalid command is called.

The code which was used for speed test can be found here.

I-ZCMD (case-sensitive) is 5.4 times faster than ZCMD

I-ZCMD (non-case-sensitive) is 2.2 times faster than ZCMD

ZCMD and y_command perform equally well in cases such as in the above speed test where there are lot of commands.

Please note that if you need any of the y_command features, then use y_commands. If you try to implement a similar feature in iZCMD then iZCMD will most likely get slower than y_commands. Use iZCMD if and only if you don't use any of y_command features.

Download
Download izcmd.inc if you need the I-ZCMD include.

Download izcmd-original.inc if you need the original ZCMD Include

Visit GitHub Project Page

Credits
Zeex for the original ZCMD Include & the concept/algorithm.
Yashas for spending 60 minutes to update the include.
Reply
#2

Nice one!
Reply
#3

Using this straight away, thank you.
Reply
#4

Why you delete the old topic? and why you create new topic for this?
Reply
#5

Quote:
Originally Posted by Humza
View Post
Why you delete the old topic? and why you create new topic for this?
A moderator deleted the old one and told him to create a new one to prevent confusions whether this include is faster than ZCMD or not, and to clean up the thread, I guess.
Reply
#6

Simple and Nice.

Now keep update that to get better results
Reply
#7

Just to point out the benchmarks have very little relevance it is like trying to measure a piece of hair with a meter stick the scale does not match reality but still interesting to look at.
Reply
#8

Good work.....
btw Potus what you recommend??
Reply
#9

What happened to the old thread.
Reply
#10

Quote:
Originally Posted by hamzajaved780
View Post
Good work.....
btw Potus what you recommend??
Well if I'm using YSI then y_commands otherwise another command processor of choice it really doesn't matter since the syntax of is same for all the standard command processor includes.
Reply
#11

In my opinion your work is good. We are lucky to have people always developing and improving systems.

P.S. - I think people are a bit shocked and don't feel like some SA-MP legends work can be improved, etc... Give them some time.
Reply
#12

This include is kinda useless. You literally took ZCMD's code and edited a few lines and published it as a new processor, boasting of speed when, for today's standards, there's no difference between this and the original ZCMD, except for a few milliseconds for which you OCD-ridden guys are mortified.

You could've added more functionality, trying to par up with y_commands.
Reply
#13

Atleast he cared to do something for public?
Reply
#14

Quote:
Originally Posted by admantis
Посмотреть сообщение
This include is kinda useless. You literally took ZCMD's code and edited a few lines and published it as a new processor, boasting of speed when, for today's standards, there's no difference between this and the original ZCMD, except for a few milliseconds for which you OCD-ridden guys are mortified.

You could've added more functionality, trying to par up with y_commands.
Read the thread again!!

I-ZCMD is not a new processor
I-ZCMD = Improved ZCMD


Edited few lines?
https://github.com/YashasSamaga/I-ZC...ab2?diff=split
71 lines added and 103 lines deleted from ZCMD

few lines? lol?

Its twice as fast for simple commands & 1.5x fast for big commands.

Read my previous reply too.

Did I ever tell that this is a new processor and boasted about its speed?I mentioned at the beginning of the topic that this is an update for ZCMD since Zeex is not going to maintain it anymore.

Quote:

ZCMD hasn't been updated in the last 6 years.We have advanced a lot in these years and these advancements haven't been implemented in ZCMD.I just re-wrote ZCMD 0.3.1 include and updated it.

Reply
#15

You can show me the code of speed tests used?

PHP код:
// INCLUDES:
#include <a_samp>
#include <zcmd>
// MAIN:
main()
{
        print(
"Development Mode: variable_benchmark.amx");
        new 
tick_1;
        print(
"ZCMD:");
        for(new 
o!= 5o++)
        {
            
tick_1 GetTickCount();
            for(new 
i!= 100000i++)
            {
                
cmd_loop(0"\1");
                
cmd_format(0"name");
                
cmd_name(0"3");
            }
            
printf("%d. %d ms"oGetTickCount() - tick_1);
        }
}
CMD:loop(playeridparams[])
    return 
1;
CMD:format(playeridparams[])
    return 
1;
CMD:name(playeridparams[])
    return 
1;
public 
OnPlayerCommandReceived(playeridcmdtext[])
{
    return 
1;
}
public 
OnPlayerCommandPerformed(playeridcmdtext[], success)
{
    return 
1;

Why this speed test , and the speed test of the post , show me the same?

Код:
[16:21:48] ZCMD:
[16:21:48] 0. 26 ms
[16:21:48] 1. 22 ms
[16:21:48] 2. 27 ms
[16:21:48] 3. 21 ms
[16:21:48] 4. 29 ms
[16:22:53] iZCMD:
[16:22:53] 0. 29 ms
[16:22:53] 1. 23 ms
[16:22:53] 2. 29 ms
[16:22:53] 3. 23 ms
[16:22:53] 4. 28 ms
(i make this speed test, and for some reason do not show me Difference)
Reply
#16

Quote:
Originally Posted by _Zume
Посмотреть сообщение
You can show me the code of speed tests used?
pawn Код:
// [ DEVELOPMENT GAMEMODE ]

// INCLUDES:

#include <a_samp>
//#include <zcmd>
#include <izcmd>

// DEFINES:

#define MAX_ITERATIONS 1000000
#define COMMANDS_CALLED 3

// MAIN:

main()
{
    print("Development Mode: cmd_benchmark.amx");

    new tick[2];
    tick[0] = GetTickCount();

    for(new i = 0; i < MAX_ITERATIONS; i ++)
    {
        CallLocalFunction("OnPlayerCommandText", "is", INVALID_PLAYER_ID, "/loop");
        CallLocalFunction("OnPlayerCommandText", "is", INVALID_PLAYER_ID, "/FORMAT hello");
        CallLocalFunction("OnPlayerCommandText", "is", INVALID_PLAYER_ID, "/name 3");
    }

    tick[1] = GetTickCount();

    printf("Benchmark of %d commands: %d", MAX_ITERATIONS * COMMANDS_CALLED, tick[1] - tick[0]);
}

// CALLBACKS:

public OnGameModeInit()
{
    return 1;
}

public OnGameModeExit()
{
    return 1;
}

public OnPlayerCommandPerformed(playerid, cmdtext[], success)
{
    //printf("[OnPlayerCommandPerformed]: CMDTEXT: %s - SUCCESS: %d", cmdtext, success);
    return 1;
}

public OnPlayerCommandReceived(playerid, cmdtext[])
{
    //printf("[OnPlayerCommandReceived]: CMDTEXT: %s", cmdtext);
    return 1;
}

// COMMANDS:

CMD:loop(playerid, params[])
{
    //printf("/loop %s", params);
    return 1;
}

CMD:format(playerid, params[])
{
    //printf("/format %s", params);
    return 1;
}

CMD:name(playerid, params[])
{
    //printf("/name %s", params);
    return 1;
}
Reply
#17

Quote:
Originally Posted by _Zume
Посмотреть сообщение
You can show me the code of speed tests used?

PHP код:
// INCLUDES:
#include <a_samp>
#include <zcmd>
// MAIN:
main()
{
        print(
"Development Mode: variable_benchmark.amx");
        new 
tick_1;
        print(
"ZCMD:");
        for(new 
o!= 5o++)
        {
            
tick_1 GetTickCount();
            for(new 
i!= 100000i++)
            {
                
cmd_loop(0"\1");
                
cmd_format(0"name");
                
cmd_name(0"3");
            }
            
printf("%d. %d ms"oGetTickCount() - tick_1);
        }
}
CMD:loop(playeridparams[])
    return 
1;
CMD:format(playeridparams[])
    return 
1;
CMD:name(playeridparams[])
    return 
1;
public 
OnPlayerCommandReceived(playeridcmdtext[])
{
    return 
1;
}
public 
OnPlayerCommandPerformed(playeridcmdtext[], success)
{
    return 
1;

Why this speed test , and the speed test of the post , show me the same?

Код:
[16:21:48] ZCMD:
[16:21:48] 0. 26 ms
[16:21:48] 1. 22 ms
[16:21:48] 2. 27 ms
[16:21:48] 3. 21 ms
[16:21:48] 4. 29 ms
[16:22:53] iZCMD:
[16:22:53] 0. 29 ms
[16:22:53] 1. 23 ms
[16:22:53] 2. 29 ms
[16:22:53] 3. 23 ms
[16:22:53] 4. 28 ms
(i make this speed test, and for some reason do not show me Difference)
LOL you never made use of ZCMD or iZCMD in your test script.

ZCMD & iZCMD are command processors which means that they will call the correct command function when a player types a command.

What you did is basically call the same function many times which you can do without ZCMD/iZCMD.

You need to use CallLocalFunction("OnPlayerCommandText","is",playe rid,"/some_cmd");

This is basically what you did.You then replaced the include which has no effect on this code.
Код:
main()
{
     for(new i = 0;i < 10000;i++)
     {
          func(0,"loop");
     }
}
public func(playerid,params[])
{
       return 1;
}
Reply
#18

Would you guys stop worrying about milliseconds over 100,000 command calls?
Reply
#19

Hey Yashas, congratulations for your ZCMD modification, its really good I have to assume, but its not the fastest command processor in fact, you can compare it to iCMD 8.0 which is being developed by one of my friends, good work anyways, keep it up.
Reply
#20

Quote:
Originally Posted by Pottus
Посмотреть сообщение
Would you guys stop worrying about milliseconds over 100,000 command calls?
I started the thread as an update for ZCMD and it ended up competing with other processors. -.-
It all started when someone's benchmarks(I-ZCMD vs y_commands) weren't matching with mine.

I had PMed Zeex and he never responded therefore I made a new thread 'I-ZCMD'.Never intended to compete with others.Moreover I named it "I-ZCMD" because it is Zeex's concept which I have just updated.

Quote:
Originally Posted by ipsLeon
Посмотреть сообщение
Hey Yashas, congratulations for your ZCMD modification, its really good I have to assume, but its not the fastest command processor in fact, you can compare it to iCMD 8.0 which is being developed by one of my friends, good work anyways, keep it up.
Its very hard.I still haven't figured out how to use it
I want to benchmark it with I-ZCMD.

Код:
#include <a_samp>
#include <icmd>
// MAIN:

main()
{
    CallLocalFunction("OnPlayerCommandText","is",0,"mycommand");
}
forward OnCommandCalled(playerid, cmd[]);
public OnCommandCalled(playerid, cmd[])
{
	if (!cmd_exists(cmd))
	{
		SendClientMessage(playerid, -1, "Comando inexistente.");
	    return ICMD_ERROR;
	}
	return ICMD_OKAY;
}
public Listeners(playerid, params[])
{
    get_cmd_params(mycommand)
	{
	   print("CMD CALLED");
	}
	return 0;
}
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)