View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000215 | LDMud 3.5 | Runtime | public | 2004-11-26 22:09 | 2009-10-06 01:55 |
Reporter | Assigned To | ||||
Priority | normal | Severity | feature | Reproducibility | N/A |
Status | new | Resolution | open | ||
Summary | 0000215: Output hook | ||||
Description | Date: Fri, 21 Jan 2000 14:47:12 +0100 (MEZ) From: Holger Kremss <jur94ewp@studserv.uni-leipzig.de> Short: Output-Hook Type: Feature State: New Hi Lars! Ich haette mal ne Bitte und die Frage, ob es moeglich waere, sowas einzubauen. Und zwar haette ich gerne ne Applied-Funktion, oder besser natuerlich nen Driver-Hook, der alles bekommt, was ein Spieler an text gesendet bekommt. Also im grund so aehnlich, wie das catch_tell und catch_msg machen, aber eben unmittelbar vor der Ausgabe an den Socket und fuer ALLEN Text. Und zwar waere das ne Moeglichkeit, Umlaute zu filtern, die bestimmte Leute auch heute noch nicht auf ihren Terminals sehen koennen. Also der Hook wuerde zum Beispiel folgendes machen: (string)str=player->modify_output(str); In modify_output wuerde man dann alle 'umlaute' und 'sz' umwandeln, so dass der Spieler eben 'ae' und 'ue' statt den Umlauten bekommt. Ich hab mich im WL immerwieder dafuer eingesetzt, Umlaute zugaenglich zu machen, aber da einige leider immernoch Terminals haben, die damit nichts anfangen koennen oder englische Consolen usw, wo sie die auch nichtmal tippen koennen, waere das eine Moeglichkeit. Ich habe mit catch_tell() und catch_msg() rumexperimentiert und festgestellt, dass da immer einiges nicht ankommt. Und zwar all die tell_object() die im Spieler erzeugt werden. Und das sind in unserer Lib sehr viele. Eine andere Moeglichkeit gibt es leider nicht. Und die gesamte Lib umschreiben, dass man mit catch_tell und so arbeiten kann, darauf hab ich ehrlich gesagt keine Lust *stoehn*. Waer doch bestimmt simpel so einen Hook (analog modiy_command) zu machen, oder? Und bestimmt auch nicht zu viel Aufwand... Leider hab ich die aktuellsten Driver-Sourcen nicht hier, aber ich denke mir, alle Textausgaben werden an einer einheitlichen Stelle gemacht. Wenn es doch eine Moeglichkeit jetzt schon gibt, die mir entgangen ist, dann waer ich ueber jeden Tip dankbar. :-) Danke und Byebye! Holger Hi Lars. Ich haette noch einen Vorschlag zu meiner letzten Mail. Ich hab mir nochmal gedanken gemacht, wie das umlaute-parsen am besten zu realisieren ist und bin drauf gekommen, dass es besser ist, die Eingabe des Spielers umzuwandeln in Spezialzeichen und erst bei der Ausgabe das wieder umzuwandeln. Das ist deshalb besser, weil der Umlaut ue nur ein zeichen lang ist, wohingegen 'ue' 2 Zeichen lang ist und dann kommen unsere ganzen zeilenumbrueche durcheinander. Also bei der Eingabe ue -> "u und dann bei der Ausgabe dann Spieler-individuell in Umlaute oder eben ue ae oe umwandeln. Dann werden die Umbrueche nur vielleicht kuerzer, nicht etwa laenger und fuer die strlen-spezifischen Sachen muss ich mir dann auch noch was einfallen lassen. ;-) Lange Rede kurzer Sinn: Neben dem output-Hook waer noch ein Input-Hook schoen. Also wo alles veraendert werden kann, was reinkommt. Nicht nur Commands (modify_command()) sondern auch all das, was an input_to() geht usw. Eben _alles_. Also meine Bitte nochmal zusammengefasst. 2 Hooks, einer fuers Input-Modifizieren und einer fuer Output-Modifizieren. :-) Wenn Du keine Lust hast, das zu machen, muss ich mich vielleicht doch mal selbst ranwagen, aber ich glaub das koennte dann dauern... Holger@Wunderland Subject: H_MODIFY_OUTPUT From: Thomas Feldmeier <tf4@informatik.uni-ulm.de> Date: Wed, 17 Mar 1999 17:26:50 +0100 (MET) Type: Feature State: Acknowledged. H_MODIFY_OUTPUT Optionaler Hook zum Modifizieren jeder Textausgabe, bevor der Spieler sie sieht. Kann eine unbound closure oder ein String sein. Ist der Hook eine Closure, wird er aufgerufen als string <closure>(string output). Ist der Hook ein String, wird eine Funktion mit diesem Namen in dem Spieler aufgerufen: string <name>(string output). this_player() enthaelt den Spieler, der die Textausgabe sieht. Bevor ein Text an einen Spieler gesendet wird, wird der Hook mit diesem Text als Paramter aufgerufen. Ist der Rueckgabewert des Hooks ein String, so wird dieser String anstelle des Textes an den Spieler gesendet. -------------------------------------- Als Vorlage zum H_MODIFY_HOOK koennte man H_MODIFY_COMMAND nehmen (aehnliche Parameteruebergabe) Ich habe mir gedacht, dass in comm.c, add_message() geaendert wird: bevor die message umgewandelt wird (also die /n zu /r/n geaendert usw.), wird ein Hook aufgerufen, der die Message aendern koennte. (vielleicht an der gleichen stelle, an der auch gesnoopt wird?) Damit wird wohl jedes printf(), write() usw. auch einen eigenen Aufruf des Hooks bewirken. Nur binary_message( ,0) nicht. Der Hook ist ja gedacht, um alle ausgaben automatisch umzubrechen, bei beruecksichtigung der ansi-steuerzeichen. pro write usw. wuerde also zusaetzlich ein hook ausgefuehrt werden, der dann ein paar mapping- operationen macht und ein aufruf von terminal_colour. ich schaetze, die cpu-last waere noch ok. Zora | ||||
Tags | No tags attached. | ||||
Attached Files | pkmud-outputhook.diff (7,381 bytes)
Date: Tue, 08 Feb 2000 09:01:45 -0700 From: Zwirch Subject: H_MODIFY_OUTPUT Type: Feature State: New From: Zwirch@PK-Mud Cc: Subject: H_MODIFY_OUTPUT-driverhook Date: Tue Feb 8 14:15:20 2000 Du kannst das Diff zu LDMud-dev164 im PK-Mud-Ftp ziehen (ftp pk.mud.de 4713, anonymous login, Software/Driver/diff-dev164-outputhook). Folgendes macht der Hook: --------------------------------------------------------------------------- H_MODIFY_OUTPUT Optional hook to modify every output that is send to an interactive user (except prompts or binary_message()). Hook setting can be an closure or the name of the function to call in the object. === More: (38%) Page 1, 1..16 [CR,u,f,l,q,/<regexp>,<page>,?] If the hook is a closure, it is called as string <closure>(string output, object player) with the output as first, and the receiving player as second argument. If the hook is a string, it is used as the name of an lfun in the command giving player, which is called as string <name>(string output) If the result is a string it is the new output, which will be sent to the player, otherwise the original output is sent. ---------------------------------------------------------------------- ----- Getestet hab ichs mit dem Hook als string und als unbound-lambda oder lfun-closure im Master. Ich hab auch mal Laufzeitfehler im Hook erzeugt bzw. vom Hook selber Textausgaben gemacht (ergibt too-deep-recursion). Beides hat zumindest mal nicht gecrasht. Ciao, Zwirch PS: ich schick die Diffs auch noch an lars@bearnip ----------diffs------------- --- ldmud-164/src/comm.c Sat Dec 18 01:43:46 1999 +++ ldmud-164-outputhook/src/comm.c Tue Feb 8 12:42:57 2000 @@ -823,6 +823,61 @@ } /*-------------------------------------------------------------------------*/ + +char * +call_modify_output(char *buff) +/* Calls the H_MODIFY_OUTPUT-driverhook (if there is one). + * Returns an xalloced copy of the modified string or + * NULL if there was no hook. + * (The inputstring itself cannot be modified) + */ +{ + svalue_t *svp; + char *output; + + svp = NULL; + output=NULL; + + if (closure_hook[H_MODIFY_OUTPUT].type == T_CLOSURE) + { + lambda_t *l; + + l = closure_hook[H_MODIFY_OUTPUT].u.lambda; + if (closure_hook[H_MODIFY_OUTPUT].x.closure_type == CLOSURE_LAMBDA) + l->ob = command_giver; + push_volatile_string(buff); + push_object(command_giver); + call_lambda(&closure_hook[H_MODIFY_OUTPUT], 2); + transfer_svalue(svp = &apply_return_value, inter_sp--); + if (!command_giver) + return NULL; + } + else if (closure_hook[H_MODIFY_OUTPUT].type == T_STRING + && !(O_DESTRUCTED & command_giver->flags)) + { + push_volatile_string(buff); + svp = + sapply(closure_hook[H_MODIFY_OUTPUT].u.string, command_giver, 1); + if (!command_giver) + return NULL; + } + + /* If svp is not NULL, it contains the new, modified output. + */ + if (svp && svp->type == T_STRING) + { + output=xalloc(svalue_strlen(svp)+1); + if(!output) + { + error("Out of memory.\n"); + /* NOTREACHED */ + return NULL; + } + strcpy(output, svp->u.string); + } + return output; +} + void add_message (char *fmt, ...) @@ -870,6 +925,7 @@ * TODO: Actually, it is used just as a flag for flush/non-flush. */ int old_message_length; /* accumulated message length so far */ + char *tmp; char *source; /* Pointer to the final message to add */ char *end; /* One char past the end of .message_buf[] */ char *dest; /* First free char in .message_buf[] */ @@ -878,6 +934,7 @@ object_t *snooper; /* Snooper of <ip> */ int n; + tmp=NULL; va_start(va, fmt); /* Test if the command_giver is a real, living, undestructed user, @@ -950,7 +1007,6 @@ if (!sending_telnet_command) { - /* If there's a shadow successfully handling the * message, return. * This may cause a recursive call to add_message()!. @@ -959,6 +1015,13 @@ if (shadow_catch_message(command_giver, source)) return; + /* call the H_MODIFY_OUTPUT-hook + * If the hook modified the output we continue with + * the modified string + */ + if(tmp=call_modify_output(source)) + source=tmp; + /* If there's a snooper, send it the new message prepended * with a '%'. * For interactive snoopers this means a recursion with @@ -1118,6 +1181,7 @@ "%s comm: write EINTR. Message discarded.\n", time_stamp()); if (old_message_length) remove_flush_entry(ip); + if(tmp) xfree(tmp); return; case EWOULDBLOCK: @@ -1125,10 +1189,12 @@ "%s comm: write EWOULDBLOCK. Message discarded.\n", time_stamp()); if (old_message_length) remove_flush_entry(ip); + if(tmp) xfree(tmp); return; case EMSGSIZE: fprintf(stderr, "%s comm: write EMSGSIZE.\n", time_stamp()); + if(tmp) xfree(tmp); return; case EINVAL: @@ -1158,6 +1224,7 @@ if (old_message_length) remove_flush_entry(ip); ip->do_close = FLAG_DO_CLOSE; + if(tmp) xfree(tmp); return; } /* for (retries) */ @@ -1177,7 +1244,8 @@ } while (*source); /* --- Final touches --- */ - + if(tmp) xfree(tmp); + ip->message_length = length = dest - ip->message_buf; /* Update the ring of interactives with pending data */ --- ldmud-164/src/make_func.y Mon Dec 6 18:41:06 1999 +++ ldmud-164-outputhook/src/make_func.y Tue Feb 1 15:10:34 2000 @@ -1284,6 +1284,8 @@ return H_MODIFY_COMMAND_FNAME; if ( !strcmp(name, "COMMAND") ) return H_COMMAND; + if ( !strcmp(name, "MODIFY_OUTPUT") ) + return H_MODIFY_OUTPUT; return -1; } --- ldmud-164/src/prolang.y Fri Dec 17 02:05:54 1999 +++ ldmud-164-outputhook/src/prolang.y Tue Feb 1 14:40:42 2000 @@ -180,7 +180,7 @@ H_ERQ_STOP: SH(T_CLOSURE), \ H_MODIFY_COMMAND_FNAME: SH(T_STRING), \ H_COMMAND: SH(T_CLOSURE) SH(T_STRING), \ - + H_MODIFY_OUTPUT: SH(T_CLOSURE) SH(T_STRING), \ #undef SH /*-------------------------------------------------------------------------*/ --- ldmud-164/mudlib/sys/driver_hook.h Tue Sep 28 23:11:40 1999 +++ ldmud-164-outputhook/mudlib/sys/driver_hook.h Tue Feb 1 14:39:25 2000 @@ -22,8 +22,9 @@ #define H_ERQ_STOP 15 #define H_MODIFY_COMMAND_FNAME 16 #define H_COMMAND 17 +#define H_MODIFY_OUTPUT 18 -#define NUM_CLOSURE_HOOKS 18 /* Number of hooks */ +#define NUM_CLOSURE_HOOKS 19 /* Number of hooks */ #endif /* _DRIVER_HOOK_ */ --------------------------- | ||||
|
Zwirch implemented the hook for PKMud. |
|
I thought, that catch_tell() receives every message sent to an interactive and only the interactive object itself can sent messages directly to its socket. So, isn't the output hook superfluous now? |
|
When this bug was created, tell_object() did not yet call catch_msg(). This was introduced with issue 354 one year later. So probably this issue is resolved by now. |
|
But on the other hand I think an interface via input and output hooks might be much cleaner than the call of catch_tell (and having a simul_efun for input_to to catch umlauts). Without an output hook the driver could still call catch_tell as a default. |
|
In Tubmud, all input from resp. output to a player is sent through encoding functions to ensure all players are able to communicate with each other. This way it's also possible for player A to use UTF8, player B to use LATIN1 and C to use plain ascii, and umlauts and other characters are converted correctly. This is of course combined with proper linebreaks even for coloured messages. Shortly, it is possible to handle that real reason behind this issue completely by the mudlib. |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-11-26 22:09 |
|
New Issue | |
2004-11-26 22:13 |
|
File Added: pkmud-outputhook.diff | |
2004-11-26 22:13 |
|
Note Added: 0000215 | |
2009-09-26 17:45 | zesstra | Note Added: 0001304 | |
2009-09-27 12:48 | Sorcerer | Note Added: 0001313 | |
2009-09-29 11:00 | Gnomi | Note Added: 0001337 | |
2009-09-29 15:24 | Coogan | Note Added: 0001353 | |
2009-10-05 16:48 | zesstra | Project | LDMud => LDMud 3.5 |
2009-10-06 01:55 | zesstra | Relationship added | has duplicate 0000426 |
2011-02-20 00:12 | zesstra | Relationship added | related to 0000289 |