DefSave implicitly saving to file

I’ve recently picked up @Pkeod’s excellent DefSave, but I’ve run into a problem I cannot seem to resolve. I set up an empty module for storing data (main.datastore), and when I load data from a file I simply change all the keys in this data storage file. This works excellent for most cases, except for one peculiar case, when it seems as if DefSave saves to file without me doing so explicitly.

I set up a barebones example below:

local data = require "main.datastore"
local defsave = require "defsave.defsave"

function init(self)
	-- This should be the value that we always see when printing defsave.get(...)
	-- as no saving is done.
	data.TEST_VALUE = {}

	-- Setting up the file
	defsave.set_appname("test_defsave")
	defsave.load("test")
	defsave.set("test", "TEST_VALUE", data.TEST_VALUE)
	defsave.save("test")
end

function update(self, dt)
	-- Move the game object to the right every frame 
	go.set_position(go.get_position() + vmath.vector3(dt, 0, 0))

	-- This seems to be the problematic piece. 
	data.TEST_VALUE[1] = go.get_position()

	-- Here we expect to print a value that is constantly growing away from the origin.
	print("Value in data:")
	pprint(data.TEST_VALUE)

	-- This value should never be anything other than (0,0,0), as no saving is done, 
	-- and yet it behaves just like the value above.
	print("Value in file:")
	pprint(defsave.get("test", "TEST_VALUE"))
end

The output from this looks like

DEBUG:SCRIPT: Value in data:
DEBUG:SCRIPT: 
{
  1 = vmath.vector3(0.28333336114883, 0, 0),
}

DEBUG:SCRIPT: Value in file:
DEBUG:SCRIPT: 
{
  1 = vmath.vector3(0.28333336114883, 0, 0),
}

which is clearly not what I expect to happen, since I am not saving anything to the file at any point.

Indeed, if I replace the line

data.TEST_VALUE[1] = go.get_position()

by

data.TEST_VALUE = go.get_position()

the output becomes, just as I would expect,

DEBUG:SCRIPT: Value in data:
DEBUG:SCRIPT: vmath.vector3(0.45000016689301, 0, 0)
DEBUG:SCRIPT: Value in file:
DEBUG:SCRIPT: 
{
}

Something seems to go wrong when using a table, clearly. Is this a bug, or am I missing something? Some help would be much appreciated! :persevere:

For reference, the data module is just

local M =  {}
return M

How us DefSave dealing with tables? What happens when you do defsave.set() on a table? Is it making a deepcopy or could it be that it is the same table you are writing to and reading from?

On vacation and finding it cumbersome to browse code on a phone… only guessing here.

Ah, the problem seems to lie somewhere there. If I do defsave.set() with a deep copy of the table instead of the original table, the problem disappears. That seems to be a workaround for now, but I am wondering if this is intended behavior or not, as it leaves less control over the save files with this kind of leaking into the files at unexpected times.

There’s a deep copy function in the source already, it needs to be applied to defsave.set

If you would like to give a shot at fixing it your PR contribution would be most welcome!

3 Likes

Latest DefSave is now using deep copy for get/set to hopefully ensure decoupled tables. Please test!

3 Likes

Thanks, I’ll test it as soon as I can!

1 Like