ID:154261
 
I'm looking for a way to scan through every turf in existence, save one or two variables, then recall those two variables to the appropriate turfs later. I've tried a few things to make this work on my own, but it's quickly becoming obvious that I don't have a clue what I'm doing. So, any help or suggestions would be appreciated :o)
I'll give you an example for one variable per turf, using multiple-dimension arrays. It can be expanded to two pretty easily. This assumes you want to save every turf in the world, and won't be very efficient if you only save a few. This will take a ton of memory if you have a lot of turfs, but theres no way to avoid it.

proc/save_turfs()
var/turflist[world.maxx][world.maxy][world.maxz]
for(var/turf/T in world)
turflist[T.x][T.y][T.z] = T.some_variable
//then just save turflist to some savefile

proc/load_turfs()
//load turflist from a savefile, then
for(var/X in 0 to world.maxx)
for(var/Y in 0 to world.maxy)
for(var/Z in 0 to world.maxz)
var/turf/T = locate(X, Y, Z)
T.some_variable = turflist[T.x][T.y][T.z]

[Edit:] I should also add that this will slow the server down a lot. If you need it to be running a lot in the background, insert some sleeps in there!

-AbyssDragon
Foomer wrote:
I'm looking for a way to scan through every turf in existence, save one or two variables, then recall those two variables to the appropriate turfs later. I've tried a few things to make this work on my own, but it's quickly becoming obvious that I don't have a clue what I'm doing. So, any help or suggestions would be appreciated :o)

How about this?
var/list/allturfs=list()
for(var/turf/T in world)
var/txt="[T.type]\n[T.icon_state]"
allturfs["[T.x],[T.y],[T.z]"]=txt

...
for(var/entry in allturfs)
// split() doesn't exist, but you can write it
var/list/xyz=split(entry,",")
var/list/properties=split(allturfs[entry],"\n")
var/turftype=properties[1]
var/turf/T=new turftype(locate(xyz[1],xyz[2],xyz[3]))
T.icon_state=properties[2]

This would be rather wasteful considering the length of each xyz string and each turftype string, but it's a good starting point. Probably a lot better would be to try to approach something like the .dmp format uses, where a character stands for each turf/obj type.

If you don't need the x,y,z values so much, another method is simply to fill your lists with the type/state values. This relies on for(var/turf/T in world) to always return the same order, though, which it might not; block() is probably more reliable for this.

Lummox JR
In response to AbyssDragon
That'd work great, if it weren't giving me Cannot read null.x errors... (And I honestly can't figure out why.)

Any attempts to fix have resulted in more errors.
In response to Foomer
In load_turfs()? I made a boo-boo. This should fix it:

proc/load_turfs()
//load turflist from a savefile, then
for(var/X in 0 to world.maxx-1)
for(var/Y in 0 to world.maxy-1)
for(var/Z in 0 to world.maxz-1)
var/turf/T = locate(X, Y, Z)
T.some_variable = turflist[T.x][T.y][T.z]

If that doesn't work, but some debug statements in to see what values of X, Y, Z are causing T to be null.

-AbyssDragon
In response to AbyssDragon
Err, actually I think it should have been for(var/X in 1 to world.maxx), because that seems to work just right.

However, I've run into another little problem with this idea. Any world that uses over roughly 65,000 turfs ends up crashing DS because of too many lists.

Shall I assume that Lummox has a fix for this in his head? **Goes to look**
Well this may help hehe I posted it for someone else and I tested and it works so if its what you want then here you go.

Go Here
In response to Foomer
Why bother with the list at all? Store it directly into the save file.

proc
SaveTurfData()
var/savefile/F = new("turfs.sav")
for(var x in 1 to world.maxx)
for(var y in 1 to world.maxy)
for(var z in 1 to world.maxz)
var/turf/T = locate(x,y,z)
F["[x],[y],[z]"] << T.yourvar

LoadTurfData()
var/savefile/F = new("turfs.sav")
for(var x in 1 to world.maxx)
for(var y in 1 to world.maxy)
for(var z in 1 to world.maxz)
var/turf/T = locate(x,y,z)
F["[x],[y],[z]"] >> T.yourvar

In response to Shadowdarke
Well, at first attempt, trying to save a 5x5 map basically freezes dreamseeker (either that, or takes such a ridiculously long time that it's not worth it.)
In response to Shadowdarke
What if you want to save all the objects located in an area instead of turf? I plan to make an area like

area/objsavetile

Now what I need is for ever area of this type to just save to disk every 30mins. And to load up on Reboot. Also hoping to save the objects which are placed inside objects as well like boxes and chest.

LJR
In response to Foomer
I just tested it with a simple numeric variable and it worked like a charm on a small map (after a minor embarassing fix: "var/x", not "var x"). More complex variables will take longer to save. With a large map, you'll want to add periodic delays or chop the world into chunks to keep from freezing the world.
In response to Shadowdarke
Mine needs to save a short text string.

At the moment, I'm considering looking into more dynamic ways of saving things. Since this is for FoomerMUD's saving system, I could probably make an option to edit a room in game, then whenever a player enters that room during the game, it loads a check from the mass savefile to see if this room has been saved or not, and if it has, it loads the save.

Something like that would probably work better...at least for the host.