Save/Restore von Properties ins Objekt verlegt.

Bislang wurden die Properties von den sefun save_object() und
restore_object() objekt-extern verarbeitet, um gespeicherte
Properties zu selektieren und in eine Speicherform zu ueberfuehren.
Diese Aenderung verlegt dieses jetzt in das zu speichernde bzw.
zu restaurierende Objekt und die sefuns informieren dieses
lediglich.
Objektdaten sollen eigentlich soviel wie moeglich innerhalb des
Objektes verbleiben und nicht extern verarbeitet werden und so
wenig wie moeglich zu anderen Objekten gereicht werden.

Change-Id: I1df63b113425f2c8bdf17bbed8e819910a11dbd2
diff --git a/std/thing/properties.c b/std/thing/properties.c
index 102e883..efbe10e 100644
--- a/std/thing/properties.c
+++ b/std/thing/properties.c
@@ -296,10 +296,17 @@
 }
 
 // Viele Properties auf einen Schlag setzen.
-// genutzt von simul_efun zum Setzen aller Properties, welche im
+// Wurde genutzt von simul_efun zum Setzen aller Properties, welche im
 // restore_object() eingelesen wurden.
+// Nutzer in Lib: Magiershell (upd), Spellbooks Zaubis, Klerus, Lupe
 // Andere objekt-externe Nutzung ausdruecklich **NICHT** supportet!
-public void SetProperties( mapping props )
+// Problem: ggf. Verlust von SECURED, wenn Props kopiert werden (im alten
+//   SECURED; im neuen nicht und nicht-privilegiertes Objekt
+// Problem 2: beim Kopieren von einem alten in ein neues Objekt gehen alle
+//   internen QM/SM auf das eigene Objekt ersatzlos kaputt.
+// Problem 3: beim "Clonen" von Objekten haben beide Clones dann geteilte
+//   Referenztypen wie Mappings/Structs/Arrays
+public deprecated void SetProperties( mapping props )
 {
   int i, j;
 
@@ -333,17 +340,25 @@
       }
     }
   }
-  return;
 }
 
 
 // Ein Mapping mit allen Properties zurueckgeben
-// genutzt von simul_efun im save_object() zur Abfrage aller Properties, um
-// hieraus die gespeicherten zu bestimmen.
+// Wurde genutzt von simul_efun im save_object() zur Abfrage aller Properties,
+// um hieraus die gespeicherten zu bestimmen.
+// Nutzer in Lib: Magiershell (upd), Spellbooks Zaubis, Klerus, Lupe,
+// Listmaster-Zaubis, Fingerdaemon, Kaempfergilde (Karteikarten)
 // Andere objekt-externe Nutzung ausdruecklich **NICHT** supportet!
 // TODO fuer zukuenftige Features (wie private Properties) auf die simul_efun
 // beschraenken.
-public mapping QueryProperties()
+// Problem: QueryProperties: die Werte entsprechen Query, nicht QueryProp und
+// Abfragende werten die QMs in der Regel nicht aus (und waere auch nicht
+// dieselbe Abfragesituation und wuerde daher nicht funktionieren).
+// Problem 2: Herausgabe interner Daten wie Closures, Referenztypen wie
+// Mappings/Arrays/Structs etc. Diese koennen dann geaendert werden oder im
+// Falle von Closures sind ggf. private lfuns rufbar (stimmt: momentan koennen
+// die auch per Query abgefragt werden).
+public deprecated mapping QueryProperties()
 {
   mapping props;
   int i, j;
@@ -364,7 +379,8 @@
   return props;
 }
 
-// Die Properties als urspruengliches Array zurueckgeben
+// Die Properties als urspruengliches Array zurueckgeben, wird fuers MG-Tool
+// benoetigt.
 public mixed *__query_properties()
 {
   if ( pointerp(prop) )
@@ -374,17 +390,54 @@
 }
 
 
-// mapping Properties setzen zum Speichern (per save_object())
-// Aufruf nur aus simul_efun heraus (sinnvoll). Diese fragt alle Properties
-// via QueryProperties() ab, filtert alle nicht-gespeicherten Properties aus
-// und setzt ueber diese Funktion die gespeicherten in der tatsaechlich von
-// save_object() gespeicherten Variable <properties>.
-public void  _set_save_data(mixed data) { properties = data; }
+// Wird aus simul_efun (und nur von dort) gerufen, sollte die Properties aufs
+// Speichern vorbereiten und alle *gespeicherten* Props in passender Form in
+// der gespeicherten Variable <properties> ablegen.
+public void _prop_prepare_save()
+{
+  // 2 Werte pro Prop (Wert + Modusflags) speichern
+  // F_SET_METHOD, F_QUERY_METHOD werden nicht gespeichert.
+  // Anzahl gespeicherter Props raten, 20% der Props mit Modusflags
+  properties = m_allocate(sizeof(props[F_MODE])/5, 2);
+  foreach(string pname, int mode: props[F_MODE])
+  {
+    if (mode & SAVE)
+    {
+      // Uralte, ungenutzte Flags loeschen sowie SETMAPPED (F_SET_METHOD wird
+      // nicht gespeichert)
+      properties[pname, F_MODE] = mode &
+            (~(SETMNOTFOUND|QUERYMNOTFOUND|QUERYCACHED|SETCACHED|SETMAPPED));
+      properties[pname, F_VALUE] = props[F_VALUE][pname];
+    }
+  }
+}
 
-// mapping Properties zum Restoren zurueckgeben
-// Aufruf nur aus simul_efun heraus (sinnvoll). Diese ruft nach dem
-// restore_object die restaurierten Properties hiermit ab und schreibt sie
-// nach Konditionierung via SetProperties() zurueck, damit die Daten (wieder)
-// in <prop> zur Verfuegung steheh.
-public mixed _get_save_data()           { return properties; }
+// Wird nach dem Speichern gerufen und kann ggf. aufraeumen. Vor allem wird
+// der Inhalt von <properties> geloescht, da dies nur beim Speichern relevant
+// ist (und auch nicht gecached werden kann!).
+public void _prop_finalize_save()
+{
+  properties = 0;
+}
 
+// Konvertiert die Daten in <properties> wieder in die Laufzeitform und mergt
+// sie mit den bereits existierenden Props.
+public void _prop_finalize_restore()
+{
+  // Da wir das eigene Savefile oder Savestring restaurieren, koennen wir
+  // alle Rechte ignorieren. Wer das Savefile schreiben kann, hat gewonnen...
+  // Und Savestrings muss das Objekt selber in seinen restore_object()-Aufruf
+  // schreiben.
+  foreach(string pname, mixed value, int mode: properties)
+  {
+    props[F_VALUE][pname] = value;
+    // mode aus dem Savefile wird uebernommen, ausser SETMAPPED, was vom
+    // bisher gueltigem mode uebernommen werden muss.
+    if (props[F_MODE][pname] & SETMAPPED)
+      mode &= SETMAPPED;
+    props[F_MODE][pname] = mode;
+    // F_SET_METHOD und F_QUERY_METHOD werden beibehalten, sollten sie vor dem
+    // restore bereits gesetzt sein. Aus dem Savefile kommen beide nie.
+  }
+  properties = 0;
+}