SYNOPSIS object shadow(object obj, int flag) BESCHREIBUNG Damit wird das aktuelle Objekt dem Objekt als Shadow uebergeworfen. Bei Erfolg liefert es 1, sonst 0 zurueck. Das aufrufende Objekt muss vom Master-Objekt die Erlaubnis haben, als Shadow zu wirken. Normalerweise kann einem Objekt, das query_prevent_shadow() == 1 zurueck liefert, kein Shadow uebergeworfen werden. In diesem Fall liefert shadow() 0 zurueck, sonst das Objekt, dem der Shadow uebergeworfen wurde. shadow() schlaeft fehl, wenn: - der Shadow vesucht, eine "nomask" definierte Funktion zu ueberlagern, - wenn im Praeprozessor #pragma no_shadow gesetzt ist, - wenn das aufrufende Objekt bereits ein Shadow ist, - wenn das aufrufende Objekt selbst einen Shadow uebergeworfen hat, - wenn das aufrufende Objekt ueber ein Environment verfuegt, - wenn das Zielobjekt selbst ein Shadow ist. Wenn ein Objekt A einem Objekt B als Shadow uebergeworfen wird, werden alle call_other() Aufrufe fuer B an A umgeleitet. Wenn A die Funktion, die von call_other() aufgerufen wird, nicht definiert hat, wird der Aufruf an B weitergeleitet. Es gibt also nur ein Objekt, welches call_other() Aufrufe fuer B machen kann: das Objekt A. Nicht einmal das Objekt B kann einen call_other() auf sich selbst machen. Hingegen werden alle normalen (internen) Funktionsaufrufe innerhalb von B werden wie gewohnt innerhalb von B bearbeitet. BEISPIELE Mit drei Objekten a.c, b.c und c.c: --- a.c --- void fun() { debug_message(sprintf("%O [a] fun()\n", this_object())); } void fun3() { debug_message(sprintf("%O [a] fun3()\n", this_object())); } --- b.c --- int fun() { debug_message(sprintf("%O [b] fun()\n", this_object())); find_object("a")->fun(); } void fun2() { debug_message(sprintf("%O [b] fun2()\n", this_object())); find_object("a")->fun3(); this_object()->fun3(); } void do_shadow(object target) { shadow(target, 1); } --- c.c --- int fun() { debug_message(sprintf("%O [c] fun()\n", this_object())); find_object("a")->fun(); } void fun3() { debug_message(sprintf("%O [c] fun3()\n", this_object())); } void do_shadow(object target) { shadow(target, 1); } Es wird nun folgender Code aufgerufen: object a, b, c; a = load_object("a"); b = load_object("b"); c = load_object("c"); b->do_shadow(a); c->do_shadow(a); debug_message("--- a->fun() ---\n"); a->fun(); debug_message("--- b->fun() ---\n"); b->fun(); debug_message("--- c->fun() ---\n"); c->fun(); debug_message("--- b->fun2() ---\n"); b->fun2(); Das ergibt diesen Output: --- a->fun() --- /c [c] fun() /b [b] fun() /a [a] fun() --- b->fun() --- /c [c] fun() /b [b] fun() /a [a] fun() --- c->fun() --- /c [c] fun() /b [b] fun() /a [a] fun() --- b->fun2() --- /b [b] fun2() /a [a] fun3() /c [c] fun3() Merke: der erste Aufruf in b::fun2() findet zuerst c::fun3()! Der Grund ist, dass fuer Aufrufe aus b fuer a der Treiber annimmt, dass alle Shadows vor c schon ihre Chance hatten. Der zweite Aufruf hingegen ergeht an b selbst, das der Treiber als vom Shadow c ueberlagert erkennt. GESCHICHTE Bis 3.2.1@46 fuehrte die Zerstoerung eines Objekts, dem ein Shadow uebergeworfen war, auch zur Zerstoerung aller seiner Shadows. Seit 3.2.1@47 ueberleben Shadows die Zerstoerung des Objektes, dem sie uebergeworfen sind (ausser, die wird von prepare_destruct() manuell erledigt). Seit LDMud 3.2.8 koenne sich Objekte dank #pragma no_shadow gezielt davor schuetzen, einen Shadow uebergeworfen zu bekommen. SIEHE AUCH query_shadowing(E), unshadow(E), query_allow_shadow(M)