AdminMod.de https://www.adminmod.de/ |
|
Seltsames Script-Problem https://www.adminmod.de/viewtopic.php?t=3318 |
Seite 1 von 1 |
Autor: | frostschutz [ 12.06.2002, 16:25 ] |
Betreff des Beitrags: | Seltsames Script-Problem |
Hi, ich hab gestern mal den Versuch angefangen, ein Adminmod-Plugin zu schreiben. Ich hab das noch nie vorher gemacht, aber habe Erfahrung mit C und anderen C-ähnlichen Sprachen, weshalb ich dachte daß das mit Small nicht so das Problem wird. Bei dem Plugin handelt es sich um eine Art Mapvote, bei dem jeder Spieler per vote eine Map "vorschlagen" können soll, und am Ende aus den vorgeschlagenen Maps zufällig eine gewählt wird - wobei die Wahrscheinlichkeit für eine Map steigt, wenn sie von mehreren Leuten vorgeschlagen wird. Ich hab nur jetzt folgendes Problem: --- code snippet --- random_map_choose() { new possible[MAX_VOTERS][MAX_NAME_LENGTH]; new count, i; say("] DEBUG: random_map_choose"); [... rest der funktion gesnipt ...] } public end_vote() { new text[MAX_TEXT_LENGTH]; say("] DEBUG: end_vote"); vote_active = false; random_map_choose(); say("] FAIR vote is now over."); [... rest der funktion gesnipt ... } ------------ Was passiert: end_vote wird aufgerufen, ich bekomme die Message "] DEBUG: end_vote". Danach wird vote_active auf false gesetzt (das ist eine globale Variable, die hat danach auch diesen Wert). Ich bekomme aber keine weiteren Messages! Ich erwarte an dieser Stelle, daß - random_map_choose aufgerufen wird - ich die message "] DEBUG: random_map_choose" sehe. - end_vote weitermacht und ich die Meldung "vote now over" bla bekomme. Das alles passiert aber nicht. Die ausführung wird da einfach abgebrochen, ich habe keine Ahnung warum. Der Code compiliert ohne Fehlermeldung. Kompletter Code ist bei: http://www.metamorpher.de/tfc/plugin_fair_vote.sma zu finden. Jemand nen Tipp was ich falsch gemacht hab? |
Autor: | frostschutz [ 12.06.2002, 16:47 ] |
Betreff des Beitrags: | |
ich hab jetzt in #adminmod.de den tipp bekommen, daß es sich um einen compilerfehler von small bei bool-variablen handeln könnte. ich hatte noch keine zeit das zu testen, könnt ihr trotzdem mal drüberfliegen und schauen ob ihr einen fehler in dem teil findet, den ich übersehen habe? fehler in anderen teilen des programms sind mir nicht so wichtig, das vote klappt noch nicht ganz so, ich will nur daß jetzt überhaupt mal diese funktion aufgerufen wird ( |
Autor: | frostschutz [ 12.06.2002, 18:07 ] |
Betreff des Beitrags: | |
Hm. An den bool Variablen liegt es nicht. Ich bin ratlos! Schnüff. Hat denn keiner einen Tipp? |
Autor: | Warhead [ 12.06.2002, 18:50 ] |
Betreff des Beitrags: | |
Unter Umständen ist das Array "possible" zu groß definiert, versuch es mal als globale Variable oder nimm eine kleinere Dimension. |
Autor: | frostschutz [ 12.06.2002, 19:21 ] |
Betreff des Beitrags: | |
Hm, das kapier ich nicht. Ich hab das jetzt gemacht, also aus [MAX_VOTERS][MAX_NAME_LENGTH] nur ein [MAX_VOTERS] gemacht, und speichere in dem Array jetzt nru die indices (ist eh besser so). Jetzt klappt es auch, super, danke! Nur verstehen tu ichs nicht! Ich bin zugegebenermassen eher Theoretiker als praktischer Programmierer, ich habe mir die Small-Dokumentation durchgelesen, auf Adminmod.org die Admin-Mod Befehle durchgelesen, und das echte hlds mapvote plugin als Beispiel angeschaut. Von der Basis ausgehend hab ich dann das Script geschrieben. Ich hab nirgends was davon gelesen, daß lokale Variablen nicht so groß sein dürfen wie globale. Das macht keinen Sinn... gibts da ne logische Erklärung für? |
Autor: | Sir Drink a lot [ 13.06.2002, 10:39 ] |
Betreff des Beitrags: | |
Äh..wie....Das eine ist ein 2 Dimensionaler Array und das andere nur ein einfacher... Das sind doch hier 2 "ganz verschiedene Sachen". Im hldsdl-mapvote wird mit der VoteAnzahl noch der dazugehörige Mapname in MAX_NAME_LENGTH gespeichert. Ich schau mir die komplette SMA jetzt mal an Das die globalen größer und die lokalen nur kleiner sein sollen, halte ich für nicht logisch... ABER, es kann zu einem Stack-Error kommen, wenn eine Funktion zu viele Lokale Arrays hat mit einer überdimensionierten Größe. |
Autor: | frostschutz [ 13.06.2002, 12:00 ] |
Betreff des Beitrags: | |
Ich hatte ne globale Variable maps[MAX_VOTERS][MAX_NAME_LENGTH], wobei MAX_VOTERS 64 oder so ist. In der Funktion hatte ich ne lokale Variable possible[MAX_VOTERS][MAX_NAME_LENGTH], also genauso deklariert... und eben das war wohl zu viel? Wenn das schon zu groß ist, hätte ich an der Stelle dann eigentlich ein Compiler Warning erwartet... oder sonst irgendwo ein Hinweis, wie kommt man darauf dass das zu gross sein könnte, ich hab nirgendwo gelesen daß es da eine Begrenzung gibt. Aber gut, jetzt habe ich possible[MAX_VOTERS] und speichere darin nur die Indices auf das funktionierende maps-Array. Das ist eh speicherfreundlicher so (obwohl das in einer Funktion die nur einmal alle 30 Minuten aufgerufen wird ziemlich egal sein sollte...). Gibt es einen Weg, wenn solche Fatal Errors auftreten, die irgendwo zu sehen? Denn bei mir wurde einfach die Ausführung abgebrochen, Warnings oder so sieht man ja im Half-Life nicht. Gibts ein Logfile o.ä. wo sowas vermerkt wird, damit ich beim nächsten Problem dieser Art erstmal selbst nachschauen kann und nicht mehr raten muß? |
Autor: | Sir Drink a lot [ 13.06.2002, 12:14 ] |
Betreff des Beitrags: | |
ich schaue es mir gerade an... also... was ich feststellen musste war, dass Du Dir übergabe des Indizes nochmal genauer überlegen solltest. Du hast in der Funktion map_vote dann (Player[],index und map[]) verwendet. index ist aber eine Funktion in der string.inc...würde ich nicht nehmen. Ich habe es in iIndex geändert.(Ich hoffe, dass diese Änderung jetzt nicht durch mein Highlighting-System passiert ist...) Du gibst in den Funktionen auch nie etwas zurück...ich weiss nicht, ob das in manchen Fällen vielleicht sinnvoll wäre, z.B. ein return PLUGIN_CONTINUE zu machen. das Vorgehen in der for schleife im random_map_chose würde ich mir nochmal überlegen...ich würde lieber hochzählen lassen...i=1;i<=MAX_VOTERS;i++... auf jedenfall würde ich mir das zusammenrechnen, was jetzt am meisten Votes bekommen hat, überlegen... Ich kontrolliere aber weiter...es sind so ein paar Sachen, die ich noch nicht ganz verstehe... Es kamen bei mir auch nie Meldungen, ob ein Vote begonnen hat. |
Autor: | Sir Drink a lot [ 13.06.2002, 12:16 ] |
Betreff des Beitrags: | |
du kannst ja mal admin_debug auf 2 stellen und log on, mp_logdetail 3 in die server.cfg schreiben.. Wie es der Zufall will, arbeite ich nämlich auch gerade an einer zuverlässigen Maprestzeit-Anzeige mit integriertem Mapvote-System... Man braucht aber LogD dafür. Ich habe es mir einfacher gemacht und das komplette hldsld plugin verwendet...mit einer kleinen Anzeige, welche map gerade gewinnt. Leider funktioniert es noch nicht 100%. http://board.battlenation.de/files/282_1023967825.zip |
Autor: | frostschutz [ 13.06.2002, 13:08 ] |
Betreff des Beitrags: | |
Also erstmal, ich habe das .sma neu hochgeladen, damit ihr den aktuellen Stand (es ist jetzt soweit funktionsfähig) einsehen könnt. -> http://www.metamorpher.de/tfc/plugin_fair_vote.sma Das mit den Indizes, daß da die Variable index heißt, ist wohl ne Stilfrage. Genauso das mit der for-schleife. Ich gehe eben einfach davon aus, daß der Compiler Variablennamen und Funktionsnamen voneinander unterscheiden kann (was er ja auch tut, sonst würde es ja nicht funktionieren). Davon abgesehen wußte ich nicht, daß es eine Funktion namens index gibt. Bei der For-Schleife ist der Rückwärtsdurchlauf zumindest in meinem C-derivat schneller, da dort die Laufvariable i nur einmal pro durchgang ausgelesen werden muss. Incrementierung und Schleifenbedingung sind so kombiniert. Und es braucht keine <=> Operatoren, da die Schleife beim Wert 0 aussteigt. Da das hier aber wohl kaum großen Einfluss hat, ist das wohl auch ne Stilfrage. Wegen dem Zusammenrechnen der Votes, ich glaube da hast du was falsch verstanden. Bei meinem Vote ist ein Vote eigentlich nur ein Vorschlag. Am Ende wird einfach aus allen Vorschlägen einer ausgewählt per Zufall. D.h. es gewinnt nicht zwingend die Map mit den meisten Votes. Es ist nur wahrscheinlicher, daß eine bestimmte Map drankommt, je mehr Votes die eben bekommen hat. Wo gibt es eigentlich eine Admin-Mod spezifische Scripting-Dokumentation, wo so Sachen wie PLUGIN_CONTINUE etc. beschrieben sind? Ich dachte bisher, daß diese Returncodes nur in Funktionen, die Plugin-Kommandos zugeordnet sind, einen Einfluß haben (nämlich, daß der Befehl bei PLUGIN_CONTINUE auch noch in anderen Plugins angefragt wird, und bei PLUGIN_HANDLED eben keine weiteren Plugins mehr benachrichtigt werden). Ich habe an Admin-Mod Dokumentation bisher nur die Funktionsliste auf adminmod.org gesehen... da fehlt mir wohl noch was. Vielen Dank für den Tipp mit dem admin_debug, das werde ich beim nächsten Problem gleich mal ausprobieren. Im Moment grüble ich, wie ich im Plugin wohl am besten mitbekommen kann, wenn sich die mp_timelimit Variable auf dem Server ändert. Ähnlich wie die say-Überlagerung ein mp_timelimit Kommando definieren? Eine Timer-Schleife? Ein Controller/Notify/Forbidden System scheint es nicht zu geben... |
Autor: | Warhead [ 13.06.2002, 13:43 ] |
Betreff des Beitrags: | |
Bezüglich des Stacküberlaufs bei zu großen Variablen: der Compiler kann keine Warnung aussprechen, da er garnicht weiß wie groß der Stack zu diesem Zeitpunkt sein wird. Weitere Funktionen findest Du in den Includes, teilweise sogar dokumentiert. Für die Änderung von Servervariablen gibts keine Events, daß geht dann in der Tat nur über Timer oder periodisch auftretende Ereignisse (Logd bietet da viele Events gratis an ) |
Autor: | Sir Drink a lot [ 13.06.2002, 19:19 ] |
Betreff des Beitrags: | |
ah..da habe ich wohl noch wirklich was mit dem Plugin nicht verstanden gehabt. Mit der Notwendigkeit von return Angaben bin ich mir auch immer noch nicht so sicher. Ich kämpfe jedesmal damit. Mit den Stilfragen scheinst Du recht zu haben...Die Idee einer "negierten Schleife" habe bisher noch nie in den Plugins gesehen. Darum dachte ich, dass da ein Fehler liegen kann. Hast Du mal mein Plugin angesehen, was ich gelinkt habe. Da habe ich wirklich versucht, mit einer Timer-Funktion und dem LogD-Event "World Action" immer abzufragen, ob sich was an der mp_timelimit ändert. Damals in meinem ersten logd_timerem habe ich einen Sekunden-Endloss-Repeat Timer verwendet, der aber manchmal den Server doch gewaltig zum laggen brachte. Leider ist der LogD-Event zur Änderung von CVars dormant. |
Autor: | daRope [ 13.06.2002, 23:08 ] |
Betreff des Beitrags: | |
"Negierte" Schleife... jetzt muss ich doch mal nachkucken gehen, was da los ist. Aha. Code: for(i = MAX_VOTERS; i--; ) { if(strcmp(maps[i], "") != 0) { possible[count] = i; count++; } }Dass man eine for-Schleife runterzaehlen laesst, ist durchaus gebraeuchlich, wenn man dabei etwas effizienteren Code schreiben kann. Diese hier ist trotzdem nicht der beste "Stil", weil man dabei nicht die "Lesbarkeit" opfern sollte. Sowas hier ist genauso effizient und entspricht trotzdem einem gewohnten Muster: Code: for ( i = MAX_VOTERS-1; i, --i )Beide verlassen sich jedoch auf zugesicherte Eigenschaften von MAX_VOTERS. Wenn man sich allerdings Gedanken um Effizienz macht, dass verstehe ich nicht, warum man zwei Zeilen weiter unten solche Killer bringt Code: if(strcmp(maps[i], "") != 0)statt einem simplen Code: if ( maps[i][0] == '^0' )Und fuer Variablen (und seien sie auch automatic) und Funktionen die gleichen Namen zu verwenden, ist in meinen Augen schlechter Stil. Sich bei sowas auf Eigenschaften eines Compilers zu verlassen ist nicht sonderlich portabel. |
Autor: | frostschutz [ 13.06.2002, 23:32 ] |
Betreff des Beitrags: | |
Zu den Variablen/Funktionsnamen. Es ist vielleicht schlechter Stil das gleich zu nennen (über Stil kann man ewig streiten... lassen wirs), aber deine Begründung, es wäre nicht portabel da ich mich auf eine Eigenschaft des Compilers verlasse, ist eigentlich falsch. Jeder Programmierer verläßt sich auf die Eigenschaft eines Compilers, nämlich die Sprache in der Form wie sie definiert ist, übersetzen zu können. Und in der Sprachdefinition steht nirgends drin, daß es verboten ist, Funktionen und Variablen den gleichen Namen zu geben. Also muß jeder Compiler damit klarkommen, basta Das mit dem strcmp liegt einfach an meinen begrenzten Small-Kenntnissen. Schließlich hab ich erst vorgestern damit angefangen. Dafür bin ich jetzt schon ziemlich weit, finde ich. In LPC (C-derivat in dem ich normalerweise programmiere) könnte ich if(maps == "") schreiben... ich bin wie gesagt eher Theoretiker und hab daher keine Ahnung von der Komplexität der Funktion, die diesen Stringvergleich vornimmt... Wenn ich in einer Programmiersprache "vergleiche string1 und string2" schreibe, erwarte ich einfach, daß dieses Problem bereits effizient gelöst wurde... sich für solche trivialen Probleme schnellere Lösungen selber überlegen zu müssen, dauert mir zu lange -> Schaut doch mal in meinen anderen Thread, da könnte ich noch Hilfe gebrauchen... |
Autor: | Sir Drink a lot [ 14.06.2002, 01:35 ] |
Betreff des Beitrags: | |
jetzt bin ich aber auch verwirrt...warum ist strcmp nicht effizient? Ok. Ich gehöre ja auch zu den Copy und Paste "Programmierern". Aber ich dachte schon, dass es effektiv sei, eben die Funktionen zu nutzen, die in den includes vorhanden sind. *total verwirrt nun bin* NACHTRAG: Ok.Ok..ich habe Deine simplen Vergleich nicht verstanden...gebe ich offen zu... |
Autor: | Warhead [ 14.06.2002, 11:36 ] |
Betreff des Beitrags: | |
Ein String wird immer mit einer terminierenden Null abgeschlossen, wenn also an der ersten Position des Strings eine Null steht, dann ist der String leer, also "". Unabhängig davon wie gut die strcmp-Funktion programmiert ist, erzeugt der Aufruf einer Funktion Stackoperationen. In diesem Fall werden die Adressen der zu vergleichenden Strings, sowie Rücksprungadressen und die Adresse fürs Resultat gespeichert (das ist sicherlich das Minimum an Stackoperationen). Danach wird die Funktion ausgeführt. In diesem Falle kommt die strcmp-Funktion auch sicherlich sofort zum Ende, jedoch erfolgen dann wieder Stackoperationen (Resultat speichern, Rücksprungadresse rausholen etc, Rücksprung in den Code). Und da ist ein schneller Byte-Vergleich effizienter. |
Autor: | daRope [ 14.06.2002, 13:23 ] |
Betreff des Beitrags: | |
Zitat: Jeder Programmierer verläßt sich auf die Eigenschaft eines Compilers, nämlich die Sprache in der Form wie sie definiert ist, übersetzen zu können. Und in der Sprachdefinition steht nirgends drin, daß es verboten ist, Funktionen und Variablen den gleichen Namen zu geben. Also muß jeder Compiler damit klarkommen, basta
Fuer die Sprache Small mag das stimmen, da ist Portabilitaet auch kein wesentlicher Aspekt. Trotzdem ist es eine schlechte Idee. Es gab mal einen Bug im AM Code, der aus einer nicht unahnlichen Situation resultierte. Aus dem Gedaechtnis in etwa so:Code: int Time; /* blah blah */ somevar = time;Das hat der Compiler nicht angemeckert. Dabei handelte es sich nur um einen Tippfehler. Die Auswirkung war aber, dass in somevar nicht der Inhalt von Time stand, sondern die Adresse der Funktion time(). Zitat: Das mit dem strcmp liegt einfach an meinen begrenzten Small-Kenntnissen. Schließlich hab ich erst vorgestern damit angefangen.
Zitat: Wenn ich in einer Programmiersprache "vergleiche string1 und string2" schreibe, erwarte ich einfach, daß dieses Problem bereits effizient gelöst wurde...
Ich war irgendwie davon ausgegangen, dass Du schon laenger programmierst und daher etwas Ahnung von C hast. Das Schleifenkonstrukt und Deine Ausage, aus der C Ecke zu kommen, legte dieses Nahe.Daher wunderte es mich halt schon, dass Du auf der einen Seite versuchst, effiziente Schleifen zu schreiben und auf der anderen Seite wesentlich mehr Zeit mit Funktionsaufrufen verplemperst. Die Erklaerung, dass ein Funktionsaufruf immer mehr Zeit kosten wird als ein einfacher Variablenvergleich, hat Warhead ja schon geliefert. |
Autor: | frostschutz [ 14.06.2002, 13:40 ] |
Betreff des Beitrags: | |
[edited 14.06.02 17:00] Ich programmiere auch schon länger und auch in C und daß ein Funktionsaufruf mehr Zeit braucht als der ==-Operator ist klar. Ich bin halt kein Programmierer. Ich schreibe normalerweise keinen Code, sondern entwickle Problemlösungen, Algorithmen, und weise die Effizienz selbiger nach bzw. berechne deren Komplexität. Und das größtenteils ganz altmodisch auf Papier. Theorie halt. Wie so ein Algorithmus dann am besten in einer bestimmten Sprache umzusetzen ist, ist dann Sache des Programmierers, das kann der viel besser als ich... -- Nachtrag -- Meinen anderen Thread (Mapchange abfangen) habe ich gelöscht. Die Sache wurde mir zu unsauber. Ich löse das Problem jetzt, indem ich es nicht löse sondern ignoriere... Ich möchte mich hier nochmal bei allen bedanken, die mir bei der Lösung meines Script-Problems geholfen haben! Ohne den Tipp mit dem zu grossen lokalen Array säße ich heute noch an dem Problem. Nette hilfreiche Leute hier. Danke! Ich sehe damit den Thread für meinen Teil für beendet an. |
Seite 1 von 1 | Alle Zeiten sind UTC+01:00 |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |