Jump to content

Recommended Posts

I made a component which should make sure, that a function is only called once per inst.
So if I attached it to a world, the function will only called once in this world.
And if I attach it to all players, a function will be called once per player.

 

local function GiveStuff(inst,fn)
    if fn~=nil then
        fn(inst)
    end
end

local StartStuff = Class(function(self, inst)
	self.inst = inst
	self.done = false
end)

function StartStuff:GiveStartStuffIn(x,fn) -- to run a function only once per inst
    if not self.done then
        self.inst:DoTaskInTime(x, GiveStuff, fn)
        self.done = true
    end
end

function StartStuff:OnSave()
	return { done = self.done }
end

function StartStuff:OnLoad(data)
	self.done = data and data.done or false
end


return StartStuff

In modmain I added:
 

local function OnPlayerSpawn(inst)
    inst:AddComponent("startstuff")
    inst.components.startstuff:GiveStartStuffIn(1,StartItems) -- is a function that spawns start items
end

AddPlayerPostInit(OnPlayerSpawn)

But the problem is now, everytime I leave and load the game, it seems I get a new wilson? The inst number of my character changes.
And the self.done of my component is always false, instead of the value it should be.
If I attach the component to the "world", it works.

The inventory and health of my char is also correct when joining again. So there must be something wrong with my component? But what?

How to achieve, that every player gets the items only once, when they join for the first time?

Edited by Serpens

StartStuff.OnLoad runs after OnPlayerSpawn.

So when you do StartStuff.GiveStartStuffIn, you are scheduling the task right away.

local function GiveStuff(inst, fn)
	if fn ~= nil then
		fn(inst)
	end
end

local function OnInit(inst, self)
	if not self.done then
		for i, v in ipairs(self.fns) do
			inst:DoTaskInTime(v.time, GiveStuff, v.fn)
		end
		self.done = true
	end
end

local StartStuff = Class(function(self, inst)
	self.inst = inst
	self.done = false
	self.fns = {}

	-- Do OnInit next frame, after OnLoad runs
	inst:DoTaskInTime(0, OnInit, self)
end)

function StartStuff:GiveStartStuffIn(x, fn)
	table.insert(self.fns, { time = x, fn = fn })
end

function StartStuff:OnSave()
	return { done = self.done }
end

function StartStuff:OnLoad(data)
	self.done = data and data.done or false
end

return StartStuff

Here I schedule OnInit to run after OnLoad, with that DoTaskInTime with time 0.

@DarkXero
First time I having such trouble with adding components :D

The component "adventurejump" you made for me, is deleting the minimap by a ~50:50 chance.
I tried:
 

AddPrefabPostInit("world", function(world)
	if world.ismastersim and world.ismastershard then
        world:AddComponent("adventurejump")
    end
end)

but also
 

local function WorldInit(world)
    world:AddComponent("adventurejump")
end

AddPrefabPostInit("world", function(world)
	if world.ismastersim and world.ismastershard then
       world:DoTaskInTime(0,WorldInit)
    end
end)


I tested and confirmed this with only this in modmain and in modworldgenmain:

local io = GLOBAL.io
local json = GLOBAL.json
local modfoldername = "adventuremod"
local tmp_filepath = "../mods/"..modfoldername.."/adventure"

GLOBAL.MakeTemporalAdventureFile = function(json_string)
	local advfile = io.open(tmp_filepath, "w")

	if advfile then
		advfile:write(json_string)
		advfile:close()
	end
end

GLOBAL.CleanTemporalAdventureFile = function()
	GLOBAL.MakeTemporalAdventureFile("")
end

GLOBAL.GetTemporalAdventureContent = function()
	local advfile = io.open(tmp_filepath, "r")

	if advfile == nil then
		print(modfoldername..": no adventure override found...")
		return nil
	end

	local adventure_stuff = nil

	local advstr = advfile:read("*all")

	if advstr ~= "" then
		adventure_stuff = json.decode(advstr)
	end

	advfile:close()

	return adventure_stuff
end



Took some hours to find out what is causing the minimap problem... :D
I can make minimap progress. But when I leave game and join again, it seems to be a 50:50 chance, that the minimap is cleared again.
If I don't add the component, the minimap is always saved properly (at least I joined 5 times in a row without loosing minimap progress)

Edited by Serpens
2 hours ago, Serpens said:

I can make minimap progress. But when I leave game and join again, it seems to be a 50:50 chance, that the minimap is cleared again.
If I don't add the component, the minimap is always saved properly (at least I joined 5 times in a row without loosing minimap progress)

http://pastebin.com/W1EQq4EQ

Try editing the component with this.

23 minutes ago, DarkXero said:

http://pastebin.com/W1EQq4EQ

Try editing the component with this.

seems to sovle the map problem, thanks :)
But ~a second after game starts, the game freezes for half a second =/
If I have to live with either the map problem, or this short freeze, I think the freezing is the minor problem.

15 minutes ago, Serpens said:

seems to sovle the map problem, thanks :)
But ~a second after game starts, the game freezes for half a second =/
If I have to live with either the map problem, or this short freeze, I think the freezing is the minor problem.

It's because I force a save so the adventure info gets saved on the component, in case anything else crashes.

You can just remove -SaveGame(false)- from the component, but if the game crashes before it reaches a saving point, and if the adventure info from the temporal file is deleted (with -CleanTemporalAdventureFile()-), then the information is lost.

Or you can replace that line with -TheWorld:PushEvent("ms_save")-.

Or you can save that stuff in persistent strings, like worldjump, if you want. Same logic.

22 minutes ago, DarkXero said:

It's because I force a save so the adventure info gets saved on the component, in case anything else crashes.

You can just remove -SaveGame(false)- from the component, but if the game crashes before it reaches a saving point, and if the adventure info from the temporal file is deleted (with -CleanTemporalAdventureFile()-), then the information is lost.

Or you can replace that line with -TheWorld:PushEvent("ms_save")-.

Or you can save that stuff in persistent strings, like worldjump, if you want. Same logic.

thank you :)
okay... so it is only for the case it crashes between world generation and the first night-saving?

What the different between SaveGame(false) and TheWorld:PushEvent("ms_save") ?
I assume there is nothing to only save the adventurejump component and keep the old information of all other components?

If "ms_save" is not better, I will use the persistent string I guess.

edit:
ah the event does the same, but also with the "saving animation". I think that is okay. So the player sees that it is saves and knows why it freeze for a short moment :)

Edited by Serpens

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
×
  • Create New...