[DGD] Saving to disk

Blain blain20 at gmail.com
Tue Apr 16 21:10:39 CEST 2013


On Tue, Apr 16, 2013 at 10:51 AM, Noah Gibbs <noah_gibbs at yahoo.com> wrote:
> The all-in-one /obj/thing isn't primarily to allow mutation of one object
type into another.  It's primarily to avoid the repetitive and error-prone
coding of many nearly-the-same sub-paths in your code for various types of
objects that don't quite share properties, but almost do.  By saying "there
is one global object type with properties and I will just code the
properties", you avoid that.  Sufficiently careful coding of your various
types, for instance by flagging them with properties, will also allow you
to avoid that...  And then you basically have one object type, but with
properties.

Yeah, someone did bring the mutation thing up before.  I considered it a
null reason for persistence, though.  I guess my main sticking point was
just bringing in behavior code somehow to a given class of object and
making it work as seamlessly as an inheritance tree.  I think, in theory,
it can be done the same either way, but when I sat down to write an
/obj/thing.c myself, I felt I was doing way too much work for less or the
same gain as just nesting inherits for each object class.  I haven't thrown
the idea out totally, yet, because I intend to make my hybrid mudlib and
then see what I can do to make a copy of it be full-on persistent after I
get used to running the lib from the inside.  Reading docs and archives
doesn't make me anywhere near expert enough to make these kinds of design
decisions until I do.

> The various player-body stuff isn't actually about save files versus
persistent.  You can implement any of the player-body features you mention
with either design.

I just didn't like the idea of letting a player's body hang about in memory
and risking the chance of losing them forever or letting them clutter up
memory.  I know it was discussed going through and culling idle bodies, but
my concerns relate to losing track of objects in persistence mode more than
anything.

> Your various arguments about swap files also apply to your save files.
 That is, none of your nominal reasons for choosing one over the other
actually favor one over the other significantly.  There's nothing wrong
with save files for objects, of course.  The basic tradeoffs are:
>
> * swapfiles are faster because the save code is done custom in C, and you
don't need to separately marshal the objects.
> * swapfiles, managed well, are already 50%+ pre-saved at any given time
because DGD swaps out idle objects.
> * swapfiles can preserved leaked objects, while good save files never
should.
> * swapfiles are less human-friendly to edit.
> * swapfiles require upgrading objects in place rather than allowing
save/restore-style upgrades.
> * swapfiles always automatically fully preserve object relationships,
while save files can have save/restore errors.
> * swapfiles require no marshalling code, while save files require writing
it.

- Saving a player to disk shouldn't take too long and its importance
supercedes any bit of time it may take.  save_object() is in DGD, so it
should be fast enough.  Only saving the inventory to string recursively
would be all LPC and take some time.
- I wonder how savable objects would handle upgrading in place...  I have
to really think about that one.
- Saving your inventory would require a mapping with the object's master
filename and its internal data dumped to string in a special format
different from anything Felix already does in save_object().  I currently
have made an LPC function that does this using a "{<filename>:var=val}"
format.  When loading from a string, it clones the filename and feeds it a
mapping of the data fields that followed.  This might be akin to the MudOS
class structure to some small degree.  The important point is that the
filename points to a class of object that has all the defaults ready to go,
and then the mapping of data overwrites whatever was overwritten in the
original inventory object.  Every object in the game will be able to do
this, just some objects, like users, won't pass their info out to the
'environment' object because they handle their owns ports-of-entry into the
game.

> That's not a slam-dunk either way.  A hybrid design gets a hybrid of
these tradeoffs -- you have to write some save/restore code and it can have
some (fewer) errors.  Savefile objects are fairly unlikely to leak, while
non-savefile objects can.  Savefile objects are editable and upgradable,
while your non-savefile objects aren't.  And so on.

Yeah, it's just that some things need to be protected from hanging about in
the swap, like users, for reasons mentioned.  I otherwise intend to use the
persistence model as best I can.  The load point trick I mentioned is
coupled with a clean-up mechanism for removing unused zones from
memory/swap, which is part of the hybridness of the lib design.  In a
futuristic-themed game with an enormous space environment, I think that
cleaning up unused zones and their contents is important.  It's probably
not as necessary to clean up a small game world, though, if the right
mechanisms are in place to remove trash objects.

> You're right about areas -- being able to write, import and export areas
requires some kind of disk format.

Especially when I plan to have two different servers running, a Dev server
for creation of the game, and a Live server for players to play on.  Areas
have to be copied from one to the other.

Thanks for taking the time to respond.  Good insight.

--Blain



More information about the DGD mailing list