Jump to content

Recommended Posts

@Ipsquiggle,There's a minor bug in modindex.lua:407. The assert is only checking for the "fn" (the result from trying to kleiloadlua() modsettings.lua) being non-nil, so it will only trigger when modsettings.lua does not exist. When it does, but there's an error in it (syntax error, for example), then fn will be a string, the assert will pass and the user will get a cryptic error message about the argument to setfenv() being a string instead of being told what the problem really is.EDIT


And by the way, I can't believe main.lua:10 was commented out! I like that it is, but I never thought it would happen because of all the code refactoring required. There are still some issues left to deal with because of that move (such as the toothtrap crash), but nevertheless you guys seem to have taken care of most problems. Edited by simplex
  • Developer

If you're puzzling out the file formats, there a few helpful links:

 

The pipeline producing the files (and showcasing the format):

http://forums.kleientertainment.com/index.php?/topic/18664-qusestion-animation-files-and-custom-characters/?hl=pipeline#entry176834

 

A sample XML:

http://forums.kleientertainment.com/index.php?/topic/21111-creating-an-anim-for-items-on-the-ground/#entry210493

 

Granted, I spent time figuring out the raw binary before I saw those posts - not the easiest to find, even when I knew what i was looking for. But ti sure helped me name stuff in the text files.

 

It looks like you're doing a good job with this, but if you've got any further questions just let me know. :) 

 

 

 

@Ipsquiggle,There's a minor bug in modindex.lua:407. The assert is only checking for the "fn" (the result from trying to kleiloadlua() modsettings.lua) being non-nil, so it will only trigger when modsettings.lua does not exist. When it does, but there's an error in it (syntax error, for example), then fn will be a string, the assert will pass and the user will get a cryptic error message about the argument to setfenv() being a string instead of being told what the problem really is.EDIT


And by the way, I can't believe you commented out main.lua:10! I like it, but I never thought it would happen because of all the code refactoring required. There are still some issues left to deal with because of that move (such as the toothtrap crash), but nevertheless you guys seems to have taken care of most of it.

 

Thanks for catching that, you're quite right. It will now print out a more useful error from modsettings. :)

Ipsquiggle
function Hunter:OnSave()    trace("Hunter:OnSave")    local time = GetTime()    local data = {}    local references = {}	    data.beastid1 = self.koalefants[1].GUID    data.beastid2 = self.koalefants[2].GUID    data.beastid3 = self.koalefants[3].GUID    data.beastid4 = self.koalefants[4].GUID    data.beastid5 = self.koalefants[5].GUID

New problem here, before the recent update it was working like this, now when some of the

self.koalefants[].GUID

is nil it crashes the game:

hunter.lua:39: attempt to index field '?' (a nil value)

Ipsquiggle

function Hunter:OnSave()    trace("Hunter:OnSave")    local time = GetTime()    local data = {}    local references = {}	    data.beastid1 = self.koalefants[1].GUID    data.beastid2 = self.koalefants[2].GUID    data.beastid3 = self.koalefants[3].GUID    data.beastid4 = self.koalefants[4].GUID    data.beastid5 = self.koalefants[5].GUID
New problem here, before the recent update it was working like this, now when some of the

self.koalefants[].GUID
is nil it crashes the game:

hunter.lua:39: attempt to index field '?' (a nil value)

Yes, the 10th line from main.lua was commented out. This was a huuuge (and undocumented) change in the game. Basically, the semantics of the Lua language were changed (to its default state).

Before, indexing nil would give you nil. Now it will give you a crash. (it's the same thing causing the vanilla crashes with toothtraps, bee mines and such)

Edited by simplex

Yes, the 10th line from main.lua was commented out. This was a huuuge (and undocumented) change in the game. Basically, the semantics of the Lua language were changed (to its default state).Before, indexing nil would give you nil. Now it will give you a crash. (it's the same thing causing the vanilla crashes with toothtraps, bee mines and such)

Its not only that line I uncommented it and game still crashed.

The thing is that game don't want to index nil but only on save, while running and loading there is no problems with indexing nil.

Its not only that line I uncommented it and game still crashed.The thing is that game don't want to index nil but only on save, while running and loading there is no problems with indexing nil.

Strange, since older version of the game didn't set up a nil metatable in other places (such as worldgen_main.lua). Maybe save runs differently now (I'll have to check), in a different state, but that'd be weird. I don't even know how it could make sense.EDIT
I wasn't able to reproduce it. Take a look at the attached mod, for example (edit SHOULD_CRASH in modmain.lua accordingly).

Crasher.zip

Edited by simplex

Now I have strange thing, even if data is saved it is not used in LoadPostPass.

So now I can't fill the table that is nil in LoadPostPass function, indexing nil don't crashes the game there but it is not doing anything else either.

function Hunter:LoadPostPass(newents, data)
  trace("Hunter:LoadPostPass")
  self.koalefants[1] = newents[data.beastid1] and newents[data.beastid1].entity
  self.koalefants[2] = newents[data.beastid2] and newents[data.beastid2].entity
  self.koalefants[3] = newents[data.beastid3] and newents[data.beastid3].entity
  self.koalefants[4] = newents[data.beastid4] and newents[data.beastid4].entity
  self.koalefants[5] = newents[data.beastid5] and newents[data.beastid5].entity

 

data.beastid1 was saved and wasn't nil and here it don't want to write it to empty table at all.

now must find component that saves and loads random number of values to empty table.

Or maybe lua have something like dynamic collections with dynamic size I can use for that?

 

Now it is impossible to declare empty local table in OnSave function and try to put data to it cause it will cause crash.

 

Quick test in lua edit shows that doing something like that is perfectly fine on lua side:

local koalefants = {}

  koalefants[1] = "ZZZ"
  koalefants[2] = "ZZZ"
  koalefants[3] = "ZZZ"
  koalefants[4] = "ZZZ"
  koalefants[5] = "ZZZ"
 
 
  for i = 1, 5 do
  print(koalefants)
  end

and doing the same in game component will cause crash.

Edited by _Q_

Is there a reason you're not doing something like:

function Hunter:OnSave()    trace("Hunter:OnSave")    local time = GetTime()    local data = {}    local references = {}        data.beasts = {}    for i,koalefant in pairs(self.koalefants) do        data.beasts[i] = koalefant.GUID    end        return data    endfunction Hunter:LoadPostPass(newents, data)    trace("Hunter:LoadPostPass")        -- make this a table if it isnt already (it should probably already be one)    if self.koalefants == nil then self.koalefants = {} end        for i,beast in pairs(data.beasts) do        if newents[beast] and newents[beast].entity then            self.koalefants[i] = newents[beast].entity        end    endend

Was unsure if you cared about the index of the koalefants remaining the same, otherwise you could use table.insert and ipairs() to loop through them.

Edited by squeek

Is there a reason you're not doing something like:

function Hunter:OnSave()    trace("Hunter:OnSave")    local time = GetTime()    local data = {}    local references = {}        data.beasts = {}    for i,koalefant in pairs(self.koalefants) do        data.beasts[i] = koalefant.GUID    end        return data    endfunction Hunter:LoadPostPass(newents, data)    trace("Hunter:LoadPostPass")        -- make this a table if it isnt already (it should probably already be one)    if self.koalefants == nil then self.koalefants = {} end        for i,beast in pairs(data.beasts) do        if newents[beast] and newents[beast].entity then            self.koalefants[i] = newents[beast].entity        end    endend

Was unsure if you cared about the index of the koalefants remaining the same, otherwise you could use table.insert and ipairs() to loop through them.

Reason is that saveindex hates tables. Last time when I tried to save table to saveindex it was crasing saveindex on load time.

Data itself is a table and you can't save table within table in case of saveindex.

Edited by _Q_

Saving tables has been working fine for me.

 

See components/leader.lua and components/inventory.lua for things that save entities using tables (leader saves the GUID while inventory gets each item's save record and uses SpawnSaveRecord to spawn each one again on load).

Saving tables has been working fine for me.

 

See components/leader.lua and components/inventory.lua for things that save entities using tables (leader saves the GUID while inventory gets each item's save record and uses SpawnSaveRecord to spawn each one again on load).

Thanks, I think I got it working on tables.

Ipsquiggle

Can you take a look at Hunter mod.

Custom dirtpiles and custom animal tracks are just vanishing in the middle of the hunt without any error message, and when you backtrack a little they appear again for a short while, I think that new texture manager is just unloading them form game.

E:/Gry/Steam/steamapps/common/dont_starve/data/../mods/Hunter/scripts/components/houndhunter.lua(153,1) Suspicious dirt placed	E:/Gry/Steam/steamapps/common/dont_starve/data/../mods/Hunter/scripts/components/birdhunter.lua(153,1) Suspicious dirt placed	E:/Gry/Steam/steamapps/common/dont_starve/data/scripts/mods.lua(276,1) unloading prefabs for mod MOD_Hunter	
Edited by _Q_

IpsquiggleIs there a way to store persistent metadata in the map, on world generation?(or at least generate and store some form of savedata during world generation, that can be loaded after?)

Edited by simplex

I got some strange error, after saving hte game with custom prefab mod when you press exit on title screen game crashes with this error in log file:

lua_close took 0.02 seconds Manager - ORPHANED UNKNOWN RESOURCES:../mods/Ghosts and Graves/images/inventoryimages/ectoplasm.xml - 1Assert failure 'mTextureHandle == INVALID_RESOURCE_HANDLE' at ..sourcegamerenderAtlas.cpp(25): Trace follows...

Got another mod bug report for you Ipsquiggle

 

The pickable component's regen handling is super inconsistent and somewhat of a mess. Sometimes it uses its getregentimefn callback, sometimes it ignores it completely. There is duplicate (but not matching) code to start the regen task in a few different places (MakeEmpty, Pick, OnLoad, LongUpdate, and Resume). It's not fun to deal with as a modder and it actually looks like it causes a few minor bugs (MakeEmpty doesn't check cycles_left before it schedules a regen, berrybushes get their getregentimefn function ignored in OnLoad and MakeEmpty, targettime not getting set to nil in MakeEmpty when the regen task is canceled, etc).

 

Here's an improved pickable.lua that tries to fix as much of the above as I could:

 

pickable.zip

 

Hope it helps. I think OnLoad could still be improved, but I left it mostly as is because I was unsure of the intention of some of the code.

 

I tried to improve the logic a bit as well. It was really inconsistent with how it handled all of the prefab callback functions. For example, my improvements make redundancy like the following commented section in prefabs/grass.lua no longer necessary as MakeBarren and MakeEmpty and the prefab's associated callbacks are now correctly called when the pickable is picked:

local function makebarrenfn(inst)    inst.AnimState:PlayAnimation("idle_dead")endlocal function onpickedfn(inst)    inst.SoundEmitter:PlaySound("dontstarve/wilson/pickup_reeds")    inst.AnimState:PlayAnimation("picking")--[[/*    if inst.components.pickable:IsBarren() then        inst.AnimState:PushAnimation("idle_dead")    else        inst.AnimState:PushAnimation("picked")    end*/]]--endlocal function makeemptyfn(inst)    inst.AnimState:PlayAnimation("picked")end

EDIT: Just realized that it uses PushAnimation in onpickedfn and PlayAnimation in makeemptyfn/makebarrenfn. Maybe it doesn't resolve that like I thought.

 

EDIT#2: Yeah, it causes some animation bugs. Re-uploaded a version that doesn't cause the animation bugs, but does still need the PushAnimation calls in grass.lua's onpickedfn (also, makeemptyfn and makebarrenfn would still get called so it'd play 3 animations with "picking" getting played last so that it overwrites the previous 2).

 

I'm sure you'll be able to rewrite this stuff better than I did, but hopefully this is at least able to point you in the right direction. The regen stuff is the most important.

Edited by squeek

Me again. AddAction doesn't actually work. It inserts it into the ACTIONS table using table.insert, but the ACTIONS table uses the action id as its keys, not numbers. If you enable the apiexamples mod, you can see that MYACT is inserted into ACTIONS[1] when it should be at ACTIONS.MYACT.

 

SImple fix in modutil.lua line 112:

 

Replace:

table.insert(ACTIONS, action)

with:

ACTIONS[action.id] = action

@Ipsquiggle

Don't bother much with my "crash report". It was really just a comment. The real issue is with Lua itself, which triggers a crash when getfenv() is called on a tail call stack index (this no longer happens in Lua 5.2, though). However, in case you're interested, what I'm using to counter that (in my own usage of getfenv()) is this (noting that I'm using that inside a proper Lua module, hence the _M):

--/*-- Returns the index (relative to the calling function) in the Lua stack of the last function with a different environment than the outer function.-- It uses the Lua side convention for indexes, which are nonnegative and count from top to bottom.---- It defaults to 2 because it shouldn't be used directly from outside this module.---- We should always reach the global environment, which prevents an infinite loop.-- Ignoring errors is needed to pass over tail calls (which trigger them).---- This could be written much more cleanly and robustly at the C/C++ side.-- The real setback is that Lua doesn't tell us what the stack size is.--*/local function GetNextEnvironmentThreshold(i)	assert( i == nil or (type(i) == "number" and i > 0 and i == math.floor(i)) )	i = (i or 1) + 1	local env	local function get_first()		local status		status, env = pcall(getfenv, i + 2)		if not status then			trace_error('Unable to get the initial environment!')		end		i = i + 1		return env	end	local function get_next()		local status				while not status do			status, env = pcall(getfenv, i + 2)			i = i + 1		end		return env	end	local first_env = get_first()	if first_env == _G then		trace_error('The initial environment is the global environment!')	end	assert( env == first_env )	while env == first_env do		env = get_next()	end	i = i - 1	if env == _G then		trace_error('Attempt to reach the global environment!')	elseif env == _M then		trace_error('Attempt to reach the core environment!')	end	--// No, this is not a typo. The index should be subtracted twice.	--// The subtractions just have different meanings.	return i - 1, envend--// Counts from 0 up, with 0 meaning the innermost environment different than the caller's.function GetEnvironmentLayer(n)	assert( type(n) == "number" )	assert( n >= 0 )	local i, env = GetNextEnvironmentThreshold()	for _ = 1, n do		i, env = GetNextEnvironmentThreshold(i)	end	return env, i - 1endlocal GetEnvironmentLayer = GetEnvironmentLayerfunction GetOuterEnvironment()	local env, i = GetEnvironmentLayer(0)	return env, i - 1end

But my question on which savedata are available at worldgen remains quite valid! (since I'd prefer to not use Profile:SetValue())

Edited by simplex
  • Developer

@Ipsquiggle

Don't bother much with my "crash report". It was really just a comment. The real issue is with Lua itself, which triggers a crash when getfenv() is called on a tail call stack index (this no longer happens in Lua 5.2, though). However, in case you're interested, what I'm using to counter that (in my own usage of getfenv()) is this (noting that I'm using that inside a proper Lua module, hence the _M):

 

But my question on which savedata are available at worldgen remains quite valid! (since I'd prefer to not use Profile:SetValue())

 

 

Ahkay, thanks for the update. :)

 

I haven't looked specifically into the best place to store worldgen data, but I do know the 'savedata.meta'/'ground.meta' structure is blindly carried forward across loads. You can see this being used at:

worldgen_main.lua:561 -- initially created

gamelogic.lua:370 -- moved from the save to the world -- accessible via GetWorld().meta

mainfunctions.lua:433 -- written back to save

 

If this table doesn't exactly suit your needs (or is inaccessible) perhaps it can point to a similar method of packing along your data. If nothing simple comes to mind let me know and I'll wire in a mechanism to let modworldgenmain push arbitrary data into the generated save, which you can pull out at runtime.

  • Developer

Me again. AddAction doesn't actually work. It inserts it into the ACTIONS table using table.insert, but the ACTIONS table uses the action id as its keys, not numbers. If you enable the apiexamples mod, you can see that MYACT is inserted into ACTIONS[1] when it should be at ACTIONS.MYACT.

 

SImple fix in modutil.lua line 112:

 

Replace:

table.insert(ACTIONS, action)

with:

ACTIONS[action.id] = action

 

Good catch, thanks! That will be fixed next release.

 

Yeah, I've encountered that confusion in pickable.lua before, if it's directly impacting you guys then I'll definitely try cleaning it up. Thanks for the implementation sample, I really appreciate it!

 

I got some strange error, after saving hte game with custom prefab mod when you press exit on title screen game crashes with this error in log file:

lua_close took 0.02 seconds Manager - ORPHANED UNKNOWN RESOURCES:../mods/Ghosts and Graves/images/inventoryimages/ectoplasm.xml - 1Assert failure 'mTextureHandle == INVALID_RESOURCE_HANDLE' at ..sourcegamerenderAtlas.cpp(25): Trace follows...

 

There were some issues with resource loading and unloading, I've hopefully got them cleaned up now though. :) Thanks for reporting it.

Yeah, I've encountered that confusion in pickable.lua before, if it's directly impacting you guys then I'll definitely try cleaning it up. Thanks for the implementation sample, I really appreciate it!

Well, it is directly impacting me :(. The mod I'm working on modifies the grow/regen rate of plants, and hooking into pickable is a gigantic pain (currently, you pretty much have to overwrite regentime and regentimefn, which I don't want to do [i multiply the default regentime by a potentially different value on each new regen task]). With growable, for example, I can just hook into StartGrowing and be done with it. The rewritten pickable that I attached has been working great for me (no bugs that I've found).

Also, another question, and I don't really know if you're the one to talk to this about, but I've reported a few code bugs (this and this) in the bug tracker that are not getting any response (while pretty much 100% of the others get some sort of response). I just want to make sure they aren't going unnoticed, or, if they are, if I should be reporting them in a different place/different way.

Edited by squeek

Good catch, thanks! That will be fixed next release.

 

Yeah, I've encountered that confusion in pickable.lua before, if it's directly impacting you guys then I'll definitely try cleaning it up. Thanks for the implementation sample, I really appreciate it!

 

There were some issues with resource loading and unloading, I've hopefully got them cleaned up now though. :-) Thanks for reporting it.

And what with the Hunter mod:

 

Ipsquiggle

Can you take a look at Hunter mod.

Custom dirtpiles and custom animal tracks are just vanishing in the middle of the hunt without any error message, and when you backtrack a little they appear again for a short while, I think that new texture manager is just unloading them form game.

E:/Gry/Steam/steamapps/common/dont_starve/data/../mods/Hunter/scripts/components/houndhunter.lua(153,1) Suspicious dirt placed	E:/Gry/Steam/steamapps/common/dont_starve/data/../mods/Hunter/scripts/components/birdhunter.lua(153,1) Suspicious dirt placed	E:/Gry/Steam/steamapps/common/dont_starve/data/scripts/mods.lua(276,1) unloading prefabs for mod MOD_Hunter	

Also after adding component to the character by using SimPostInit, that component is not able to load any saved data. Is there a good way for adding custom component to a character so the component can write and read data from save at load time?

 

Also it seems that gate wall mod got affected byt the same error with vanishing textures:

No more update?

 

Textures of my regular walls disappears when your mod is loade :(

Edited by _Q_

Also after adding component to the character by using SimPostInit, that component is not able to load any saved data. Is there a good way for adding custom component to a character so the component can write and read data from save at load time?

Yes, you'd need AddPrefabPostInit() for that, but that's not quite viable when interacting with character mods (unless you get yours to always load last). I came up with the following solution:
AddPrefabPostInit("world", function(inst)	print(">> Hello, world!")	GLOBAL.assert( GLOBAL.GetPlayer() == nil )	local player_prefab = GLOBAL.SaveGameIndex:GetSlotCharacter()	-- /*	--[[	-- Unfortunately, we can't add new postinits by now. So we have to do	-- it the hard way...	--]]	-- */	GLOBAL.TheSim:LoadPrefabs {player_prefab}	local oldfn = GLOBAL.Prefabs[player_prefab].fn	GLOBAL.Prefabs[player_prefab].fn = function()		local inst = oldfn()		-- /*		--[[		-- Add components here.		--]]		-- */				print(">> Hello, " .. player_prefab .. "!")		return inst	endend)
Edited by simplex
  • Like 1

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...