Das neue Message System. ------------------------ Messages werden in der Mudlib ueber eine ganze Menge von Funktionen erzeugt. State of the Art sind momentan die folgenden 6 Lfuns(Lfun-Gruppe message): set_message_filter query_message_filter propagate_message_to_env send_message_to send_message receive_message Zu diesen Funktionen gibt es in der Enzyclopedia UNItopia jeweils einen Eintrag. ------------------------------------------------------------------------------- Machen wir erst mal ein Beispiel: Ein Spieler tritt in einem speziellen Raum gegen ein v_item "felsblock": #include add_v_item(([ "name":"felsblock", "gender":"maennlich", "id":({"felsblock", "fels", "block"}), "long":"Ein grosser Felsblock. Sieht so aus, als koenne man dagegen " "treten"])); Im init ist eine add_action: add_action("treten", "tritt"); Und nu braucht man ein treten(): int treten(string str) { mapping stein; if (here(str, "felsblock", &stein)) { this_player()->send_message_to(this_player(), MT_NOTIFY, MA_MOVE, "Du trittst volle Kanone gegen "+den(stein)+". AUA!\n"); this_player()->send_message(MT_LOOK, MA_MOVE, wrap(Der()+" tritt volle Kanone gegen "+den(stein)+". Das " "muss doch weh tun."), "", this_player()); this_player()->send_message(MT_NOISE, MA_MOVE, wrap(Der()+" schreit laut auf."), "", this_player()); this_player()->add_hp(-5); return 1; } } ------------------------------------------------------------------------------- Zum Beispiel gibt's zu sagen: - Der Raum inherited zwar auch message.c, aber es ist nicht der Raum, der die Messages erzeugt, sondern der Player, also wird das bei dem aufgerufen. So werden dann auch die richtigen Filter (so sie existieren) ausgewertet. - Man haette die 2 send_message() auch in einer formulieren koennen: this_player()->send_message(MT_LOOK | MT_NOISE, MA_MOVE, wrap(Der()+" tritt volle Kanone gegen "+den(stein)+". Das " "muss doch weh tun.\n"+Der()+" schreit laut auf."), "", this_player()); Das hat aber den Nachteil, dass ein Tauber Spieler trotzdem den Schrei "hoert", es sei denn, er ist auch blind. (Message Types kann man |ern, die Message wird aber weitergeleitet, wenn nur einer der angesprochenen Sinne funktioniert) ------------------------------------------------------------------------------- Was ist jetzt dieses MT_XXXX und MA_XXXX? Messages haben einen Typ und eine Aktionsart, dazu gib es in /sys/message.h jeweils defines: Message-Typ: Der Typ definiert, welcher Sinn beim Empfaenger der Message angesprochen wird: MT_UNKNOWN Sollte nicht verwendet werden, ist eine Notloesung MT_LOOK alles, was man sieht MT_NOISE alles, was man hoert MT_FEEL alles, was man fuehlt MT_TASTE alles, was man schmeckt MT_SMELL alles, was man riecht MT_SENSE alle uebersinnlichen Wahrnehmungen, z.B. rede MT_NOTIFY Statusmeldungen: "Ok.", "Du nimmst den Blasuelz." MT_CHANNEL Kurier-Kanaele. MT_FAR alles, was aus der Ferne kommt (nicht vom gleichen Raum) MT_DEBUG Debugmeldungen (geht nur an Goetter) Message-Aktionen: Die Aktion legt fest, durch welche Aktion eine Message ausgeloest wird MA_UNKNOWN Die Notloesung. MA_LOOK Jemand sieht etwas an MA_NOISE Jemand macht ein Geraeusch MA_FEEL Jemand betastet etwas MA_TASTE Jemand leckt etwas ab MA_SMELL Jemand schnueffelt herum MA_SENSE Jemand macht eine uebersinnliche Wahrnehmung MA_PUT Jemand legt etwas hin MA_TAKE Jemand nimmt etwas MA_MOVE_IN Jemand betritt den Raum MA_MOVE_OUT Jemand betritt verlaesst Raum MA_MOVE Jemand bewegt sich MA_EMOTE Jemand grinst (oder so) MA_FIGHT Jemand kaempft MA_WIELD Jemand fuehrt eine Waffe MA_UNWIELD Jemand senkt eine Waffe MA_WEAR Jemand zieht etwas an MA_UNWEAR Jemand zieht etwas aus MA_EAT Jemand isst etwas (kotzen ist ein MA_EMOTE, kein MA_UNEAT) MA_DRINK Jemand trinkt etwas MA_COMM Jemand sagt was MA_MAGIC Keines von alledem, is aber magisch MA_READ Jemand liest etwas MA_USE Jemand benutzt etwas MA_CRAFT Jemand werkelt rum (bearbeitet etwas) MA_REMOVE Etwas verschwindet. Wozu braucht man das? Na klar, um effektive Filter zu bauen. So kann man nun selektiv jeden einzelnen Sinn des Spielers blockieren oder festlegen, dass eine Tasche z.B. nur Geraeusche nach aussen dringen laesst, aber keine Gerueche (bei Stofftaschen des Mittelalters eher unrealistisch). ------------------------------------------------------------------------------- Message Filter: Im Standard-Container sind die Funktionen set_message_filter() und das Gegenstueck query_message_filter() definiert, mit denen man sehr einfach eine Tasche definiert, die nur Geraeusche durchlaesst. (Nehmen wir mal an, ein Spieler hat einen Wecker in der Tasche, den kann man natuerlich klingeln hoeren. Ausserdem liegt ein Kaese drin, der gelegentlich Gestankwolken von sich gibt, was man dann auch im Raum riecht.) Dazu muss man einfach set_message_filter(MT_NOISE | MT_SMELL) in der Tasche aufrufen und die entsprechende Message wird an das Environment der Tasche weitergeleitet. Damit man von aussen Fragen kann, welche Message-Eigenschaften (geruchsdicht, schalldicht, blickdicht) ein Container hat, kann man den Message Filter auch mit query_message_filter() abfragen. ACHTUNG: Das Argument von set_message_filter() gibt an, welche Meldung durchgelassen werden soll. Mit MT_MASK kann man einen Container definieren, der alle Message-Typen passieren laesst. ------------------------------------------------------------------------------- receive_message: Ein Objekt, das Messages empfangen koennen soll, muss die ALfun receive_message() definieren. Livings haben das bereits, aber auch tote Objekte koennen Messages ueber diese Funktion empfangen. #include void receive_message(int msg_type, int msg_action, object who, string msg) { if (msg_type & MT_NOISE) { send_message_to(owner, msg_type, msg_action, "Dein magisches Ohr hoert:\n"+msg); } } ------------------------------------------------------------------------------- Ich hab hier ein halbes MB an Sourcen, aber die verwenden say, write, tell_room, tell_object usw. Konvertierung dieser Funktionen ist leider nicht automatisierbar, der Messagetyp und der Aktionstyp ist jeweils fuer jede einzelne Message zu waehlen. Oft macht es auch Sinn, die Message zu splitten, um die angesprochenen Sinne zu trennen. urheber ist typischerweise this_object(), also das Objekt, das die Message erzeugt, ausloeser this_player(), also das Objekt, das die Message ausloest. MT_XXX, MA_YYY sind die jeweils ausgeknobelten Types. Und nicht vergessen: Bei der Konvertierung muss bei jedem File, das Messages verwendet, ein #include oben rein. say("blablub") => urheber->send_message(MT_XXX, MA_YYY, "blablub", "", ({urheber, ausloeser})) write("blablub") => urheber->send_message_to(ausloeser, MT_XXX, MA_YYY, "blablub") tell_object(ob, "blablub") => urheber->send_message_to(ob, MT_XXX, MA_YYY, "blablub") tell_room(raum, "blablub") => raum->send_message(MT_XXX, MA_YYY, "blablub") printf(format, var, ...) => urheber->send_message_to(ausloeser, MT_XXX, MA_YYY, sprintf(format, var, ...)) message("blablub", => urheber->send_message(MT_XXX, "suelz", MA_YYY, ({ob1, ob2 })) "blablub", "suelz", ({ob1, ob2}))