AdminMod.de https://www.adminmod.de/ |
|
Timer-Schleife https://www.adminmod.de/viewtopic.php?t=3444 |
Seite 1 von 1 |
Autor: | frostschutz [ 29.06.2002, 16:39 ] |
Betreff des Beitrags: | Timer-Schleife |
Hallo, in einem Plugin verwende ich eine Timer-Schleife, die ungefähr so aussieht: Code: public mach_was() { mach_dies(); mach_das(); if(problem()) { loesung(); } say("mach_was hat dies und das gemacht"); set_timer("mach_was", 60, 1); }Die Funktion wird nur an einer Stelle einmalig von aussen aufgerufen (um die Timer-Schleife in Gang zu bringen). Im Normalfall sieht man auf dem Server 1mal pro Minute die say-Meldung. Ab und zu kommt es jedoch vor, daß die Meldung jeweils doppelt vorkommt. Das heißt, die Timer-Schleife hat sich verdoppelt, die Funktion wurde wohl ein 2. Mal von aussen aufgerufen. Daher nun die Frage: Wie verhindere ich doppelte Timer-Schleifen innerhalb der Timer-Funktion? |
Autor: | daRope [ 29.06.2002, 18:06 ] |
Betreff des Beitrags: | |
1.) Funktionen, die von einem Timer aufgerufen werden, haben eine bestimmte Signatur (Parameter). Ich weiss nicht, ob Du die jetzt nur weggelassen hast. Schau Dir das aber mal an. 2.) Zum Problem. Es sollten eigentlich *immer* zwei Aufrufe kommen. Was bei Dir passiert, ist, dass sich Timer ueberlagern. Du verwendest set_timer("ebbes", x, y). Die set_timer() funktion setzt einen Timer, der eine Funktion "ebbes" nach x Sekunden aufruft. Dieser Timer wird y-mal wiederholt. Einmal wird er auf jedenfall ausgefuehrt. Wenn Du den Timer also nur einmal setzen willst, dann schreib set_timer( "ebbes", 60, 0 ); So wie Du die Funktion geschrieben hast, macht sie allerdings nicht viel Sinn. Statt den Timer immer wieder zu setzen, kannst Du ihn auch nur einmal setzen und y-mal wiederholen lassen. Allerdings weiss ich jetzt nicht, wie Deine echte Funktion aussieht, da macht das vielleicht mehr Sinn. |
Autor: | frostschutz [ 29.06.2002, 19:35 ] |
Betreff des Beitrags: | |
Das Problem tritt nur sehr selten auf. Es kann also kein genereller Fehler sein. Es wird einfach manchmal aus einem mir unbekannten Grund die Schleife verdoppelt. Von den Parametern einer Timer-Funktion habe ich keine Ahnung, da ich nirgendwo etwas gefunden habe, wo das steht. Meine einzige Referenz ist derzeit die Functions-Übersicht auf adminmod.org/ascript, und die ist derbe uninformativ. Jemand meinte, man könnte da auch viel in den .inc's nachlesen. Gibts denn irgendwo auch eine richtige Funktionsübersicht, die in etwa so informativ ist wie die Small-Sprachdefinition? Mir geht es ja nur darum, generell verhindern zu können, dass aus der Timer-Schleife eine Doppel-Schleife entsteht. Und zwar soll dies die Timer-Funktion selbst verhindern. |
Autor: | Sir Drink a lot [ 29.06.2002, 20:18 ] |
Betreff des Beitrags: | |
Nimm doch mal als Repeat 0, so wie es daRope vorgeschlagen hat. Vielleicht ist dann das mit dem Wiederholen ja vorbei. Oder rufst du zwischendurch nochmal mach_was() auf? von mach_dies oder mach_das? Och ist das schön theoretisch... Aber eine aufgerufene Timer-Funktion hat normalerweise solches aussehen: public timer_function(Timer,Repeat,HLUser,HLParam) ich benutze so eine Timer-Schleife z.B. für das Timerem, um die Restzeit anzuzeigen, die auf der Map noch verbleibt. |
Autor: | sentinel [ 29.06.2002, 21:17 ] |
Betreff des Beitrags: | |
tschuldigung aber wozu is das gut? |
Autor: | frostschutz [ 29.06.2002, 21:53 ] |
Betreff des Beitrags: | |
Steht das auch irgendwo, was eine Timer-Funktion für Parameter hat und vor allem, was sie bedeuten? Und kann man die dazu verwenden, doppelte Timer-Schleifen abzustellen? Fragen über Fragen... |
Autor: | Sir Drink a lot [ 30.06.2002, 09:19 ] |
Betreff des Beitrags: | |
ok. ich habe auch meist von den Bedeutungen keine Ahnung. Also gehe ich hin und schreibe so ein Code wie Du ihn oben theoretisch beschrieben hast. Dann versuche ich eben mit convert_string für die HL-Daten mir klar zu machen, was da an Informationen rüberkommt. Diese Infos lasse ich mir dann mit say, selfmessage, consgreet etc. auf den Bildschirm ausgeben. Ok. Jetzt bezüglich zu einem Timer: Ob die Parameter Timer und Repeat sich ausgeben lassen, weiß ich nicht. Um den Timer-Index herauszubekommen, habe ich eine Variable timer global definiert und dann in einer Funktion die Timer-Funktion so aufgerufen: timer=set_timer("xxx",a,b,z.B. sName); Damit kann man dann wunderbar nachher kill_timer(timer) anwenden, wenn man den Timer stoppen möchte. a ist die Verzögerung, b ist die Wiederholung und sName ist ein Parameter, den man an die Timerfunktion übergibt. So kann man z.B. von der Ausgangsfunktion, durch ein vorheriges "convert_string(HLUserName,sName,MAX_NAME_LENGTH);", den String sName an die Timer Funktion übergeben und in der Timer Funktion selber wieder mit "convert_string(HLParam,sName,MAX_NAME_LENGTH);" sName wieder benutzen, um damit weiter zu arbeiten. Es ist eben darauf zu achten, das der Parameter, den man an die Timer-Funktion übergibt, in HL-Form rüberkommt und man ihn innerhalb der Timer-Funktion mit convert_string in SMALL-Form umwandeln muss. Ui..ich hoffe, das ist jetzt klar geworden. Bin doch nicht so gut im Erklären. Wahrscheinlich, um das richtig programmiertechnisch auszudrücken, muss wohl doch daRope wieder eingreifen.... Meine Erfahrung mit dem "Repeat" haben gezeigt, dass wenn man die Verzögerungszeit sehr klein und die Repeat-Anzahl sehr groß wählt, dass es dann zu Lags führen kann oder das ein Timeraufruf "vergessen" wird, da CS ja noch ein paar andere Aufgaben zu erledigen hat. @Sentinel: Du kennst ja, denke ich, das Timerem. Das funktionierte früher mit min. 10 Timern, die alle bei der Initialisierung des Plugins aufgerufen wurden. Ein Timer für 30Min,25,20,15, etc. Ich habe bei dem unten aufgeführten Beispiel einen einzigen Timer verwendet, der sich eben alle a Minuten wieder aufruft, wenn er eben "20 Minuten remaining", "15 Minuten remaining" etc. anzeigen soll. Hier mal der Code: Code: #include <core> #include <console> #include <string> #include <admin> #include <adminlib> #define ACCESS_CONSOLE 131072 new STRING_VERSION[MAX_DATA_LENGTH] = "Beta 1.0"; #define MinutesRed 255 #define MinutesGreen 0 #define MinutesBlue 0 #define SecondsRed 255 #define SecondsGreen 255 #define SecondsBlue 255 new GameCommencing=0; new checktime; new origtimelimit; new timer; new Map[MAX_NAME_LENGTH]; public timerem2_welt(HLCommand,HLData,HLUserName,UserIndex){ new Data [MAX_DATA_LENGTH]; new x [MAX_DATA_LENGTH]; new dummy[MAX_DATA_LENGTH]; convert_string( HLData, Data, MAX_DATA_LENGTH ); strsplit(Data,"_",x,MAX_DATA_LENGTH,dummy,MAX_DATA_LENGTH); if(strcmp(x,"Game")==0 && GameCommencing == 0){ GameCommencing = 1; checktime =systemtime(); origtimelimit = getvar("mp_timelimit")*60+2; kill_timer(timer); timer=set_timer("warn",1, 0); } else if(strcmp(x,"Restart")==0){ origtimelimit =getvar("mp_timelimit")*60+2; checktime = systemtime(); kill_timer(timer); timer=set_timer("warn",1,0); } else if(strcmp(x,"Round")==0){ if (getvar("mp_timelimit")*60+2 != origtimelimit){ checktime = systemtime()-(systemtime()- checktime); origtimelimit= getvar("mp_timelimit")*60+2; kill_timer(timer); timer=set_timer("warn",1,0); } } return PLUGIN_CONTINUE; } public warn(Timer,Repeat,HLUser,HLParam) { new a; new time; new Msg[MAX_TEXT_LENGTH]; if (getvar("mp_timelimit")*60+2 != origtimelimit){ checktime = systemtime()-(systemtime()- checktime); origtimelimit= getvar("mp_timelimit")*60+2; } time = (origtimelimit-(systemtime()-checktime)); switch(time){ case 1800:{ execclient_all("speak ^"fvox/thirty minutes remaining^""); centersay("30 Minuten bis zum Mapchange!",12,MinutesRed,MinutesGreen,MinutesBlue); a = 300; } case 1500:{ execclient_all("speak ^"fvox/twenty five minutes remaining^""); centersay("25 Minuten bis zum Mapchange!",12,MinutesRed,MinutesGreen,MinutesBlue); a = 300; } case 1200:{ execclient_all("speak ^"fvox/twenty minutes remaining^""); centersay("20 Minuten bis zum Mapchange!",12,MinutesRed,MinutesGreen,MinutesBlue); a = 300; } case 900:{ execclient_all("speak ^"fvox/fifteen minutes remaining^""); centersay("15 Minuten bis zum Mapchange!",12,MinutesRed,MinutesGreen,MinutesBlue); a = 300; } case 600:{ execclient_all("speak ^"fvox/ten minutes remaining^""); centersay("10 Minuten bis zum Mapchange!",12,MinutesRed,MinutesGreen,MinutesBlue); a = 300; } case 300:{ execclient_all("speak ^"fvox/five minutes remaining^""); centersay("5 Minuten bis zum Mapchange!",12,MinutesRed,MinutesGreen,MinutesBlue); a = 180; } case 120:{ execclient_all("speak ^"fvox/two minutes remaining^""); centersay("2 Minuten bis zum Mapchange!",12,MinutesRed,MinutesGreen,MinutesBlue); a = 60; } case 60:{ execclient_all("speak ^"fvox/sixty seconds remaining^""); centersay("60 Sekunden bis zum Mapchange!",12,SecondsRed,SecondsGreen,SecondsBlue); a = 30; } case 30:{ execclient_all("speak ^"fvox/thirty seconds remaining^""); centersay("30 Sekunden bis zum Mapchange!",12,SecondsRed,SecondsGreen,SecondsBlue); a = 20; } case 10:{ execclient_all("speak ^"fvox/ten^""); centersay("TEN!",12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 9:{ execclient_all("speak ^"fvox/nine^""); centersay("NINE!",12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 8:{ execclient_all("speak ^"fvox/eight^""); centersay("EIGHT!",12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 7:{ execclient_all("speak ^"fvox/seven^""); centersay("SEVEN!",12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 6:{ execclient_all("speak ^"fvox/six^""); centersay("SIX!",12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; nextmap( Map, MAX_NAME_LENGTH ); } case 5:{ execclient_all("speak ^"fvox/five^""); snprintf(Msg,MAX_TEXT_LENGTH,"FIVE! ^nNext Map:%s",Map); centersay(Msg,12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 4:{ execclient_all("speak ^"fvox/four^""); snprintf(Msg,MAX_TEXT_LENGTH,"FOUR! ^nNext Map:%s",Map); centersay(Msg,12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 3:{ execclient_all("speak ^"fvox/three^""); snprintf(Msg,MAX_TEXT_LENGTH,"THREE! ^nNext Map:%s",Map); centersay(Msg,12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 2:{ execclient_all("speak ^"fvox/two^""); snprintf(Msg,MAX_TEXT_LENGTH,"TWO! ^nNext Map:%s",Map); centersay(Msg,12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 1:{ execclient_all("speak ^"fvox/one^""); snprintf(Msg,MAX_TEXT_LENGTH,"ONE! ^nNext Map:%s",Map); centersay(Msg,12,SecondsRed,SecondsGreen,SecondsBlue); a = 1; } case 0:{ execclient_all("speak ^"have a nice day^""); snprintf(Msg,MAX_TEXT_LENGTH,"Game Over!^nChanging Map to:%s",Map); centersay(Msg,12,SecondsRed,SecondsGreen,SecondsBlue); say(Msg); changelevel(Map,5); } default:{ if(time>1800){ a = time-1800; }else if(time<1800 && time>1500){ a = time - 1500; }else if(time<1500 && time>1200){ a = time - 1200; }else if(time<1200 && time>900){ a = time - 900; }else if(time<900 && time>600){ a = time - 600; }else if(time<600 && time>300){ a = time - 300; }else if(time<300 && time>120){ a = time - 120; }else if(time<120 && time>60){ a = time - 60; }else if(time<60 && time>30){ a = time - 30; }else{ a=1; } } } execclient_all("timeleft");/*Debug-Funktion, um zu sehen, ob das Announcing stimmt*/ /* new Msg[MAX_TEXT_LENGTH]; snprintf(Msg,MAX_TEXT_LENGTH,"Naechste Timer in %i Sekunden",a); say(Msg); */ timer=set_timer("warn",a, 0); return PLUGIN_CONTINUE; } public plugin_init(){ plugin_registerinfo("Ein Timeremember auf LogD-Basis","",STRING_VERSION); plugin_registercmd("timerem2_welt", "timerem2_welt", ACCESS_CONSOLE); exec("logd_reg 62 admin_command timerem2_welt"); checktime =systemtime(); origtimelimit = getvar("mp_timelimit")*60+2; timer=set_timer("warn",1, 0); return PLUGIN_CONTINUE; }P.S.: So ein Mist...ich muss mal UltraEdit richtig einstellen, damit es nicht zu den vielen loose Identations kommt... Sorry!!! |
Autor: | frostschutz [ 30.06.2002, 11:05 ] |
Betreff des Beitrags: | |
Danke vielmals. Die von dir gelieferten Informationen reichen für meine Zwecke völlig aus. kill_timer kannte ich bisher gar nicht - die Funktion steht in der Funktionsliste der AScript-Seite nicht drin. Diese Timer-Sache verstärkt jedoch mal wieder meinen traurigen Eindruck, daß die ganze Adminmod-Geschichte extrem schlecht dokumentiert ist... wenn selbst die langerfahrenen Scripter wie SDal raten müssen, welcher Parameter was macht *grusel* |
Autor: | Sir Drink a lot [ 30.06.2002, 16:35 ] |
Betreff des Beitrags: | |
naja...."langerfahren" ist übertrieben auch fehlt mir eben enorm viel Basis-Wissen, darum fange ich immer klein an und baue dann darauf auf. |
Autor: | daRope [ 30.06.2002, 19:01 ] |
Betreff des Beitrags: | |
Manchmal weiss ich nicht, ob wir ein Talent haben aneinander vorbeizureden, oder ob Du mich veraeppeln willst. ?-) Es ist logisch, dass bei Dir die Funktion zweimal aufgerufen wird, wenn man sich das mal verdeutlicht, wie die Timer gesetzt und aufgerufen werden. Code: 0-------60-------120-------180-------240-------300 1 + * * 2 | + * * 3 | | + * * etc.pp. 4 | | | + * 5 | | | | + | | | | | | | | | |>Timer 3 wird wiederholt und geloescht,Timer 4wird ausgefuehrt,Timer 5 wird gesetzt | | | | | | | |>Timer 2 wird wieder holt und geloescht, Timer 3 wird ausgefuehrt, Timer 4 wird gesetzt. | | | | | |>Timer 1 wird wiederholt und geloescht, Timer 2 wird ausgefuehrt, Timer 3 wird gesetzt. | | | |>Timer 1 wird ausgefuehrt, Timer 2 wird gesetzt. | |>Timer 1 wird gesetztAb dem dritten Interval werden also immer zwei Timer ausgefuehrt, die sich moeglichweise jetzt gegeseitig auf die Fuesse treten. Was die Dokumentation angeht, so ist man leider darauf angeweisen, sich an die Sourcen der Beispielplugins zu halten. |
Autor: | Warhead [ 30.06.2002, 20:38 ] |
Betreff des Beitrags: | |
... bzw. sollte man mal in den Includes nachschauen, damit man nicht wieder von einer neuen Funktion "überrascht" wird. |
Autor: | frostschutz [ 01.07.2002, 00:08 ] |
Betreff des Beitrags: | |
Ich will dich nicht veräppeln, es ist nur so, daß der Effekt der Doppelten Timer-Schleife nur sehr, sehr selten auftritt! D.h. die Schleife kann mal 90 Minuten laufen ohne den Effekt und plötzlich irgendwann kommt das (aus mir nicht bekannten Gründen) dazu. Wenn es so wäre wie du schreibst, wäre der Effekt ja ständig bemerkbar, insofern kann da ja was nicht ganz stimmen. Ich bezweifle also, daß ein Timer mit dem Repeatcount von 1 mehr als 1mal aufgerufen wird. Der lange Lauf der Timer-Schleife ohne den Verdopplungseffekt sollte das ausreichend zeigen. Ich gehe davon aus, daß bei repeatcount 0 (== parameter nicht angegeben) das auf 1 gesetzt wird. Ich habe es auch geändert und der Effekt tritt immer noch auf. -> Habe das ganze nun mit globaler Timer-Variable unterbunden. Bessere Vorschläge (die ohne globale Variable auskommen) willkommen. // Edit Ich habe etwa das gleiche weiter oben auch schon geantwortet, direkt auf dein Posting: Zitat:
Das Problem tritt nur sehr selten auf. Es kann also kein genereller Fehler sein. Es wird einfach manchmal aus einem mir unbekannten Grund die Schleife verdoppelt.
|
Autor: | Warhead [ 01.07.2002, 01:31 ] |
Betreff des Beitrags: | |
Deinem Code zufolge soll der Timer mach_was() alle 60 Sekunden ausgeführt werden. Warum startest Du den nicht von "außen" mit 99999 als Repeatcount? |
Autor: | frostschutz [ 01.07.2002, 08:30 ] |
Betreff des Beitrags: | |
99999 ist eine endliche Zahl. Ich möchte, daß der Timer unendlich lange weiterläuft. (Mir ist bewußt, daß diese Begründung etwas realitätsfern ist, da niemand 99999 Minuten lang einem Plugin zuschauen wird). Davon abgesehen hätte es das Problem nicht gelöst. Die Timer-Funktion wird ausschließlich von Timern aufgerufen. Daß sie sich verdoppelt, heißt, daß ein neuer Timer gestartet wurde während ein alter noch lief (unerwarteter Aufruf von plugin_init). Desweiteren wollte ich mir die Möglichkeit offen halten, den Timer jederzeit beenden zu können. Von der Existenz der Funktion kill_timer habe ich erst in diesem Thread erfahren, die Funktion ist nicht in der Funktionsliste von Adminmod.org enthalten und RTFS zählt nicht zu meinen Lieblingsbeschäftigungen. |
Autor: | [WING] Black Knight [ 01.07.2002, 09:11 ] |
Betreff des Beitrags: | |
99999 wird von AdminMod als unendlich interpretiert. Der Timer läuft also auch unendlich lang. Aber selbst wenn dies nicht der Fall gewesen wäre, hätte der Timer mindestens eine Laufzeit von über einem Tag gehabt. Und wer lässt schon eine Map den ganzen Tag ohne Wechsel bzw. gelegentlichen Reload laufen. |
Autor: | daRope [ 01.07.2002, 12:05 ] |
Betreff des Beitrags: | |
Eigentlich wollte ich Dir jetzt meinen XEmacs um die Ohren hauen. Aber bei der Gelegenheit habe ich festgestellt, dass Du recht hast. In AM 2.10 war es so, dass ein Repeatcount von 1 wirklich eine Wiederholung also zwei Ausfuehrungen bedeutete. Seit 2.50 ist es wohl so, dass der Repeatcount die Gesamtzahl der Ausfuehrungen angibt. Code: v2.10 if(timers[iTimer].repeats <= 0) { vs. v25.0 if(timers[iTimer].iRepeatCount <= 1 || iForceDelete) {Mea culpa. Trotzdem ist es so, dass zu einem Zeitpunkt immer nur genau ein Timer feuern kann. Wenn Du wissen willst, was in Deinem AM abgeht, solltest Du mal admin_debug anstellen. Dann schreibt er Dir ins Log, wenn ein Timer erzeugt, ausgefuehrt und geloescht wird. |
Autor: | frostschutz [ 01.07.2002, 12:42 ] |
Betreff des Beitrags: | |
Zitat: 99999 wird von AdminMod als unendlich interpretiert. Der Timer läuft also auch unendlich lang.
Ja doch. Ich schrieb ja, daß die Begründung etwas realitätsfern ist. Es war ja nur einer von drei angeführten Gründen.Davon, 99999 als unendlich zu interpretieren, halte ich persönlich nichts. Eine Service-Funktion hat nicht das Recht, übergebene Parameter auf diese Weise zu interpretieren. Sie schränkt damit sich selbst und den Programmierer nur unnötig ein. -> Unendlich viele Wiederholungen kann der Programmierer auch so erreichen. -> Dem Programmierer wird durch Interpretation jedoch die Möglichkeit genommen, 99999 echte Wiederholungen anzugeben. Just my 2 cents @daRope XEmacs, gute Wahl Daß das Verhalten früher so war, wie du beschrieben hast, wußte ich nicht - ich bin ja erst seit kurzem dabei. Derartige Umstellungen in der Funktionalität sind ärgerlich und führen zu solchen Fehlern. |
Autor: | [WING] Black Knight [ 01.07.2002, 13:34 ] |
Betreff des Beitrags: | |
OK, das Argument sticht natürlich. Kannst ja den Antrag stellen, den Wert von 99999 auf -1 zu ändern. Das wird vermutlich wie die Sache mit AuthID zu verstärktem Newbieärger sorgen, weil diverse Plugins nicht mehr funktionieren. Aber es würde der allgemein verwendeten Logik entsprechen. Andererseits habe ich ja schon angesprochen, dass die Wahrscheinlichkeit von einer Straßenbahn im fünften Stock überfahren zu werden wesentlich höher ist als die Wahrscheinlichkeit, dass ein Programmierer genau 99999 mal einen Timer aufrufen möchte. Diese Größe ist halt gleichbedeutend mit unendlich bezogen auf die allgemeine Spielweise von HL, CS & Co. Ich weiß, dass dieses Verständnis nichts für einen Mathematiker oder Informatiker ist, aber als Ingenieur passt das in erster Näherung. Und so programmiere ich halt auch. |
Autor: | daRope [ 01.07.2002, 21:35 ] |
Betreff des Beitrags: | |
Das ist eine Frage der Verhaeltnisse. Es gibt auf dem Computer keine Darstellung fuer Unendlich. Also muss man etwas anderes nehmen. Wenn man jetzt -1 nimmt, dann ist das je nach Datentyp dasselbe wie 255 oder 4294967295. Jetzt kann man wieder kommen und sagen "was ist wenn jemand aber genau 4294967295 Wiederholungen haben will". Das ist doch ein rein akademisches Problem. 99999 ist sicherlich nicht sonderlich elegant geloest, aber es tut was es soll. |
Seite 1 von 1 | Alle Zeiten sind UTC+01:00 |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |