blob: efbe10e87c2776d30d972c27093cce3284176e62 [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
MG Mud User88f12472016-06-24 23:31:02 +020019
Zesstra830b2af2021-12-29 16:44:09 +010020#include <driver_info.h>
21
MG Mud User88f12472016-06-24 23:31:02 +020022#define NEED_PROTOTYPES
23
24#include "/sys/thing/properties.h"
25#include "/secure/wizlevels.h"
26
MG Mud User88f12472016-06-24 23:31:02 +020027// the mapping where the actual properties are stored. Direct initialization.
Zesstra3f3e7842022-01-16 22:33:03 +010028// Indexed with F_VALUE, F_MODE, F_SET_METHOD, F_QUERY_METHOD, F_VALIDATOR
29// F_MODE, F_SET_METHOD, F_QUERY_METHOD and F_VALIDATOR are usually 'sparse'
30// (i.e. there is no entry for most properties), therefore it is more
31// memory-efficient to store them like this than in one mapping, although it
32// requires more mapping lookups.
33private nosave mapping *prop = allocate(F_PROP_ENTRIES, ([]));
MG Mud User88f12472016-06-24 23:31:02 +020034
Zesstra375df1e2021-04-21 11:09:06 +020035// the mapping that is used for saving. During save_object/restore_object it
36// contains the properties with SAVE flag.
37// This is empty outside of a save_object() or restore_object() call!
MG Mud User88f12472016-06-24 23:31:02 +020038private mapping properties;
39
MG Mud User88f12472016-06-24 23:31:02 +020040
Zesstraf971f3a2021-04-13 11:48:37 +020041// Z.Zt. nur Abschalten des Resets noetig.
MG Mud User88f12472016-06-24 23:31:02 +020042protected void create() {
43 // Blueprints in /std benoetigenkeinen Reset ....
44 if (object_name()=="/std/thing/properties")
45 set_next_reset(-1);
46}
47
48protected void create_super() {
49 set_next_reset(-1);
50}
51
Zesstrad2c193e2022-01-16 22:49:38 +010052// Prueft, ob ein Zugriff auf eine Property erlaubt ist.
53// Properties, die SECURED oder PROTECTED sind, duerfen nur vom Objekt
54// selber, EM+ oder ROOT veraendert werden.
55#define SAVE_OBJECT 1
56#define PROP_SET 2
57#define PROTECTED_SET 3
58#define PROTECTED_DELETE 4
59#define SECURED_SET 5
60#define SECURED_DELETE 6
61nomask private int prop_check_privilege(int drop_priv, int mode,
62 int op=PROP_SET)
MG Mud User88f12472016-06-24 23:31:02 +020063{
Zesstrad2c193e2022-01-16 22:49:38 +010064 // Interne Calls oder eigenes Objekt (als letzter 'externer' Aufrufer via
65 // Callother) darf alles
66 if (!drop_priv || previous_object() == this_object())
Zesstra0c38e162022-01-20 00:00:39 +010067
Zesstrad2c193e2022-01-16 22:49:38 +010068 return 1;
69
70 // Ab hier nur noch fremde Objekte
71 switch(op)
72 {
73 case SAVE_OBJECT:
74 // Eigentlich nur vom jeweils aktiven simul_efun-Objekt gerufen, aber
75 // der einfacheit halber sind alle ROOT-Objekte erlaubt. Aber nur
76 // direkten Caller pruefen, *nicht* ROOT_SECURITY!
77 if (get_euid(previous_object()) == ROOTID)
78 return 1;
79
80 case SECURED_DELETE:
81 // Das SECURED-Flag darf bei Properties nicht mehr geloescht werden
82 return 0;
83
84 case SECURED_SET:
85 if (geteuid(previous_object()) == ROOTID || ARCH_SECURITY)
86 return 1;
87
88 case PROTECTED_DELETE:
89 case PROTECTED_SET:
90 case PROP_SET:
91 // Properties, die schon SECURED oder PROTECTED sind, duerfen
92 // nur vom Objekt selber manipuliert werden
93 if (!(mode & (PROTECTED|SECURED)) // nicht geschuetzt
94 || (geteuid(previous_object()) == ROOTID || ARCH_SECURITY))
95 return 1;
96 }
97 return 0;
98}
MG Mud User88f12472016-06-24 23:31:02 +020099
100// Set() -- provides direct access to a property, no filters
Zesstra5c0c4092021-09-08 23:27:54 +0200101// Type=F_VALUE und drop_priv=extern_call() by default
102public mixed Set(string name, mixed Value, int Type, int drop_priv)
MG Mud User88f12472016-06-24 23:31:02 +0200103{
Zesstrad2c193e2022-01-16 22:49:38 +0100104 int mode = prop[F_MODE][name];
Zesstra830b2af2021-12-29 16:44:09 +0100105 // Es ist verfuehrerisch, das 'drop_priv||extern_call()' durch 'drop_priv' zu
106 // ersetzen, weil extern_call() das default-argument fuer <drop_priv> ist.
107 // Das ist keine gute Idee, weil <drop_priv> unter der Kontrolle des Aufrufers
108 // ist und dieser 0 uebergeben kann. Sprich: wenn es 0 ist, muessen wir
109 // dennoch selber pruefen. Wir glauben aber immer, wenn es 1 ist, der
110 // Aufrufer hat nichts davon und das eigene Objekt darf Privilegien abgeben.
Zesstrad2c193e2022-01-16 22:49:38 +0100111 drop_priv = drop_priv||extern_call();
Zesstra5c0c4092021-09-08 23:27:54 +0200112
Zesstrad2c193e2022-01-16 22:49:38 +0100113 // Erstmal pruefen, ob Aenderung der Prop erlaubt ist.
114 if (!prop_check_privilege(drop_priv, mode, PROP_SET))
115 return -1;
116 // Bemerkung: aktuell koennen alle Objekte PROTECTED setzen. Loeschen
117 // koennen es ROOT, EM+ und ME ueber den Check oben.
118
119 // Soll SECURED geloescht werden und ist das erlaubt?
120 if ((Type==F_MODE||Type==F_MODE_AD) && (Value & SECURED)
121 && !prop_check_privilege(drop_priv, mode, SECURED_DELETE))
MG Mud User88f12472016-06-24 23:31:02 +0200122 return -2;
Zesstra5c0c4092021-09-08 23:27:54 +0200123
Zesstrad2c193e2022-01-16 22:49:38 +0100124 // Soll SECURED gesetzt werden und ist das erlaubt?
Zesstra830b2af2021-12-29 16:44:09 +0100125 if ((Type==F_MODE||Type==F_MODE_AS) && (Value&SECURED)
Zesstrad2c193e2022-01-16 22:49:38 +0100126 && !prop_check_privilege(drop_priv, mode, SECURED_SET) )
MG Mud User88f12472016-06-24 23:31:02 +0200127 return -3;
128
129 switch(Type)
130 {
131 // Je nach Modus Flags veraendern
132 case F_MODE_AS: prop[F_MODE][name]|= Value;
133 return prop[F_MODE][name];
134 case F_MODE_AD: prop[F_MODE][name]&= ~Value;
135 if (!prop[F_MODE][name]) prop[F_MODE]-=([name]);
136 return prop[F_MODE][name];
137 case F_MODE: prop[F_MODE][name]^= Value;
138 if (!prop[F_MODE][name]) prop[F_MODE]-=([name]);
139 return prop[F_MODE][name];
Zesstraf54f03a2021-12-29 19:55:08 +0100140
141 // Query- und Setmethoden laufen ab hier durch.
MG Mud User88f12472016-06-24 23:31:02 +0200142 case F_SET_METHOD:
Zesstraf54f03a2021-12-29 19:55:08 +0100143 case F_SET_MAPPER:
144 // SETMAPPED passend setzen
145 if (Type==F_SET_METHOD)
146 prop[F_MODE][name] &= ~SETMAPPED;
147 else
148 prop[F_MODE][name] |= SETMAPPED;
149 // Ab hier alles gleich
MG Mud User88f12472016-06-24 23:31:02 +0200150 // -1 als Setz-Methode: Nosetmethod setzen
151 if (Value == -1)
152 {
153 prop[F_SET_METHOD]-=([name]);
154 prop[F_MODE][name] |= NOSETMETHOD;
155 return 0;
156 }
Zesstraf54f03a2021-12-29 19:55:08 +0100157 // Kein break! Rest wie Querymethod
MG Mud User88f12472016-06-24 23:31:02 +0200158 case F_QUERY_METHOD:
Zesstra746046c2018-11-04 11:44:44 +0100159 // Ungebundene Lambda_Closure? Heutzutage ein Fehler.
160 if (closurep(Value) && !query_closure_object(Value))
MG Mud User88f12472016-06-24 23:31:02 +0200161 {
Zesstra746046c2018-11-04 11:44:44 +0100162 raise_error("Ungebundene Lambdas sind als Querymethoden "
163 "nicht mehr unterstuetzt.\n");
MG Mud User88f12472016-06-24 23:31:02 +0200164 }
165 // Kein break!
166 default:
167 if (!Value) prop[Type]-=([name]);
168 else prop[Type][name] = Value;
169 }
170
171 // Gesamtwert zurueckgeben
172 return prop[Type][name];
173}
174
175
176// Direktes Auslesen der Property ohne Filter ...
Zesstra5c0c4092021-09-08 23:27:54 +0200177// Type = F_VALUE by default
178public mixed Query( string name, int Type )
MG Mud User88f12472016-06-24 23:31:02 +0200179{
180 if (pointerp(prop)) return prop[Type][name];
181 return 0;
182}
183
184// Property setzen unter Verwendung evtl. vorhandener Zugriffsfunktionen
Zesstraffcd0fe2021-09-08 23:33:17 +0200185public mixed SetProp( string name, mixed Value, int drop_priv)
MG Mud User88f12472016-06-24 23:31:02 +0200186{
MG Mud User88f12472016-06-24 23:31:02 +0200187 mixed result;
Zesstra10412ed2019-11-23 15:54:09 +0100188
Zesstraf54f03a2021-12-29 19:55:08 +0100189 int mode = prop[F_MODE][name];
MG Mud User88f12472016-06-24 23:31:02 +0200190 // NOSETMETHOD: Darf nicht gesetzt werden
Zesstraf54f03a2021-12-29 19:55:08 +0100191 if (mode & NOSETMETHOD ) return -1;
MG Mud User88f12472016-06-24 23:31:02 +0200192
193 // Set-Method abfragen, so vorhanden
Zesstra10412ed2019-11-23 15:54:09 +0100194 // TODO: nachdem alle moeglichen Werte als Set-Methode illegal sind, auf
195 // closure aendern.
196 mixed func = prop[F_SET_METHOD][name];
197 if (func)
MG Mud User88f12472016-06-24 23:31:02 +0200198 {
MG Mud User88f12472016-06-24 23:31:02 +0200199 // Wert als Set-Method? gleich zurueckgeben
200 if (!closurep(func)) return func;
201
202 // An dieser Stelle muss func eine Closure sein. Da Set() ungebundene
203 // Lambdas bindet, kann es auch nur eine gebundene Closure sein und das
204 // Objekt existiert auch noch (sonst waere func == 0).
205
MG Mud User88f12472016-06-24 23:31:02 +0200206 // Dann mal die Closure aufrufen. Bei Fehler selbige loeschen
207 if (catch(result=funcall(func, Value, name);publish))
208 {
209 prop[F_SET_METHOD]-=([name]);
210 }
Zesstraf54f03a2021-12-29 19:55:08 +0100211 else // Erfolgreicher call
212 {
213 if (mode & SETMAPPED) // SM hat noch nicht selber gesetzt
Zesstrad2c193e2022-01-16 22:49:38 +0100214 result = Set( name, result, F_VALUE, drop_priv||extern_call() );
Zesstraf54f03a2021-12-29 19:55:08 +0100215 }
Zesstraffcd0fe2021-09-08 23:33:17 +0200216
MG Mud User88f12472016-06-24 23:31:02 +0200217 // Und zurueckgeben
Zesstraf54f03a2021-12-29 19:55:08 +0100218 return result;
MG Mud User88f12472016-06-24 23:31:02 +0200219 }
220
Zesstraffcd0fe2021-09-08 23:33:17 +0200221 // _set_*-Methode vorhanden? falls ja, aufrufen.
MG Mud User88f12472016-06-24 23:31:02 +0200222 if (call_resolved(&result,this_object(),"_set_"+name,Value ))
223 return result;
224
225 // Letzte Moeglichkeit: Muss eine 'normale' Property sein
Zesstraffcd0fe2021-09-08 23:33:17 +0200226 // Es ist verfuehrerisch, das 'drop_priv||extern_call()' durch 'drop_priv'
227 // zu ersetzen, weil extern_call() das default-argument fuer <drop_priv>
228 // ist. Das ist keine gute Idee, weil <drop_priv> unter der Kontrolle des
229 // Aufrufers ist und dieser 0 uebergeben kann. Sprich: wenn es 0 ist,
230 // muessen wir dennoch selber pruefen. Wir glauben aber immer, wenn es 1
231 // ist und der Aufrufer Privilegien abgeben will.
232 return Set( name, Value, F_VALUE, drop_priv||extern_call() );
MG Mud User88f12472016-06-24 23:31:02 +0200233}
234
235
236// Property auslesen unter Verwendung evtl. vorhandener Zugriffsfunktionen
237public mixed QueryProp( string name )
238{
MG Mud User88f12472016-06-24 23:31:02 +0200239 mixed result;
MG Mud User88f12472016-06-24 23:31:02 +0200240 // Query-Methode vorhanden?
Zesstra10412ed2019-11-23 15:54:09 +0100241 mixed func = prop[F_QUERY_METHOD][name];
242 if (func)
MG Mud User88f12472016-06-24 23:31:02 +0200243 {
MG Mud User88f12472016-06-24 23:31:02 +0200244 // Wert als Query-Method? Gleich zurueckgeben ...
245 if (!closurep(func)) return func;
246
247 // An dieser Stelle muss func eine Closure sein. Da Set() ungebundene
248 // Lambdas bindet, kann es auch nur eine gebundene Closure sein und das
249 // Objekt existiert auch noch (sonst waere func == 0).
250
MG Mud User88f12472016-06-24 23:31:02 +0200251 // Dann Mal die Closure aufrufen. Bei Fehler selbige loeschen
Zesstraa81eb292021-12-29 19:46:25 +0100252 if (catch(result=funcall(func, prop[F_VALUE][name]);publish))
MG Mud User88f12472016-06-24 23:31:02 +0200253 {
254 prop[F_QUERY_METHOD]-=([name]);
255 }
MG Mud User88f12472016-06-24 23:31:02 +0200256
257 // Und zurueckgeben
258 return result;
259 }
MG Mud User88f12472016-06-24 23:31:02 +0200260 // _query_*-Methode vorhanden? falls ja, aufrufen.
Zesstrad2c193e2022-01-16 22:49:38 +0100261 else if (call_resolved(&result,this_object(),"_query_"+name))
MG Mud User88f12472016-06-24 23:31:02 +0200262 return result;
Zesstrad2c193e2022-01-16 22:49:38 +0100263
MG Mud User88f12472016-06-24 23:31:02 +0200264 // Hilft alles nichts. Es ist eine 'normale' Property ...
265 return prop[F_VALUE][name];
266}
267
Zesstrafaebc152021-07-06 22:21:47 +0200268// Addiert einen Wert zu einer Prop. Eigentlich ist es nur ein Short-Cut fuer
269// QueryProp und += und SetProp. Dementsprechend gehen auch hier nur
270// Typ-Kombinationen, die += auch kann.
271public mixed AddToProp(string pname,
272 <int|float|string|mixed*|mapping|bytes> add_value)
273{
274 mixed value = QueryProp(pname);
275 string err = catch(value += add_value; nolog);
276 if (err)
277 raise_error(sprintf("Nicht unterstuetzter Typ des Summanden: %s\n",
278 err[strstr(err,":")+2..]));
279
280 return SetProp(pname, value, extern_call());
281}
282
283// "subtrahiert" einen Wert von einer Prop. Eigentlich ist es nur ein
284// Short-Cut fuer QueryProp und -= und SetProp. Dementsprechend gehen auch
285// hier nur Typ-Kombinationen, die -= auch kann.
286public mixed SubFromProp(string pname,
287 <int|float|string|mixed*|mapping|bytes> sub_value)
288{
289 mixed value = QueryProp(pname);
290 string err = catch(value -= sub_value; nolog);
291 if (err)
292 raise_error(sprintf("Nicht unterstuetzter Typ des Subtrahenden: %s\n",
293 err[strstr(err,":")+2..]));
294
295 return SetProp(pname, value, extern_call());
296}
MG Mud User88f12472016-06-24 23:31:02 +0200297
Zesstra375df1e2021-04-21 11:09:06 +0200298// Viele Properties auf einen Schlag setzen.
Zesstra7426b7f2022-01-17 13:04:27 +0100299// Wurde genutzt von simul_efun zum Setzen aller Properties, welche im
Zesstra375df1e2021-04-21 11:09:06 +0200300// restore_object() eingelesen wurden.
Zesstra7426b7f2022-01-17 13:04:27 +0100301// Nutzer in Lib: Magiershell (upd), Spellbooks Zaubis, Klerus, Lupe
Zesstra375df1e2021-04-21 11:09:06 +0200302// Andere objekt-externe Nutzung ausdruecklich **NICHT** supportet!
Zesstra7426b7f2022-01-17 13:04:27 +0100303// Problem: ggf. Verlust von SECURED, wenn Props kopiert werden (im alten
304// SECURED; im neuen nicht und nicht-privilegiertes Objekt
305// Problem 2: beim Kopieren von einem alten in ein neues Objekt gehen alle
306// internen QM/SM auf das eigene Objekt ersatzlos kaputt.
307// Problem 3: beim "Clonen" von Objekten haben beide Clones dann geteilte
308// Referenztypen wie Mappings/Structs/Arrays
309public deprecated void SetProperties( mapping props )
MG Mud User88f12472016-06-24 23:31:02 +0200310{
Zesstrad2c193e2022-01-16 22:49:38 +0100311 int i, j;
312
MG Mud User88f12472016-06-24 23:31:02 +0200313 // Kein Mapping? Schlecht ...
314 if(!mappingp(props)) return;
315
Zesstrad2c193e2022-01-16 22:49:38 +0100316 string *names = m_indices(props);
317
MG Mud User88f12472016-06-24 23:31:02 +0200318 // Das SECURED-Flag darf nur durch das Objekt selber gesetzt werden:
Zesstrad2c193e2022-01-16 22:49:38 +0100319 // mode ist hier egal. Antwort cachen fuer den Loop
320 int no_secure = !prop_check_privilege(extern_call(), 0, SECURED_SET);
MG Mud User88f12472016-06-24 23:31:02 +0200321
322 j=sizeof(names);
323 while(j--)
324 {
Zesstrad2c193e2022-01-16 22:49:38 +0100325 if (prop_check_privilege(extern_call(), prop[F_MODE][names[j]],
326 PROP_SET))
MG Mud User88f12472016-06-24 23:31:02 +0200327 {
Zesstrad2c193e2022-01-16 22:49:38 +0100328 // Prop-Setzen erlaubt, aber ggf. SECURED flag loeschen, wenn nicht
329 // das nicht erlaubt ist (s.o.).
330 if (no_secure)
331 props[names[j], F_MODE] &= ~SECURED;
332 // jetzt die einzelnen Teile der Prop seztzen.
Zesstra3f3e7842022-01-16 22:33:03 +0100333 i=F_PROP_ENTRIES;
MG Mud User88f12472016-06-24 23:31:02 +0200334 while(i--)
335 {
336 if(props[names[j],i])
337 prop[i][names[j]] = props[names[j], i];
338 else
339 prop[i]-=([names[j]]);
340 }
341 }
342 }
MG Mud User88f12472016-06-24 23:31:02 +0200343}
344
345
346// Ein Mapping mit allen Properties zurueckgeben
Zesstra7426b7f2022-01-17 13:04:27 +0100347// Wurde genutzt von simul_efun im save_object() zur Abfrage aller Properties,
348// um hieraus die gespeicherten zu bestimmen.
349// Nutzer in Lib: Magiershell (upd), Spellbooks Zaubis, Klerus, Lupe,
350// Listmaster-Zaubis, Fingerdaemon, Kaempfergilde (Karteikarten)
Zesstra375df1e2021-04-21 11:09:06 +0200351// Andere objekt-externe Nutzung ausdruecklich **NICHT** supportet!
Zesstrad2c193e2022-01-16 22:49:38 +0100352// TODO fuer zukuenftige Features (wie private Properties) auf die simul_efun
353// beschraenken.
Zesstra7426b7f2022-01-17 13:04:27 +0100354// Problem: QueryProperties: die Werte entsprechen Query, nicht QueryProp und
355// Abfragende werten die QMs in der Regel nicht aus (und waere auch nicht
356// dieselbe Abfragesituation und wuerde daher nicht funktionieren).
357// Problem 2: Herausgabe interner Daten wie Closures, Referenztypen wie
358// Mappings/Arrays/Structs etc. Diese koennen dann geaendert werden oder im
359// Falle von Closures sind ggf. private lfuns rufbar (stimmt: momentan koennen
360// die auch per Query abgefragt werden).
361public deprecated mapping QueryProperties()
MG Mud User88f12472016-06-24 23:31:02 +0200362{
363 mapping props;
364 int i, j;
365 string *names;
366
Zesstra3f3e7842022-01-16 22:33:03 +0100367 props = m_allocate( sizeof(prop[F_VALUE]), F_PROP_ENTRIES );
Zesstrad2c193e2022-01-16 22:49:38 +0100368
MG Mud User88f12472016-06-24 23:31:02 +0200369 if (pointerp(prop))
370 {
Zesstra3f3e7842022-01-16 22:33:03 +0100371 i=F_PROP_ENTRIES;
MG Mud User88f12472016-06-24 23:31:02 +0200372 while(i--)
373 {
374 names = m_indices(prop[i]);
375 j=sizeof(names);
376 while(j--) props[names[j], i] = prop[i][names[j]];
377 }
378 }
379 return props;
380}
381
Zesstra7426b7f2022-01-17 13:04:27 +0100382// Die Properties als urspruengliches Array zurueckgeben, wird fuers MG-Tool
383// benoetigt.
MG Mud User88f12472016-06-24 23:31:02 +0200384public mixed *__query_properties()
385{
386 if ( pointerp(prop) )
387 return(deep_copy(prop));
388 else
Zesstra3f3e7842022-01-16 22:33:03 +0100389 return allocate(F_PROP_ENTRIES, ([]));
MG Mud User88f12472016-06-24 23:31:02 +0200390}
391
392
Zesstra7426b7f2022-01-17 13:04:27 +0100393// Wird aus simul_efun (und nur von dort) gerufen, sollte die Properties aufs
394// Speichern vorbereiten und alle *gespeicherten* Props in passender Form in
395// der gespeicherten Variable <properties> ablegen.
396public void _prop_prepare_save()
397{
398 // 2 Werte pro Prop (Wert + Modusflags) speichern
399 // F_SET_METHOD, F_QUERY_METHOD werden nicht gespeichert.
400 // Anzahl gespeicherter Props raten, 20% der Props mit Modusflags
401 properties = m_allocate(sizeof(props[F_MODE])/5, 2);
402 foreach(string pname, int mode: props[F_MODE])
403 {
404 if (mode & SAVE)
405 {
406 // Uralte, ungenutzte Flags loeschen sowie SETMAPPED (F_SET_METHOD wird
407 // nicht gespeichert)
408 properties[pname, F_MODE] = mode &
409 (~(SETMNOTFOUND|QUERYMNOTFOUND|QUERYCACHED|SETCACHED|SETMAPPED));
410 properties[pname, F_VALUE] = props[F_VALUE][pname];
411 }
412 }
413}
MG Mud User88f12472016-06-24 23:31:02 +0200414
Zesstra7426b7f2022-01-17 13:04:27 +0100415// Wird nach dem Speichern gerufen und kann ggf. aufraeumen. Vor allem wird
416// der Inhalt von <properties> geloescht, da dies nur beim Speichern relevant
417// ist (und auch nicht gecached werden kann!).
418public void _prop_finalize_save()
419{
420 properties = 0;
421}
MG Mud User88f12472016-06-24 23:31:02 +0200422
Zesstra7426b7f2022-01-17 13:04:27 +0100423// Konvertiert die Daten in <properties> wieder in die Laufzeitform und mergt
424// sie mit den bereits existierenden Props.
425public void _prop_finalize_restore()
426{
427 // Da wir das eigene Savefile oder Savestring restaurieren, koennen wir
428 // alle Rechte ignorieren. Wer das Savefile schreiben kann, hat gewonnen...
429 // Und Savestrings muss das Objekt selber in seinen restore_object()-Aufruf
430 // schreiben.
431 foreach(string pname, mixed value, int mode: properties)
432 {
433 props[F_VALUE][pname] = value;
434 // mode aus dem Savefile wird uebernommen, ausser SETMAPPED, was vom
435 // bisher gueltigem mode uebernommen werden muss.
436 if (props[F_MODE][pname] & SETMAPPED)
437 mode &= SETMAPPED;
438 props[F_MODE][pname] = mode;
439 // F_SET_METHOD und F_QUERY_METHOD werden beibehalten, sollten sie vor dem
440 // restore bereits gesetzt sein. Aus dem Savefile kommen beide nie.
441 }
442 properties = 0;
443}