ID:1819392
 
(See the best response by Ter13.)


Problem description:All mobs have the list 'target'. When world/New() is called, I'm trying to reset every savefiles 'target' list back to null. I'm sure there's a way to do this, I'm just not too experienced with savefiles. Any suggestions?

Best response
Don't save the target list in the first place. It should be marked temporary.

http://www.byond.com/docs/ref/info.html#/var/tmp

Because you've saved other players inside of savefiles already, your savefiles are too polluted to be fixed.
...Wow, for some reason the idea of making it a tmp var just went right over my head. Thanks a lot, really simplifies my problem.
You've given me a topic for Snippet Sunday #10. I'll be talking about strategies for dealing with a whole bunch of problems you probably don't know you are going to run into with your target list.

I don't wanna spoil it, but thanks for reminding me I haven't done an article on reference cleaning.
Oh, also, sorry to bump again so soon, but I wrote a two-part article on using savefiles a little over a year ago.

http://www.byond.com/forum/?post=1187245

I also go over some common mistakes and pitfalls in these articles. You'll probably benefit from reading them.
You also have the option of cleansing old savefiles during the load process, so you can clear out the list before it loads if you want to keep old savefiles without wiping.

mob/Read(savefile/F)
F["target"] << null
..()

I also posted a tutorial on savefile issues some time ago, which would be good to read alongside Ter's article.
^That's a great tutorial, Lummox. It covers all of the stuff I rant about pretty well. Also, I definitely like your method of blanking out information that's saved unintentionally better than mine.
In response to Lummox JR
Lummox JR wrote:
You also have the option of cleansing old savefiles during the load process, so you can clear out the list before it loads if you want to keep old savefiles without wiping.

mob/Read(savefile/F)
> F["target"] << null
> ..()

I also posted a tutorial on savefile issues some time ago, which would be good to read alongside Ter's article.



Can you give me an example of when this would be any different than just making it a tmp var? Does this not do the same thing that they do?
In this case, it'd be better to mark it tmp. But in other cases, Lummox's solution might be better.
You should do both, if you already have savefiles with this var set. It should have been /tmp from the beginning, but if there are savefiles in the wild that have a target list saved, you need to clear the list before it loads (not after!) to avoid problems like the dreaded rollback.

Essentially, the pre-clear avoids the need to wipe all savefiles. Most of the time when games "pwipe" it's a sign they were designed badly--there's almost always a workaround.
Here's how I do it, it's pretty much a plug'in.

If you're not wanting a variable saved just set it to tmp.

mob
var/tmp/file_path = "players"
var/tmp/save_loc = FALSE
proc
save()
var/savefile/S = new("[file_path]/[ckey].sav")
for(var/i in vars)
if(!(i in global.skip_vars) && issaved(vars[i]))
S[i] << vars[i]
if(save_loc)
S["x"] << x
S["y"] << y
S["z"] << z
S["step_x"] << step_x
S["step_y"] << step_y
return 1
load()
if(fexists("[file_path]/[ckey].sav"))
var/savefile/S = new("[file_path]/[ckey].sav")
for(var/i in vars)
if(!(i in global.skip_vars) && issaved(vars[i]))
S[i] >> vars[i]
if(save_loc)
S["x"] >> x
S["y"] >> y
S["z"] >> z
S["step_x"] >> step_x
S["step_y"] >> step_y
return 1
return 0

var/tmp/list/skip_vars = list(\
"icon","icon_state","tag","name","desc","suffix","text","dir","luminosity","opacity",
"overlays","underlays","density","layer","gender","pixel_x","pixel_y",
"infra_luminosity","invisibility","mouse_drop_zone","mouse_drop_pointer",
"mouse_drag_pointer","mouse_over_pointer","pixel_z","screen_loc","see_infrared",
"see_invisible","see_in_dark","key","sight","blend_mode","color","alpha","maptext",
"maptext_height","maptext_width","contents","group",
"bounds","step_x","step_y","step_size","glide_size")
Here's a thought to improve on the skip_vars list: Maybe have a proc that runs early on, like in world/New(), that converts the list to an associative list. All you need to do is this:

for(var/v in skip_vars) skip_vars[v] = 1

The reason is that it's faster to check skip_vars[i] rather than (i in skip_vars).

BTW, you also don't need skip_vars to be /tmp since it's global. It doesn't hurt anything, but it doesn't help anything either.
In response to Lummox JR
Lummox JR wrote:
Here's a thought to improve on the skip_vars list: Maybe have a proc that runs early on, like in world/New(), that converts the list to an associative list. All you need to do is this:

for(var/v in skip_vars) skip_vars[v] = 1

The reason is that it's faster to check skip_vars[i] rather than (i in skip_vars).

BTW, you also don't need skip_vars to be /tmp since it's global. It doesn't hurt anything, but it doesn't help anything either.

Wow, thanks that helped alot.