Jump to content

How do you save component data?


Recommended Posts

So I have a component that I want to save the data for, but ultimately I keep ending up with corrupted save files.

 

Here is the code I'm using:

function IceGrowth:OnSave()	return 		{ 			thickness = self.thickness, 			avg_count = self.avg_temp.count, 			avg_total = self.avg_temp.total,		}endfunction IceGrowth:OnLoad(data)	if data then		self.thickness = data.thickness or self.thickness		self.avg_temp.count = data.avg_count or self.avg_temp.count		self.avg_temp.total = data.avg_total or self.avg_temp.total	endend 

 

Here is the error:

[00:06:53]: [string "scripts/saveindex.lua"]:414: Corrupt Save file [survival_5]
LUA ERROR stack traceback:
=[C]:-1 in (global) assert © <-1--1>
scripts/saveindex.lua:414 in () ? (Lua) <388-419>
   load_success = true
   str = return {world_network={persistdata={clock={moonphase="full",cycles=24,phase="day",remainingtimeinphase=153.03047180176,totaltimeinphase=210,segs={night=4,day=7,dusk=5}},seasons={remainingdaysinseason=11,totaldaysinseason=15,preendlessmode=false,lengths={summer=20,winter=15},elapseddaysinseason=4,mode="cycle",season="winter",segs={summer={night=2,day=10,dusk=4},winter={night=4,day=6,dusk=6}}},weather={seasontemperature=-12.808041855562,preciptype="none",daylight=true,moistureceil=1262.5141601563,moisturefloor=641.82092285156,moisturerateval=1,snowcovered=true,moistureceilmultiplier=1,moisture=1162.9274902344,stopsnowthreshold=10,snowlevel=0.17661800980568,moisturerateoffset=0,precipmode="dynamic",noisetime=11574.833007813,moisturerate=1,lightningmode="rain",nextlightningtime=13.988006225776,startsnowthreshold=5,precipintensity=0.15930661559105,winterlight=true,moistureratemultiplier=1,phasetemperature=3.7638549392745}}},super=true,ents={beefalo={{id=100028,x=-201.101,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-191.33050537109,name="herd",z=-26.006000518799}}}},z=-25.47},{id=100029,x=-149.971,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-149.97099304199,name="herd",z=-18.010999679565}}}},z=-18.011},{id=100030,x=-162.75,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-164.80549621582,name="herd",z=-70.180999755859}}}},z=-73.931},{id=100031,x=-181.56,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-191.33050537109,name="herd",z=-26.006000518799}}}},z=-26.542},{id=100032,x=-166.861,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-164.80549621582,name="herd",z=-70.180999755859}}}},z=-66.431},{id=100033,x=-546.881,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-550.85095214844,name="herd",z=-178.13049316406}}}},z=-186.04},{id=100034,x=-545.391,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-517.59997558594,name="herd",z=-265.51098632813}}}},z=-258.942},{id=100035,x=-586.951,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-549.42999267578,name="herd",z=-233.6309967041}}}},z=-233.161},{id=100036,x=-554.821,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-550.85095214844,name="herd",z=-178.13049316406}}}},z=-170.221},{id=100037,x=-586.881,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-586.88098144531,name="herd",z=-161.83999633789}}}},z=-161.84},{id=100038,x=-545.461,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-517.59997558594,name="herd",z=-265.51098632813}}}},z=-254.53},{id=100039,x=-570.131,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-550.85095214844,name="herd",z=-178.13049316406}}}},z=-166.5},{id=100040,x=-549.43,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-549.42999267578,name="herd",z=-233.6309967041}}}},z=-233.631},{id=100041,x=-517.6,data={beard={growth=9,bits=3},health={health=1000},knownlocations={locations={{y=0,x=-517.59997558594,name="herd",z=-265.51098632813}}}},z=-265.511}},berrybush2={{data={pickable={paused=true,caninteractwith=true}},x=-29.601,z=-109.6},{data={pickable={paused=true,caninteractwith=true}},x=-30.8,z=-109.6},{data={pickable={paused=true,caninteractwith=true}},x=-32,z=-109.6},{data={pickable={paused=true,caninteractwith=true}},x=-29.601,z=-110.804},{data={pickable={paused=true,caninteractwith=true}},x=-30.8,z=-110.804},{data={pickable={paused=true,caninteractwith=true}},x=-32,z=-110.804},{data={pickable={paused=true,caninteractwith=true}},x=-29.601,z=-112},{data={pickable={pause
[00:06:53]: SCRIPT ERROR! Showing error screen

[00:06:53]: ModIndex: Load sequence finished successfully.

 

I'm at a complete loss. All these values are integers or floats/decimals, nothing fancy.

Link to comment
Share on other sites

  • Developer

Your code looks fine to me. Your failure is a result of the saved data not being able to loaded back in a lua sandbox. There's a section in SaveIndex:GetSaveDataFile that's commented out. If you uncomment it back in, it should write out the bad saved data. Hopefully that'll provide some insight as to what is corrupted.

Link to comment
Share on other sites

@PeterA, writing 0 out seems to allow it to be saved correctly. I need to look into my equation to determine what is happening. I think it has to do with the modifications I've made to make it compatible with the Don't Starve world. Real life != Don't Starve world.  :indecisiveness:  

Link to comment
Share on other sites

Kzisor, but does the OnSave return something, really?

local function OnSave(inst, data)   data.x = inst.x   data.y = data.yendlocal function OnLoad(inst, data)   if data then      inst.x = data.x      inst.y = data.y   endendinst.OnSave = OnSaveinst.OnLoad = OnLoad

Isn't this how it is done?

Link to comment
Share on other sites

Kzisor, but does the OnSave return something, really?

local function OnSave(inst, data)   data.x = inst.x   data.y = data.yendlocal function OnLoad(inst, data)   if data then      inst.x = data.x      inst.y = data.y   endendinst.OnSave = OnSaveinst.OnLoad = OnLoad

Isn't this how it is done?

 

Only if you don't do it like I've done it. You added two additional lines compared to mine.

 

To answer your question, yes it does return something. The issue lied in my equation.

Edited by Kzisor
Link to comment
Share on other sites

So I have a component that I want to save the data for, but ultimately I keep ending up with corrupted save files.

 

Here is the code I'm using:

function IceGrowth:OnSave()	return 		{ 			thickness = self.thickness, 			avg_count = self.avg_temp.count, 			avg_total = self.avg_temp.total,		}endfunction IceGrowth:OnLoad(data)	if data then		self.thickness = data.thickness or self.thickness		self.avg_temp.count = data.avg_count or self.avg_temp.count		self.avg_temp.total = data.avg_total or self.avg_temp.total	endend 

 

I am very interested to save some component data for a pet, so I came for a look :)

 

Can you tell me, is any function I write named Something:OnSave and Something:OnLoad automatically executed on save and loads or is something else also required? I'd love a working example of saving some kind of detail to something <3

Link to comment
Share on other sites

@outseeker, the code that is posted above, is a working example. The problem wasn't in the code I posted, but in my equation being too complicated for Lua's math functionality so it was returning an indeterminate number. I'm working to resolve the limitations of Lua, but I'm not sure if it's even possible to do that.

Link to comment
Share on other sites

@Kzisor

You're getting this issue because on some scenario thickness is negative infinity (-math.huge), and DS's save system can't handle denormalised numbers, which is a category including +-inf.

Having U&A enabled will allow infinite values to be correctly saved (even in other mods), but I digress, since it's unreasonable to expect end users to have U&A enabled just for that. What you should do is check what is causing thickness to become infinite (the most common scenario is dividing a number by zero). And if you absolutely must be able to represent infinite values in savedata, the only way to do it (other than extending the save system itself, like U&A/wicker do) is reserving special values for them (this is usually called a "trap representation"), i.e. if thickness should ordinarily be non-negative, storing -1 in the save can be translated into an infinite value when loading.

Link to comment
Share on other sites

@simplex, thank you for the reply, but I've already fixed the issue.

 

Edit:

It had nothing to do with the save file, for completeness sake. It has to do with the limitation of Lua parsing negative numbers into the math.pow function. Lua cannot return a power of a negative number which a work around is to make the number absolute and multiply the end result by -1.

Edited by Kzisor
Link to comment
Share on other sites

@simplex, thank you for the reply, but I've already fixed the issue.

Edit:

It had nothing to do with the save file, for completeness sake. It has to do with the limitation of Lua parsing negative numbers into the math.pow function. Lua cannot return a power of a negative number which a work around is to make the number absolute and multiply the end result by -1.

Ah, so you were getting -NaN, not -inf.

Anyway, this has nothing to do with Lua, let alone some "Lua" limitation, since Lua's math library is just a binding to the C mathematical library. But this is also not a C limitation, this is fundamental, irremovable mathematical limitation. There is no (continuous) extension of the exponential function with real exponents over negative bases. It's defined for integral exponents, but not for the general case unless we allow complex values (which Lua/C's pow function does not). So it makes no sense to raise a negative number to an arbitrary exponent if we are dealing just with real numbers.

This is the mathy reasoning behind it:

Let 'a' be a real negative number. We may assume without loss of generality that a = -1, since if (-1)^x is defined, so is a^x, and likewise if a^x is defined then we may define (-1)^x by dividing a^x by |a|^x. Suppose, by way of contradiction, there exists a continuous function f: R -> R such that f(n) = (-1)^n for every n in |. Let eps be a real number such that 0 < eps < 2. I shall show there is no delta > 0 such that |x| < delta implies |f(x) - 1| < eps, which in turn contradicts the continuity of f.

Let delta > 0 be a real number. By abstract nonsense*, there exists a positive integer q such that 1/q < delta. We may assume q is odd, since otherwise we could replace q with q + 1. The oddness of q implies (-1)^q = -1, so that f(1/q) = -1, which in turn implies |f(1/q) - 1| = 2 > eps. The contradiction follows.

* i.e., since R is an archimedean field.

EDIT: buggy demonstration.

Edited by simplex
Link to comment
Share on other sites

@outseeker, IceGrowth is the name of the component. Replace that with your components name. 

 

Thanks mate. I was looking to record and retain the leader component for pets so they can remember you after restarts- I don't see how to do that using this as an example, though I am still tooling around with it

Edited by outseeker
Link to comment
Share on other sites

@simplex, Or more simply, because a base a exponential function can be written as a^x = e^xln(a), a can't be negative as the natural log is only defined on R+. :razz:

But 0^x is still defined (at least for positive x), even if ln(0) is not :razz:.

And, *drums*, the natural logarithm can be defined for negative arguments! If we allow complex values, that is. Let r > 0. Then we can set:

HksU2yZ.png

so that

LNrMsao.png

:razz:

EDIT: The last value in the equality chain should be "-r", not "r". And my use of absolute values was a bit redundant since I stated that r > 0. But meh, I'm not recompiling the formulas.

Edited by simplex
Link to comment
Share on other sites

@simplex@Jjmarco,  I reject your mathematical science and substitute my own! Sometimes you just have to bypass the laws of mankind and step into nature's realm of science where everything and anything is possible!

 

FWIW, the equation I have stuck with is pretty slick although it has some small issues that I'm still working out. Should have a realistic ice growth component soon for ponds and at that point I will make you all cry!

 

@outseeker, try something like:

 

function Follower:OnSave()

    -- INSERT SAVE DATA

end

 

function Follower:OnLoad(data)

    if data then

        -- DO LOAD SEQUENCE

    end

end

 

Unless you are specifically setting up a custom component you might need to use AddPrefabPostInit and change Follower to inst.

Link to comment
Share on other sites

@simplex, yes, I am aware that the natural log can be defined for negative arguments, but because you said yourself that Lua's pow function doesn't allow for complex numbers, I only limited myself to R.

 

Though you got me with 0^x still being defined, I didn't thought of that. xD

 

What did you use to make those fancy equations?

 

@Kzisor, Nature makes the laws, we only (try to) describe them.

This also applies to your ice growth equation. :razz:

 

But doesn't the leader component already have a save sequence? I think custom followers are still taken into account in it.

Link to comment
Share on other sites

@simplex, yes, I am aware that the natural log can be defined for negative arguments, but because you said yourself that Lua's pow function doesn't allow for complex numbers, I only limited myself to R.

 

Though you got me with 0^x still being defined, I didn't thought of that. xD

I had just mentioned the complex log as a piece of trivia for whoever may pass by, I didn't mean to imply you did or didn't know about it. But in either case, my point was that checking the existence of logs isn't enough to disprove the existence of the base 'a' exponential: if the log exists, then we can define the exponential in terms of that (so existence of log(a) implies existence of exponential base 'a'), but inexistence of a log is not enough to show there is no other way of defining the exponential base 'a' (hence my base '0' example).

But anyway, this discussion also led me to see my original demonstration wasn't quite correct :razz:. As your formula shows, if the log exists, the exponential exists. Therefore, if we allow complex values, usage of a complex log allows us to construct an exponential function. My proof was only correct (with some minor tweaks) if we disallow complex values. My faulty argument was this:

I had claimed that, if a < 0 and q is a positive integer, then a^(1/q) < 0. This is silly, with the obvious counterexample of (-1)^(1/2) = i (or -i), which is not even real, let alone negative. Don't ask me where I pulled that from, since it'd fail even for natural exponents, i.e. (-1)^2 = 1 > 0.

I fixed the original demonstration.

EDIT: Oops, I had forgotten to reply to this part:

What did you use to make those fancy equations?

I used LaTeX, which is the markup language usually used for writing papers/books in maths and the natural sciences.

I usually use texify to generate tex snippets as a .png URL to link to somewhere, but the site was down, so I generated them locally and uploaded them to imgur. The LaTeX code to do that was

\documentclass[border=1pt, varwidth]{standalone}\usepackage{standalone}\usepackage{amsmath}\usepackage{amssymb}\begin{document}\[ e^{i \pi} + 1 = 0 \]\end{document}
though I passed the formula in the command line instead of hardcoding it like in what I posted above.

Edited by simplex
Link to comment
Share on other sites

@simplex, Yes, I see now where my formula falls short. The existence of ln(a) is a sufficient, but not a necessary condition to the existence of ax.

(I just noticed there is a function to put text as an exponent on the editor :razz:)

 

So, basically, in your demonstration, you are proving that f isn't continuous at 0 (and thus ins't continuous at all on R), if I understood correctly.

 

LaTeX seems pretty interesting, thanks :-) I hope texify will be up again, it seems really handy for quickly generating neat equations.

Link to comment
Share on other sites

@simplex, Yes, I see now where my formula falls short. The existence of ln(a) is a sufficient, but not a necessary condition to the existence of ax.

Exactly, it's a sufficient but not necessary condition.

 

 

So, basically, in your demonstration, you are proving that f isn't continuous at 0 (and thus ins't continuous at all on R), if I understood correctly.

Yes, that's exactly what I showed. Though one can also show it's not continuous anywhere; this is because if f is a function and c is a non-zero constant, then f is continuous at some point x if and only if the function g(x) = c*f(x) is continuous at x. Therefore, if we fix any x0 in R, by setting g(x) = ax0 + x = ax0 * ax it follows that, since ax is not continuous at 0, g is not continuous at 0, which since g(x) = ax0 + x means ax is not continuous at x0.

 

There are some other more obvious issues with a real exponential function with a negative base, though, like the impossibility of defining (-1)1/2 as a real number. So my demonstration is mostly relevant to show that, even if we restricted that function only for exponents where it's well defined, it still wouldn't be continuous. These issues disappear when we allow complex values, of course (I only say "of course" because it follows directly from your formula). The situation from my proof where (-1)1/q = -1 for odd q comes from the value having to be real; if working over the complex numbers and fixing a complex logarithm (let's say the principal value logarithm), then we would be taking ei*pi/q as the value of (-1)1/q, which does get closer and closer to 1 as q tends to infinity.

 

LaTeX seems pretty interesting, thanks :-) I hope texify will be up again, it seems really handy for quickly generating neat equations.

texify is pretty handy. The formulas it generates are a bit pixelated (probably to save some bandwidth on their end), but it's much easier than generating an image yourself, uploading it and then linking to that. However many websites, like Wikipedia, math-related StackExchange derivatives and some blog engines have built-in support for rendering LaTeX (usually marked by writing the formula code within '$'s, which is in fact how you write equations in the middle of text for a regular LaTeX document).

 

(I just noticed there is a function to put text as an exponent on the editor :razz:)

Ah, I had forgotten about that! That notation is borrowed from MathML, which is yet another math markup language. It's useful because modern browsers have built-in support for rendering it directly, but it's a bit awkward to write it by hand; some sites (like Wikipedia) translate LaTeX into MathML when possible though, to avoid having to create/transmit an image (when possible; LaTeX is much more generic than MathML, so there's not always a conversion).

Edited by simplex
Link to comment
Share on other sites

@simplex, stop giving me a freaking headache with all your complicated math equations and jargin. Ugh!!!! *runs to nearest brick wall and bangs head against it* /sarcasm

 

Thanks for the information, it is helpful however it doesn't explain why the any calculator will allow you to use a negative value for the left and right side of the power symbol and give you an accurate reading. What equation are they using and why doesn't C/C++/Lua use that equation?

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