Jump to content

Can't save/load component data if the component is added via SimPostInit?


Recommended Posts

I'm trying to add a unique spawner component to the world. Other spawners, such as hounded, are added in the master_postinit:

local function master_postinit(inst)
    --Spawners
    inst:AddComponent("hounded")
end

return MakeWorld("forest", prefabs, assets, common_postinit, master_postinit, {"forest"})

My spawner fires up and works fine. The problem is I can't save and load any of its data. 

I first tried attaching the component to TheWorld like so:

AddSimPostInit(function() 
	if GLOBAL.TheWorld.ismastersim then
		GLOBAL.TheWorld:AddComponent("spawner")
	end
end)

But it causes a crash upon saving, giving this error: 

[string "scripts/dumper.lua"]:112: Cannot dump userdata (DynamicShadow (1DBC1E48) - unknown)

Here's what the save and load functions look like in the component:

function self:OnSave()  
	local data =	
	{
		savetest = _savetest,
	}
	return data
end

function self:OnLoad(data)
	if data and data.savetest then
		_savetest = data.savetest
	end
end

I've also tried creating an entity in modmain, and attaching the component to that entity:

AddSimPostInit(function() 
	if GLOBAL.TheWorld.ismastersim then
		local spawner = GLOBAL.CreateEntity()
		spawner.entity:AddTransform()
		spawner.persists = true
		spawner:AddComponent("spawner") 
	end
end)

This gets the component going, but the save and load functions now aren't even activated upon saving/loading. 

I've been combing through old forum threads looking for a solution, and I came across this post that suggests there's some issue with saving/loading if you've added a component via SimPostInit. 

Any ideas?

Link to comment
Share on other sites

17 minutes ago, Ryuushu said:

@BluesyBuesy

What are you trying to save/load?

Variables, an entity, and a few tables full of entities. For example, similar to hounded, I'm saving a "timetoattack" variable that counts down as the world clock progresses. If that isn't saved, then it'll just keep resetting to the original value. I need to tell whether anything is currently spawned, and if so, I save the entity so that I can easily refer to it upon loading. I also save tables of entities like cave entrances because I modify them pretty frequently, so I figure it's better to have a handy table to quickly access them rather than constantly looking through Ents.

Link to comment
Share on other sites

@BluesyBuesy

Ah, that's why it isn't working, you're trying to save complex objects. If you look at other component's OnSave/OnLoad, you'll notice that they save simple values like booleans, numbers, strings or tables of them. Instead saving those entities and cave entrances, index them again on world load.

Link to comment
Share on other sites

21 minutes ago, Ryuushu said:

@BluesyBuesy

Ah, that's why it isn't working, you're trying to save complex objects. If you look at other component's OnSave/OnLoad, you'll notice that they save simple values like booleans, numbers, strings or tables of them. Instead saving those entities and cave entrances, index them again on world load.

I've taken the entities out, but it's still not saving anything. I'm not getting that error any more though!

I can see that the save function is being passed through with a print, but the load function doesn't seem to be activated at all. 

Link to comment
Share on other sites

@BluesyBuesy

Alright, I think I managed to figure it out. AddSimPostInit is called after the world has been already loaded. Since you're adding the component there, its OnLoad function is never called, only the OnSave one.

However, you can hook it from somewhere else. The overworld is a prefab called forest, so you can use AddPrefabPostInit to add the component there, let it load, and then index entities/do other stuff in AddSimPostInit.

My current setup seems to work:

modmain.lua

AddPrefabPostInit("forest", function(inst)
	if GLOBAL.TheWorld.ismastersim then
		inst:AddComponent("mycomponent")
	end
end)

AddSimPostInit(function(sim)
	if GLOBAL.TheWorld.ismastersim and GLOBAL.TheWorld.components.mycomponent then
		print("AddSimPostInit", GLOBAL.TheWorld.components.mycomponent.test)
	end
end)
mycomponent.lua

--------------------------------------------------------------------------
--[[ MyComponent class definition ]]
--------------------------------------------------------------------------

return Class(function(self, inst)

assert(TheWorld.ismastersim, "MyComponent should not exist on client")

self.inst = inst

--------------------------------------------------------------------------
--[[ Save/Load ]]
--------------------------------------------------------------------------

self.test = nil

function self:OnSave()
	--print("AddPrefabPostInit Saved!", self.inst)
	return 
	{
		test = "This is a test string"
	}
end

function self:OnLoad(data)
	self.test = data.test
	--print(self.test)
	--print("AddPrefabPostInit Loaded!", self.inst)
end

end)

This will print "AddSimPostInit nil" the first time you run it and "AddSimPostInit This is a test string" subsequent times.

Edited by Ryuushu
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...