Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/d/seher/haeuser/modules/losa.c b/d/seher/haeuser/modules/losa.c
new file mode 100644
index 0000000..893ca51
--- /dev/null
+++ b/d/seher/haeuser/modules/losa.c
@@ -0,0 +1,378 @@
+// losa.c -- Modul fuer Laden und Speichern der Hausdaten
+//
+// (c) 1995 Wargon@MorgenGrauen
+// 2006 Vanion@MorgenGrauen, fuer die rebootfesten Moebel
+// $Id: losa.c,v 1.1.1.1 2000/08/20 20:22:42 mud Exp $
+//
+#pragma strong_types,rtt_checks
+
+#define NEED_PROTOTYPES
+#include "../haus.h"
+#include <container.h>
+#include <thing/properties.h>
+#include <room/exits.h>
+#include <thing/description.h>
+#undef NEED_PROTOTYPES
+#include <properties.h>
+#include <wizlevels.h>
+#include <moving.h>
+
+static void start_reload_furniture();
+
+private int csaved;
+
+// Variablen zur Verwaltung der Moebel im Raum.
+mapping furniture;
+mapping broken_furniture;
+
+protected void
+create()
+{
+ Set(H_CHEST, SAVE, F_MODE);
+ Set(H_CHEST, 0);
+
+ Set(H_FURNITURE, SAVE, F_MODE);
+ Set(H_FURNITURE, 0);
+
+// Set(H_SPECIAL, SAVE|SECURED, F_MODE);
+// Set(H_SPECIAL, ([:2]), F_VALUE);
+}
+
+/* Scheint nirgendwo benutzt zu werden...
+varargs int AddSpecial(int typ, string key, string extra)
+{
+ if (!this_interactive() || !IS_ARCH(this_interactive()) ||
+ !(PATH+"access_rights")->access_rights(geteuid(this_interactive()),""))
+ return -1;
+
+ if (typ != HS_EXIT && typ != HS_ITEM)
+ return 0;
+
+ Set(H_SPECIAL, Query(H_SPECIAL) + ([ key : typ; extra ]));
+ Save();
+ return 1;
+}
+
+void RemoveSpecial(string key)
+{
+ if (!this_interactive() || !IS_ARCH(this_interactive()) ||
+ !(PATH+"access_rights")->access_rights(geteuid(this_interactive()),""))
+ return;
+
+ Set(H_SPECIAL, m_delete(Query(H_SPECIAL), key));
+ Save();
+}
+*/
+
+void
+reset()
+{
+ if (QueryOwner() &&
+ !sizeof(filter(all_inventory(),#'interactive)) &&
+ !csaved)
+ Save(1);
+}
+
+// crunched komprimiert das Savefile
+varargs void
+Save(int crunched)
+{
+ mixed o1, o2, o3;
+ closure pc;
+ object *obs;
+ int i, found;
+
+ o3 = 0;
+
+ if (!(o1 = Query(P_DETAILS)))
+ Set(P_DETAILS, QueryProp(P_DETAILS), F_VALUE);
+
+ if (!(o2 = Query(P_READ_DETAILS)))
+ Set(P_READ_DETAILS, QueryProp(P_READ_DETAILS), F_VALUE);
+
+ if (csaved = crunched)
+ {
+ pc = symbol_function("PCrunch", VERWALTER);
+ Set(P_DETAILS, funcall(pc, Query(P_DETAILS)), F_VALUE);
+ Set(P_READ_DETAILS, funcall(pc, Query(P_READ_DETAILS)), F_VALUE);
+ o3 = Query(H_COMMANDS, F_VALUE);
+ Set(H_COMMANDS, funcall(pc, o3), F_VALUE);
+ }
+
+ // Autoload-Einrichtung identifizieren und speichern
+ // Code in Anlehnung an dem Autoload-Mechanismus fuer Spieler
+ furniture=([]);
+
+ // Alle Autoloader filtern
+ obs=filter_objects(all_inventory(this_object()), "QueryProp", H_FURNITURE);
+ found = 0;
+
+ // Ueber alle Moebel iteritieren
+ for( i=sizeof(obs)-1;i>=0;i--)
+ {
+ if( clonep(obs[i]))
+ {
+ if ( ++found <= MAX_FURNITURE_PER_ROOM )
+ furniture += ([ object_name(obs[i]):obs[i]->QueryProp(H_FURNITURE) ]);
+ }
+ }
+ if (found > MAX_FURNITURE_PER_ROOM)
+ {
+ tell_object(this_player(),
+ break_string("Du hast "+found+" Moebelstuecke im Raum stehen. "
+ "Gespeichert werden nur "+MAX_FURNITURE_PER_ROOM+". "
+ "Du solltest Dich von einigen Einrichtungsgegenstaenden "
+ "trennen.",78));
+
+ }
+ HDEBUG("Saving "+ sizeof (furniture) +" (plus "+sizeof(broken_furniture)+
+ " broken) objects in room "+
+ object_name(this_object()) + ".");
+
+ save_object( HAUSSAVEPATH+QueryOwner(1));
+
+ Set(P_DETAILS, o1, F_VALUE);
+ Set(P_READ_DETAILS, o2, F_VALUE);
+ if (o3)
+ Set(H_COMMANDS, o3, F_VALUE);
+}
+
+void
+Load()
+{
+ mixed prop;
+ int i;
+
+ restore_object( HAUSSAVEPATH+QueryOwner(1));
+
+ // Details und Kommandos werden beim Speichern de-dupliziert und in einem
+ // speziellen Format abgespeichert (s. PCrunch() im Hausverwalter). Sie
+ // muessen nach dem Laden durch die entsprechenden Add...()-Aufrufe
+ // wieder eingetragen werden.
+ prop=Query(P_DETAILS, F_VALUE);
+ RemoveDetail(0);
+ if (pointerp(prop))
+ {
+ foreach(<string*|string>* item : prop)
+ AddDetail(item[0], item[1]);
+ }
+ else if (mappingp(prop))
+ {
+ foreach(string key, mixed val : prop)
+ AddDetail(key, val);
+ }
+ else
+ SetProp(P_DETAILS, prop);
+
+ prop = Query(P_READ_DETAILS, F_VALUE);
+ RemoveReadDetail(0);
+ if (pointerp(prop))
+ {
+ foreach(<string*|string>* item : prop)
+ AddDetail(item[0], item[1]);
+ }
+ else if (mappingp(prop))
+ {
+ foreach(string key, mixed val : prop)
+ AddReadDetail(key, val);
+ }
+ else
+ SetProp(P_READ_DETAILS, prop);
+
+ prop = Query(P_EXITS, F_VALUE);
+ RemoveExitNoCheck(0);
+ if (mappingp(prop))
+ {
+ if (widthof(prop) <= 1)
+ {
+ foreach(string key, string dest : prop)
+ AddExitNoCheck(key, dest);
+ }
+ else
+ {
+ foreach(string key, string dest, string msg : prop)
+ {
+ if (stringp(msg))
+ _AddExit(key, dest, msg);
+ else if (stringp(dest) && strstr(dest,"#") != -1)
+ AddExitNoCheck(key, dest);
+ else
+ _AddExit(key, dest, 0);
+ }
+ }
+ }
+
+ prop=Query(H_COMMANDS, F_VALUE);
+ if (pointerp(prop))
+ {
+ Set(H_COMMANDS, ([]), F_VALUE);
+ for (i=sizeof(prop)-1; i>=0; i--)
+ this_object()->AddUserCmd(prop[i][0], 0, prop[i][1], prop[i][2]);
+ }
+
+ if (environment())
+ environment()->SetProp(P_NEVER_CLEAN, 1);
+
+ if (previous_object() && object_name(previous_object())==VERWALTER)
+ {
+ if (Query(H_CHEST))
+ this_object()->AddItem(PATH+"truhe",REFRESH_NONE,
+ ([ "owner" : QueryOwner() ]));
+/* Das scheint nirgendwo benutzt zu werden und in allen Seherhaeusern leer zu
+ * sein.
+ mapping special = Query(H_SPECIAL, F_VALUE);
+ if (special)
+ {
+ foreach(string key, int type, string extra : special)
+ {
+ switch(type)
+ {
+ case HS_ITEM:
+ AddItem(SPECIALPATH + extra, REFRESH_DESTRUCT);
+ break;
+ case HS_EXIT:
+ AddExitNoCheck(key, extra);
+ break;
+ }
+ }
+ }
+*/
+ }
+
+ // Das Laden der Autoloader wird erst am Ende angestossen.
+ // Dann ist es nicht schlimm, wenn alle Eval Ticks verbraucht werden.
+ start_reload_furniture();
+}
+
+// Mehrere Save-Anforderungen zusammenfassen.
+static void queued_save()
+{
+ HDEBUG("QS");
+ while (remove_call_out("Save")!=-1);
+ call_out("Save",3);
+}
+
+static int reload_error(string file, mixed data, string message)
+{
+ HDEBUG(message);
+ broken_furniture+=([file:data]);
+ log_file("seher/haeuser/autoloader_error",
+ dtime(time())+"\n"+
+ break_string(object_name(this_object())+" ("+QueryOwner(1)+")",78, " FILE: ",1)+
+ break_string(message, 78, " MSG: ",1)+
+ break_string(sprintf("%O", data),78, " DATA: ",1)+"\n");
+
+ return 0; // 0 fuer das filter, damit dieser Eintrag
+ // aus furniture geloescht wird.
+}
+
+// Laedt ein einzelnes Moebelstuecks
+static int load_furniture_object( string file, mixed data )
+{
+ object ob;
+ string error;
+ string blueprint;
+ closure pc;
+ // mixed data;
+
+ // Wenn genug Ticks frei sind, wird versucht, das Objekt zu erzeugen.
+ // Ansonsten ist die Gefahr zu gross, dass ein Erzeugungs-Prozess abbricht.
+ if (get_eval_cost() < 500000)
+ {
+ // HDEBUG("Suspending Object: "+file+". Only "+to_string(get_eval_cost())+" ticks left.");
+ return 1; // 1 bedeutet, dass dieser Eintrag es im Mapping bleibt.
+ }
+
+ // HDEBUG("Processing Object: "+file+" with Data: "+sprintf("%O",data)+".");
+
+ // Nummern der Clones sind beim Speichern noetig, um die Identitaeten
+ // der Objekte zu bestimmen (mehrere Objekte vom gleichen Blueprint
+ // speichern). Hier braucht man sie nicht mehr
+
+ blueprint = explode(file,"#")[0];
+
+ // Data aus dem Mapping holen
+ // data=furniture[file];
+
+ // Muss ich die Blueprint suchen?
+ ob = find_object(file);
+
+ // Nein.
+ if (!ob)
+ {
+ // Existiert die BP oder ein VC fuers File?
+ if (file_size(blueprint+".c")<0&&
+ file_size(implode(explode(blueprint,"/")[0..<2],"/")+
+ "/virtual_compiler.c")<0)
+ {
+ return reload_error(file, data, "Error in file: "+ file +
+ ". File does not exist.");
+
+ }
+
+ // File gefunden. Versuch, es zu laden.
+ if (error = catch(call_other( blueprint,"???")))
+ {
+ return reload_error(file, data, "Error loading file: "+file+". "+error);
+ }
+ }
+
+ // Clone erzeugen
+ if ( error = catch(ob = clone_object(blueprint)) )
+ {
+ return reload_error(file, data, "Error cloning object: "+file+". "+error);
+ }
+
+ HDEBUG(sprintf("%O",furniture));
+ // Autoload-Daten setzen
+ HDEBUG(object_name(ob)+"->SetProp("+sprintf("%O", data)+")");
+ if (ob)
+ catch(ob->SetProp( H_FURNITURE, data ));
+
+ // Furniture in das Seherhaus moven
+ if ( error = catch(ob->move( this_object(), M_NOCHECK )) ) {
+ ob->remove();
+ if(ob) destruct(ob);
+ return reload_error(file, data, "Error moving object: "+file+". "+error);
+ }
+
+ // post_create anstossen
+ pc=symbol_function("post_create", ob);
+ if (closurep(pc))
+ call_out(pc, 1);
+
+ return 0; // 0 bedeutet hier, dieses Objekt nicht noch einmal anstossen.
+}
+
+static void load_furniture()
+{
+ int i;
+ string rv;
+ string current_key;
+
+ // Abbruchbedingung ist, dass nichts mehr zu laden ist.
+ if (sizeof(furniture)==0) return;
+
+ // Anstoßen des naechsten Durchlaufs, falls die Ticks nicht reichen.
+ while (remove_call_out(#'load_furniture) != -1);
+ call_out(#'load_furniture, 1);
+
+ // Laden aller Moebel anstoßen
+ furniture=filter(furniture, #'load_furniture_object);
+}
+
+// Diese Funktion bereitet das Reloaden der Einrichtung vor
+static void start_reload_furniture()
+{
+ // Wenn es keine Moebel gibt, ist das Laden beendet.
+ if (!mappingp(furniture)) return;
+ if (broken_furniture==0) broken_furniture=([]);
+
+ // Falls ein Key von furniture 0 ist, wird dieser geloescht.
+ m_delete(furniture,0);
+
+ // Laden des Furniture anstossen
+ load_furniture();
+}
+
+