GTA Közösség - A magyar GTA fórum

San Andreas Multiplayer (SA-MP) => SA-MP: Szerverfejlesztés => Hivatalos fórumról áthozott szkriptek => A témát indította: balintx - 2013. Január 16. - 18:12:28

Cím: ZCMD_fixed (0.3.1)
Írta: balintx - 2013. Január 16. - 18:12:28
(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:
 
  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;
}

 

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.
Cím: ZCMD_fixed (0.3.1)
Írta: Mike. - 2013. Január 16. - 18:14:48
Ezt nem ide kellett volna nyitni!
Amúgy szép leírás.
Cím: ZCMD_fixed (0.3.1)
Írta: balintx - 2013. Január 16. - 18:17:02
Hát hova? Ez egy include.
Cím: ZCMD_fixed (0.3.1)
Írta: Live - 2013. Január 16. - 18:24:35
Szép lett!
Cím: ZCMD_fixed (0.3.1)
Írta: DrAkE - 2013. Január 16. - 20:29:10
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).
Cím: ZCMD_fixed (0.3.1)
Írta: balintx - 2013. Január 16. - 20:36:55
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)
Cím: ZCMD_fixed (0.3.1)
Írta: Pajd Tamás - 2013. Január 17. - 20:01:48
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]
Cím: ZCMD_fixed (0.3.1)
Írta: hegdavid95 - 2013. Január 18. - 23:36:03
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);
Cím: ZCMD_fixed (0.3.1)
Írta: Zsolesszka - 2013. Január 19. - 00:09:20
Mindegy.
Vagy készíts gyorsaság tesztet hogy kiderítsd melyik native funkció gyorsabb, a format vagy a strins.
Cím: ZCMD_fixed (0.3.1)
Írta: balintx - 2013. Január 19. - 00:14:10
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
Cím: ZCMD_fixed (0.3.1)
Írta: Zsolesszka - 2013. Január 19. - 00:19:51
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
Cím: ZCMD_fixed (0.3.1)
Írta: balintx - 2013. Január 19. - 00:24:45
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]);
}
}
Cím: ZCMD_fixed (0.3.1)
Írta: hegdavid95 - 2013. Január 19. - 00:28:36
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.
Cím: ZCMD_fixed (0.3.1)
Írta: balintx - 2013. Január 19. - 00:30:52
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 :)
Cím: ZCMD_fixed (0.3.1)
Írta: Zsolesszka - 2013. Január 19. - 00:33:15
@balintx
Átalakítja.  :D
@hegdavid95
Az strfind lassú.
Cím: ZCMD_fixed (0.3.1)
Írta: balintx - 2013. Január 19. - 00:34:54
Idézetet írta: hegdavid95 date=1358551716\" data-ipsquote-contentapp=\"forums\" data-ipsquote-contenttype=\"forums\" data-ipsquote-contentid=\"32537\" data-ipsquote-contentclass=\"forums_Topic
strins kb 2x olyan gyors de mindegy.
A format-nál elképzelhetõ, de ahogy most átalakítottam így már nem lenne gyorsabb. Ugyanis így direktbe beírja a szöveget az arraybe, míg a másik megoldással ezután még meg kell hívni az strins-t, ami átmásolgatja a cellákat...
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.
 
[/quote]Ennek pedig azért nincs értelme, mert a pos már úgyis tartalmazza azt a karaktert, ami a szóköz ascii értékénél nem nagyobb. Tehát nagy valószínûséggel egy szóköz vagy NULL karakter van benne. strfind pedig az elejétõl vizsgálná meg az egész stringet, ami lássuk be megint nem valami gyors megoldás.. arról nem beszélve hogy a stringet még át kell küldeni a native-nak, ami szintén idõ.