Serpens Posted August 19, 2019 Share Posted August 19, 2019 (edited) Hi, I already made several mods with modworldgenmain and know the basics. But currently I have a problem, that modworldgenmain is called twice everytime the game starts, while at the first time, many GLOBAL variables are unknown/empty. And this first time, the modworldgenmains are not called in the correct order for several mods (not in order of their priority).What I want to achieve: Mod 1 runs first and puts some info into a GLOBAL table. Mod 2 runs last and his modworldgenmain should do something depending on what was put into that table by Mod 1. Problem: At world generation, modworldgenmain runs once, before any modmain and without any order. After that the mods are loaded in correct order, so only in this second run, the table was actually filled. At opening an already generated world: It seems to be the other way round? First are the mods laoded and after that modworldgenmain without any information about my table. So I thought it would be time to find out, why is it called twice. What is done in the first/second run. And how to differentiate between those two. Anyone knows that? Edited August 21, 2019 by Serpens Link to comment Share on other sites More sharing options...
Developer zarklord_klei Posted August 19, 2019 Developer Share Posted August 19, 2019 (edited) You have some things majorly confused, I'm gonna clear some things up, but I'm gonna introduce a couple terms so its clear what I'm referring to. modfrontendmain = modworldgenmain, when its called on the frontend in the ServerCreationScreen. modbackendmain = modworldgenmain, when its called on the backend, which is world gen, and normal world loading. worldgen_main = when the game solely loads modbackendmain, and doesn't load modmain, this environment is completely separate from main. main = when the game loads both modbackendmain and then modmain right after, this environment is completely separate from worldgen_main. environment = the environment that you can access with GLOBAL inside modmain/modworldgenmain, different environments means that you can't(easily) pass between different GLOBAL environments. alright, with all the terms defined here is all the ways these files get loaded. on the frontend: modfrontendmain gets loaded for all server mods, in a undefinable order, order is never predictable, so don't even think about directly relying on order. modfrontendmain can get loaded and unloaded multiple times, so if the user keeps enabling and disabling the mod, whatever code is supposed to run, can run multiple times. on the backend: during worldgen_main, all mods get just modbackendmain loaded in the worldgen_main environment, with load priority used. during main, all mods get modbackendmain and modmain(right after modbackendmain) loaded in the main environment, with load priority used. EDIT: as for the solution to your problem about the table thing, you can do something like this: --YOUR MOD: GLOBAL.global("YOURUNIQUETABLENAME")--this line is for something to do with a file called strict.lua, if you care investigate yourself, otherwise just do this. for i, v in ipairs(GLOBAL.YOURUNIQUETABLENAME or {}) do --do your thing with if it already existed in the table end GLOBAL.YOURUNIQUETABLENAME = GLOBAL.setmetatable({}, {__newindex = function(t, k, v)--t is the table, k is the key they attempted to store it at, v is the value they were storing --do your thing with if it attempts to get added to the table. end})--look up lua metatables to understand why this works. --OTHER MODS: GLOBAL.global("YOURUNIQUETABLENAME")--same deal, this can be called multiple times without harm. --if this is undefined, define it. if GLOBAL.YOURUNIQUETABLENAME == nil then GLOBAL.YOURUNIQUETABLENAME = {} end --add your thing the callback list --DO NOT APPEND YOUR FUNCTION ANYWHERE BUT THEN END GLOBAL.YOURUNIQUETABLENAME[#GLOBAL.YOURUNIQUETABLENAME + 1] = YOURVALUE --DO NOT use table.insert, that bypasses the __newindex metatable value. Edited August 19, 2019 by Zarklord Link to comment Share on other sites More sharing options...
Serpens Posted August 19, 2019 Author Share Posted August 19, 2019 (edited) 18 minutes ago, Zarklord said: You have some things majorly confused, I'm gonna clear some things up, but I'm gonna introduce a couple terms so its clear what I'm referring to. modfrontendmain = modworldgenmain, when its called on the frontend in the ServerCreationScreen. modbackendmain = modworldgenmain, when its called on the backend, which is world gen, and normal world loading. worldgen_main = when the game solely loads modbackendmain, and doesn't load modmain, this environment is completely separate from main. main = when the game loads both modbackendmain and then modmain right after, this environment is completely separate from worldgen_main. environment = the environment that you can access with GLOBAL inside modmain/modworldgenmain, different environments means that you can't(easily) pass between different GLOBAL environments. alright, with all the terms defined here is all the ways these files get loaded. on the frontend: modfrontendmain gets loaded for all server mods, in a undefinable order, order is never predictable, so don't even think about directly relying on order. modfrontendmain can get loaded and unloaded multiple times, so if the user keeps enabling and disabling the mod, whatever code is supposed to run, can run multiple times. on the backend: during worldgen_main, all mods get just modbackendmain loaded in the worldgen_main environment, with load priority used. during main, all mods get modbackendmain and modmain(right after modbackendmain) loaded in the main environment, with load priority used. uff... that sounds very complicated. And can you translate this somehow into typical stuff that is done within modmain and stuff that is done within modworldgenmain? Cause currently it is very hard to understand, if I can't connect this with something I "know". I think some commands are not executed during the modfrontendmain for the modworldgenmain. In the end: I want to make an API mod that is used by other mods to generate a custom world. So the other mods will put some taskdata into a global table and my API mod should generate the world accordingly. Also the modmain of API mod should do somehting depending of the conent of global table. How should the mods look like to make this a success? Problem right now is, that every now and then and depending on where I put the code, this table is nil. edit: btw do you know the difference between task and level? Their preinit functions look the same I think, both have required_prefabs and stuff like this in them and both work, so not sure which I should use to change the world generation. Edited August 19, 2019 by Serpens Link to comment Share on other sites More sharing options...
Developer zarklord_klei Posted August 19, 2019 Developer Share Posted August 19, 2019 25 minutes ago, Serpens said: uff... that sounds very complicated. And can you translate this somehow into typical stuff that is done within modmain and stuff that is done within modworldgenmain? Cause currently it is very hard to understand, if I can't connect this with something I "know". I think some commands are not executed during the modfrontendmain for the modworldgenmain. In the end: I want to make an API mod that is used by other mods to generate a custom world. So the other mods will put some taskdata into a global table and my API mod should generate the world accordingly. Also the modmain of API mod should do somehting depending of the conent of global table. How should the mods look like to make this a success? Problem right now is, that every now and then and depending on where I put the code, this table is nil. If I simplify it, it loses some of its information, if their is a term(or terms) that I'm using that your not familiar with, by all means ask and I can tell you and update my main post. Link to comment Share on other sites More sharing options...
Serpens Posted August 19, 2019 Author Share Posted August 19, 2019 (edited) 1 hour ago, Zarklord said: If I simplify it, it loses some of its information, if their is a term(or terms) that I'm using that your not familiar with, by all means ask and I can tell you and update my main post. In case it is really important to understand your terms and there is really no easier way, I need examples to understand it. I'm bad at theory, I always need examples and try/error myself to understand things. And how they are connected or if one is a generic term of others. Currently those are only a handful words and I have absolutely no clue what to do with them This is of course because I have no programming knowledge and also no server/game knowledge. All knowledge I have is modding knowledge, so use existing "easy" tools provided from the developers to modders, although I would call me already advanced, while you seem to be an expert. And I already have experience learning and teaching stuff and know that it sounds super easy for you, but super complicated for me. Therefore I need easier words/examples. But I understand if that would be too much work for you and I'm quite sure this knowledge would be far beyond the scope of the mod I want to make. wow... you are using alot of words and code (your edit in your first post) I have never heard of wihtin my ~some years of DST modding, never needed it before. So.. is this complicated "global(" and "metatable" and "always adding at the end of table" needed, if I instead simply use the TUNING list? I just want to clarify if this complicated stuff is something I really need to solve the problem, or if there are easier ways, eg using existing TUNING table. Another problem is of course that I don't understand what exactly is currently happening within my mod, where I already use the TUNING list. I would like to tell you what I have/tried and what the result was, but it is beyond my understanding. But my current code would be (other mods load first, at last the API mod): -- Other mod in modmain: local _G = GLOBAL if not _G.TUNING.TELEPORTATOMOD then _G.TUNING.TELEPORTATOMOD = {} end if not _G.TUNING.TELEPORTATOMOD.WORLDS then _G.TUNING.TELEPORTATOMOD.WORLDS = {} end local WORLDS = _G.TUNING.TELEPORTATOMOD.WORLDS local function AdventurePortalWorld(tasksetdata) if not tasksetdata.ordered_story_setpieces then tasksetdata.ordered_story_setpieces = {} end table.insert(tasksetdata.ordered_story_setpieces,adventureportal) tasksetdata.tasks = {"Swamp start"} tasksetdata.numoptionaltasks = 0 tasksetdata.optionaltasks = {} tasksetdata.set_pieces = {} tasksetdata.required_prefabs = {"spawnpoint_master","adventure_portal"} tasksetdata.overrides={...} return tasksetdata end table.insert(WORLDS, {name="Maxwells Door", taskdatafunction_forest=AdventurePortalWorld}) -- this list should contain several worlds and api mod will choose a random one -- ########################## -- API mod in modworldgenmain: local _G = GLOBAL if _G.TUNING.TELEPORTATOMOD then local WORLDS = _G.TUNING.TELEPORTATOMOD.WORLDS if _G.next(WORLDS) then --- put the taskdata from a random WORLDS entry into AddTaskSetPreInitAny end end -- ########################## -- API mod in modmain: local _G = GLOBAL local WORLDS = _G.TUNING.TELEPORTATOMOD.WORLDS if _G.next(WORLDS) then AddPrefabPostInit... -- eg. add teleportato and init it and so on end This code does not work, the world is not changed, cause AddTaskSetPreInitAny is not called I guess (at least not at the time it would be necessary, cause _G.TUNING.TELEPORTATOMOD was nil. edit: I think I understood why you made such a complicated code. You assume a different priority of mods. So first the API mod and then the other mods, and you added this "__newindex" function so our API mod is "notified" when someone else is putting new stuff into the table. Hmm... do you really think this order is better? My API mod should not react to something being added. It just should choose a random entry from that WORLDS list and generate the world from this chosen entry. So with your solution my API mod has to add the stuff to a local table when __newidex is called. But it sounds like this will have exactly the same problems I already have with my TUNING solution, so I guess this does not solve the base problem (described in my code above). does it? Edited August 19, 2019 by Serpens Link to comment Share on other sites More sharing options...
Developer zarklord_klei Posted August 19, 2019 Developer Share Posted August 19, 2019 5 hours ago, Serpens said: In case it is really important to understand your terms and there is really no easier way, I need examples to understand it. I'm bad at theory, I always need examples and try/error myself to understand things. And how they are connected or if one is a generic term of others. Currently those are only a handful words and I have absolutely no clue what to do with them This is of course because I have no programming knowledge and also no server/game knowledge. All knowledge I have is modding knowledge, so use existing "easy" tools provided from the developers to modders, although I would call me already advanced, while you seem to be an expert. And I already have experience learning and teaching stuff and know that it sounds super easy for you, but super complicated for me. Therefore I need easier words/examples. But I understand if that would be too much work for you and I'm quite sure this knowledge would be far beyond the scope of the mod I want to make. wow... you are using alot of words and code (your edit in your first post) I have never heard of wihtin my ~some years of DST modding, never needed it before. So.. is this complicated "global(" and "metatable" and "always adding at the end of table" needed, if I instead simply use the TUNING list? I just want to clarify if this complicated stuff is something I really need to solve the problem, or if there are easier ways, eg using existing TUNING table. Another problem is of course that I don't understand what exactly is currently happening within my mod, where I already use the TUNING list. I would like to tell you what I have/tried and what the result was, but it is beyond my understanding. But my current code would be (other mods load first, at last the API mod): -- Other mod in modmain: local _G = GLOBAL if not _G.TUNING.TELEPORTATOMOD then _G.TUNING.TELEPORTATOMOD = {} end if not _G.TUNING.TELEPORTATOMOD.WORLDS then _G.TUNING.TELEPORTATOMOD.WORLDS = {} end local WORLDS = _G.TUNING.TELEPORTATOMOD.WORLDS local function AdventurePortalWorld(tasksetdata) if not tasksetdata.ordered_story_setpieces then tasksetdata.ordered_story_setpieces = {} end table.insert(tasksetdata.ordered_story_setpieces,adventureportal) tasksetdata.tasks = {"Swamp start"} tasksetdata.numoptionaltasks = 0 tasksetdata.optionaltasks = {} tasksetdata.set_pieces = {} tasksetdata.required_prefabs = {"spawnpoint_master","adventure_portal"} tasksetdata.overrides={...} return tasksetdata end table.insert(WORLDS, {name="Maxwells Door", taskdatafunction_forest=AdventurePortalWorld}) -- this list should contain several worlds and api mod will choose a random one -- ########################## -- API mod in modworldgenmain: local _G = GLOBAL if _G.TUNING.TELEPORTATOMOD then local WORLDS = _G.TUNING.TELEPORTATOMOD.WORLDS if _G.next(WORLDS) then --- put the taskdata from a random WORLDS entry into AddTaskSetPreInitAny end end -- ########################## -- API mod in modmain: local _G = GLOBAL local WORLDS = _G.TUNING.TELEPORTATOMOD.WORLDS if _G.next(WORLDS) then AddPrefabPostInit... -- eg. add teleportato and init it and so on end This code does not work, the world is not changed, cause AddTaskSetPreInitAny is not called I guess (at least not at the time it would be necessary, cause _G.TUNING.TELEPORTATOMOD was nil. edit: I think I understood why you made such a complicated code. You assume a different priority of mods. So first the API mod and then the other mods, and you added this "__newindex" function so our API mod is "notified" when someone else is putting new stuff into the table. Hmm... do you really think this order is better? My API mod should not react to something being added. It just should choose a random entry from that WORLDS list and generate the world from this chosen entry. So with your solution my API mod has to add the stuff to a local table when __newidex is called. But it sounds like this will have exactly the same problems I already have with my TUNING solution, so I guess this does not solve the base problem (described in my code above). does it? whenever your doing something that will affect worldgen, ALL code must be contained inside modworldgenmain.lua. modmain.lua doesn't run when the world is generating. Link to comment Share on other sites More sharing options...
Serpens Posted August 19, 2019 Author Share Posted August 19, 2019 (edited) 6 minutes ago, Zarklord said: whenever your doing something that will affect worldgen, ALL code must be contained inside modworldgenmain.lua. modmain.lua doesn't run when the world is generating. of course, but why are you writing this? My code should be correct regarding this matter. The modmain of "other mod" is only putting something into the table, so the modworldgenmain of API mod can use it. And the modmain of API mod is only doing modmain stuff, like AddPrefabPostInit and so on. What else should I do instead? Putting the table.insert stuff into modworldgenmain form "other mod" won't change anything, right? Edited August 19, 2019 by Serpens Link to comment Share on other sites More sharing options...
Developer zarklord_klei Posted August 19, 2019 Developer Share Posted August 19, 2019 Just now, Serpens said: of course, but why are you writing this? My code should be correct regarding this matter. The modmain of "other mod" is only putting something into the table, so the modworldgenmain of API mod can use it. What else should I do instead? Putting the table.insert stuff into modworldgenmain form "other mod" won't change anything, right? yes, it will. modmain from any mod wont run during the entire duration of worldgen. meaning you would always be checking an empty table. moving the code to modworldgenmain will cause the WORLDS table to not be empty. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now