ID:151713
 
I'm trying to come up with a really quick way of finding out which of an object's variables - the variables to be checked are listed in another variable - have been changed since the object was created, or also have been modified in the map editor.

However, I'm using this for a map saving library, so it basically gets called for every object in the world. Every object is checked, it loops through each of the variables that the object says it wants to keep track of, checks if those variables have changed, and then records which ones have changed. I imagine this gets pretty cumbersome when there are a lot of items to check.

Any suggestions on how to do this extra-quick? Here's what I'm using at the moment:

mydatum/proc/BuildSavedVarsData(atom/A)

// Get the list of saved vars, and if there aren't any then return null.
var/saved_vars = SavedVars(A)
if(!saved_vars)
return null

// Find out which vars out of the provided list have changed from their default value.
var/list/changed_vars = list()
for(var/v in params2list(saved_vars))
if(A.vars[v] != initial(A.vars[v]) && issaved(A.vars[v]))
changed_vars[v] = A.vars[v]

// If there are changed vars to save...
if(changed_vars.len)
var/params = list2params(changed_vars)
//return params
return params

// If no changed vars to save were found, return null.
return null


I've thought about perhaps having each object in the game record its default values for its saved variables list, then store them in another params set, just to save some processing time during the map saving, but that would likely just transfer the delay to the start of the program, and it would probably take up quite a bit of memory, too.
Foomer wrote:
Any suggestions on how to do this extra-quick? Here's what I'm using at the moment:

Personally I'd say doing things this way is just too inefficient.

You're probably better off using a proc to make any var changes to things that you want saved, and have that proc flag when the var has been changed.

I.E:
datum/var/SavedVars[]
turf/SavedVars=list("ID")
datum/proc/Set(Var,Val)
vars[Var]=Val
if(!SavedVars) return
if(SavedVars.Find(Var))
SavedVars[Var]=1


And just look through the savedvars list to check to see if they were changed or not.
In response to Garthor
Garthor wrote:
initial()

If you look at his code he already uses this. But when you're talking about multiple vars on thousands of atoms, this becomes very resource intensive very quickly.
Are you looping through all the changed vars a 2nd time when you go to save them?
In response to Falacy
Shouldn't be. This function basically just checks all that variables that the object wants to keep track of, finds out which ones have changed via initial(), and then returns a set of params containing the changes variables and their new values.

Those params are stored in the savefile, so that when the map is loaded, it will know which variables need to be restored to their changed value.
I agree with AJX: It would probably be far simpler to record this information as data is changed.
datum
var/list/changed_vars // allocated only when needed

proc/setVar(variable, value)
ASSERT(variable in vars)
vars[variable] = value

// I don't know why you use issaved() and saved_vars, but I'll just go with the former
if(issaved(vars[variable])) // could add initial() call to see if it is non-default
if(!changed_vars) changed_vars = new
changed_vars[variable] = value

mob
var
tmp/hp = 100
max_hp = 100

verb/Test()
setVar("max_hp", 200)
setVar("hp", 200)
for(var/i in changed_vars) src << "[i] = [changed_vars[i]]"


Of course, you could improve compiler checking by substituting out setVar() for individual set[varName]() procs, but this also requires significantly more code.

Unfortunately, if your library's design is to fit into any project without requiring much code refactoring, these ideas may not prove feasible.
In response to Kuraudo
Kuraudo wrote:
Unfortunately, if your library's design is to fit into any project without requiring much code refactoring, these ideas may not prove feasible.

Which is exactly the problem. I want my libraries to be plug and play, where all you have to do is include the library and call its functions, not rewrite a bunch of code to support it.