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.