blob: e1fd51dbc513d4e40134d9ecd0e57973721d9d27 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2/** \file /secure/shadowmaster.c
3* Objekt, welches eine Liste mit aktiven Shadows hat.
4* Die simul_efun shadow() meldet das beschattende Objekt hier an. Nuetzlich,
5* damit man als Magier endlich mal rauskriegen kann, welche Shadows es
6* eigentlich gibt.
7* \author Zesstra
8* \date 07.08.2009
9* \version $Id$
10*/
11/* Changelog:
12*/
13#pragma strong_types
14#pragma no_clone
15#pragma no_inherit
16#pragma no_shadow
17#pragma pedantic
18
19#include <defines.h>
20#include <wizlevels.h>
21
22#define HOME(x) (__PATH__(0)+x)
23
24/** shadows ist ein mapping, welches alle Schatten und ihre Opfer enthaelt.
25 *
26 * Struktur: Schatten als Schluessel (object) und Beschatteter (object) als
27 * Wert.
28*/
29private mapping shadows = ([]);
30
31#ifndef DEBUG
32#define DEBUG(x) if (find_player("zesstra"))\
33 tell_object(find_player("zesstra"),\
34 "SMDBG: "+x+"\n")
35#endif
36
37#define MEMORY "/secure/memory"
38
39#define SHADOW_OK 1
40#define SHADOW_ACCESS_DENIED -1
41#define SHADOW_EXISTS -2
42#define SHADOW_UNKNOWN -3
43
44protected void create() {
45 mixed tmp;
46 seteuid(getuid());
47 if (mappingp(tmp=MEMORY->Load("Schatten"))) {
48 shadows = tmp;
49 DEBUG("Daten aus MEMORY geladen.\n");
50 }
51 else {
52 DEBUG("Keine Daten in MEMORY vorhanden - reinitialisiere.\n");
53 if (MEMORY->Save("Schatten", shadows) != 1)
54 raise_error("Konnte Daten nicht im Memory ablegen.\n");
55 }
56}
57
58/** Liefert einen String mit allen Schatten und beschatteten Objekten zurueck.
59 * @return string - Liste von Schatten und Opfern
60 */
61public void DumpShadows() {
62 if (extern_call() && !ELDER_SECURITY ) return 0;
63
64 string res = "";
65 foreach(object schatten, object opfer: shadows)
66 if (schatten && opfer)
67 res += sprintf("%O -> %O\n",schatten,opfer);
68
69 printf("Folgende Shadows sind bekannt: \n\n%s\n", res);
70}
71
72/** Findet zu einem beschatteten Objekt den zugehoerigen Schatten.
73 @param[in] object - ein beschattetes Objekt.
74 @return object - Den Schatten oder 0.
75 @sa FindShadowsObject(), QueryObject(), QueryInfo()
76*/
77public object FindShadow(object opfer) {
78 if (!objectp(opfer))
79 return 0;
80
81 foreach(object schatten, object victim: shadows) {
82 if (opfer == victim)
83 // Schatten gefunden.
84 return schatten;
85 }
86 return 0;
87}
88
89/** Findet zu einem Schatten das beschattete Objekt.
90 @param[in] object - ein beschattendes Objekt.
91 @return object - Das beschattete Objekt oder 0.
92 @sa FindShadow(), QueryObject(), QueryInfo()
93*/
94public object FindShadowedObject(object schatten) {
95 return shadows[schatten];
96}
97
98/** Gibt Schatten und Beschatteten zurueck, falls ob eines von beiden ist.
99 Ist ob ein Schatten oder ein beschattetes Objekt, wird ein Array aus
100 Objekten geliefert. Hierbei werden ggf. alle Objekte in der
101 Beschattungshierarchie geliefert, von der ob Bestandteil ist.
102 @param[in] object - ein Objekt.
103 @return object* - ({a, b, c, d}) oder 0.
104 @sa FindShadow(), FindShadowedObject, QueryInfo()
105*/
106public object* QueryObject(object ob) {
107
108 if (!objectp(ob)) return 0;
109
110 object *res = ({ob});
111 object sh = FindShadow(ob);
112
113 while(sh) {
114 // es gibt einen Schatten, also Kette nach oben verfolgen.
115 res = ({sh}) + res;
116 sh = FindShadow(sh);
117 }
118
119 object vic = FindShadowedObject(ob);
120 while(vic) {
121 // es gibt ein beschattetes Objekt, Kette nach unten verfolgen.
122 res = res + ({vic});
123 vic = FindShadowedObject(vic);
124 }
125
126 if (sizeof(res) < 2) {
127 // Offenbar wird ob weder beschattet noch beschattet selber.
128 // Moeglicherweise wurde jedoch durch wilde Zerstoerung die Hierarchie
129 // getrennt. Falls ob nen Schatten ist, laesst sich das reparieren. Falls
130 // ob beschattet wird, hilft eigentlich nur ein reset(). Den moechte ich
131 // hier aber nicht machen, weils u.U. teuer sein koennte.
132 if (query_shadowing(ob)) {
133 shadows[ob] = query_shadowing(ob);
134 // nochmal.
135 return QueryObject(ob);
136 }
137 // scheinbar nicht.
138 return 0;
139 }
140
141 return res;
142}
143
144/** Gibt einen String mit Infos ueber ob zurueck.
145 Ist ob ein beschattetes Objekt oder ein Schatten, wird ein beschreibender
146 String zurueckgeliefert (schatten -> beschattetes Objekt). Hierbei wird ggf.
147 die gesamte Beschattungshierarchie angegeben (a -> b -> c -> d).
148 @param[in] object - ein Objekt.
149 @return string - String mit Infos ueber ob.
150 @sa FindShadow(), FindShadowedObject(), QueryObject()
151*/
152public string QueryInfo(object ob) {
153 object *shs = QueryObject(ob);
154 if (!shs) return 0;
155
156 return CountUp(map(shs, #'object_name), " -> ", " -> ");
157}
158
159/** Registriert einen Schatten und sein Opfer.
160 Registriert den Schatten und sein Opfer. Sollte ausschliesslich durch die
161 simul_efun oder spare_simul_fun gerufen werden.
162 @sa UnregisterShadow()
163*/
164public int RegisterShadow(object schatten) {
165 object opfer;
166
167 //DEBUG(sprintf("[%O] %O\n", schatten, caller_stack()));
168
169 // Irgendein Sicherheitscheck ist eigentlich nicht noetig hier, da das Opfer
170 // ohnehin per efun ermittelt wird und kein Eintrag erfolgt, wenn kein
171 // beschattetes Objekt zu finden ist.
172
173 // das von schatten beschattete Objekt ermitteln
174 if (objectp(opfer=query_shadowing(schatten))) {
175 if (shadows[schatten] == opfer)
176 return SHADOW_EXISTS;
177
178 // Neueintrag oder ggf. auch Aendern.
179 shadows[schatten] = opfer;
180 //DEBUG(DumpShadows());
181 return SHADOW_OK;
182 }
183 return SHADOW_ACCESS_DENIED;
184}
185
186/** Traegt einen Schatten wieder aus.
187 Der Schatten wird wieder ausgetragen. Sollte ausschliesslich durch die
188 simul_efun oder spare_simul_fun gerufen werden.
189 Werden Schatten oder beschattete Objekte zerstoert ohne vorher die
190 Schattierung zu beenden, fuehrt dies zu Inkonsistenzen und zerbrochenen
191 Beschattungshierarchien.
192 @sa RegisterShadow(), UnregisterOpfer()
193*/
194public int UnregisterShadow(object caller) {
195 object schatten, opfer;
196
197 // Ein Sicherheitscheck fuer den Aufruf ist eigentlich nicht noetig, da ein
198 // Eintrag nur entfernt wird, wenn die Beschattung nachweislich beendet
199 // wurde.
200
201 //DEBUG(sprintf("[%O] %O\n", caller, caller_stack()));
202 if (!objectp(caller)) return SHADOW_UNKNOWN;
203
204 // Schatten und beschatteten aus den lokalen Daten ermitteln.
205 if (member(shadows, caller)) {
206 schatten = caller;
207 opfer = shadows[schatten];
208 }
209 else if (objectp(schatten = FindShadow(caller))) {
210 opfer = caller;
211 }
212 // wenn nicht bekannt, ist jetzt eh Ende.
213 if (!schatten) return SHADOW_UNKNOWN;
214
215 //DEBUG(sprintf("%O -> %O (%O, %O)\n",
216 // schatten, opfer, caller, query_shadowing(schatten)));
217
218 // Schattierung wirklich beendet? Wenn nicht -> Ende
219 if (opfer && query_shadowing(schatten) == opfer)
220 return SHADOW_ACCESS_DENIED;
221
222 // war schatten in einer Beschattungshierarchie?
223 object up = FindShadow(schatten);
224 if (up && query_shadowing(up) == opfer) {
225 shadows[up] = opfer; // Kette neu verlinken
226 }
227
228 // jetzt kann geloescht werden.
229 m_delete(shadows,schatten);
230 return SHADOW_OK;
231}
232
233public int ResetAll() {
234 if (!ARCH_SECURITY) return SHADOW_ACCESS_DENIED;
235
236 DEBUG("ResetAll() called.\n");
237
238 shadows = ([]);
239
240 if (MEMORY->Save("Schatten", shadows) != 1)
241 raise_error("Konnte Daten nicht im Memory ablegen.\n");
242
243 return SHADOW_OK;
244}
245
246/** Raeumt die Daten ueber die Schatten auf.
247 Zerstoeren sich beschattete Objekte, werden die Schatten nicht
248 ausgetragen, daher wird das von zeit zu zeit hier gemacht.
249*/
250public void reset() {
251 foreach(object schatten, object opfer: shadows) {
252 if (!objectp(opfer)) {
253 // war schatten evtl. in einer Hierarchie und beschattet jetzt was
254 // anderes?
255 if (query_shadowing(schatten))
256 shadows[schatten] = query_shadowing(schatten);
257 else
258 m_delete(shadows, schatten);
259 }
260 }
261}
262