ID:1373812
 
(See the best response by Ter13.)
Problem description:
I am currently creating a single player game with levels in it. I have a list variable named Levels that keeps track of all the levels the player has beat (it also keeps track of how many moves the player used to beat the level). I've tried to set it up so that the game saves this list. The problem is I can't seem to get it to work and I don't know why. I've looked up a lot of resources and I think I'm doing it right, but its not working.

Can someone help me out, I don't know what the problem is, whether its saving incorrectly or loading incorrectly or something.


Code:
//Saving
var/Levels[120] //currently 120 levels
var/lvl //keeps track of the current level
turf/end
Entered(mob/player) //saves whenever player reaches end of level
if(!Levels[lvl] || player.moves < Levels[lvl]) //If this is the first time beating a level save it, or if you do it in less moves save the better moves.
Levels[lvl] = player.moves
player.Save()

mob/proc/save()
var/savefile/F = new()
Write(F)
client.Export(F)

mob/Write(savefile/F)
F.cd = "list"
for(var/v in Levels)
F<< v
F.cd = ".."

//loading
mob/Login()
..()
var/savefile/F = client.Import()
if(F) Read(F)

mob/Read(savefile/F)
var/v = null
F.cd = "list"
while(!F.eof)
F >> v
Levels += v
F.cd = ".."


I've done several variations of this code and none of them have seemed to work. I don't think the savefile is being exported correctly but honestly I'm not sure at all.

Thanks for any help in advance!
I've also done this for my read proc. (Which also doesn't work)
mob/Read(savefile/F)
var/i = 1
F.cd = "list"
for(i,i<= Levels.len, i++)
F >> Levels[i]
F.cd = ".."
Is there something about savefiles I don't understand. Does anybody see a problem with my code? If there isn't a problem in my code than what is the problem? This code does create a .sav file, but I'm not sure if it stores the information correctly. Is there another way I could do this, like just make a .txt file? If so how can I do this? I've gone to a few tutorials and looked some things up but I honestly cannot find an answer anywhere.
F.ExportText(, "output.txt")
//Saving
var/Levels[120] //currently 120 levels
var/lvl //keeps track of the current level
turf/end
Entered(mob/player) //saves whenever player reaches end of level
if(!Levels[lvl] || player.moves < Levels[lvl]) //If this is the first time beating a level save it, or if you do it in less moves save the better moves.
Levels[lvl] = player.moves
player.Save()

mob/proc/save()
var/savefile/F = new("Data.sav")
F["levels"] << Levels
client.Export(F)

//loading
mob/Login()
..()
var/savefile/F = client.Import()
if(F) F["levels"] >> Levels

I've no idea what you're trying to do and don't care to try figure it out, but i've given you a conventional fix. Note that if you're not calling your save() proc anywhere, the file won't save. I'm assuming the player manually saves the game, as you haven't included the Logout() proc here.
Best response
Oh... Wow... Yeah, your problem is mostly due to you abusing the save function, and segmenting your data in a manner that is... Well, bizarre.

Don't invoke Write()/Read() manually unless you *really* know what you are doing. Especially if you are doing strange things like saving global variables in a player-specific array.

save()
var/savefile/F = new/savefile("savegame.sav")
F.cd = "levels"
for(var/v in levels)
F << v

load()
var/savefile/F = new/savefile("savegame.sav")
var/sc = 1
var/v = null
F.cd = "levels"
while(!F.eof)
F >> v
levels[sc++] = v


You need to remember to assign the variables into your level array by numeric index, because just adding them in is likely the problem you are having.
Instead of using savefile.eof, you can loop over savefile.dir after setting savefile.cd to the directory you want to loop over, it's a little cleaner to read and a bit faster on large savefiles. It also lets you reference the data a bit more friendly-like.

F.cd = "levels"
for(var/L in F.dir)
levels[L] = F.dir[L]


You can save/load them however you want then and they'll still be spit back out properly.

At the same time you can also simplify the process a lot by just saving and loading the list and letting the savefile system handle structure for you.

F["levels"] << levels // For saving
if(F["levels"]) F["levels"] >> levels // For loading.


Occasionally things saved this way end up out of order, but since you're using hard references in the list anyways you don't need to worry about it too much. Keep in mind though, using actual numbers as the index name can muck this up, so whenever I'm worried about the ordering I just use text indexes, makes manual look-up easier anyways.
Thanks everyone. You are life savers. I clearly have a poor grasp of save files. Fortunately everything is now hunky-doory.
Think of savefiles like a file system, there are directories containing files (and other directories of course), which contain data. Once you know how they work fundamentally you can manipulate them to do some pretty interesting things, like simple and efficient map region saving.