[C] Problem bei einem Eggdrop Modul - Function nach x Sekunden

Gargoyle

Grünschnabel
Hallo zusammen

Ich bin ein C Anfänger und hab mir die schier unmögliche Aufgabe gemacht ein TCL Script
in ein Modul umzuschreiben. Ich bin eigentlich schon recht weit, nur mit dem "Timer" habe
ich meine liebe Mühe.

Ich möchte innerhalb einer Function einen Befehl erst nach einer gewissen Anzahl
Sekunden ausführen, der anschliessende Code der Function soll aber normal durchlaufen
da sonst der Bot blockiert wird.

In TCL ist das so gelöst:
Code:
utimer <zeit in sekunden> <befehl der ausgeführt werden soll>

In meinem bisherigen C Code hab ich das mit sleep(int time); gelöst.
Ist aber richtig blöd da der Bot dann die Zeit lang einfriert .. und da die Zeit da
eigentlich eine Minute betragen soll kann ich das so nicht brauchen.

Hat jemand eine Idee ?
 
Glaub dann wiste mit C nicht weiterkommen wenn ich mich recht erinnere brauchste dann die Eventloop und einen Timer aus C++. (Zumindest würde ich das so machen.)

Zu dem Thema findeste hier und im MFC Teil des Forums ne ganze Menge, einfach mal suchen ;)

Gruss

MFC OpenGL
 
moin


Du könntest nen Thread "anlegen", in dem eine Schleife läuft, in der nach bestimmten Unterbrechungen immer etwas ausgeführt wird.


mfg
umbrasaxum
 
Danke für die Inputs.
Leider helfen die mir im Moment nicht weiter.

Ich gebe noch einen Input zu der Funktion die ich machen will:

Es geht um eine Art "Russisch Roulette" im IRC.

über einen Befehl (.roulette) im Channel kann man quasi die "Waffe abfeuern"
Entweder es gibt einen CLICK oder ein BANG.
Beim CLICK passiert nichts weiter, beim BANG wird der entsprechende user gebannt und gekickt.

Ich brauche diese Timer Funktion um diesen Ban nach einer gewissen Zeit wieder
aufzuheben und den User zu benachrichtigen dass er jetzt wieder joinen kann.

Das mit dem Thread der einfach ständig im Hintergrund läuft und alle X Sekunden prüft ob
einer entbannt werden muss ist zwar gut, aber dann werden die Leute unregelmässig lange
gebannt und das wiederum ist etwas unfair.

Man müsste das utimer vom TCL doch irgendwie in C abbilden können ohne dass der Bot mit allem wartet bis die Zeit abgelaufen ist?
 
Ich hab zwar keine Ahnung wie ich das machen soll ... aber ich werd mich mal in diese Richtung weiter informieren! Danke
 
moin


Guck mal in mein Tutorial in meiner Signatur. Da hab ich nen Thread verwendet um Nachrichten von nem IRC-Server zu holen.
Da hab ich auch ne Unterbrechung eingefügt, man müsste also nur noch die unterbrechungen mitzählen und mal der Länger der unterbrechung rechnen, so könnte mand as alles realisieren.


mfg
umbrasaxum
 
Ich habe es nun geschafft.

Beim Eggdrop kann man in verschiedenen Intervallen Funktionen ausführen lassen (sekunden-, minuten-, stunden- und wochenintervalle).

Hab's jetzt so gelöst:
Code:
typedef struct {
  char nick[40];
  char host[200];
  char channel[200];
  int timeleft;
} timerstruct;

typedef timerstruct runban[1000];

runban ru;

void add_roulette_ban(char *nick, char *host, char *channel) {
  int i=0;
  while(ru[i].timeleft != 0) { i++; }
  strcpy(ru[i].nick,nick);
  strcpy(ru[i].host,host);
  strcpy(ru[i].channel,channel);
  ru[i].timeleft = roulette_bantime;
}

int del_roulette_ban(char *nick,char *channel) {
  int i=0;
  while(strcmp(nick,ru[i].nick) != 0 && strcmp(channel,ru[i].channel) != 0) {
    if(ru[i].timeleft == 0) {
      return -1;
    }
    i++;
  }
  putlog(LOG_CMDS,"*","%s: Remove !roulette Ban on %s after %d seconds",ru[i].channel,ru[i].nick,roulette_bantime);
  dprintf(DP_MODE,"MODE %s -b %s\n",ru[i].channel,ru[i].host);
  
  while(ru[i+1].timeleft != 0) {
    strcpy(ru[i].nick,ru[i+1].nick);
    strcpy(ru[i].host,ru[i+1].host);
    strcpy(ru[i].channel,ru[i+1].channel);
    ru[i].timeleft = ru[i+1].timeleft;
    i++;
  }
  strcpy(ru[i].nick,"");
  strcpy(ru[i].host,"");
  strcpy(ru[i].channel,"");
  ru[i].timeleft = 0;
  return 1;
}

void check_roulette_ban() {
  int i=0;
  while(ru[i].timeleft != 0) {
    ru[i].timeleft = ru[i].timeleft-1;
    if (ru[i].timeleft == 0) {
      del_roulette_ban(ru[i].nick,ru[i].channel);
      i--;
    }
    i++;
  }
}

check_roulette_ban() wird jetzt jede Sekunde aufgerufen.

Das funktioniert soweit wunderbar, danke für die Inputs die ich hier bekommen konnte :)
 
Eigentlich ist es ganz simpel.

Wenn sich ein Schuss löst und der User gebannt wird schreibe ich einfach einen neuen eintrag in das struct ru mit den membern "nick, host, channel, timeleft" ... damit ist die aufgabe der einen funktion abgeschlossen.

Die Funktion check_roulette_ban() zählt den Zähler "timeleft" jede Sekunde um eins zurück
und überprüft gleich ob er bei 0 angekommen ist, ist dem so löscht er den Ban und schiebt
die verbleibenden Werte im Array nach vorne.

Oder in kurz, die eine Funktion überprüft simpel im Sekundenintervall das Array nach
abgelaufenen Ban's, das Spiel selbst schreibt da nur noch Ban's hinein und fertig.
Also zwei völlig eigenständige Prozesse, der Bot "friert" so nicht mehr ein.

Hoffe hab's so erklärt dass man das auch versteht.

Vielleicht noch zur verdeutlichung die Funktion die aufgerufen wird wenn einer den Trigger im Channel schreibt:

Code:
/*
 * pub_roulette
 * Funktion die ausgeführt wird wenn jemand !roulette in nem channel trötet
 */
static int pub_roulette(char *nick, char *host, char *hand, char *channel, char *text)
{
  Context;
  if (!ngetudef("roulette", channel)) {
    putlog(LOG_CMDS, "*", "%s: !roulette by %s not allowed in this Channel",channel,nick);
    return 1;
  }

  FILE* f;
  char uhost[UHOSTLEN];
  int zz,roulettecount=0;

  zz = RND(roulette_rnd);
  strcpy(uhost,host);
  get_host(uhost);

  f = fopen(roulettefile,"r");
  if (f) {
    fscanf(f,"%u",&roulettecount);
    fclose(f);  
  }
  f = fopen(roulettefile,"w");
  fprintf(f,"%u",++roulettecount);
  fclose(f);
  /*
   * Bis hier hin alles ok
   * uhost = hostname des users (um ircops vor dem kicken zu schützen da die meisten eh sajoin haben)
   * zz = zufallszahl .. bei 0 gibts BANG!
   */

  if (zz == 0) { //Counter ist auf 0 --> BANG
    if (strncmp(uhost,roulette_securehost,strlen(roulette_securehost)) == 0) { //User ist vor dem BANG geschützt
      putlog(LOG_CMDS, "*", "%s: !roulette by %s (Soft BANG!)",channel,nick);
      dprintf(DP_SERVER,"PRIVMSG %s :[roulette] *Den Kopf von %s pack und ein paar mal gegen die Wand hau!* ... Erschiessen geht ja eh nicht ... BANG! ( %d )\n",channel,nick,roulettecount);
    } else { //User ist nicht geschützt .. let's BANG
      add_roulette_ban(nick,host,channel);
      putlog(LOG_CMDS, "*", "%s: Banning %s because !roulette (BANG!) for %d seconds",channel,nick,roulette_bantime);
      dprintf(DP_MODE,"MODE %s +b %s\n",channel,host);
      dprintf(DP_MODE,"KICK %s %s :BANG! ( %d )\n",channel,nick,roulettecount);
    }
  } else {  //Nur ein CLICK
    putlog(LOG_CMDS, "*", "%s: !roulette by %s (CLICK!)",channel,nick);
    dprintf(DP_SERVER,"PRIVMSG %s :[roulette] %s: CLICK! ( %d )\n",channel,nick,roulettecount);
  }
  return 0;
}
 
Zurück