Trouble saving and loading arrays from a file

Im making a system where, in one collection, there are items the player picks up, which are then added to the inventory array. When an item is added to the array, the array is immediatly saved to the file. This all works and i end up with this in the file:

HDTB inventoryQ [“Crate”,“Crate”,“Crate”,“Crate”,“Crate”,“Crate”,“Crate”,“Crate”,“Crate”,“Crate”]

The scripts that handle this are the crate script:

function init(self)
	msg.post(".", "acquire_input_focus")
	ObjectName = "Crate"--the name saved in the save file
end

function on_input(self, action_id, action)
	if action_id == hash("interact")then
		if self.Touching == hash("/Player") then--only runs if the player is touching a collision object on the object
			msg.post(self.Touching, "ItemPickedUp",{objecturl = ObjectName})--tells the player that it has picked up this item
			go.delete()
		end
	end
end

function on_message(self, message_id, message, sender)
	--this part is for the proximity trigger
	if message_id == hash("collision_response") then--if it's colliding with something
		self.Touching = message.other_id--self.Touching is set to the id of that object
	end
end

And part of the player script:

local json = require("json")--need this to save and load arrays
savefile_path = sys.get_save_file("StellarSalvagers", "SaveFile")--defines file path where game data is saved
inventory = {}--creates the inventory array
inventoryslots = 10--number of slots the player has


function on_message(self, message_id, message, sender)
	if message_id == hash("ItemPickedUp") then--(for the item picking up) if it receives a message from an object that it has been picked up
		if #inventory < 10 then --only runs if the number of objects in the inventory array is less thn 10 (Change to set the max slots)
			local itempickedup = message.objecturl
			table.insert(inventory, itempickedup)--adds the item picked up to the inventory
			inventoryslots = inventoryslots - 1--removes one from the slots left
			msg.post("/Player#SalvagingHUD","UpdateHUDSlots",{inventoryslotsremaining = inventoryslots})--sends a message to the GUI script to update the HUD
			sys.save(savefile_path, {inventory = json.encode(inventory)})--cant save arrays themselves, have to encode them first into a string to save them
		end
	end

	if message_id == hash("trigger_response") then--(for the door system)
		if message.enter then --if the player enters a trigger
			msg.post(message.other_id, "Triggered")
		else
			msg.post(message.other_id, "UnTriggered")
		end
	end

end

When the other collection, the ship, is loaded, my intention is for the inventory to be added to another array called cargo, which the script then checks, and spawns all the items in that array using a collection factory. This is the ship script:

local json = require("json")--need this to save and load arrays
savefile_path = sys.get_save_file("StellarSalvagers", "SaveFile")--defines file path where game data is saved
SavedData = sys.load(savefile_path)--loads the data file and assigns it to a variable

function init(self)
	sound.play("/Ship#Ship")

	local Inventory = {}--ensures the array always exists even if its empty to prevent errors
	if SavedData.inventory then--if it exists in the save file
		Inventory = json.decode(SavedData.inventory)--defines the decoded inventory array as a variable
	end

	for i =1,#Inventory do--prints the entire Inventory array
		print("Inventory Item",i,":",Inventory[i])
	end

	cargo = {}
	if SavedData.cargo then
		cargo = json.decode(SavedData.cargo)
	end

	if #cargo < 15 then--wont continue adding items from the inventory if cargo is full (15 slots)
		for i = 1, #Inventory do--inserts each value from inv into cargo one at a time
			table.insert(cargo, Inventory[i])
		end
	end

	for i =1,#cargo do--prints the entire cargo array
		print("Cargo Item",i,":",cargo[i])
	end
	
	sys.save(savefile_path, {cargo = json.encode(cargo)})--saves the cargo array to the data file
end

function SpawnItem()--function to spawn an item in
	local CargoSlots = {
		{11,{x = 170, y = 1220, z = 1}},
		{12,{x = 245, y = 1220, z = 1}},
		{13,{x = 320, y = 1220, z = 1}},
		{21,{x = 170, y = 1145, z = 1}},
		{22,{x = 245, y = 1145, z = 1}},
		{23,{x = 320, y = 1145, z = 1}},
		{31,{x = 170, y = 1070, z = 1}},
		{32,{x = 245, y = 1070, z = 1}},
		{33,{x = 320, y = 1070, z = 1}},
		{41,{x = 170, y = 1000, z = 1}},
		{42,{x = 245, y = 1000, z = 1}},
		{43,{x = 320, y = 1000, z = 1}},
		{51,{x = 170, y = 920, z = 1}},
		{52,{x = 245, y = 920, z = 1}},
		{53,{x = 320, y = 920, z = 1}}
	}--array storing each slot and its coordinates but with a z of 1 so that the items spawn on top

	for i=1,#cargo do--starts at 1 and ends when the array ends
		local XCoord = CargoSlots[i][2].x--sets x coordinate of variable to the one in the array
		local YCoord = CargoSlots[i][2].y
		local ZCoord = CargoSlots[i][2].z
		local pos = vmath.vector3(XCoord,YCoord,ZCoord)--creates variable of coordinates based on the xyz values in the array

		factory.create("/Factories#Crate", pos)--spawns the object at the pos
	end
end

SpawnItem()

I get this error in the ship: ERROR:SCRIPT: main/Ship.script:54: Unsupported serialized table data: version = 0x20202004 (current = 0x4)

Any help would be greatly appreciated. Might have missed some key info out but tried not to, lmk. Thanks

Isn’t your array is CargoSlots? So it should be for i = 1, #CargoSlots do

Didnt explain it too well sorry. No, CargoSlots is the array im using to store the position of a bunch of physical places where the items in the cargo array should be spawned in at.

If I look at the main/Ship.script you shared above it doesn’t seem like line 54 has anything to do with saving or loading files. Are you sure you are showing the entire file?

In any case it seems like you are trying to sys.load() something which wasn’t saved using sys.save().

1 Like

I just re-ran it and for some reason it had given me line 54 but its line 3 at least now. Thats the entire ship script ye

So, I guess your cargo is a global variable? It’s better to loop in CargoSlots since we don’t know how many data in cargo variable, it could be greater than CargoSlots.

Once thing I’m noticing that you are using your own json library. Why don’t you just use Defold built-in json api?

Looping based on CargoSlots wouldn’t create the amount of objects in Cargo though, it would just be filling every CargoSlot regardless of whats in Cargo if I’m not wrong. Cargo is also capped at 15 so it doesn’t have a greater number of values in it than the number of CargoSlots. I’m very new sorry, I didn’t intend to use my own JSON library. Maybe that’s the issue. Could you please elaborate on that?

Thank you

You just need to remove this line from all your scripts

local json = require("json")--need this to save and load arrays
1 Like

Ok thanks. I’ll update once I’m on my pc.

Just tested this and it doesn’t appear to have had any effect.

EDIT:

I just tried calling the function in init instead, which i didnt think would make a difference and didnt even know was possible but it is in lua. The system now works. Thank you for helping chung and britzl.

Incase anyone wants the script for the future:


savefile_path = sys.get_save_file("StellarSalvagers", "SaveFile")--defines file path where game data is saved
SavedData = sys.load(savefile_path)--loads the data file and assigns it to a variable

function init(self)
	sound.play("/Ship#Ship")
	local Inventory = {}--ensures the array always exists even if its empty to prevent errors
	if SavedData.inventory then--if it exists in the save file
		Inventory = json.decode(SavedData.inventory)--defines the decoded inventory array as a variable
	end

	for i =1,#Inventory do--prints the entire Inventory array
		print("Inventory Item",i,":",Inventory[i])
	end

	cargo = {}
	if SavedData.cargo then
		cargo = json.decode(SavedData.cargo)
	end

	if #cargo < 15 then--wont continue adding items from the inventory if cargo is full (15 slots)
		for i = 1, #Inventory do--inserts each value from inv into cargo one at a time
			table.insert(cargo, Inventory[i])
		end
	end

	for i =1,#cargo do--prints the entire cargo array
		print("Cargo Item",i,":",cargo[i])
	end
	sys.save(savefile_path, {cargo = json.encode(cargo)})--saves the cargo array to the data file
	SpawnItem()
end

function SpawnItem()--function to spawn an item in
	local CargoSlots = {
		{11,{x = 170, y = 1220, z = 1}},
		{12,{x = 245, y = 1220, z = 1}},
		{13,{x = 320, y = 1220, z = 1}},
		{21,{x = 170, y = 1145, z = 1}},
		{22,{x = 245, y = 1145, z = 1}},
		{23,{x = 320, y = 1145, z = 1}},
		{31,{x = 170, y = 1070, z = 1}},
		{32,{x = 245, y = 1070, z = 1}},
		{33,{x = 320, y = 1070, z = 1}},
		{41,{x = 170, y = 1000, z = 1}},
		{42,{x = 245, y = 1000, z = 1}},
		{43,{x = 320, y = 1000, z = 1}},
		{51,{x = 170, y = 920, z = 1}},
		{52,{x = 245, y = 920, z = 1}},
		{53,{x = 320, y = 920, z = 1}}
	}--array storing each slot and its coordinates but with a z of 1 so that the items spawn on top

	for i=1,#cargo do--starts at 1 and ends when the array ends
		local XCoord = CargoSlots[i][2].x--sets x coordinate of variable to the one in the array
		local YCoord = CargoSlots[i][2].y
		local ZCoord = CargoSlots[i][2].z
		local pos = vmath.vector3(XCoord,YCoord,ZCoord)--creates variable of coordinates based on the xyz values in the array

		factory.create("/Factories#Crate", pos)--spawns the object at the pos
	end
end

This is it.

2 Likes