Commands mit Parameter,was ist das?
An Beispielen wird euch das sicherlich deutlich,
Keine Paramter:
Zitat/lossantos - einfacher Teleport
/help
/time
Mit Paramtern:
Zitat/kick [playerid]
/announce [text]
/register [passwort] [password]
Natürlich ist den meisten hier im Forum die strtok variante sehr geläufig bei Commands mit Paramtern,eventuell
auch Commands mit strget zu erstellen.Doch es geht bei weitem einfacher und schneller
sowohl bei der Ausführung durch den Server als auch beim scripten.
Ich spreche von der Methode Commands zu erstellen in Verbindung von dcmd und sscanf.
Vorteile:
* Command ist viel besser strukturiert und besser lesbar
* CPU schonender als strtok oder strget (Code wird schneller ausgeführt durch CPU->Kann laggs vermindern)
* Bessere Gesamtstruktur des Scriptes (Es ist möglich die Commands in einem extra include aufzubewahren)
* DCMD enthält einen Filter (Command muss exakt eingegeben werden)
Hier ein einfaches Beispiel wie ein einfacher Command aussehen könnte mit einem extra Parameter,
/kick [playerid]
public OnPlayerCommandText(playerid, cmdtext[])
{
new
idx,
cmd[128];
cmd=strtok(cmdtext,idx);
if(!strcmp(cmd,"/kick",true,5)) {
new
sID[128],
pID;
sID=strtok(cmdtext,idx);
if(!strlen(sID)) {
return SendClientMessage(playerid,COLOR_RED,"USAGE: /kick [playerid]");
}
pID=strval(sID);
if(!IsPlayerConnected(pID)) {
return SendClientMessage(playerid,COLOR_RED,"Kein Spieler mit angegebener ID Online");
}
Kick(pID);
SendClientMessage(playerid,COLOR_YELLOW,"Erfolgreich Spieler vom Server gekickt!");
}
return 0;
}
Natürlich funktioniert der Command auch so wunderbar,aber nur weil es funktioniert heisst nicht,dass es
so auch die beste Lösung ist.Sehr anläufig für viele Bugs.Was ist wenn wir einen String bestehend aus "gwefd23f%D" in einen Integer konvertieren wollen?Gut,dafür gibt es IsNumeric,aber wir werden später sehen,es geht besser.
Dazu kommt,dass man so auch euren Server crashen kann (Ja,das ist tatsächlich möglich mit dem Beispielcommand).
dcmd
Erfinder des dcmd's ist Dracoblue,vielleicht kennt ihr ihn eher von DINI,DUDB,Dutils oder djason.Das sind ebenfalls seine Werke.
Als erstes brauchen wir das dcmd-Macro.
#define dcmd(%1,%2,%3) if ((strcmp((%3)[1], #%1, true, (%2)) == 0) && ((((%3)[(%2) + 1] == 0) && (dcmd_%1(playerid, "")))||(((%3)[(%2) + 1] == 32) && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1
Der Command nun in der dcmd Form
public OnPlayerCommandText(playerid, cmdtext[])
{
dcmd(kick,4,cmdtext);
return 0;
}
dcmd_kick(playerid,params[]) {
if(!strlen(params)) {
return SendClientMessage(playerid,COLOR_RED,"USAGE: /kick [playerid]");
}
new
pID=strval(params);
if(!IsPlayerConnected(pID)) {
return SendClientMessage(playerid,COLOR_RED,"Kein Spieler mit angegebener ID Online");
}
Kick(pID);
SendClientMessage(playerid,COLOR_YELLOW,"Erfolgreich Spieler vom Server gekickt!");
return 1;
}
Auf den ersten Blick ist der Code nicht unbedingt viel kürzer,aber die länge ist nicht unbedingt ein wichtiges
Merkmal wie gut oder schlecht ein Code ist.Oft ist trotzdem kürzer besser ;P
Nun zu der Erklärung.Wie bereits erwähnt ist der Code lediglich etwas kürzer,dennoch wie Ich finde viel übersichtlicher
da das OnPlayerCommandText - Callback nicht voller endloslangen Codes ist.
Was bedeutet aber die Zeile in OnPlayerCommandText genau?
dcmd(kick,4,cmdtext);
kick,dass ist der Name des Commands den wir im 3 Paramter,cmdtext suchen.Es wird
überprüft ob ein Spieler /kick eingegeben hat.Die 4 steht dabei für die länge von kick.Das ganze muss man
ohne / angeben.Wieso ist relativ unwichtig,es sollte für den normalen gebrauch reichen.
Wichtig ist noch zu wissen,dass die Definitionszeile ( dcmd(<cmdname>,<cmdlänge>,<source>) ) immer unter das Callback OnPlayerCommandText(playerid,cmdtext[]) gehört.
So müsste als Beispiel die Definition von /ban aussehene:
dcmd(ban,3,cmdtext);
Kommen wir nun zu dem eigentlichen Command,dcmd_kick:
Wieso es dcmd_kick heisst sollte relativ klar sein,es ist einfach der Name des Commands.
Nun zu den Parametern.
dcmd_kick(playerid,params[])
Der erste Paramter,playerid ist wie der Name sagt die playerid von demjenigen der den Command ausgeführt hat.Der zweite Paramter wird meistens params genannt.Falls der Spieler nun /kick 34er2 eingegeben hat,würde params nun 34er2 enthalten.Sollte er auch nur /kick eingegeben hat,enthält params nicht.Ist also ein leerer String.
Wenn man das ganzes einmal verstanden hat,wird man merken das es so sehr sehr einfach ist.
Es gibt außerdem noch einen weitern Vorteil bei dcmd.Es enthält einen "Filter".Wer sich das ganze mal angucken möchte,nur zu: [HowTo] Fast command processor: DCMD
Allerdings müsste man auch strtok wieder benutzten,sobald man mehr als einen Paramter haben möchte in seinem Command,zB /kick [playerid] [grund].Jetzt kommt sscanf zum Einsatz.
Wenn die Funktion keine Parameter braucht, (zB bei Teleportcommands wie /sf (Teleportiert Spieler nach San Fierro)) kann man
folgende Warnung leicht unterdrücken.
Zitatwarning 203: symbol is never used: "params"
dcmd_info(playerid, params[]) {
#pragma unused params
//Do something here
}
Update 19.8.2010, Tutorial auf 2 ( 3 ) Post's aufgeteilt,da das Postlimit erreicht wurde ( Kein Edit mehr möglich ).