blob: 06592bfcb1aa813f1b0cf3d2bf7dd3c5c303ca68 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// thing/properties.c -- most general class (property handling)
4//
5// $Id: properties.c 6951 2008-08-09 23:08:31Z Zesstra $
6
7// Properties.c -- Propertyverwaltung
8// (c) 1993 Hate@MorgenGrauen, Mateese@NightFall
9// Idea and Code Flames and Destructions
10// -> *grin* thats the point actually :)
11//
12// Ueberarbeitet von Jof am 12.06.1994
13// Ueberarbeitet von Mandragon am 11.05.2003
14
15#pragma strict_types
16#pragma save_types
17#pragma range_check
18#pragma no_clone
19#pragma pedantic
20
21#define NEED_PROTOTYPES
22
23#include "/sys/thing/properties.h"
24#include "/secure/wizlevels.h"
25
26
27// the mapping where the actual properties are stored. Direct initialization.
28private nosave mapping *prop = ({ ([]), ([]), ([]), ([]) });
29
30// the mapping that is used for saving
31private mapping properties;
32
33// security-flag
34private nosave int closure_call;
35
36// Initialisierung der Props. Kann leider momentan nicht private sein, weil
37// Padreic son komisches Objekt hat, was die Funktion hier ruft.
38// TODO: irgendwann mal private machen.
39// TODO: Da props jetzt einfach bei der Deklaration initlisiert wird,
40// eruebrigt sich diese Funktion eigentlich. Bis auf Padreics Objekt...
41protected void InitializeProperties() {
42 prop = ({ ([]), ([]), ([]), ([]) });
43 return;
44}
45
46// Props nur dann initialisieren, wenn sie es noch nicht sind
47protected void create() {
48 // Blueprints in /std benoetigenkeinen Reset ....
49 if (object_name()=="/std/thing/properties")
50 set_next_reset(-1);
51}
52
53protected void create_super() {
54 set_next_reset(-1);
55}
56
57// Welche externen Objekte duerfen zugreifen?
58nomask private int allowed()
59{
60 if ( (previous_object() && IS_ARCH(getuid(previous_object())) &&
61 this_interactive() && IS_ARCH(this_interactive())) ||
62 (previous_object() && getuid(previous_object()) == ROOTID &&
63 geteuid(previous_object()) == ROOTID) )
64 return 1;
65 return 0;
66}
67
68
69// Set() -- provides direct access to a property, no filters
70public varargs mixed Set( string name, mixed Value, int Type, int extern )
71{
72
73 if (!objectp(this_object()))
74 return 0;
75
76 // Properties, die SECURED oder PROTECTED sind, duerfen nur vom Objekt
77 // selber, EM+ oder ROOT veraendert werden
78 if ((prop[F_MODE][name]&(PROTECTED|SECURED))&&
79 (closure_call||extern||extern_call()) &&
80 previous_object() != this_object() && !allowed())
81 return -1;
82
83 // Das SECURED-Flag darf bei Properties nicht mehr geloescht werden
84 if ((prop[F_MODE][name]&SECURED)&&
85 (Type==F_MODE||Type==F_MODE_AD)&&(Value & SECURED))
86 return -2;
87
88 // Setzen duerfen das SECURED-Flag nur das Objekt selber, EM+ oder ROOT
89 if ((Type==F_MODE||Type==F_MODE_AS)&&(Value&SECURED)&&
90 (closure_call ||extern || extern_call()) &&
91 previous_object() != this_object() && !allowed() )
92 return -3;
93
94 switch(Type)
95 {
96 // Je nach Modus Flags veraendern
97 case F_MODE_AS: prop[F_MODE][name]|= Value;
98 return prop[F_MODE][name];
99 case F_MODE_AD: prop[F_MODE][name]&= ~Value;
100 if (!prop[F_MODE][name]) prop[F_MODE]-=([name]);
101 return prop[F_MODE][name];
102 case F_MODE: prop[F_MODE][name]^= Value;
103 if (!prop[F_MODE][name]) prop[F_MODE]-=([name]);
104 return prop[F_MODE][name];
105 case F_SET_METHOD:
106 // -1 als Setz-Methode: Nosetmethod setzen
107 if (Value == -1)
108 {
109 prop[F_SET_METHOD]-=([name]);
110 prop[F_MODE][name] |= NOSETMETHOD;
111 return 0;
112 }
113 // Kein break!
114 case F_QUERY_METHOD:
115 // Ungebundene Lambda_Closure? Binden!
116 if (closurep(Value)&&!query_closure_object(Value))
117 {
118 if (extern_call() &&
119 (getuid(previous_object()) != getuid()||
120 geteuid(previous_object()) != geteuid()))
121 return prop[Type][name];
122
123 Value = bind_lambda( Value,this_object());
124 }
125 // Kein break!
126 default:
127 if (!Value) prop[Type]-=([name]);
128 else prop[Type][name] = Value;
129 }
130
131 // Gesamtwert zurueckgeben
132 return prop[Type][name];
133}
134
135
136// Direktes Auslesen der Property ohne Filter ...
137public varargs mixed Query( string name, int Type )
138{
139 if (pointerp(prop)) return prop[Type][name];
140 return 0;
141}
142
143// Property setzen unter Verwendung evtl. vorhandener Zugriffsfunktionen
144public mixed SetProp( string name, mixed Value )
145{
146 closure func;
147 mixed result;
148
149 // nur fuer heute
150 if (!objectp(this_object()))
151 return 0;
152
153 // NOSETMETHOD: Darf nicht gesetzt werden
154 if (prop[F_MODE][name] & NOSETMETHOD ) return -1;
155
156 // Set-Method abfragen, so vorhanden
157 if (func=prop[F_SET_METHOD][name])
158 {
159 int flag;
160
161 // Wert als Set-Method? gleich zurueckgeben
162 if (!closurep(func)) return func;
163
164 // An dieser Stelle muss func eine Closure sein. Da Set() ungebundene
165 // Lambdas bindet, kann es auch nur eine gebundene Closure sein und das
166 // Objekt existiert auch noch (sonst waere func == 0).
167
168 // closure_call setzen, falls noch nicht gesetzt
169 if ((flag=closure_call<time()))
170 closure_call = time()+59;
171
172 // Dann mal die Closure aufrufen. Bei Fehler selbige loeschen
173 if (catch(result=funcall(func, Value, name);publish))
174 {
175 prop[F_SET_METHOD]-=([name]);
176 }
177
178 // Wenn closure_call gesetzt wurde, wieder loeschen
179 if (flag) closure_call = 0;
180
181 // Und zurueckgeben
182 return result;
183 }
184
185 // _set_*-Methode vorhanden? falls ja, aufrufen.i
186 // TODO: Closurecache einfuehren und Funktionaufruf nur noch machen, wenn es
187 // die _set_* auch gibt?
188 if (call_resolved(&result,this_object(),"_set_"+name,Value ))
189 return result;
190
191 // Letzte Moeglichkeit: Muss eine 'normale' Property sein
192 return Set( name, Value, F_VALUE, extern_call() );
193}
194
195
196// Property auslesen unter Verwendung evtl. vorhandener Zugriffsfunktionen
197public mixed QueryProp( string name )
198{
199 closure func;
200 mixed result;
201
202 // nur fuer heute
203 if (!objectp(this_object()))
204 return;
205
206 // Query-Methode vorhanden?
207 if ( func = prop[F_QUERY_METHOD][name] )
208 {
209 int flag;
210
211 // Wert als Query-Method? Gleich zurueckgeben ...
212 if (!closurep(func)) return func;
213
214 // An dieser Stelle muss func eine Closure sein. Da Set() ungebundene
215 // Lambdas bindet, kann es auch nur eine gebundene Closure sein und das
216 // Objekt existiert auch noch (sonst waere func == 0).
217
218 // closure_call setzen, falls noch nicht gesetzt
219 if ((flag=closure_call<time()))
220 closure_call = time()+59;
221
222 // Dann Mal die Closure aufrufen. Bei Fehler selbige loeschen
223 if (catch(result=funcall(func);publish))
224 {
225 prop[F_QUERY_METHOD]-=([name]);
226 }
227 // Wenn closure_call gesetzt wurde, wieder loeschen
228 if (flag) closure_call = 0;
229
230 // Und zurueckgeben
231 return result;
232 }
233
234 // _query_*-Methode vorhanden? falls ja, aufrufen.
235 // TODO: Closurecache und nur rufen, wenn es _query_* auch gibt?
236 if (call_resolved(&result,this_object(),"_query_"+name))
237 return result;
238
239 // Hilft alles nichts. Es ist eine 'normale' Property ...
240 return prop[F_VALUE][name];
241}
242
243
244// Das gesamte Property-Mapping auf einen Schlag setzen
245public void SetProperties( mapping props )
246{
247 string *names;
248 int i, j, same_object;
249
250 // Kein Mapping? Schlecht ...
251 if(!mappingp(props)) return;
252
253 // Setzen wir selber?
254 same_object = (!closure_call &&
255 (!extern_call()||previous_object()==this_object()||
256 allowed()));
257 names = m_indices(props);
258
259 // Das SECURED-Flag darf nur durch das Objekt selber gesetzt werden:
260 // Alle SECURED-Flags aus props loeschen
261 if (!same_object)
262 {
263 j=sizeof(names);
264 while(j--) props[names[j], F_MODE] &= ~SECURED;
265 }
266
267 j=sizeof(names);
268 while(j--)
269 {
270 // Properties, die schon SECURED oder PROTECTED sind, duerfen
271 // nur vom Objekt selber manipuliert werden
272 if (same_object||!(prop[F_MODE][names[j]] & (PROTECTED|SECURED)) )
273 {
274 i=4;
275 while(i--)
276 {
277 if(props[names[j],i])
278 prop[i][names[j]] = props[names[j], i];
279 else
280 prop[i]-=([names[j]]);
281 }
282 }
283 }
284 return;
285}
286
287
288// Ein Mapping mit allen Properties zurueckgeben
289public mapping QueryProperties()
290{
291 mapping props;
292 int i, j;
293 string *names;
294
295 props = m_allocate( 0, 4 );
296
297 if (pointerp(prop))
298 {
299 i=4;
300 while(i--)
301 {
302 names = m_indices(prop[i]);
303 j=sizeof(names);
304 while(j--) props[names[j], i] = prop[i][names[j]];
305 }
306 }
307 return props;
308}
309
310// Die Properties als urspruengliches Array zurueckgeben
311public mixed *__query_properties()
312{
313 if ( pointerp(prop) )
314 return(deep_copy(prop));
315 else
316 return ({ ([]),([]),([]),([]) });
317}
318
319
320// mapping Properties setzen zum Speichern (per save_object())
321// Aufruf nur aus simul_efun heraus
322public void _set_save_data(mixed data) { properties = data; }
323
324// mapping Properties zum Restoren zurueckgeben
325public mixed _get_save_data() { return properties; }
326