/* Do not remove the headers from this file! see /USAGE for more info. */
/*
** Inheritable for persistance.
** Beek for nightmare, ported by Rust.
** could use helper funs that save directly to
** a file, and some security (when programatic security arrives)
** save() and restore() or save_to_file(), etc....
**
** Beek - protected a bunch of things which shouldn't be called externally
*/
#include <mudlib.h>
//:MODULE
//This module implements persistence
private nosave int save_recurse;
private nosave mixed *saved = ({});
//###These filenames can legally be remapped to other objects (these moved)
private nosave string * old_fnames = ({ "/obj/shells/wish", "/obj/pshell" });
//:FUNCTION add_save
//Mark a variable as one that gets saved.
protected void add_save(mixed *vars) {
saved += vars;
// saved = clean_array(saved + vars);
}
//:FUNCTION get_saved
//returns the array of variables that get saved.
//###Security problem here - Beek. What is it used for anyway?
string *get_saved() { return saved; }
//:FUNCTION set_save_recurse
//sets whether or not a save is recursive.
protected void set_save_recurse(int flag) { save_recurse = flag; }
//:FUNCTION save_to_string
//saves an object into a string representation.
varargs string save_to_string(int recursep) {
string *tmpsaved;
string var;
mapping map = ([]);
//### setting a property based on a function arg? Gross.
if (recursep)
set_save_recurse(1);
tmpsaved = decompose(map(saved, (: functionp($1) ? evaluate($1, "saving") : $1 :)));
tmpsaved -= ({0});
foreach (var in tmpsaved)
map[var] = fetch_variable(var);
map["#base_name#"] = base_name(this_object());
if (save_recurse)
map["#inventory#"] = all_inventory()->save_to_string(1) - ({ 0 });
return save_variable(map);
}
//:FUNCTION load_from_string
//loads an object from a string representation.
//### obsolete code
void old_load_from_string(mixed value, int recurse) {
string obj;
object ob;
int i;
string *tmpsaved;
if(!stringp(value))
return;
value = restore_variable(value);
if (value[0] != base_name(this_object()))
{
/*
** If the saved fname is not a "legal" old name, then raise an
** error. There are certain files that have moved, so we must
** deal appropriately with errors.
*/
if ( member_array(value[0], old_fnames) == -1 )
error("Invalid save string (ob)\n");
}
tmpsaved = decompose(map(saved, (: functionp($1) ? evaluate($1, "loading") : $1 :)));
tmpsaved -= ({0});
if (sizeof(tmpsaved) != sizeof(value[1]))
error("Invalid save string (size)\n");
for (i = 0; i < sizeof(tmpsaved); i++)
store_variable(tmpsaved[i], value[1][i]);
if (sizeof(value) == 3) {
foreach(obj in value[2]) {
value = restore_variable(obj);
ob = new(value[0]);
ob->load_from_string(value, 1);
}
}
if (recurse) move_object(previous_object());
}
void load_from_string(mixed value, int recurse) {
mixed data;
mixed *tmpsaved;
string var;
mixed val;
string obj;
object ob;
if (!mapp (value))
data = restore_variable(value);
else
data = value;
if (arrayp(data)) {
old_load_from_string(value, recurse);
return;
}
if (data["#base_name#"] != base_name(this_object()))
{
/*
** If the saved fname is not a "legal" old name, then raise an
** error. There are certain files that have moved, so we must
** deal appropriately with errors.
**
** use throw() so we don't get a trace; this is a normal exception
** in some situations.
*/
if ( member_array(data["#base_name#"], old_fnames) == -1 )
throw("Invalid save string (ob)\n");
}
tmpsaved = decompose(map(saved, (: functionp($1) ? evaluate($1, "loading") : $1 :)));
tmpsaved -= ({0});
foreach (var, val in data) {
if (var[0] == '#') continue;
store_variable(var, val);
}
if (data["#inventory#"]) {
foreach(obj in data["#inventory#"]) {
val = restore_variable(obj);
if(!(ob = new(val["#base_name#"])))
continue;
ob->load_from_string(val, recurse+1);
}
}
// We don't want to move the object we're restoring into the
// previous_object () (happens at the end)... When you restored the body,
// the body moved into the user object, but couldn't move out! -- Rust
if (recurse > 1)
{
move_object(previous_object());
}
}