Das Script in-Game auslesen! Aber wie?

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
  • Schönen guten Abend, liebe Breadfish Community.


    Gestern kam mir eine Idee, ob sie gut oder schlecht ist wird sich noch heraus stellen, doch habe derzeit kein "Plan" wie sich die Idee verwirklichen lässt.
    Es geht um folgendes.. der Gamemode / das Script soll IG (in-Game) auslesbar sein, wie ich mir das vorgestellt habe werde ich anhand von zwei Beispielen verdeutlichen.


    Beispiel Eins:



    Der Client gibt einen Befehl ein Bsp: "/Befehl", der besagte Befehl ist meinetwegen in den Zeilen 1000-1005 geschrieben, als Block gesehen oder eben nur die einzelne Zeile in welcher der Befehl steht aufs Beispiel bezogen Zeile 1000.
    Nun soll der Befehl ganz normal ausgeführt werden aber parallel dazu soll dem Client die Zeilen in welchen der besagte Befehl steht ausgegeben werden.
    Beispiel: Client gibt ein "/Befehl", der Befehl wird ausgeführt und dazu bekommt der Client ausgegeben (SendClientMessage evtl.) : "Zeile 1000" oder so ähnlich.


    Auf dem ersten Blick vielleicht etwas unnötig, doch ich habe etwas damit geplant, was ich derzeit aber noch nicht bekannt geben kann / mag.


    Beispiel Zwei:



    Kommen wir nun zur Dynamik.
    Ich möchte zu dieser "Funktion" sprich das auslesen des Scripts auch noch einen passenden Befehl haben Bsp: "/Zeile (ZeilenID / ZID)" Beispiel Ausführung: "/Zeile 1000".
    Dann soll dem Client (Mir) ausgegeben werden was nun genau in dieser Zeile steht, diesmal aber nicht der ganze Block sondern nur diese eine Zeile. Bsp: "SendClientMessage(playerid, COLOR, "Zeile %i(Als Integer (ZID / ZeilenID) : TEXT" Sprich: "Zeile 1000 : CMD:Befehl(playerid,params) | Also der genaue Aufbau der Zeile soll wiedergegeben werden.



    Ich hoffe ich konnte es ein wenig näher erläutern, doch wie gesagt fehlt mir derzeit die Idee wie oder womit ich anfange, deshalb frage ich euch vielleicht hat ja jemand von euch eine gute Idee.
    Ich hoffe das ist der richtige Bereich für diese Frage, es gibt ja den Bereich "kleine/re Scripting-Anfragen" doch dies ist ja eigentlich keine kleine Anfrage.


    Ich bedanke mich im voraus für jede Antwort.
    Mit freundlichen Gruß
    ItsFreaky | Marcel


    PS: Bitte nicht klauen.. ich gehe jetzt einfach mal davon aus das ich der erste bin dem diese Idee gekommen ist


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

  • Machbar ist das sicherlich, wenn du mit dem Plugin:
    http://forum.sa-mp.com/showthread.php?t=92246


    Den Code öffnest und durchliest. Die Zeilen vergleichst du dann, ob dort zum Beispiel der Beginn des Befehls ist, wenn ja, gibst du die Zeilen bis zur letzten Klammer zu aus.


    Letztlich ist es nur eine Frage von string-comparing, also dem vergleichen von Strings.




    Du kannst auch auf das Plugin verzichten, wenn du eine Kopie von der pwn Datei in dem Scriptfiles Ordner hast.

  • Vielen Dank für deine Antwort, ich werde mir das mal anschauen.
    Mal schauen ob ich es gescheit hinbekomme. :D


    Sonnst noch jemand ne Idee? :)


    Aber vielen Dank an dich Jeffry




    Edit: Ich weiß leider nicht wie ich das Plugin richtig benutze...


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

    Einmal editiert, zuletzt von ItsFreaky | Marcel ()

  • Versuch es doch erst mal mit einer Kopie des Codes im Scriptfiles Ordner. Wenn du das funktionsfähig hast, kannst du dich immer noch an das Plugin machen, falls dir das den Mehraufwand wert ist.


    Oder du schaust Dir einfach mal den Beispiel Code an der dabei ist, das sollte eigentlich alle Fragen klären.

  • Wenn ich das nun richtig im Kopf habe kann ich wenn ich die Kopie des Scripts im Scriptfiles Ordner habe per file.inc doch eigentlich wie folgt vorgehen oder nicht?



    new File:hFile;
    hFile = fopen("TestScript.pwn", io_read);
    fClose(hFile);


    So müsste die Datei ja ausgelesen werden, aber wie gebe ich sie wieder beziehungsweise wie gebe ich genau die gewünschte Zeile aus?


    Kann ich vorher irgendwie abfragen ob die Datei existiert?
    Aber wie gebe ich das dann aus, klar es mir den Aufwand wert, ich hab auch schon einen Teil davon verstanden, nur schließt sich das ganze mir leider noch nicht wirklich auf.


    Zumindest wie gebe ich die Zeile dann aus, wie gebe ich es allgemein aus?
    Muss ich es für jede Zeile einzeln Abfragen oder kann ich das ganze in einem Stock oder in einer Function schreiben so das ich global darauf zugreifen kann.


    Ich versteh es leider nur Stückweise aber "programmieren" ist auch kein Ponyhof.


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

  • Zur Info, wenn du eine Kopie der PWn auf dem Server hast kann man dir einfacher das Script klauen, da mann nur Server zugrff braucht und keinen Zugriff auf deinen PC. Ich würd mir das 5 mal überlegen wenn ich du wäre.

  • Zur Info, wenn du eine Kopie der PWn auf dem Server hast kann man dir einfacher das Script klauen, da mann nur Server zugrff braucht und keinen Zugriff auf deinen PC. Ich würd mir das 5 mal überlegen wenn ich du wäre.

    Natürlich ist mir dies bewusst. Nur möchte ich keinen Server machen sondern soll dies lediglich für mich sein, ich plane etwas damit doch habe nicht vor damit in SA:MP einen öffentlichen Server zu errichten.
    Dieses "System" oder Script wird ausschließlich auf meinem Homeserver laufen. :)


    Danke trotzdem für deinen Rat/Tipp


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)


  • Okay, vielen dank für deine schnelle Hilfe.
    Ich werde mal schauen ob ich es hinbekomme.



    new File:hFile;
    hFile = fOpen)("TestScript.pwn", io_read);
    while(fread(hFile, string))
    {
    i++;if(i==1000) print(string);
    }



    So ungefähr? Dann müsste es doch eigentlich auch möglich sein durch die if-Abfrage eine beliebige Zeile zu erfragen und sie direkt auszugeben.
    Vorstellung:


    Die Script Datei als .txt statt .pwn falls das Include damit besser klar kommt.



    new File:hFile;
    if(fexist("TestScript.txt"))
    {
    hFile = fOpen)("TestScript.txt", io_read);
    }
    while(fread(hFile, string))
    {
    i++;
    format(string, sizeof(string), "%s");
    if(i==%d) SendClientMessage(playerid, FARBE, "Zeile %d: %s);
    }


    Kann ich das ganze in eine Function schreiben?


    Edit: Wieso schreibt er den verdammten Code immer nebeneinander -.-'


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

    Einmal editiert, zuletzt von ItsFreaky | Marcel ()

  • Ja, das kann man als Funktion machen, wobei das eher nicht empfehlenswert ist, nur eine Zeile in der Funktion auszugeben.


    Ich würde dir raten, das mit einer Variable zu machen, oder direkt. Wenn du dir meinen Post oben nochmal ansiehst, dann siehst du warum es nicht sinnvoll ist, eine einzelne Zeile per Funktion ausgegeben zu lassen, da man bei drei Zeilen die ganze Datei drei mal durchlesen würde.


    Übrigens ist in deinem Code eine Klammer zu viel bei fOpen.


    EDIT: Weil du einen Editor mit einem anderen Zeilenumbruch benutzt.

  • Ja, es ist eher Sinnfrei und nicht dynamisch weil er die Datei immer wieder durchließt und dadurch vermutlich mengen an Ressourcen "verschwendet".


    Nun aber die Frage, hab ich es jetzt anhand meines Beispiels richtig gemacht?
    Liegen dort Fehler? (Hab es jetzt hinbekommen untereinander zu schreiben)



    Und die wichtigere Frage, wie anders machen.
    Ich hab mir alles noch einmal angeschaut und werde den Code gleich sofern er richtig ist zum ersten mal in der Theorie testen.
    Nur verstehe ich Filemanager.inc nicht ganz, ich werde mit damit auf jeden Fall nochmal genau auseinander setzen.


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

  • Ja, setze dich damit mal auseinander.


    Code
    new File:hFile, i, string[128];
    new zahl = 1000;
    if(fexist("TestScript.txt"))
    {
    hFile = fopen("TestScript.txt", io_read);
    while(fread(hFile, string))
    {
    i++;
    if(i==zahl) format(string, sizeof(string), "Zeile %d: %s", i, string), SendClientMessage(playerid, FARBE, string);
    }
    }


    #Handy

  • Damit kann ich auf jeden Fall schon einmal was anfangen.
    Nun nur noch das Problem, die Zahl ist vorher ja nicht festgelegt.


    Sprich :
    new Zahl = 1000;


    Sondern das war ja nur ein Beispiel.
    Das ganze soll ja so gesehen mit unbekannten Zahlen & Texten laufen.


    Wie folgt:


    Client gibt ein /Befehl
    /Befehl wird ausgeführt dazu wird ausgeben in welcher Zeile /Befehl steht.
    IG über SendClientMessage.
    Weil printen tut er ja nur in der Konsole.


    Nun dazu aber auch die unbekannten Texte ...
    Bsp: /Zeile (ZID) - Die Zeilen ID (Bsp: 1000)
    Ausgeben wird folgendes Zeile (%d - in diesem Fall ->) 1000 : CMD:Befehl(playerid,params)
    Wieder per SendClientMessage.



    Allerdings kann ich dir gar nicht genug danken für deine Hilfe.
    Ich werde mich mit dem Filemanager und deinem Beispiel Code mal auseinander setzen, ob ich den Praxis Test heute noch schaffe weiß ich noch nicht.
    Aber die Theorie hab ich zumindest schon einmal ein bisschen mehr verstanden und im Kopf.


    Ansonsten hätte ich vielleicht noch eine "abstrakte" Lösung im Kopf und zwar folgende..
    Der gesuchte Text / die gesuchte Zeile (Bsp: /Zeile 1000) wird im Script gesucht und verglichen ob es mehrere Treffer gibt eher unwarscheinlich wenn man nach einer Zeile speziell sucht aber trotzdem.
    Die Zeile wird gefunden und ist auch nur einmal vorhanden (eigentlich logisch es kann ja auch nur eine Zeile 1000 geben).
    Die Zeile wird ausgelesen und der Inhalt wird dem Clienten ausgegeben.


    Nun zu einer anderen Vorstellung wegen der unbekannten Zahl und zwar das es im Script schon so geschrieben wird:
    new Zahl = %d / %i


    %i wegen einem Integer aber %d erfüllt auch den Zweck.
    Ich kenne leider nicht den vollständigen Umfang und den Bereich der Möglichkeiten von PAWN.
    Aber irgendwie muss das ganze doch dynamisch und Komfortabel zu händeln sein oder nicht.


    Vorgang:
    Der Vorgang aus dem Beispiel leuchtet mir soweit ja auch ein, nur irgendwo dazwischen muss es doch noch weitere Möglichkeiten geben dies dynamisch und Komfortabel zu gestalten.
    Das was ich im Kopf hab ist wirklich nicht einfach zu erklären, vielleicht auch gar nicht möglich.


    Orientiren wir uns mal ein wenig am Hilfesystem von (darf ich den Namen nennen? Ich tu es jetzt einfach mal) German-Roleplay.
    Dort wird wie folgt gesucht, die Datenbank erfasst Einträge sagen wir mal von 0 - 100.
    Die Einträge liegen wohl in den Scriptfiles als .txt so gehe ich jetzt einfach mal davon aus.
    Du suchst einen bestimmten Eintrag, Beispiel: /Help 50
    Der Eintrag Nummer 50 wird gesucht und ausgegeben.


    Hat vielleicht nicht ganz so viel mit meinem vorhaben zu tun ist aber vielleicht eine kleine Hilfe.


    So ähnlich soll es bei mir auch ablaufen, nur das bei mir diese "Einträge" fest im Script sind in Form von den Zeilen.
    Beispiel: "/Zeile 50"
    Zeile 50 wird gesucht & gelesen.
    Zeile 50 wurde gefunden, gelesen und wird nun ausgegeben.
    "Zeile 50: Hallo Welt, ich bin Zeile 50 im TestScript"


    So viel zur Theorie.
    Jede Antwort und Anregung ist weiterhin herzlich willkommen.



    Aber an dieser Stelle noch einmal einen großen und besonderen dank an Jeffry :love:


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

  • Bei 99.9% der Nutzer hier muss man zehn mal sagen, sie sollen doch mehr Informationen posten, du überschüttest einen mit Informationen. :thumbup:
    Wobei das natürlich eine lange Rede mit kurzem Sinn ist, du willst einen Befehl: /zeile [Nummer]


    dcmd_zeile(playerid, params[])
    {
    if(strval(params) < 1) return SendClientMessage(playerid, ROT, "Error: Ungültige Zeile");
    new File:hFile, i, string[128], found;
    new zahl = strval(params);
    if(fexist("TestScript.txt"))
    {
    hFile = fopen("TestScript.txt", io_read);
    while(fread(hFile, string))
    {
    i++;
    if(i==zahl) format(string, sizeof(string), "Zeile %d: %s", i, string), SendClientMessage(playerid, FARBE, string), found = 1;
    }
    }
    if(found != 1) return SendClientMessage(playerid, ROT, "Error: Ungültige Zeile (nicht gefunden)");
    return 1;
    }


    Das sollte passen.

  • Das Funktioniert wunderbar. =)
    Die Zeilen werden mir Ausgegeben + Inhalt.
    Bsp: /Zeile 219 -> Zeile 219: cmd:zeile(playerid,params[])


    Läuft perfekt.
    Nun nur noch das Problem, wie mache ich das wenn ich ein Befehl eingebe das mir die Zeile mit ausgegeben wird.
    Wieder Beispiel /sayhay
    SendClientMessageToAll(playerid, 0xFF0000FF, "Hallo an Alle!");
    SendClientMessage(playerid, 0xFF0000FF, "Zeile 225 : cmd:sayhay(playerid,params[])"
    ODER: SendClientMessage(playerid, 0xFF0000FF, "Du hast grade Zeile %d (225) benutzt!");



    Aber vielen vielen dank Jeffry *_*
    Es funktioniert soweit schon einmal <3
    :love:


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

  • Meep, jetzt mach ich dir ja alles, eigentlich solltest du das selbst machen. 8o
    Aber naja, das ist nichts weltbewegendes an Code, zwei Minuten.


    public OnPlayerCommandText(playerid, cmdtext[])
    {
    new eingabe[128];
    format(eingabe, sizeof(eingabe), "cmd:%s(playerid,params[])", cmdtext[1]);
    new File:hFile, i, string[128];
    if(fexist("TestScript.txt"))
    {
    hFile = fopen("TestScript.txt", io_read);
    while(fread(hFile, string))
    {
    i++;
    if(strfind(string, eingabe, true) != -1) format(string, sizeof(string), "Zeile ben. %d: %s", i, string), SendClientMessage(playerid, FARBE, string);
    }
    }
    return 0;
    }


    Ich nutze strfind, weil es ja sein kann, dass du dahinter noch einen Kommentar hast.

    3HZXdYd.png

    Einmal editiert, zuletzt von Jeffry ()

  • Danke dir Jeffry


    Jaa, stimmt. Aber ich lerne noch und ich habe auf jeden Fall was gelernt dabei, ich werde mich weiter damit auseinander setzen.
    Dir gebührt mein Dank, du hast mir ganz schön geholfen jetzt, danke dir. =)
    Danke für deine Hilfe und deine Beispiele / Grundlagen / Lösungen, ich werde mir das weiter anschauen und die einzelnen Schritte verinnerlichen. :)


    Mit allerfreundlichsten Gruß
    Marcel :)




    EDIT: Bekomme Error :error 025: function heading differs from prototype
    Zeile:
    public OnPlayerText(playerid, cmdtext[]) :D



    Re-Edit: Gelöst, OnPlayerText(playerid, text[])
    So lautet der Public eigentlich. :D
    Hab es nun in der a_samp.inc geändert zu : OnPlayerText(playerid,cmdtext[])


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

    4 Mal editiert, zuletzt von ItsFreaky | Marcel ()

  • Achso okay, dann änder ich es jetzt nochmal :D
    Danke :D



    Edit: Nun kommen wir zur Erweiterung.


    Ich möchte das mehrere Zeilen gelesen und ausgegeben werden, am besten dann in einem anklickbaren Textdraw, da ich den Code / die Zeilen IG auch bearbeiten möchte.
    Sprich: Neue Zeilen hinzufügen, vorhandene Zeilen editieren, um es auch Deutsch zu sagen, ich möchte von IG aus Scripten können.
    Beispiel: Ich stehe vor einem Hofeingang, habe mir ein IG Objecteditor geholt, stelle dort ein Tor hin, dann möchte ich mit meinem "System" IG mein Script öffnen z.B per /Script [Zeile] [Zeile], oder ich suche einen bestimmten Bereich durch mein System sagen wir mit dem Schlüsselwort "OnGamemodeInit", dann wird mir die Zeile ausgegeben in der OnGamemodeInit (Sagen wir mal 500) steht oder auch gleich per Textdraw geladen.
    Ich öffne die Zeile folgendermaßen : /Script 500 520, dann wird ein Textdraw geöffnet in der die Zeilen 500 - 520 stehen und ich sie frei editieren kann, neues hinzufügen, altes entfernen oder editieren.


    Soweit zur Theorie.


    Orientieren tu ich mich dabei am Beispiel Code von Jeffry und am Hilfesystem von GRP (/Help [Suchtext])


    Der Code der mir dabei im Kopf schwebt ist folgender, (Ich weiß nicht ob er richtig ist leider... )


    CMD:Test(playerid,params[])
    {
    new File:Text, i, string[128];
    new Zahl = strval(params);
    new Zahl1 = strval(params);
    if(fexist("Text.txt"))
    {
    Text = fopen("Text.txt", io_read);
    while(fread(Text, string))
    {
    i++;
    if(i==Zahl && i==Zahl1) format(string, sizeof(string), "Gesuchter Text in Zeile %d: %s", i, string), SendClientMessage(playerid, RED, string);
    }
    }
    return 1;
    }



    Re-Edit: Den Code habe ich getestet doch bekomme da immer nur "Unknown Command".
    Ich hab heute auch schon ein wenig rumprobiert und gesucht doch immer mit dem gleichen Ergebnis nämlich nichts.
    Entweder Unknown Command oder ich habe nichts passendes gefunden / hinbekommen.
    Ich hab es erst einmal an einem andern Befehl und neuem Text getestet doch wieder das gleiche Ergebnis.
    Ich werde mich dann mal mit Filemanager auseinander setzen ich befürchte das werde ich bei meinem Vorhaben sowieso müssen, damit es realisierbar ist.
    Ich möchte es ja möglichst dynamisch und komfortabel gestalten.


    Alle Menschen sind eins. Was sie unterscheidet, ist der Name, den man ihnen gibt.
    (Buddha)


    Uns zivilisierten Menschen ist zwar gelungen, das Raubtier in uns auszuschalten, nicht aber den Esel.
    (Winston Churchill)


    Wenn du denkst, die ganze Welt sei schlecht, dann vergisst nicht, dass Leute wie du darin leben.
    (Mahatma Gandhi)

    7 Mal editiert, zuletzt von ItsFreaky | Marcel ()

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen