Szerző Téma: ZCMD_fixed (0.3.1)  (Megtekintve 2924 alkalommal)

ZCMD_fixed (0.3.1)
« Dátum: 2013. január 16. - 18:12:28 »
+2 Show voters
(A fordítás eredetije megtalálható a http://forum.sa-mp.com/showthread.php?t=91354 oldalon. A módosításokat a fordítás végén közlöm)
Leírás
Ez egy kis include, ami az OnPlayerCommandText() callback-et használja a játékosok parancsainak feldolgozására. Minden parancsnak van egy külön funkciója, mint a dcmd-ben, de a zcmd követlenül hívja meg a CallLocalFunction() segítségével. Ez a módszer sokkal gyorsabb, mintha egymás után hasonlítanád össze a szövegeket a beírt paranccsal minden egyes scriptedben lévõ parancsnál (különösen ha egy nem létezõ parancsot ír be a játékos, az összeset végignézi) valamint a fölénye a régi változattal szemben egyenesen arányos a parancsok számával. Készítettem egy sebesség tesztet amikor még csak gondolkoztam ezen a dolgon, az eredményei megtalálhatóak itt.
Használat
Egy parancs létrehozásához csupán egy public funkciót kell létrehoznod egy speciális elõredefiniált makró segítségével, így:
 

COMMAND:parancsom(playerid, params[]) // vagy CMD:parancsom(playerid, params[])
{
  // Csinalj valamit
  return 1;
}

 
vagy (régi mód):
 

command(parancsom, playerid, params[]) // or cmd(parancsom, playerid, params[])
{
  // Csinalj valamit
  return 1;
}

 
Itt a params[] egy string ami a paramétereket tartalmazza, a playerid az ID-je a játékosnak, aki ezt a parancsot beírta.
Ez minden! Nagyon egyszerû, ugye?
 
  Fontos: A 0.3-as verzió óta az OnPlayerCommandText nem használható többé (a ZCMD_NO_CALLBACK opció is el lett távolítva), de van helyette 2 új callback:
 
 OnPlayerCommandReceived(playerid, cmdtext[])

 
Ez akkor hívódik meg, mikor a játékos beír egy parancsot. Ha itt return 0 -val térünk vissza, a parancs nem kerül feldolgozásra.
 
 OnPlayerCommandPerformed(playerid, cmdtext[], success)

 
Ez pedig a parancs lefutása után hívódik meg, ha itt return 0 -val térünk vissza, a játékos a szokásos \"SERVER: Unknown command\" üzenetet fogja megkapni. A \"success\" paraméter az az érték, amivel a parancs funkciója visszatér (ha nincs ilyen funkció, a success értéke 0).
Ezeket a callback-eket nem szükséges beleírni a scriptedbe, ha nem használod õket.
  Hogy csináljunk két különbözõ parancsot, amik ugyanazt teszik
Például, van egy /valami parancs:
 

COMMAND:valami(playerid, params[])
{
  // valami dolog itt
  return 1;
}

 
és szeretnél egy másikat is csinálni, pl. /masik ami azt csinálja, amit a /valami csinál. A legegyszerûbb módja ennek:
 

COMMAND:masik(playerid, params[])
{
  return cmd_valami(playerid, params);
}

 
  Megjegyzés #1: Ha a zcmd-t egy filterscriptben szeretnéd használni, include elé szúrd be ezt a define-t:(a javított kiadásban erre nincs szükség)
 
#define FILTERSCRIPT

 
  Megjegyzés #2: Ha meg szeretnéd vizsgálni, hogy a \"params\"(paraméterek) string üres-e, ne így tedd:
 

if (!strlen(params))
{
  // nincs parameter
}

 
vagy:
 

if (!params[0])

 
mivel a string hossza sosem nulla (errõl bõvebben: itt), egyszerûen használd a zcmd-be épített isnull() függvényt:
 

if (isnull(params))

 
Tulajdonképpen, ha az sscanf-et használod, nem kell elvégezned ezt az ellenõrzést, mivel abban van beépített \"isnull\" vizsgálat.
Itt egy példa, hogyan készíthetünk egy /givemoney parancsot zcmd és sscanf használatával:
 

COMMAND:givemoney(playerid, params[])
{
if (IsPlayerAdmin(playerid))
{
new
  kinek, // a jatekos, akinek a penzt szeretnenk adni
  mennyit;
// a jatekos ID-je es a mennyiseg kinyerese a parameterekbol:
if (!sscanf(params, \"ui\", kinek, mennyit))
{
  if (kinek != INVALID_PLAYER_ID)
  {
    new
      uzenet[40];
    GivePlayerMoney(kinek, mennyit);
    format(uzenet, sizeof(uzenet), \"Kaptál $%d-t az admintól!\", mennyit);
    SendClientMessage(kinek, 0x00FF00FF, uzenet);
  }
  else SendClientMessage(playerid, 0xFF0000FF, \"A játékos nem elérhetõ\");
}
else SendClientMessage(playerid, 0xFFFFFFFF, \"Használat: /givemoney <játékosnév/id> <mennyiség>\");
}
else SendClientMessage(playerid, 0xFF0000FF, \"Csak adminisztrátorok használhatják ezt a parancsot!\");
return 1;
}

 


Változtatások balintx által
A ZCMD_fixed két fõ változtatást foglal magában:
 
  • Mostantól nincs szükség a FILTERSCRIPT makró definiálására, ha filterscriptben kívánjuk használni a zcmd-t.
    Nem csak felesleges, de biztosan volt már, hogy elfelejtkeztünk róla és nem értettük miért nem mûködnek parancsaink.

  • ZCMD mostantól támogatja a magyar ékezetes parancsokat.
    Ennek mûködése:

  1. a játékos által beírt parancs ékezetes betûinek ékezet nélkülivé alakítása

  2. az ékezet nélkülivé alakított parancs funkciójának meghívása


Használatához nem kell átírni a már létezõ modokat, csupán újra kell fordítani a zcmd_fixed.inc -el.
Példa a használatra:
 

CMD:jatekosnev(playerid, params[])
{
    szUzenet[MAX_PLAYER_NAME + 12];
    strcat(szUzenet, \"* Neved: \");
    GetPlayerName(playerid, szUzenet[9], MAX_PLAYER_NAME);
    SendClientMessage(playerid, -1, szUzenet);
    return 1;
}

 

  • a fenti kód le fog futni a /jatekosnev, /játékosnév parancsokra is.

Letöltés
 
/**********************************
*                                *
*   @Author:      ZeeX           *
*   @Version:     0.3.1          *
*   @Released:    31/10/2009     *
*                                *
**********************************/
// Edited by KoczkaHUN
//
// Now it supports Hungarian language
// and you do not have to use the
// FILTERSCRIPT define before
// #include-ing zcmd.
//
// Created 17/05/2012
#if defined _zcmd_included
#endinput
#endif
#define _zcmd_included
#define MAX_FUNC_NAME (32)
#define COMMAND:%1(%2)          \\
   forward cmd_%1(%2); \\
   public cmd_%1(%2)
#define CMD:%1(%2) \\
   COMMAND:%1(%2)
#define command(%1,%2,%3) \\
   COMMAND:%1(%2, %3)
#define cmd(%1,%2,%3) \\
   COMMAND:%1(%2, %3)
#if !defined isnull
#define isnull(%1) \\
      ((!(%1[0])) || (((%1[0]) == \'\\1\') && (!(%1[1]))))
#endif
 
forward OnPlayerCommandReceived(playerid, cmdtext[]);
forward OnPlayerCommandPerformed(playerid, cmdtext[], success);
 
static
bool:zcmd_g_HasOPCS = false,
bool:zcmd_g_HasOPCE = false;
 
public OnFilterScriptInit()
{
zcmd_g_HasOPCS = funcidx(\"OnPlayerCommandReceived\") != -1;
zcmd_g_HasOPCE = funcidx(\"OnPlayerCommandPerformed\") != -1;
    return CallLocalFunction(\"zcmd_OnFilterScriptInit\", \"\");
}
#if defined _ALS_OnFilterScriptInit
    #undef OnFilterScriptInit
#else
    #define _ALS_OnFilterScriptInit
#endif
#define OnFilterScriptInit zcmd_OnFilterScriptInit
forward zcmd_OnFilterScriptInit();
public OnGameModeInit()
{
zcmd_g_HasOPCS = funcidx(\"OnPlayerCommandReceived\") != -1;
zcmd_g_HasOPCE = funcidx(\"OnPlayerCommandPerformed\") != -1;
if (funcidx(\"zcmd_OnGameModeInit\") != -1)
{
return CallLocalFunction(\"zcmd_OnGameModeInit\", \"\");
}
return 1;
}
#if defined _ALS_OnGameModeInit
    #undef OnGameModeInit
#else
    #define _ALS_OnGameModeInit
#endif
#define OnGameModeInit zcmd_OnGameModeInit
forward zcmd_OnGameModeInit();
public OnPlayerCommandText(playerid, cmdtext[])
{
    if (zcmd_g_HasOPCS && !CallLocalFunction(\"OnPlayerCommandReceived\", \"is\", playerid, cmdtext))
    {
        return 1;
    }
    new
        pos,
        funcname[MAX_FUNC_NAME] = \"cmd_\";
      while (cmdtext[++pos] > \' \')
{
switch (cmdtext[pos])
{
   case \'á\',\'Á\': funcname[pos+3] = \'a\';
   case \'é\',\'É\': funcname[pos+3] = \'e\';
   case \'í\',\'Í\': funcname[pos+3] = \'i\';
   case \'ó\',\'ö\',\'õ\',\'Ó\',\'Ö\',\'Õ\': funcname[pos+3] = \'o\';
   case \'ú\',\'ü\',\'û\',\'Ú\',\'Ü\',\'Û\': funcname[pos+3] = \'u\';
   default: funcname[pos+3] = tolower(cmdtext[pos]);
}
}
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]);
}
#if defined _ALS_OnPlayerCommandText
    #undef OnPlayerCommandText
#else
    #define _ALS_OnPlayerCommandText
#endif
#define OnPlayerCommandText zcmd_OnPlayerCommandText
forward zcmd_OnPlayerCommandText(playerid, cmdtext[]);

 

Legal
Az eredeti include Zeex tulajdona.
Az eredeti publikáció itt megtalálható: http://forum.sa-mp.com/showthread.php?t=91354
A módosítás az utolsó, 0.3.1-es zcmd változathoz készült.
« Utoljára szerkesztve: 2013. január 19. - 00:22:49 írta balintx »

Nem elérhető Mike.

  • 720
    • Profil megtekintése
ZCMD_fixed (0.3.1)
« Válasz #1 Dátum: 2013. január 16. - 18:14:48 »
0 Show voters
Ezt nem ide kellett volna nyitni!
Amúgy szép leírás.

ZCMD_fixed (0.3.1)
« Válasz #2 Dátum: 2013. január 16. - 18:17:02 »
0 Show voters
Hát hova? Ez egy include.

Nem elérhető Live

  • 507
    • Profil megtekintése
ZCMD_fixed (0.3.1)
« Válasz #3 Dátum: 2013. január 16. - 18:24:35 »
0 Show voters
Szép lett!

Nem elérhető DrAkE

  • 2078
    • Profil megtekintése
ZCMD_fixed (0.3.1)
« Válasz #4 Dátum: 2013. január 16. - 20:29:10 »
0 Show voters
Nem kellene azért kiszedni a FILTERSCRIPT makrót, ugyanis így még a filterscriptben is lesz OnGameModeInit eljárás, ami szinte szükségtelen, ezen felül több minden kerül beágyazásra (nem mint ha sokat fordítana).

ZCMD_fixed (0.3.1)
« Válasz #5 Dátum: 2013. január 16. - 20:36:55 »
0 Show voters
Idézetet írta: DrAkE date=1358364550\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"32537\" data-ipsquote-contentclass=\"forums_Topic
Nem kellene azért kiszedni a FILTERSCRIPT makrót, ugyanis így még a filterscriptben is lesz OnGameModeInit eljárás, ami szinte szükségtelen, ezen felül több minden kerül beágyazásra (nem mint ha sokat fordítana).
 
Filterscriptben hiába van OnGameModeInit és OnGameModeExit, sosem hívódik meg. Ugyanígy gamemode-ban az OnFilterScriptInit és az OnFilterScriptExit sem.
Ha figyelembe vesszük, hogy úgysem hívódik meg, az a pár bájt nem sokat zavar az amx fájlban viszont elég sok kellemetlen perctõl szabadulunk meg ezzel. (Személy szerint értelmetlennek tartom a FILTERSCRIPT makró használatát mindenhol)

ZCMD_fixed (0.3.1)
« Válasz #6 Dátum: 2013. január 17. - 20:01:48 »
0 Show voters
Idézetet írta: Mike. date=1358356488\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"32537\" data-ipsquote-contentclass=\"forums_Topic
Ezt nem ide kellett volna nyitni!
Amúgy szép leírás.
 
Bálint ezt szerintem nem leírásnak szánta.
 
ZCMD_fixed
[/quote]

ZCMD_fixed (0.3.1)
« Válasz #7 Dátum: 2013. január 18. - 23:36:03 »
0 Show voters
Nagyon zsír :D Egyébként egy ötlet
 
format(funcname, sizeof(funcname), \"cmd_%s\", funcname);

 
Ez helyett nem lenne jobb ez? :D
 
strins(funcname,\"cmd_\",0,MAX_FUNC_NAME);

ZCMD_fixed (0.3.1)
« Válasz #8 Dátum: 2013. január 19. - 00:09:20 »
0 Show voters
Mindegy.
Vagy készíts gyorsaság tesztet hogy kiderítsd melyik native funkció gyorsabb, a format vagy a strins.

ZCMD_fixed (0.3.1)
« Válasz #9 Dátum: 2013. január 19. - 00:14:10 »
0 Show voters
Az eredeti változatban ugyanez a sor szerepel, így nem változtattam. Majd megnézem hogy lehet gyorsítani rajta. Bár szerintem nem érdemes

ZCMD_fixed (0.3.1)
« Válasz #10 Dátum: 2013. január 19. - 00:19:51 »
0 Show voters
Azért fura hogy, pont ilyen eljárással publikáltam korábban egy zcmd módosítást. Na mindegy.
http://sampforum.hu/index.php?topic=32138.0
Edit:
Azért szép munka, lehet nem is láttad és pont ugyanazt találtad ki, vagy én nem láttam és ugyanazt találtam ki.  :D
« Utoljára szerkesztve: 2013. január 19. - 00:29:06 írta ɐʞzssǝlosz »

ZCMD_fixed (0.3.1)
« Válasz #11 Dátum: 2013. január 19. - 00:24:45 »
0 Show voters
Idõközben megszületett a javítás, eredeti postban frissítettem a linket. Tesztelve. mostmár nem kell format -ot használnunk (-1 native hívás, valószínûleg ->profit)
 
        funcname[MAX_FUNC_NAME] = \"cmd_\";
      while (cmdtext[++pos] > \' \')
{
switch (cmdtext[pos])
{
   case \'á\',\'Á\': funcname[pos+3] = \'a\';
   case \'é\',\'É\': funcname[pos+3] = \'e\';
   case \'í\',\'Í\': funcname[pos+3] = \'i\';
   case \'ó\',\'ö\',\'õ\',\'Ó\',\'Ö\',\'Õ\': funcname[pos+3] = \'o\';
   case \'ú\',\'ü\',\'û\',\'Ú\',\'Ü\',\'Û\': funcname[pos+3] = \'u\';
   default: funcname[pos+3] = tolower(cmdtext[pos]);
}
}

ZCMD_fixed (0.3.1)
« Válasz #12 Dátum: 2013. január 19. - 00:28:36 »
0 Show voters
strins kb 2x olyan gyors de mindegy. Még egy tipp esetleg
while (cmdtext[pos] == \' \') pos++;
helyett lehetne használni
pos = strfind(...) ot is szerintem, mivel ha jól értelmezem akkor ez megkeresi az elsõ szóközt. és az strfind pedig visszatér a legelsõ találat pozíciójával a szövegben 0 hogy ha a legelsõ karakter az 1 hogy ha a 2. és így tovább.
Ha pedig nem talál sehol ilyet, akkor -1 el tér vissza.
« Utoljára szerkesztve: 2013. január 19. - 00:31:37 írta hegdavid95 »

ZCMD_fixed (0.3.1)
« Válasz #13 Dátum: 2013. január 19. - 00:30:52 »
0 Show voters
Idézetet írta: ɐʞzssǝlosz date=1358551191\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"32537\" data-ipsquote-contentclass=\"forums_Topic
Azért fura hogy, pont ilyen eljárással publikáltam korábban egy zcmd módosítást. Na mindegy.
http://sampforum.hu/index.php?topic=32138.0
Edit:
Azért szép munka, lehet nem is láttad és pont ugyanazt találtad ki.
 
Ezt még tavaly írtam, aztán abbahagytam a samp-ot, most visszatértem egy projekt miatt és gondoltam megosztom a többiekkel.
Rákerestem fórumon a zcmd -re, includeok között is néztem de semmit nem találtam. Ezért raktam fel.
Egyébként ha megnézed, azért más elven mûködik a kettõ, én például nem vagyok benne biztos hogy a tolower az ékezetes betûket is átalakítja [vagyis hogy ascii-ban nagyobb az értékük mint 32 (space)].
Fogalmam sem volt, hogy valaki már hasonlót megírt :)

ZCMD_fixed (0.3.1)
« Válasz #14 Dátum: 2013. január 19. - 00:33:15 »
0 Show voters
@balintx
Átalakítja.  :D
@hegdavid95
Az strfind lassú.

 

SimplePortal 2.3.7 © 2008-2024, SimplePortal