Zesstra | d59c389 | 2019-11-28 20:53:39 +0100 | [diff] [blame^] | 1 | SYNOPSIS |
| 2 | object shadow(object obj, int flag) |
| 3 | |
| 4 | BESCHREIBUNG |
| 5 | Damit wird das aktuelle Objekt dem Objekt <obj> als Shadow |
| 6 | uebergeworfen. Bei Erfolg liefert es 1, sonst 0 zurueck. |
| 7 | |
| 8 | Das aufrufende Objekt muss vom Master-Objekt die Erlaubnis haben, |
| 9 | als Shadow zu wirken. Normalerweise kann einem Objekt, das |
| 10 | query_prevent_shadow() == 1 zurueck liefert, kein Shadow |
| 11 | uebergeworfen werden. In diesem Fall liefert shadow() 0 zurueck, |
| 12 | sonst das Objekt, dem der Shadow uebergeworfen wurde. |
| 13 | |
| 14 | shadow() schlaeft fehl, wenn: |
| 15 | - der Shadow vesucht, eine "nomask" definierte Funktion zu |
| 16 | ueberlagern, |
| 17 | - wenn im Praeprozessor #pragma no_shadow gesetzt ist, |
| 18 | - wenn das aufrufende Objekt bereits ein Shadow ist, |
| 19 | - wenn das aufrufende Objekt selbst einen Shadow uebergeworfen hat, |
| 20 | - wenn das aufrufende Objekt ueber ein Environment verfuegt, |
| 21 | - wenn das Zielobjekt <obj> selbst ein Shadow ist. |
| 22 | |
| 23 | Wenn ein Objekt A einem Objekt B als Shadow uebergeworfen wird, |
| 24 | werden alle call_other() Aufrufe fuer B an A umgeleitet. Wenn A die |
| 25 | Funktion, die von call_other() aufgerufen wird, nicht definiert hat, |
| 26 | wird der Aufruf an B weitergeleitet. Es gibt also nur ein Objekt, |
| 27 | welches call_other() Aufrufe fuer B machen kann: das Objekt A. Nicht |
| 28 | einmal das Objekt B kann einen call_other() auf sich selbst machen. |
| 29 | Hingegen werden alle normalen (internen) Funktionsaufrufe innerhalb |
| 30 | von B werden wie gewohnt innerhalb von B bearbeitet. |
| 31 | |
| 32 | BEISPIELE |
| 33 | Mit drei Objekten a.c, b.c und c.c: |
| 34 | |
| 35 | --- a.c --- |
| 36 | void fun() { |
| 37 | debug_message(sprintf("%O [a] fun()\n", this_object())); |
| 38 | } |
| 39 | void fun3() { |
| 40 | debug_message(sprintf("%O [a] fun3()\n", this_object())); |
| 41 | } |
| 42 | |
| 43 | --- b.c --- |
| 44 | int fun() { |
| 45 | debug_message(sprintf("%O [b] fun()\n", this_object())); |
| 46 | find_object("a")->fun(); |
| 47 | } |
| 48 | void fun2() { |
| 49 | debug_message(sprintf("%O [b] fun2()\n", this_object())); |
| 50 | find_object("a")->fun3(); |
| 51 | this_object()->fun3(); |
| 52 | } |
| 53 | |
| 54 | void do_shadow(object target) { shadow(target, 1); } |
| 55 | |
| 56 | --- c.c --- |
| 57 | int fun() { |
| 58 | debug_message(sprintf("%O [c] fun()\n", this_object())); |
| 59 | find_object("a")->fun(); |
| 60 | } |
| 61 | void fun3() { |
| 62 | debug_message(sprintf("%O [c] fun3()\n", this_object())); |
| 63 | } |
| 64 | void do_shadow(object target) { shadow(target, 1); } |
| 65 | |
| 66 | Es wird nun folgender Code aufgerufen: |
| 67 | |
| 68 | object a, b, c; |
| 69 | |
| 70 | a = load_object("a"); |
| 71 | b = load_object("b"); |
| 72 | c = load_object("c"); |
| 73 | b->do_shadow(a); |
| 74 | c->do_shadow(a); |
| 75 | debug_message("--- a->fun() ---\n"); |
| 76 | a->fun(); |
| 77 | debug_message("--- b->fun() ---\n"); |
| 78 | b->fun(); |
| 79 | debug_message("--- c->fun() ---\n"); |
| 80 | c->fun(); |
| 81 | debug_message("--- b->fun2() ---\n"); |
| 82 | b->fun2(); |
| 83 | |
| 84 | Das ergibt diesen Output: |
| 85 | |
| 86 | --- a->fun() --- |
| 87 | /c [c] fun() |
| 88 | /b [b] fun() |
| 89 | /a [a] fun() |
| 90 | --- b->fun() --- |
| 91 | /c [c] fun() |
| 92 | /b [b] fun() |
| 93 | /a [a] fun() |
| 94 | --- c->fun() --- |
| 95 | /c [c] fun() |
| 96 | /b [b] fun() |
| 97 | /a [a] fun() |
| 98 | --- b->fun2() --- |
| 99 | /b [b] fun2() |
| 100 | /a [a] fun3() |
| 101 | /c [c] fun3() |
| 102 | |
| 103 | Merke: der erste Aufruf in b::fun2() findet zuerst c::fun3()! |
| 104 | Der Grund ist, dass fuer Aufrufe aus b fuer a der Treiber |
| 105 | annimmt, dass alle Shadows vor c schon ihre Chance hatten. Der |
| 106 | zweite Aufruf hingegen ergeht an b selbst, das der Treiber als |
| 107 | vom Shadow c ueberlagert erkennt. |
| 108 | |
| 109 | GESCHICHTE |
| 110 | Bis 3.2.1@46 fuehrte die Zerstoerung eines Objekts, dem ein Shadow |
| 111 | uebergeworfen war, auch zur Zerstoerung aller seiner Shadows. |
| 112 | Seit 3.2.1@47 ueberleben Shadows die Zerstoerung des Objektes, dem |
| 113 | sie uebergeworfen sind (ausser, die wird von prepare_destruct() |
| 114 | manuell erledigt). |
| 115 | Seit LDMud 3.2.8 koenne sich Objekte dank #pragma no_shadow gezielt |
| 116 | davor schuetzen, einen Shadow uebergeworfen zu bekommen. |
| 117 | |
| 118 | SIEHE AUCH |
| 119 | query_shadowing(E), unshadow(E), query_allow_shadow(M) |