Dokumentation zu: event_senders(WL)

HR Image


KONZEPT
        Event-Sender

AUTOR
        Holger@Wunderland

VORBEMERKUNG
        Bevor man daran geht, Events zu benutzen oder gar zu erzeugen,
        sollte man verstanden haben, um was es geht. Also bitte erst 
        events(WL) lesen und verstehen und dann hier nachgucken, wies geht.
        Danke. :-)

BESCHREIBUNG
        Wenn man einen Event senden will, sollte man erstmal wissen, wie
        der Event heisst, also den Event-Typ kennen (event_types(WL)).

        Danach sollte man pruefen, ob dieser Event nicht ohnehin schon
        erzeugt wird (wie zum Beispiel ET_GO, wenn ein Lebewesen umher
        laeuft). Ist dies nicht der Fall und/oder gibt es keinen Event,
        der sich 'gebrauchen' laesst, kann man den Event selbst senden.

        Die Event-Typen sind wohl meist vorgegeben und dokumentiert 
        (event_types(WL)). Zum Thema 'private Events' bitte die Manpage
        events_fuer_alle(WL) lesen.

        Einen Event senden ist simpel:

        result=send_event(typ, data [, dest [, modus]] );

        typ   - (string) Ein Event-Typ. (event_types(WL))
        data  - (mapping) Die Event-Daten.
        dest  - (mixed) Objekt oder Array aus Objekten, an die der
                Event gesendet werden soll. Globale Lauscher oder globale
                Handler muessen nicht angegeben werden! (automatisch)
                Alle Objekte im deep_inventory() von dest erhalten den
                Event, wenn sie ihm lauschen.
        modus - Ein Sende-Modus. In /sys/events.h sind diese definiert:
                EM_SIMPLE      - Standard Modus - maximale Performance
                EM_COPY        - einfache Kopie des Daten-Mappings
                EM_DEEP_COPY   - echte Kopie des Daten-Mappings
                EM_FAKE        - Simuliert den Event nur intern im Daemon
                                 interessant i.V.m. EM_DEBUG, um alle Lauscher
                                 auf einen Event zu finden
                Der Modus kann kombiniert werden mit:
                EM_COMPLEX     - Mehr Daten in E_RECEIVERS
                EM_DEBUG       - maximale Infos in E_DEBUG_INFO
                EM_STOP_CANCEL - 'spekulative Ausfuehrung', siehe unten
                EM_STOP_HANDLE - fuer verspaetete Reaktionen
        
        Um alle Lauscher eines Events zu finden, ohne den Event wirklich
        auszufuehren, empfiehlt sich: modus=(EM_FAKE|EM_DEBUG). Dann steht
        im Daten-Mapping in E_DEBUG_INFO eine Alist mit folgendes Werten:
        ({ Prios, Closures, Kosten }) (Kosten ist bei EM_FAKE nat. immer 0);

        Die Modi EM_STOP_CANCEL und EM_STOP_HANDLE sind nur fuer die
        extrem fortgeschrittene Ereignisprogrammiererin vorgesehen. Wo
        welcher Stoppunkt greift kann man im Diagramm von events(WL) sehen.
        Bitte wirklich nur benutzen wenn man Ereignisse im Schlaf beherrscht!
        Besondere Vorsicht ist gegenueber Laufzeitfehlern walten zu lassen,
        da diese nicht zu halbfertigen Ereignissen fuehren duerfen.

BEISPIEL
        Will man in einem Raum einen GO-Event senden, wenn der Spieler
        'keller' eingibt, sieht das wie folgt aus:

        mapping result;
        object zielraum; // Der Zielraum als Objekt

        result = send_event(ET_GO,
                   ([ E_MOVE_OBJ  : this_player(),
                      E_MOVE_DEST : zielraum,
                      E_MOVE_MSGS : 
                        ({"Du steigst in den Keller.",
                          "&Name steigt in den Keller.",
                          "&Name kommt herab."})
                    ]), ({ this_object(), zielraum }) );
        
        Danach wird der Event wie ein normaler GO-Event behandelt, wie ihn
        die MUDlib selbst auch ausloest. result[E_HANDLED] ist auf ME_OK
        oder ME_SILENT gesetzt, wenn alles geklappt hat.

SPEKULATIV
        Es besteht die Moeglichkeit Ereignisse spekulativ auszufuehren. Dies
        wird fuer einige Bequemlichkeits-Funktionen der Mudlib verwendet und
        sollte nur sehr erfahrenen Event-Programmierern vorbehalten bleiben.

        Folgendes Szenario: Wir haben eine Liste von moeglichen Events,
        wissen aber nicht, welches von diesen zum Erfolg fuehren wird.
        Wir wollen nun einen nach dem anderen ausprobieren. Wenn er klappt
        ist gut und das Verhalten soll normal sein. Wenn er nicht klappt
        soll nichts (!) geschehen und der naechste Event wird probiert.

        Weiterhin soll - wenn alle Ereignisse fehlschlugen - eines der
        Ereignisse ausgesucht werden koennen und dann 'normal' fehlschlagen,
        also eine Meldung an den Spieler ausgeben und aehnliches.

        Hierzu gibt es den Modus EM_STOP_CANCEL. Das Ereignis wird dann
        direkt bei einem cancel_event() eingefrohren. Es werden also keine
        Objekte der Prioritaeten EPRIO_C_HANDLE oder EPRIO_C_REACT aufgerufen.

        Man kann das Ereignis jedoch auch wieder 'auftauen' und weiterlaufen
        lassen. Hierzu muss man einfach EVENTD->continue_event(e) aufrufen.
        Als Parameter e ist dabei der Rueckgabewert von send_event() zu
        verwenden, welches bei dem fraglichen Ereignis benutzt wurde.

        Beispiel:
           Wir haben ein Array aus Objekten und wollen fuer jedes Objekt (in
           der Reihenfolgen von vorne nach hinten - Reihenfolge ist ja aus
           Spielersicht da manchmal wichtig) ein Ereignis erzeugen, bis mal
           eins klappt. Wenn keins klappt wollen wir das allererste
           fehlschlagen lassen.

           object* obs;
           mapping ret, first_ret;

           for (i = 0; i < sizeof(obs); ++i) {
             ret = send_event(ET_XXX, ([]), dest, EM_SIMPLE|EM_STOP_CANCEL);

             // Erstes Event speichern falls wir da mal weitermachen muessen
             if (!first_ret) first_ret = ret;
           }

           if (ret[E_HANDLED]) return; // naja, ein Ereignis klappte

           // Hier kommen wir nur an wenn kein einziges Ereignis klappte.
           // Jetzt fuehren wir das erste (fehlgeschlagene) Ereignis weiter,
           // so dass dort EPRIO_C_HANDLE usw zum Zuge kommt

           ret = EVENTD->continue_event(first_ret);

SIEHE AUCH
        events(WL), event_types(WL), event_prioriaeten(WL), 
        event_listeners(WL), events_fuer_alle(WL), send_event(S)


Start » Magierhandbuch » Docu » Konzepte » Event_senders Letzte Generierung: 25.04.2021, 01:58
Email an: mud@wl.mud.de
Valid HTML 4.01!