ID:158921
 
How would i Make a World Save Verb? would i just take the Save Verb and change Save() to world.Save()? Heres my Save Verb just to look at as a reference
 mob
verb
Save()
var/savefile/F=new("players/[copytext(src.ckey,1,2)]/[src.ckey]/slot[sslot].sav")
F["x"]<<src.x
F["y"]<<src.y
F["z"]<<src.z

src.Write(F)
No, and that save verb is wrong. It's producing a mangled save file which can result in loss of data. You should NOT be calling Write() or Read() directly, but instead rely on the << and >> operators on a savefile in order to read and write. They will call Write() and Read() themselves, after formatting it properly. If you need to do any special processing when saving or loading, that should all go in Write() and Read(). Like so:

mob
Write(var/savefile/F)
..()
//save our location:
F["x"] << x
F["y"] << y
F["z"] << z
Read(var/savefile/F)
..()
//read our location
var/tx, ty, tz
F["x"] >> tx
F["y"] >> ty
F["z"] >> tz
var/turf/T = locate(tx, ty, tz)
if(T)
loc = T


I strongly suggest reading LummoxJR's article The Pitfalls of Savefiles

Anyway, for saving the world, you can't just write F << world. You need to save individual objects. Most straightforward is just to save every turf. You'll lose area information, but fixing that is a pain (areas do not load from savefiles very well). So, you'd just do this:

proc
worldsave()
var/savefile/F = new("world.save")
for(var/turf/T)
F << T

worldload()
var/savefile/F = new("world.save")
var/atom/A
//load everything in the file
while(!F.eof)
F >> A


Note that there are still going to be some issues with this, aside from having a needlessly huge save file. Like, for example, saving copies of players. Have I mentioned that you should read LummoxJR's article The Pitfalls of Savefiles? The fix to that problem, in this case, isn't exactly trivial. Saving the entire world is generally something you don't want to do, and I suggest thinking what it is, exactly, that you want to save.
In response to Garthor
Garthor wrote:
No, and that save verb is wrong. It's producing a mangled save file which can result in loss of data. You should NOT be calling Write() or Read() directly

Eh, I don't see where any mangling would come from, but anyway, that is wrong. You can either use the savefile operators, or call the object savefile procs directly to save objects. Both are valid, and are different kinds of saves; using F << obj is essentially an entire object save, and reloading it with >> means recreating the entire object from scratch. Using Write() is more like saving only the properties of an object, and using Read() restores them to an existing object.
The difference between the approaches isn't great, but it's there. Main point is, you can use direct Write()-Read() calling without issues (just don't mix << with Read(), etc). Even the DM Guide explains this and there are examples that use the procs.
In response to Kaioken
I was being a bit overdramatic, "mangling" was perhaps not the correct word to use, and I didn't get to my main point, which was that if you use Write() and Read(), type data is not saved. So, if you made a /mob/ninja, saved it, and then tried to load it, you would not know which type of mob to create to Read() the savefile into.

I also meant to get into the apparent "save slots" that he was using (via multiple savefiles) which are unnecessary when one file could hold as many separate characters as needed. However, there would not be any straightforward means of doing this if Read() and Write() were called directly. If << and >> were used, it would be as simple as:

F["slot[n]"] << src
In response to Kaioken
Kaioken wrote:
Garthor wrote:
You should NOT be calling Write() or Read() directly

..., but anyway, that is wrong. You can either use the savefile operators, or call the object savefile procs directly to save objects. Both are valid, and are different kinds of saves; ... ...Even the DM Guide explains this and there are examples that use the procs.

Actually you're both wrong. You can call Read() or Write() whenever you want, and it is in absolutely no way a bad practice, unless you are doing so inside the Read() and Write() procs. Then you are going to encounter some problems.

Savefile << Object and Object.Write(Savefile) are identical IF you are using << to write an entire datum. Mixing the two is in fact a bad idea, as Garthor says, because you're calling the same proc you are using INSIDE OF ITSELF. That is bad.
EDIT: OR you are calling the same proc twice, assuming this isn't being done in Read() or Write(), which could possibly leave you with a bunch of duplicate information, or not at all. But it's still unnecessary overhead.

Obviously the same goes for >> and Read(Savefile), they are identical when used in reference to an entire datum.


To the OP:
Saving the entire world is a hefty business if you do it inefficiently.
Looping through every object in the world (even ones that are set during compile time) and saving them is usually a bad idea. Also saving mobs is bad. A few things for you to think about. There are world saving libs out there, download a few and see how they work and what features they offer you.
In response to Garthor
Garthor wrote:
I was being a bit overdramatic

Eh... "a bit", huh? ;)

However, there would not be any straightforward means of doing this if Read() and Write() were called directly.

I guess that depends on whether or not you consider changing the dir in order to write into a different dir straightforward. =P
In response to Kaioken
Kaioken wrote:
Garthor wrote:
However, there would not be any straightforward means of doing this if Read() and Write() were called directly.

I guess that depends on whether or not you consider changing the dir in order to write into a different dir straightforward. =P

Overwriting the original functionality of Read() and Write() isn't that un-straitforward. But I'd also suggest avoiding doing so whenever possible.
In response to AJX
AJX wrote:
Actually you're both wrong.

Good to know, but funny, I don't see why I am in your post. ;P

You can call Read() or Write() whenever you want

No. Obviously, you can only call Read() on an existing object. You can't use Read() to create a new object, and so load an object from scratch.


Savefile << Object and Object.Write(Savefile) are identical IF you are using << to write an entire datum.

No, they're not identical. The resulting data in the savefile is of a slightly different structure, and using << stores the type, as >> needs it in order to know what type of object to create when loading.

Mixing the two is in fact a bad idea, as <s>Garthor</s> (Kaioken)
In response to AJX
Uh, nothing you said there actually has to do with what you're replying to. Where the heck was overriding the procs mentioned? Clearly you don't need to do that in order to just change to a different dir in the savefile...
In response to Kaioken
Kaioken wrote:
AJX wrote:
No, they're not identical. The resulting data in the savefile is of a slightly different structure, and using << stores the type, as >> needs it in order to know what type of object to create when loading.
I stand corrected. They aren't identical, just incredibly incredibly similar. :p
In response to AJX
Small differences matter. I'd rather stick to the one that's easier to use and more versatile.