ID:161294
 
is there any way/code to make save files smaller?

268 saves take 20.9mb which is bit inconvenient when sharing with other hosts.
piece of my save code:
client
proc
Load()
if(src.mob.save_file_1)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 1.sav")
load["mob"] >> src.mob
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z
if(src.mob.save_file_2)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 2.sav")
load["mob"] >> src.mob
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z
if(src.mob.save_file_3)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 3.sav")
load["mob"] >> src.mob
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z


Save()
if(!src)return
if(!src.mob)return

if(src.mob.save_file_1)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 1.sav")
save["mob"] << src.mob
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
if(src.mob.save_file_2)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 2.sav")
save["mob"] << src.mob
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
if(src.mob.save_file_3)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 3.sav")
save["mob"] << src.mob
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
Hmm, that's odd... there used to be a zipfile library, Dantom.zipfile. However, I can't find it on the hub at the moment, so I assume it was taken down for some reason.
I think you can reduce the savefile size by using the ExportText() function to generate a text-format version of the savefile. Here's a model:

var/t

client/verb
Save()
var/savefile/S = new("somefile.sav")
S["1"] << 1
S["2"] << 2
S["3"] << 3
S["x"] << mob
t = S.ExportText()
src << "Savefile of length ([length(S)]) exported to text of length ([length(t)])."
src << "Target is [length(t)/length(S)*100]% size of source.<hr>"

Load()
if(t)
var/savefile/S = new("somefile.sav")
S.ImportText("", t)
src << "Savefile of length ([length(S)]) loaded from text of length ([length(t)])."
src << "Target is [length(S)/length(t)*100]% size of source.<hr>"
else
src << "Use Save first!<hr>"


I think, in most cases, the return value from ExportText() is smaller in size than the actual savefile, and you can then return to the normal savefile via ImportText().
Gogeta126 wrote:
is there any way/code to make save files smaller?

dont save the mob as this could end up saving several icon files which make save files huge.
write out a line for every variable you NEED to save like you did for x y and z

EDIT: also ive found it helps keep size down if you fdel() the save file before saving it again. And as for converting to a text file you could always just give it a .txt extension to begin with instead of a .sav
In response to Falacy
Falacy wrote:
And as for converting to a text file you could always just give it a .txt extension to begin with instead of a .sav

Changing the extension doesn't do anything. ExportText() does, however, seem to result in a smaller file size than the original savefile, for some reason.
In response to Garthor
hub://Dantom.zipfile

I find it incredibly odd that the ExportText() savefile is smaller than that of the savefile in standard form. That's nuts!
In response to Kuraudo S.
Kuraudo S. wrote:
I think you can reduce the savefile size by using the ExportText() function to generate a text-format version of the savefile. Here's a model:

var/t
>
> client/verb
> Save()
> var/savefile/S = new("somefile.sav")
> S["1"] << 1
> S["2"] << 2
> S["3"] << 3
> S["x"] << mob
> t = S.ExportText()
> src << "Savefile of length ([length(S)]) exported to text of length ([length(t)])."
> src << "Target is [length(t)/length(S)*100]% size of source.<hr>"
>
> Load()
> if(t)
> var/savefile/S = new("somefile.sav")
> S.ImportText("", t)
> src << "Savefile of length ([length(S)]) loaded from text of length ([length(t)])."
> src << "Target is [length(S)/length(t)*100]% size of source.<hr>"
> else
> src << "Use Save first!<hr>"

I think, in most cases, the return value from ExportText() is smaller in size than the actual savefile, and you can then return to the normal savefile via ImportText().

im not too good y'know but i did like this:
client
proc
Load()
if(src.mob.save_file_1)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 1.txt")
load["mob"] >> src.mob
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z
load.ImportText("", t)
if(src.mob.save_file_2)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 2.txt")
load["mob"] >> src.mob
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z
load.ImportText("", t)
if(src.mob.save_file_3)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 3.txt")
load["mob"] >> src.mob
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z
load.ImportText("", t)


Save()
if(!src)return
if(!src.mob)return

if(src.mob.save_file_1)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 1.txt")
save["mob"] << src.mob
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
t = save.ExportText()
if(src.mob.save_file_2)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 2.txt")
save["mob"] << src.mob
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
t = save.ExportText()
if(src.mob.save_file_3)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 3.txt")
save["mob"] << src.mob
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
t = save.ExportText()

var/t


i suppose i did something wrong as the savefile aint affected a lot. AND i cant load it so i guess i'll change it back to .sav
In response to Gogeta126
Gogeta126 wrote:
im not too good y'know but i did like this:
> client
> proc
> Load()
> if(src.mob.save_file_1)
> var/savefile/load
> load = new ("Player Saves/[mob.ckey]/Save File 1.txt")
> load["mob"] >> src.mob
> load["x"] >> src.mob.x
> load["y"] >> src.mob.y
> load["z"] >> src.mob.z
> load.ImportText("", t)
> if(src.mob.save_file_2)
> var/savefile/load
> load = new ("Player Saves/[mob.ckey]/Save File 2.txt")
> load["mob"] >> src.mob
> load["x"] >> src.mob.x
> load["y"] >> src.mob.y
> load["z"] >> src.mob.z
> load.ImportText("", t)
> if(src.mob.save_file_3)
> var/savefile/load
> load = new ("Player Saves/[mob.ckey]/Save File 3.txt")
> load["mob"] >> src.mob
> load["x"] >> src.mob.x
> load["y"] >> src.mob.y
> load["z"] >> src.mob.z
> load.ImportText("", t)
>
>
> Save()
> if(!src)return
> if(!src.mob)return
>
> if(src.mob.save_file_1)
> var/savefile/save
> save = new ("Player Saves/[mob.ckey]/Save File 1.txt")
> save["mob"] << src.mob
> save["x"] << src.mob.x
> save["y"] << src.mob.y
> save["z"] << src.mob.z
> t = save.ExportText()
> if(src.mob.save_file_2)
> var/savefile/save
> save = new ("Player Saves/[mob.ckey]/Save File 2.txt")
> save["mob"] << src.mob
> save["x"] << src.mob.x
> save["y"] << src.mob.y
> save["z"] << src.mob.z
> t = save.ExportText()
> if(src.mob.save_file_3)
> var/savefile/save
> save = new ("Player Saves/[mob.ckey]/Save File 3.txt")
> save["mob"] << src.mob
> save["x"] << src.mob.x
> save["y"] << src.mob.y
> save["z"] << src.mob.z
> t = save.ExportText()
>
> var/t


No, not like that. First off, ending a savefile in .txt doesn't magically make it a text-file; you can give it whatever extension you want and it will still save and load as normal. In my example, t was just a temporary container for the file; you would actually want to output that as a file after exporting it from the savefile, and import it before loading. Something like this should work:
client
proc
Load()
var/savefile/load = new
var/filetext

// You should come up with a better way of managing which savefile to use
if(src.mob.save_file_1)
filetext = file2text("Player Saves/[mob.ckey]/Save File 1.txt")
else if(src.mob.save_file_2)
filetext = file2text("Player Saves/[mob.ckey]/Save File 2.txt")
else if(src.mob.save_file_3)
filetext = file2text("Player Saves/[mob.ckey]/Save File 3.txt")

if(filetext)
load.ImportText("", filetext)
if(load)
/*
Load from file here
*/

return 1 // Savefile existed
return 0


Save()
if(!src.mob)return

var/saveName

if(src.mob.save_file_1)
saveName = "Player Saves/[mob.ckey]/Save File 1.txt"
else if(src.mob.save_file_2)
saveName = "Player Saves/[mob.ckey]/Save File 2.txt"
else if(src.mob.save_file_3)
saveName = "Player Saves/[mob.ckey]/Save File 3.txt"

if(saveName)
if(fexists(saveName))
fdel(saveName)

var/savefile/save = new

/*
Save to file here
*/


text2file(save.ExportText(), saveName)

return 1
else
return 0


It's also important that you read through the code for meaning, and try to understand how it's working, rather than simply pulling from the forums with the ever-attractive copy&paste mechanism. If you have questions, try to solve them yourself, and if you can't, ask about them here.
In response to Falacy
Falacy wrote:
write out a line for every variable you NEED to save like you did for x y and z

Stop giving horrible advice, it's doing the opposite of helping. No you don't NEED to do it and you can still skip certain variables however you want, if you know what you're doing.

And as for converting to a text file you could always just give it a .txt extension to begin with instead of a .sav

Also, don't talk about things you clearly have no clue about. File extensions are just a part of the file's name. If you change a file's name, it doesn't alter the file itself in any way. Extensions are only an indicator of files' format.
In response to Kaioken
Kaioken wrote:
Falacy wrote:
write out a line for every variable you NEED to save like you did for x y and z

Stop giving horrible advice, it's doing the opposite of helping. No you don't NEED to do it and you can still skip certain variables however you want, if you know what you're doing.

learn to read retard, i said he only needs to write a save line for each variable that is needed at load time
Saving the entire mob is what's making your save files so big. You should only save the variables you want to keep track of.
client
proc
Load()
if(src.mob.save_file_1)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 1.sav")
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z
if(src.mob.save_file_2)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 2.sav")
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z
if(src.mob.save_file_3)
var/savefile/load
load = new ("Player Saves/[mob.ckey]/Save File 3.sav")
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z


Save()
if(!src)return
if(!src.mob)return

if(src.mob.save_file_1)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 1.sav")
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
if(src.mob.save_file_2)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 2.sav")
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
if(src.mob.save_file_3)
var/savefile/save
save = new ("Player Saves/[mob.ckey]/Save File 3.sav")
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
In response to SuperAntx
y does everyone keep quote posting this giant save system
you dont need everything 3 times, all you need is 1 save slot variable
client
proc
Load()
var/savefile/load
load = new ("Player Saves/[src.mob.ckey]/Save File [src.mob.SaveSlot].sav")
load["x"] >> src.mob.x
load["y"] >> src.mob.y
load["z"] >> src.mob.z


Save()
if(!src)return
if(!src.mob)return

var/savefile/save
save = new ("Player Saves/[src.mob.ckey]/Save File [src.mob.SaveSlot].sav")
save["x"] << src.mob.x
save["y"] << src.mob.y
save["z"] << src.mob.z
In response to Falacy
Falacy wrote:
y does everyone keep quote posting this giant save system
you dont need everything 3 times, all you need is 1 save slot variable

So he understands the changes. He didn't ask you to optimize his system, he just wanted to know why his saves were so big.
In response to SuperAntx
SuperAntx wrote:
You should only save the variables you want to keep track of.

Which should be mostly any variable that has changed from its initial value, and that's already how the BYOND built-in object saving system (which you should use) works. In addition, any variable you specifically do not wish to save should be marked 'tmp' for compability with the issaved() proc and the built-in saving system, which you can then use to your liking.
In response to Kaioken
Kaioken wrote:
Which should be mostly any variable that has changed from its initial value

in paradise city, out of the 40+ variables that i've defined and the countless built-in byond variables, I only save 11 of them, 2 of which are basicaly just temporary variables that are only used during the save/load process
In response to Falacy
Falacy wrote:
learn to read retard,

Seriously, re-read the posts you're replying to and your own posts before you submit them. Do not question another's ability to read while proving your own inability. :O

i said he only needs to write a save line for each variable that is needed at load time

That doesn't matter, it's already what I referred to and still a hideous, horrible, non-robust, non-flexible, error-prone, and generally bad method, and its effect can be much more easily replicated by much better code. That's enough for you to understand? Maybe I should add color as well.

in paradise city, out of the 40+ variables that i've defined

40+? Most of them probably stem of very bad design, I'd imagine.

and the countless built-in byond variables, I only save 11 of them,

Again, the variables you don't want to save should be marked tmp, which will cause them not to be saved when using the much better built-in object saving method, as well as allow the built-in issaved() proc to be utilized on them. For any further customization of it, you can override the Write() procedure as needed.

2 of which are basicaly just temporary variables that are only used during the save/load process

^Yes, most likely definitely bad design indeed.
In response to Garthor
Zipfile is great. I use to allow the dmb for the Chatters channel server to extract its resources and necessary files from a zip I package with the server, to reduce the download size of the distribution package. I've also used it to create backup archives of error logs, which can be useful sometimes. Especially if you're like me and don't always get around to fixing the bugs in a timely manner. >.>