ID:138272
 
I'm adding some Really Cool multi-character saving functionality to BaseCamp, so that you can support your players having multiple characters without you having to write any savefile code.

But...DM doesn't seem to be happy with the concept. It insists on only allowing one character to persist in the savefile!

How it works is this...BaseCamp has it's own version of client, called Player. This class exists so it can be saved to disk, and it handles player meta-data, including player mobs. The Player object is saved upon quitting.

What happens is if I create multiple mobs in the same session and save them to the savefile, I'm able to list them all. Then when I quit and return, only one mob is showing in the savefile.

I must be missing something basic...

Here is the code...

BaseCamp/Player
Read(savefile/F)
// It is critical that the superclass set things up before we read from the directory.
var/result = ..()

// For any customized savefile work, find out the path we're stored at.
savefile_path = F.cd
return result

Write(savefile/F)
// It is critical that the superclass set things up before we write to the directory.
var/result = ..()
savefile_path = F.cd
if (base_save_mob)
SaveMob()
return result

proc
SaveMob()
// Saves the player's current mob based on the ckey of its name.

var/mob/Mob = mob()
var/name_ckey = ckey(Mob.name)
var/savefile/F = GameController.game_savefile
F.cd = "[savefile_path]/mobs/[name_ckey]"
F["name"] << Mob.name
F["mob"] << Mob
world << "Saved mob to '[savefile_path]/mobs/[name_ckey]/mob'." // DEBUG

LoadMob(char_name)
// Look for a character with the ckey version of this name.
// If found, load it, set the client mob to it, and return it.
// Otherwise return null.
var/mob/Mob
var/char_ckey = ckey(char_name)
var/savefile/F = GameController.game_savefile

F.cd = "[savefile_path]/mobs"
var/list/characters = F.dir
if (!characters.Find(char_ckey))
BASE_LOG("[type].LoadCharacter() could not locate character [char_name].")
client.mob << "Unable to load [char_name]."
return null
F["[char_ckey]/mob"] >> Mob
if (Mob)
client.mob = Mob
return Mob
return null

</<></<>
On 12/7/00 12:53 am Deadron wrote:

I must be missing something basic...

Not that I can tell, but without a bit more info I don't think I can help you out. It would be good to see the output of your test. One possible stumbling point would be if savefile_path were getting messed up when doing multiple saves. It's not altogether clear to me how that works from the code, but that is mostly because I don't know exactly how this is being called.

It is strange that it would work during the session but not afterwards. From that I would conclude that the buffer isn't being flushed to disk. You can test this by recreating the savefile everytime you write and read to it rather than keeping it open globally.

We'll get to the bottom of this!

Speaking of savefiles, did Z ever manage to get her situation working?
In response to Tom H.
On 12/7/00 5:10 am Tom H. wrote:
On 12/7/00 12:53 am Deadron wrote:

I must be missing something basic...

Not that I can tell, but without a bit more info I don't think I can help you out. It would be good to see the output of your test. One possible stumbling point would be if savefile_path were getting messed up when doing multiple saves. It's not altogether clear to me how that works from the code, but that is mostly because I don't know exactly how this is being called.

The savefile path appears to be the same each time.

It is strange that it would work during the session but not afterwards. From that I would conclude that the buffer isn't being flushed to disk.

Actually it seems to be the LAST one saved that survives each time, so buffer flushing probably isn't it.


You can test this by recreating the savefile everytime you write and read to it rather than keeping it open globally.

This is worth trying...

We'll get to the bottom of this!

If I don't get it working tonight I'll send you the code (I'm trying to spare you cause I know you are busy).

Speaking of savefiles, did Z ever manage to get her situation working?

Yes she said she got it working when she stopped saving out the contents of mobs I believe...
In response to Deadron
On 12/7/00 8:51 am Deadron wrote:
On 12/7/00 5:10 am Tom H. wrote:
Speaking of savefiles, did Z ever manage to get her situation working?

Yes she said she got it working when she stopped saving out the contents of mobs I believe...

Yeah, it was funny, saving and loading contents through:

for (v in src.vars) F[v] >> src.vars[v]

was creating the duplicates, while

for (v in src.vars)
if (v != "contents") F[v] >> src.vars[v]

F["contents"] >> src.vars[v]

worked fine. Which makes sense in a way, because the only real difference between the old, working code and the new, not-working code was that I'd started saving vars by looping through them.

Z
Ok here is the problem...this is a central one for robust savefile functionality...

What I'm doing is this:

On saving a player object, I call:

var/directory = "/players/[ckey]"
db["[directory]"] << player


The player Write code does this to add some customized behavior to the automated savefile behavior:

Player
Write(savefile/F)
var/result = ..()
savefile_path = F.cd
if (base_save_mob)
SaveMob()
return result

proc
SaveMob()
// Saves the player's current mob based on the ckey of its name.
var/savefile/F = GameController.game_savefile

var/mob/Mob = mob()
var/name_ckey = ckey(Mob.name)
var/directory = "[savefile_path]/mobs/[name_ckey]"
F.cd = directory
F["name"] << Mob.name
F["mob"] << Mob


What was confusing me was that if I called SaveMob() directly while the game was running, I could save and query multiple mobs for myself.

But upon quitting, when the entire player is saved to the file, the mobs I had saved previously are blown away. It appears that calling this line when there was already a pre-existing player in the file is destructive:

db["[directory]"] << player

Can we figure out a way around this? I want to be able to re-save the player without blowing away the custom directories I've added.

The workaround (which I'm about to do) is to store the mobs elsewhere, and not as part of the player directory structure.