Closed andrelo1 closed 2 years ago
JDB is public, shared object for all, you usually should not touch the other's data. Hence, don't rely on init order too. Just go, set up your values upfront and read them later.
Sometimes I need to read values from JDB in OnInit event, that kicks off right after start of the game, so there is no way to init values earlier. How can I be sure that values have been set up ? I don't want to use global variable and infinite loop to wait for initialization completion:
while !isJDBInitialized
---Utility.Wait(0.01)
endwhile
;Read values from JDB.
To be more specific, I wanted to store some settings of my mod in JDB instead of script object. When I used a script I was able to read its properties at any time, even in OnInit event, because I can assign default values to properties. In JDB there are no values at all by default, and that is a problem.
I'm getting lost. Select your most "first" function, set all JDB values which has not been set and then use them later.
But there is no most "first" function, because Papyrus language is multithreading, all OnInit events on all game objects start simultaneously, and you can't select one object, that is initialized first, to set up JDB values.
I can make a "proxy" functions to access JDB values:
bool initialized = false
int function GetJDBValueInt(string path)
---if !initialized
------Initialize()
---endif
---return JDB.solveInt(path)
endfunction
; Same thing for Float, String, Obj and Form types
But this is not good solution too, in my opinion.
Have 1 main script perform the initalization in the OnInit event:
event OnInit()
---; Init db here
---; Utility.wait(1.0) ; Allow other scripts to finish registering for custom mod event
---; self.SendModEvent("JDBInit")
endevent
In the other scripts register for the mod event in their OnInit. You now have a way to ensure that all other scripts will only access the JDB object after it has been initialized:
event OnInit()
---self.RegisterForModEvent("JDBInit", "OnJDBInit")
endevent
event OnJDBInit(string eventName, string strArg, float numArg, Form sender)
--- ; Do whatever you need to do after JDB has been initialized
endEvent
Well, this is a better solution. I thought that init.lua was intended for such initialization, including initialization of JDB.
Edit: I have looked at source code and found that init.lua is used for context setup when evalLua* function is called, and thus it would be wrong place for JDB initialization.
Is there way to initialize JDB with default values ?
I have to wrap each JDB value into property:
int MyInt_Default = 0
int property MyInt
---int function get()
------return JDB.solveInt(".MyMod.MyInt", MyInt_Default)
---endfunction
---function set(int value)
------JDB.SolveIntSetter(".MyMod.MyInt", value, true)
---endfunction
endproperty
I'm not happy with such cumbersome code. I can use OnInit or OnPlayerLoadGame event to initialize JDB, but it doesn't guaranty that another script won't try to read uninitialized values from JDB. Can I access JDB from init.lua to do my initialization before any script can access it ?