Befehle mit Übergabewerten

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • 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.

    Zitat

    warning 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 ).


    >> Teil 2 des Tutorials

  • Jo zumal der Gebrauch von dcmd noch andere Vorteile mit sich bringt. Zum einen natürlich die hier angesprochene bessere Übersichtlichkeit und eine bessere Struktur. Zum anderen ist die Methode dcmd-sscanf 30-40 mal schneller als die strcmp-strtok Geschichte, eure Server-CPU wirds euch also auch danke ;)
    Zum dritten kann man damit wirklich sehr elegant seinen gamemode strukturieren, indem man die Commands in eine include reinpfeffert, und so vor allem Freeroam oder RolePlay-Skripte viel übersichtlicher machen kann, weil in diesen Skripten, OnPlayerCommandText auch mal gerne die Hälfte der .pwn einnehmen kann.


    Goldkiller:
    Schönes Tutorial, ist auch gut verständlich geschrieben.

  • Jap, ich habe um die 50 Commands von strget in dcmd umgeschrieben.
    Das gute auch an dcmd ist, du kannst statt nur den Integerwert für die Playerid auch den Teil des Playernamen nehmen :D
    Mit
    sscanf(params,"u",player)
    z.B

  • Der Datentyp "u" ist natürlich was sehr feines.Gibts glaub ich noch gar nicht so lange.
    Damit ist es jetzt sogar noch einfacher Commands mit Parametern zu erstellen bei denen ein Parameter der Spieler ist.


    Zitat

    Zum dritten kann man damit wirklich sehr elegant seinen gamemode strukturieren, indem man die Commands in eine include reinpfeffert, und so vor allem Freeroam oder RolePlay-Skripte viel übersichtlicher machen kann, weil in diesen Skripten, OnPlayerCommandText auch mal gerne die Hälfte der .pwn einnehmen kann.


    Ist generell ekelig sich so ein Script anzugucken.Wenn ich schon sehe das dort überall tmp=strtok,cmd=strtok ... steht landet das Script im Papierkorb :pinch: .Versteht man meist nur Bahnhof wenn man den Code nur überfliegt.Bei sscanf kann man trotz überfliegen den Command leicht und schnell verstehen.

  • public OnPlayerCommandText(playerid, cmdtext[])
    {
    dcmd(givemoney,9,cmdtext);
    return 0;
    }
    dcmd_givemoney(playerid,params[])
    {
    new moneyid, moneyamount;
    if(sscanf(params,"dd",moneyid,moneyamount))
    {
    SendClientMessage(playerid,0xFF0000FF," [FEHLER]: /givemoney [id] [money] ");
    }
    else if(!IsPlayerConnected(moneyid))
    {
    SendClientMessage(playerid,0xFF0000FF," Spieler nicht gefunden!");
    }
    else if(moneyamount < 1 || moneyamount > 9999)
    {
    SendClientMessage(playerid,0xFF0000FF," Summe ungültig!");
    }
    else
    {
    GivePlayerMoney(moneyid,moneyamount);
    GivePlayerMoney(playerid,-moneyamount);
    }
    return 1;
    }
    Ein Command von mir :D
    Es ist wirklich einfacher, als ich dachte. Trotzdem werde ich nicht meinen ganzen GM umbauen ;)


    Ich scripte NICHT mehr, ich möchte mit NIEMANDEM einen Server aufmachen habe auch NICHTS mehr mit LoH zu tun, also lasst es mit den PNs!

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen
  • also wenn man ein GM hat, wo alles noch beim Alten ist, ist das ziemlich umsändlich alles zu ändern.... weiß da einer ne Möglichkeit, dass man durch ein "Script" oder sonstwas durchlaufen lassen könnte, dass alles umschreibt ?... :(
    Ansonsten, ist es ein Problem, wenn ich das alte lasse und mit dem neuen anfange?

  • Die einzige Möglichkeit wäre, eigenständig alle Commands auf dcmd & sscanf umzuschreiben. Ich überlege mir gerade ob ich ein GF so umschreiben und dann veröffentlichen sollte. Ein Haufen Arbeit, aber, es lohnt sich ganz sicher.

    Help dcmd & sscanf to their way to Pawn domination. Read the tutorial below, and use it.
    dcmd & sscanf

  • dcmd_jail(playerid,params[]) {
    new target;
    if(sscanf(params,"u",target)) {
    if(IsACop(playerid)) { // GF Deklaration
    return SendClientMessage(playerid, 0xFF0000FF, "Benutze /jail [PlayerID] um jemanden ins Gefängnis zu stecken.");
    }}
    if(IsACop(target)) {
    return SendClientMessage(playerid, 0xFF0000FF, "Der angegebene User ist ein Cop!");
    // ...... Hier den eig. Jail Code reinschreiben, z.B. SetPlayerPos(......) usw.
    // ......
    return 1;
    }

  • hey cooles tut XD


    ich hab da ma ne frage:


    funktioniert dashier?
    if (sscanf(params, "d/d/d", Tag, Monat, Jahr))
    also das man jetzt "24/7/1990" eingeben muss. also die 3 daten mit "/" voneinander trennen und ohne "/" am anfang eingeben muss.


    MFG
    Ich


    MY SELFMADE GAMEMODE "NoName"

    Spoiler anzeigen


    - AccountSystem: 100%
    - LizenzenSystem: 5%
    - TelefonSystem: 5%
    - JobSystem: 3%
    - GeldSystem: 80%
    - AutoSystem: 75%
    - FahndungsSystem: [color=#ff6600]10%
    [color=#000000]- HausSystem: [color=#ff0000]0%

    [color=#000000]- GeschäftsSystem: [color=#ff0000]0%

    [color=#000000]- ZahlTag System: [color=#ff0000]0%

    [color=#000000]- WetterSystem: [color=#ff0000]0%

    [color=#000000]- AntiCheatSystem: [color=#ff0000]0%

    Spoiler anzeigen
    GameModeName: [GM]MyGamemode
    Filterscripts: None
    Benutze Includes: [Inc]MyInclude
    Voraussichtliche Fertigstellung: Unbekannt
    Voraussichtliche Servereröffnung: Unbekannt
    Voraussichtliche Veröffentlichung des Scripts: Wahrscheinlich NIE
    Voraussichtliche Veröffentlichung des Scripts: Wahrscheinlich NIE
    Sonstige Anmerkungen: Selfmade