Pawn. Создание команд разными способами
1 минут
На данный момент существует множество способов создания команд в SA-MP'е. Самые известные из них: простое добавление команд в OnPlayerCommandText
, zcmd и dcmd.
Как работает zcmd?🔗︎
Каждая созданная команда создаёт паблик функцию.
#define COMMAND:%1(%2) \
forward cmd_%1(%2); \
public cmd_%1(%2)
Всё, что написано в вашем OnPlayerCommandText
игнорируется.
#define OnPlayerCommandText zcmd_OnPlayerCommandText
forward zcmd_OnPlayerCommandText(playerid, cmdtext[]);
В самом инклуде создаётся OnPlayerCommandText
в котором написан обработчик команд.
if (zcmd_g_HasOPCS && !CallLocalFunction("OnPlayerCommandReceived", "is", playerid, cmdtext))
{
return 1;
}
new pos, funcname[MAX_FUNC_NAME];
while (cmdtext[++pos] > ' ')
{
funcname[pos-1] = tolower(cmdtext[pos]);
}
format(funcname, sizeof(funcname), "cmd_%s", funcname);
while (cmdtext[pos] == ' ') pos++;
if (!cmdtext[pos])
{
if (zcmd_g_HasOPCE)
{
return CallLocalFunction("OnPlayerCommandPerformed", "isi", playerid, cmdtext, CallLocalFunction(funcname, "is", playerid, "\1"));
}
return CallLocalFunction(funcname, "is", playerid, "\1");
}
if (zcmd_g_HasOPCE)
{
return CallLocalFunction("OnPlayerCommandPerformed", "isi", playerid, cmdtext, CallLocalFunction(funcname, "is", playerid, cmdtext[pos]));
}
return CallLocalFunction(funcname, "is", playerid, cmdtext[pos]);
Очень много лишнего, что несомненно сказывается на скорости работы при небольшом количестве команд.
Тест скорости(с одной командой)🔗︎
Исходник теста
#include <..\compiler\includes\a_samp>
#include "zcmd"
#define C_TICK 50000
#define ncmd(%0,%1,%2) \
if(!strcmp(%0,#/%1,true,%2) && ((%0[%2+1] == ' ') || (%0[%2+1] == 0))) \
return ncmd_%1(playerid,%0[%2+1+1])
#define dcmd(%1,%2,%3) \
if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) \
return 1
main()
{
new tick;
// ----------
tick = GetTickCount();
for (new i=0;i<C_TICK;i++)
{
CallRemoteFunction("OnPlayerCommandText","is",0,"/test_zcmd 0 param1");
}
printf("zcmd: %d",GetTickCount() - tick);
// ----------
tick = GetTickCount();
for (new i=0;i<C_TICK;i++)
{
CallRemoteFunction("old_OnPlayerCommandText","is",0,"/test_old 0 param1");
}
printf("old: %d",GetTickCount() - tick);
// ----------
tick = GetTickCount();
for (new i=0;i<C_TICK;i++)
{
CallRemoteFunction("new_OnPlayerCommandText","is",0,"/test_new 0 param1");
}
printf("new: %d",GetTickCount() - tick);
// ----------
tick = GetTickCount();
for (new i=0;i<C_TICK;i++)
{
CallRemoteFunction("dcmd_OnPlayerCommandText","is",0,"/test_dcmd 0 param1");
}
printf("dcmd: %d",GetTickCount() - tick);
}
// ----------
forward OnPlayerCommandText(playerid,cmdtext[]);
public OnPlayerCommandText(playerid,cmdtext[])
{
zcmd_OnPlayerCommandText(playerid,cmdtext);
return 0;
}
COMMAND:test_zcmd(playerid, params[])
{
return 1;
}
// ----------
forward old_OnPlayerCommandText(playerid,cmdtext[]);
public old_OnPlayerCommandText(playerid,cmdtext[])
{
if(!strcmp(cmdtext,"/test_old",true,9))
{
return 1;
}
return 0;
}
// ----------
forward new_OnPlayerCommandText(playerid,cmdtext[]);
public new_OnPlayerCommandText(playerid,cmdtext[])
{
ncmd(cmdtext,test_new,8);
return 0;
}
#define NCMD:%1(%2) \
forward ncmd_%1(%2); \
public ncmd_%1(%2)
NCMD:test_new(playerid,params[])
{
return 1;
}
// ----------
forward dcmd_OnPlayerCommandText(playerid,cmdtext[]);
public dcmd_OnPlayerCommandText(playerid,cmdtext[])
{
dcmd(test_dcmd,9,cmdtext);
return 1;
}
forward dcmd_test_dcmd(playerid,params[]);
public dcmd_test_dcmd(playerid,params[])
{
return 1;
}
В тесте участвовали обычные проверки(old), zcmd, dcmd и ncmd(new).
zcmd: 739
old: 399
new: 415
dcmd: 507
zcmd: 788
old: 413
new: 392
dcmd: 432
zcmd: 777
old: 422
new: 379
dcmd: 457
Вывод🔗︎
Если в вашем моде большое количество команд, то команды следует перевести на систему zcmd. При небольшом количестве команд(< 10) следует использовать старый добрый метод с проверками или ncmd.