blob: cfcf0b01aadaf0d0ef561b5b7ccbc502cb6ace10 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001Das neue Hooksystem
2(Implementierung von Muadib, ueberarbeitet von Zesstra)
3
4EINLEITUNG
5==========
6Das neue Hooksystem baut nicht mehr auf der Eintragung eines Hooks in einer
7Property auf. Dadurch wird es moeglich, dass nicht nur ein Objekt sich als
8Hook eintraegt.
9
10Es gibt verschiedenen Arten von Hooks, die man eintragen kann:
11* Listener (H_LISTENER)
12 diese Hooks werden ueber ein Ereignis nur informiert,
13 koennen aber nicht eingreifen oder aendern.
14 max. Anzahl: 5
15* Data-Modifier (H_DATA_MODIFICATOR)
16 diese Hooks duerfen die Daten eines Ereignisses aendern.
17 max. Anzahl: 3
18* Hook-Modifier (H_HOOK_MODIFICATOR)
19 diese Hooks duerfen die Daten des Ereignisses aendern und
20 zusaetzlich das Ereignis auch abbrechen.
21 max. Anzahl: 2
22* Surveyor (H_HOOK_SURVEYOR)
23 diese Hooks duerfen alles oben beschriebene. Zusaetzlich werden
24 sie aber auch gefragt, wenn andere Objekte einen Hook eintragen
25 wollen, einen Hook abbrechen wollen oder Daten aendern wollen.
26 Oder anders: Surveyorhooks entscheiden, was andere duerfen.
27 Kein normales Objekte sollte diese Art von Hook eintragen. Der RM
28 muss die Verwendung eines Surveyors genehmigen.
29 max. Anzahl: 1
30
31Ausserdem lassen sich Hooks noch mit unterschiedlicher Prioritaet eintragen,
32welche dann in der entsprechenden Reihenfolge abgearbeitet werden. Wenn ein
33neuer Hook eingetragen wird, aber eigentlich die max. Anzahl schon erreicht
34wird, wird der Konsument mit der niedrigsten Prioritaet geloescht. In diesem
35Fall wird die superseededHook() im verdraengten Konsumenten gerufen.
36
37Um das neue Hook-System zu realisieren, gibt es zwei wesentliche Klassen.
38Die Objekte, die die Eintragung von Hooks erlauben, erben hierzu von
39hook_provider. Objekte, die einen Surveyor-Hook eintragen wollen, sollten von
40der Klasse hook_surveyor erben. Objekte mit normalen Hooks brauchen nichts zu
41erben.
42
43
44Welche Hooks gibt es zur Zeit in der Basis-Mudlib?
45=================================================
46* H_HOOK_MOVE
47 Bei Bewegung eines Objektes ausgeloest. Kann Bewegung beeinflussen oder
48 abbrechen.
49* H_HOOK_DIE
50 Beim Tod eines Lebewesens ausgeloest. Kann den Tod abbrechen oder
51 <poisondeath> abaendern.
52* H_HOOK_DEFEND
53 Im Defend() eines Lebenwesens ausgeloest. Kann das Defend() abbrechen und
54 Daten des Defend() aendern.
55* H_HOOK_ATTACK
56 Im Attack() eines Lebenwesens ausgeloest. Kann das Attack() abbrechen.
57* H_HOOK_HP
58 Bei Veraenderung der HP (LP) eines Lebewesens gerufen. (Zur Zeit keine
59 Datenveraenderung moeglich)
60* H_HOOK_SP
61 Bei Veraenderung der SP (KP) eines Lebewesens gerufen. (Zur Zeit keine
62 Datenveraenderung moeglich)
63* H_HOOK_ATTACK_MOD
64 Wird im Attack() ausgeloest, nachdem die fuer den Angriff wichtigen Daten
65 ermittelt und berechnet wurden. Diese koennen dann vom Hookonsumenten
66 nochmal geaendert werden. Auch ein Abbruch des Attack() ist hier noch
67 moeglich.
68* H_HOOK_ALCOHOL
69 Bei Veraenderung von P_ALCOHOL im Lebewesens gerufen.
70* H_HOOK_FOOD
71 Bei Veraenderung von P_FOOD im Lebewesens gerufen.
72* H_HOOK_DRINK
73 Bei Veraenderung von P_DRINK im Lebewesens gerufen.
74* H_HOOK_POISON
75 Bei Veraenderung von P_POISON im Lebewesens gerufen.
76* H_HOOK_CONSUME
77 Beim Konsumieren von Speisen und Getraenken in Kneipen im Lebewesens
78 gerufen.
79* H_HOOK_TEAMROWCHANGE
80 Bei Teamreihenwechsel vom Lebewesen ausgeloest.
81* H_HOOK_INSERT
82 Wird von Spielerobjekten ausgeloest, wenn ein Objekt ins Spielerinventar
83 bewegt wird. (Keine Datenveraenderung moeglich)
84* H_HOOK_EXIT_USE
85 Wird von einem Raum ausgeloest, wenn ein Lebewesen einen Ausgang benutzt.
86 Abbruch und Aenderung der Daten des Ausgangs moeglich.
Zesstraecf99342019-07-02 22:46:00 +020087* H_HOOK_INIT
Zesstra@Morgengrauen0f34a7e2016-10-30 22:33:25 +010088 Wird von einem Raum ausgeloest, wenn init() gerufen wird (d.h. ein Lebewesen
89 den Raum betritt). Hat keine Daten.
90 Abbruch moeglich.
Zesstraecf99342019-07-02 22:46:00 +020091 ACHTUNG: bei Abbruch von init() sind schwere Bugs wahrscheinlich!
Zesstra@Morgengrauen0f34a7e2016-10-30 22:33:25 +010092
MG Mud User88f12472016-06-24 23:31:02 +020093
94HOOK-KONSUMENTEN
95================
96Der Hook-Provider ruft bei Ausloesen des Hooks in allen Konsumenten eine
97bestimmte Methode auf. Wenn bei der Registrierung eines Objekts keine Closure
98angeben wurde, die in diesem Fall gerufen werden, wird standardmaessig die
99lfun HookCallback() gerufen (gibt man eine Closure an, bekommt sie die
100gleichen Argumente und es werden die beschriebenen Rueckgabewerte erwartet):
101 * mixed HookCallback(object hookSource, int hookid, mixed hookData)
102 Diese Methode wird in jedem Hook-Konsumenten eines Hook-Providers
103 aufgerufen, solange die Verarbeitung nicht vorher abgebrochen wurde.
104 Die Reihenfolge der Abarbeitung wird nach Liste (Surveyor,
105 Hook-Modifikator, Data-Modifikator, Listener) und dort nach Prioritaet
106 durchgefuehrt.
107 Ein Surveyor-Hook kann verhindern, dass Hooks bestimmte Aenderungen
108 durchfuehren.
109
110 Rueckgabewert ist ein Array, das die folgenden Werte beinhaltet.
111
112 H_RETCODE Gibt an, welcher Hook-Typ verwendet wurde.
113 H_NO_MOD => Nichts wurde veraendert.
114 H_ALTERED => Daten wurden veraendert.
115 H_CANCELLED => Hook-Kette soll abgebrochen werden.
116 => Ausserdem soll die Hook-ausloesende Stelle
117 abgebrochen werden. Z.B. wird das Defend()
118 abgebrochen, wenn ein H_HOOK_DEFEND
119 mit cancelled beantwortet wird.
120 H_RETDATA Gibt die (evtl. geaenderten) Daten an.
121 mixed-Objekt, das wie der Parameter hookData aufgebaut ist.
122
123Ein Objekt darf sich mehrfach fuer den gleichen Hook registrieren. Allerdings
124ist fuer jede Registrierung eine andere Closure noetig.
125
126 * void superseededHook(int hookid, object hookprovider)
127 Wird gerufen, wenn der Konsument von einem anderen mit hoeherer Prioritaet
128 verdraengt wurde.
129
130
131HOOK-PROVIDER
132=============
133 Der Hook-Provider bietet eine Menge von Methoden an, die eine Konfiguration
134 ermoeglichen und die Eintragung von Hook-Konsumenten erlauben. Im
135 Normalfall sollte er geerbt und nicht modifiziert werden (ausser natuerlich,
136 die vom Objekte bereitgestellten Hooks einzutragen).
137
138 * int* HListHooks();
139 Diese Methode liefert eine Liste von Hooktypen, fuer die das Objekt
140 Eintragungen annimmt. Hier koennte beispielsweise eine Liste mit den
141 Eintraegen fuer Attack-, Defend- und Move-Hooks stehen.
142
143
144 * protected void offerHook(int hookid, int offerstate);
145 Diese Methode dient dazu, einen bestimmten Hook (z.B. H_HOOK_MOVE)
146 anzubieten. Nur Hooks, die hiermit angeboten wurden, stehen zur
147 Registrierung zur Verfuegung.
148 'offerstate': 0 (nicht verfuegbar), 1 (verfuegbar/angeboten)
149
150
151 * int HRegisterToHook(int hookid, mixed consumer, int hookprio,
152 int consumertype, int timeInSeconds);
153 Registriert ein Objekt oder eine Closure als Hook-Konsument.
154 Parameter:
155 'hookid' gibt den Hook-Typ an, z.B. den Defend-Hook.
156 Man kann sich nur fuer Hooktypen eintragen, die die Methode
157 HListHooks() angeboten hat.
158 'consumer' Wenn ein Objekt, wird das Objekt eingetragen und spaeter
159 HookCallback() gerufen.
160 Wenn eine Closure, wird das Objekt der Closure eingetragen
161 und spaeter diese Closure gerufen.
162 'hookprio' Gibt die Prioritaet an, mit der der Hook laufen soll.
163 Diese Angabe bestimmt die Reihenfolge, in der die Hooks
164 in der Liste der Hooks eingetragen werden. Die Prioritaet
165 ist H_HOOK_LIBPRIO(x), H_HOOK_GUILDPRIO(x) oder
166 H_HOOK_OTHERPRIO(x). x darf 0, 1 oder 2 sein (je niedriger,
167 desto hoeher die Prioritaet).
168 'consumertype' Gibt an, um welche Art von Hook es sich handelt.
169 Es gibt vier festgelegten Typen, die fuer alle Hooks
170 existieren koennen. Die Methode HConsumerTypeIsAllowed()
171 gibt Aufschluss darueber, welche Hook-Typen existieren.
172 Die Hook-Typen sind in hook.h definiert.
173 'timeInSeconds' gibt die Laufzeit des Hooks an. Falls 0 eingetragen wird,
174 laeuft der Hook ewig.
175 Rueckgabewerte:
176 1 - Registrierung erfolgreich
177 <=0 - Registrierung fehlgeschlagen:
178 -1 : Hook unbekannt
179 -2 : consumer ist keine closure und es konnte kein Callback auf
180 HookCallback im consumer erstellt werden.
181 -3 : consumer ist bereits registriert
182 -4 : consumertyp ist nicht erlaubt
183 -5 : hookprio ist nicht erlaubt
184 -6 : Surveyor hat Registrierung nicht erlaubt
185 -7 : zuviele Hooks registriert / kein Hookeintrag frei
186
187 * int HUnregisterFromHook(int hookid, mixed consumer);
188 Hebt die Registrierung von <consumer> fuer einen bestimmten Hook-Typ wieder
189 auf.
190 Parameter:
191 'hookid' Die Kennung des Hook-Typs, z.B. die Kennung des Attack-Hooks.
192 'consumer' Das Objekt oder die Closure, die/das nicht mehr registriert sein
193 soll. Bei einer Closure wird genau diese ausgetragen. Bei der
194 Angabe eines Objekts wird versucht, die Closure auf
195 HookCallback() in diesem Objekt auszutragen.
196 Rueckgabewerte:
197 0 - 'consumer' nicht als Konsument gefunden
198 1 - Austragen erfolgreich
199
200 * int HConsumerTypeIsAllowed(int type, object consumer);
201 Diese Methode liefert 1 zurueck, wenn ein bestimmter Konsumenten-Typ
202 (fuer diesen Konsumenten) erlaubt wird.
203 Die Standardmethode liefert immer 1 (true) zurueck. Erbende Objekte
204 koennen diese Methode ueberschreiben, wenn sie nicht alle Hooktypen
205 anbieten.
206
207
208 * int HPriorityIsAllowed(int prio, object consumer);
209 Diese Methode gibt an, ob eine bestimmte Prioritaet (fuer den angegebenen
210 Konsumenten) erlaubt ist. Die Standardmethode liefert immer 1 (true)
211 zurueck. Erbende Objekte koennen diese Methode ueberschreiben, wenn
212 sie die verfuegbaren Hook-Prioritaeten einschraenken wollen.
213
214
215 * int HIsHookConsumer(int hookid, mixed consumer);
216 Ist <consumer> ein Objekt, liefert die Methode die Anzahl, wie oft dieses
217 Objekt (mit verschiedenen Closures) fuer den Hook <hookid> eingetragen ist.
218 Ist <consumer> eine Closure, liefert diese Methode 1, wenn diese
219 Closure fuer den Hook <hookid> eingetragen ist.
220
221
222 * protected mapping HCopyHookMapping();
223 Diese Methode liefert eine Kopie des Hook-Mappings.
224 ACHTUNG: diese Daten sollten das Objekt NIEMALS verlassen. (Ausser fuer
225 Debugzwecke)
226
227
228
229HOOK-SURVEYOR
230=============
231 Objekte mit Surveyorhooks muessen eine Menge von Methoden definieren, die
232 der Hookprovider aufruft:
233
234 * status HookRegistrationCallback(
235 object registringObject,
236 int hookid,
237 object hookSource,
238 int registringObjectsPriority,
239 int registringObjectsType)
240 Diese Methode wird vom Hook-Provider aufgerufen, wenn der Hook-Konsument
241 als Surveyor eingetragen ist und ein weiterer Hook eingetragen werden soll.
242 Gibt diese Methode 0 zurueck, dann verbietet der Konsument, dass der
243 andere Konsument als Hook eingetragen wird.
244
245 * int HookCancelAllowanceCallback(
246 object cancellingObject,
247 int hookid,
248 object hookSource,
249 int cancellingObjectsPriority,
250 mixed hookData)
251 Diese Methode wird aufgerufen, um herauszufinden, ob ein bestimmter
252 anderer Hook die Ausfuehrung der Hook-Kette unterbrechen darf.
253 Nur Hooks im Bereich H_HOOK_MODIFICATOR werden der Methode uebergeben.
254
255 * int HookModificationAllowanceCallback(
256 object modifyingObject,
257 int hookid,
258 object hookSource,
259 int modifyingObjectsPriority,
260 mixed hookData)
261 Diese Methode wird aufgerufen, um herauszufinden, ob ein bestimmter
262 anderer Hook die Daten des Hooks veraendern darf oder nicht.
263 Es werden die Hooks in den Bereichen H_HOOK_MODIFICATOR und
264 H_DATA_MODIFICATOR (in dieser Reihenfolge) aufgerufen.
265
266
267WAS KOSTET DAS?
268 Das Ausloesen eines Hooks per HookFlow() kostet 111 Ticks und ca. 7 us, wenn
269 es gar keinen gibt, der drauf lauscht (sozusagen Fixkosten).
270 Pro H_LISTENER kommen dann 31 Ticks und ca. 2 us dazu.
271
272 Gibts einen Surveyor-Hook (der wird dann gefragt, ob andere Objekte die
273 Daten des Hooks aendern oder die Hookverarbeitung abbrechen duerfen):
274 Fixkosten: 155 Ticks, 11 us.
275 Plus pro Data-Modifier:
276 106 Ticks, 5.6 us
277 Plus pro Hook-Modifier, der aber nur Daten aendert:
278 112 Ticks, 6.4 us
279 Und ein Hook-Modifier, der den Hook abbricht:
280 76 Ticks, 4 us
281
282 (Macht der Surveyor natuerlich irgendwas anderes als 'return 1;', wirds
283 natuerlich entsprechend teurer.)
284