blob: 2d45a2883c71c2b33e6c2995bbd7de937b1045e3 [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:
Zesstra746046c2018-11-04 11:44:44 +0100115 // Ungebundene Lambda_Closure? Heutzutage ein Fehler.
116 if (closurep(Value) && !query_closure_object(Value))
MG Mud User88f12472016-06-24 23:31:02 +0200117 {
Zesstra746046c2018-11-04 11:44:44 +0100118 raise_error("Ungebundene Lambdas sind als Querymethoden "
119 "nicht mehr unterstuetzt.\n");
MG Mud User88f12472016-06-24 23:31:02 +0200120 }
121 // Kein break!
122 default:
123 if (!Value) prop[Type]-=([name]);
124 else prop[Type][name] = Value;
125 }
126
127 // Gesamtwert zurueckgeben
128 return prop[Type][name];
129}
130
131
132// Direktes Auslesen der Property ohne Filter ...
133public varargs mixed Query( string name, int Type )
134{
135 if (pointerp(prop)) return prop[Type][name];
136 return 0;
137}
138
139// Property setzen unter Verwendung evtl. vorhandener Zugriffsfunktionen
140public mixed SetProp( string name, mixed Value )
141{
142 closure func;
143 mixed result;
144
145 // nur fuer heute
146 if (!objectp(this_object()))
147 return 0;
148
149 // NOSETMETHOD: Darf nicht gesetzt werden
150 if (prop[F_MODE][name] & NOSETMETHOD ) return -1;
151
152 // Set-Method abfragen, so vorhanden
153 if (func=prop[F_SET_METHOD][name])
154 {
155 int flag;
156
157 // Wert als Set-Method? gleich zurueckgeben
158 if (!closurep(func)) return func;
159
160 // An dieser Stelle muss func eine Closure sein. Da Set() ungebundene
161 // Lambdas bindet, kann es auch nur eine gebundene Closure sein und das
162 // Objekt existiert auch noch (sonst waere func == 0).
163
164 // closure_call setzen, falls noch nicht gesetzt
165 if ((flag=closure_call<time()))
166 closure_call = time()+59;
167
168 // Dann mal die Closure aufrufen. Bei Fehler selbige loeschen
169 if (catch(result=funcall(func, Value, name);publish))
170 {
171 prop[F_SET_METHOD]-=([name]);
172 }
173
174 // Wenn closure_call gesetzt wurde, wieder loeschen
175 if (flag) closure_call = 0;
176
177 // Und zurueckgeben
178 return result;
179 }
180
181 // _set_*-Methode vorhanden? falls ja, aufrufen.i
182 // TODO: Closurecache einfuehren und Funktionaufruf nur noch machen, wenn es
183 // die _set_* auch gibt?
184 if (call_resolved(&result,this_object(),"_set_"+name,Value ))
185 return result;
186
187 // Letzte Moeglichkeit: Muss eine 'normale' Property sein
188 return Set( name, Value, F_VALUE, extern_call() );
189}
190
191
192// Property auslesen unter Verwendung evtl. vorhandener Zugriffsfunktionen
193public mixed QueryProp( string name )
194{
195 closure func;
196 mixed result;
197
198 // nur fuer heute
199 if (!objectp(this_object()))
200 return;
201
202 // Query-Methode vorhanden?
203 if ( func = prop[F_QUERY_METHOD][name] )
204 {
205 int flag;
206
207 // Wert als Query-Method? Gleich zurueckgeben ...
208 if (!closurep(func)) return func;
209
210 // An dieser Stelle muss func eine Closure sein. Da Set() ungebundene
211 // Lambdas bindet, kann es auch nur eine gebundene Closure sein und das
212 // Objekt existiert auch noch (sonst waere func == 0).
213
214 // closure_call setzen, falls noch nicht gesetzt
215 if ((flag=closure_call<time()))
216 closure_call = time()+59;
217
218 // Dann Mal die Closure aufrufen. Bei Fehler selbige loeschen
219 if (catch(result=funcall(func);publish))
220 {
221 prop[F_QUERY_METHOD]-=([name]);
222 }
223 // Wenn closure_call gesetzt wurde, wieder loeschen
224 if (flag) closure_call = 0;
225
226 // Und zurueckgeben
227 return result;
228 }
229
230 // _query_*-Methode vorhanden? falls ja, aufrufen.
231 // TODO: Closurecache und nur rufen, wenn es _query_* auch gibt?
232 if (call_resolved(&result,this_object(),"_query_"+name))
233 return result;
234
235 // Hilft alles nichts. Es ist eine 'normale' Property ...
236 return prop[F_VALUE][name];
237}
238
239
240// Das gesamte Property-Mapping auf einen Schlag setzen
241public void SetProperties( mapping props )
242{
243 string *names;
244 int i, j, same_object;
245
246 // Kein Mapping? Schlecht ...
247 if(!mappingp(props)) return;
248
249 // Setzen wir selber?
250 same_object = (!closure_call &&
251 (!extern_call()||previous_object()==this_object()||
252 allowed()));
253 names = m_indices(props);
254
255 // Das SECURED-Flag darf nur durch das Objekt selber gesetzt werden:
256 // Alle SECURED-Flags aus props loeschen
257 if (!same_object)
258 {
259 j=sizeof(names);
260 while(j--) props[names[j], F_MODE] &= ~SECURED;
261 }
262
263 j=sizeof(names);
264 while(j--)
265 {
266 // Properties, die schon SECURED oder PROTECTED sind, duerfen
267 // nur vom Objekt selber manipuliert werden
268 if (same_object||!(prop[F_MODE][names[j]] & (PROTECTED|SECURED)) )
269 {
270 i=4;
271 while(i--)
272 {
273 if(props[names[j],i])
274 prop[i][names[j]] = props[names[j], i];
275 else
276 prop[i]-=([names[j]]);
277 }
278 }
279 }
280 return;
281}
282
283
284// Ein Mapping mit allen Properties zurueckgeben
285public mapping QueryProperties()
286{
287 mapping props;
288 int i, j;
289 string *names;
290
291 props = m_allocate( 0, 4 );
292
293 if (pointerp(prop))
294 {
295 i=4;
296 while(i--)
297 {
298 names = m_indices(prop[i]);
299 j=sizeof(names);
300 while(j--) props[names[j], i] = prop[i][names[j]];
301 }
302 }
303 return props;
304}
305
306// Die Properties als urspruengliches Array zurueckgeben
307public mixed *__query_properties()
308{
309 if ( pointerp(prop) )
310 return(deep_copy(prop));
311 else
312 return ({ ([]),([]),([]),([]) });
313}
314
315
316// mapping Properties setzen zum Speichern (per save_object())
317// Aufruf nur aus simul_efun heraus
318public void _set_save_data(mixed data) { properties = data; }
319
320// mapping Properties zum Restoren zurueckgeben
321public mixed _get_save_data() { return properties; }
322