28.06.2014, 22:44
(
Последний раз редактировалось Mellnik; 01.05.2016 в 11:16.
)
mcmd - beta 0.0.1
This is the latest project I have been working on. mcmd, the first command processor which a) completely overwrites the default SA-MP command system and b) processes commands without PAWN interaction to pass OnPlayerCommandText parameters to the plugin. Even tho of it's memory hacking, it was designed to work with any version of the 0.3 branch.
Defining commands
To create commands, simply go to any location in your code and using following syntax. Commands are processed in lower case meaning /HellO is the same as /HELLo or /hello.
Handling user input
To control any player input before the actual command gets executed, this callback is being called in the gamemode.
Returning 0 stops any further processing of this command request, returning 1 calls the command as long as it exists. So giving the player an error if the command doesn't exist would be:
Anti spam
mcmd provides an inbuild function to control command spam.
This function returns the passed time since the last command request of a specific player. In other words, the time since the player sent a command to the server in seconds (Will be milliseconds in future releases). To prevent command spam, you can restrict the player under OnPlayerRequestCommand. Exmaple:
How it works
Here are the assembly instructions from the SA-MP 0.3z R2-2 server where it calls OnPlayerCommandText.
http://i.imgur.com/veUXSa2.png
mcmd erases everything from 0x46AA17 to 0x46AA85 and places a JMP to the internal function engine_opct_hook. cmdtext is located in register ebx and playerid in ebp, these are being pushed onto the stack and engine_command_detour is being called.
Linux:
http://urlremoved/SAMP/mcmd/opct.txt
The return locations differ (See engine.c for more information). cmdtext is located at EBP-0x14, playerid at EBP+0xC.
Speed
I did not create this plugin to make a faster version of y_commands or any other cmd processor. It was more like out of fun since I do find reverse engineering really interesting. I had this idea in mind for a long time but wasn't able to accomplish it until recently. Anyways, here is the speedtest I did in the early phase of the plugin. To test mcmd I've created an additional native function to call the internal engine_command_detour.
Download
v0.0.1-beta for Windows:
https://github.com/Mellnik/mcmd/rele...-beta/mcmd.rar
Source hosted at GitHub
https://github.com/Mellnik/mcmd
Credits:
MyU for helping me with IDA
maddinat0r for general coding help
This is the latest project I have been working on. mcmd, the first command processor which a) completely overwrites the default SA-MP command system and b) processes commands without PAWN interaction to pass OnPlayerCommandText parameters to the plugin. Even tho of it's memory hacking, it was designed to work with any version of the 0.3 branch.
Defining commands
To create commands, simply go to any location in your code and using following syntax. Commands are processed in lower case meaning /HellO is the same as /HELLo or /hello.
pawn Код:
mcmd:examplecommand(playerid, params[])
{
return 1;
}
To control any player input before the actual command gets executed, this callback is being called in the gamemode.
playerid | The id of the player who requested the command. |
cmdtext[] | The full command string including slash and parameters. |
exists | 1 = command was found in the script, 0 = command not found |
pawn Код:
forward OnPlayerRequestCommand(playerid, cmdtext[], exists);
pawn Код:
public OnPlayerRequestCommand(playerid, cmdtext[], exists)
{
if(!exists)
{
SendClientMessage(playerid, 0xFFFFFFFF, "This command does not exist!");
return 0;
}
return 1;
}
mcmd provides an inbuild function to control command spam.
pawn Код:
native GetPlayerLastRequestTime(playerid);
pawn Код:
public OnPlayerRequestCommand(playerid, cmdtext[], exists)
{
if(GetPlayerLastRequestTime(playerid) < 1)
{
SendClientMessage(playerid, 0xFFFFFFFF, "You may only use 1 command per second!");
return 0; // Do not call the command
}
if(!exists)
{
SendClientMessage(playerid, 0xFFFFFFFF, "This command does not exist!");
return 0;
}
return 1;
}
Here are the assembly instructions from the SA-MP 0.3z R2-2 server where it calls OnPlayerCommandText.
http://i.imgur.com/veUXSa2.png
mcmd erases everything from 0x46AA17 to 0x46AA85 and places a JMP to the internal function engine_opct_hook. cmdtext is located in register ebx and playerid in ebp, these are being pushed onto the stack and engine_command_detour is being called.
Linux:
http://urlremoved/SAMP/mcmd/opct.txt
The return locations differ (See engine.c for more information). cmdtext is located at EBP-0x14, playerid at EBP+0xC.
Speed
I did not create this plugin to make a faster version of y_commands or any other cmd processor. It was more like out of fun since I do find reverse engineering really interesting. I had this idea in mind for a long time but wasn't able to accomplish it until recently. Anyways, here is the speedtest I did in the early phase of the plugin. To test mcmd I've created an additional native function to call the internal engine_command_detour.
Quote:
Defaults: 100000 iterations +2700 commands in the gamemode custom callbacks enabled 3 cmd calls per iteration: (0, "/first testparams yes") (0, "/last testparams yes") (0, "/none testparams yes") Results: mcmd: 199 ms zcmd: 626 ms + internal OnPlayerCommandText execution from the samp-server (not measured) |
v0.0.1-beta for Windows:
https://github.com/Mellnik/mcmd/rele...-beta/mcmd.rar
Source hosted at GitHub
https://github.com/Mellnik/mcmd
Credits:
MyU for helping me with IDA
maddinat0r for general coding help