Cthonicus Posted January 5, 2020 Share Posted January 5, 2020 (edited) Hello there! I recently have composed a character mod that consists of a character and a custom item this character uses. All seemed to work just fine, even to where I uploaded it to the workshop. However, I soon discovered that the mod absolutely does not work with caves and I cannot figure out why. The mod works perfectly fine with no caves, but once they're added, the server immediately disconnects and loses connection right after spawning in. If this matters, my character's perks are: -sanity gain near certain mobs -spawns with a custom weapon -loses additional sanity at night I have attached my character, modinfo and modmain .lua files in case anyone wants to view them. Thank you for your time! modinfo.lua modmain.lua wolyo.lua (EDIT): I singled out the issue and found the specific lines that are causing the crash. It is these lines of code in my modmain.lua that cause the server to disconnect upon launch - AddPrefabPostInit("butterfly", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("bee", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("chester", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("glommer", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("hutch", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) If these lines work without caves, what would make them work with caves? Edited January 5, 2020 by Cthonicus Link to comment https://forums.kleientertainment.com/forums/topic/114787-mod-crashes-with-caves/ Share on other sites More sharing options...
Ultroman Posted January 5, 2020 Share Posted January 5, 2020 (edited) Your mod doesn't work for clients, so it doesn't work fine without caves either. When you add caves, it splits the game into two server shards, forest and cave. You then become a client on forest and can transition to caves. Without caves, there's only one server shard needed so you become the server instead of a client. It's badly explained, but that's the gist of it. Some code explodes when it runs on the clients, because clients do not have components on their entities like the server does. They only have shells of the entities which are controlled by the server, and they also don't have access to calling functions on the server. So, all your code that messes with components and calls postinit functions and all that, that can't be run on the clients. Start by wrapping your many AddPrefabPostInit calls like this: if GLOBAL.TheNet and GLOBAL.TheNet:GetIsServer() then AddPrefabPostInit("butterfly", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("bee", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("chester", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("glommer", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("hutch", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) end There are also things in custom items which need networking attention. Components should only be added to the item on the server. Edited January 5, 2020 by Ultroman Corrected _G to GLOBAL Link to comment https://forums.kleientertainment.com/forums/topic/114787-mod-crashes-with-caves/#findComment-1296701 Share on other sites More sharing options...
Cthonicus Posted January 5, 2020 Author Share Posted January 5, 2020 (edited) 1 hour ago, Ultroman said: Your mod doesn't work for clients, so it doesn't work fine without caves either. When you add caves, it splits the game into two server shards, forest and cave. You then become a client on forest and can transition to caves. Without caves, there's only one server shard needed so you become the server instead of a client. It's badly explained, but that's the gist of it. Some code explodes when it runs on the clients, because clients do not have components on their entities like the server does. They only have shells of the entities which are controlled by the server, and they also don't have access to calling functions on the server. So, all your code that messes with components and calls postinit functions and all that, that can't be run on the clients. Start by wrapping your many AddPrefabPostInit calls like this: if _G.TheNet and _G.TheNet:GetIsServer() then AddPrefabPostInit("butterfly", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("bee", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("chester", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("glommer", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("hutch", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) end There are also things in custom items which need networking attention. Components should only be added to the item on the server. I tried this and it results in me being unable to start the server. It tells me "There was some sort of trouble starting the server. Please try again." I attached the log below if that helps. Thanks for the reply! client_log.txt modmain.lua Edited January 5, 2020 by Cthonicus I attached the modmain.lua AFTER the newly added line. Link to comment https://forums.kleientertainment.com/forums/topic/114787-mod-crashes-with-caves/#findComment-1296710 Share on other sites More sharing options...
Ultroman Posted January 5, 2020 Share Posted January 5, 2020 (edited) The client log doesn't help much when you use caves, since everything then runs on the server shards. We need the server logs from both the forest and cave server shards, as well as the client log, from just after a crash happened. Please check out the newcomer post. It has information about where to find these files, and how to debug your mod in general. BUT, in this case, there is one error you should fix before debugging any further. The code I pasted uses _G, which is what I always save my GLOBAL reference as, just to save on characters. Here's an example using your own code. local _G = GLOBAL local require = _G.require local STRINGS = _G.STRINGS local Ingredient = _G.Ingredient local RECIPETABS = _G.RECIPETABS local Recipe = _G.Recipe local TECH = _G.TECH local TUNING = _G.TUNING local GetPlayer = _G.GetPlayer -- This is for the sanity aura Wolyo gains from "cute" things if _G.TheNet and _G.TheNet:GetIsServer() then AddPrefabPostInit("butterfly", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("bee", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("chester", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("glommer", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("hutch", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) end Edited January 5, 2020 by Ultroman Link to comment https://forums.kleientertainment.com/forums/topic/114787-mod-crashes-with-caves/#findComment-1296721 Share on other sites More sharing options...
Cthonicus Posted January 5, 2020 Author Share Posted January 5, 2020 6 minutes ago, Ultroman said: The client log doesn't help much when you use caves, since everything then runs on the server. We need the server logs from both the forest and cave server shards, as well as the client log, from just after a crash happened. Please check out the newcomer post. It has information about where to find these files, and how to debug your mod in general. BUT, in this case, there is one error you should fix before debugging any further. The code I pasted uses _G, which is what I always save my GLOBAL reference as, just to save on characters. Here's an example using your own code. local _G = GLOBAL local require = _G.require local STRINGS = _G.STRINGS local Ingredient = _G.Ingredient local RECIPETABS = _G.RECIPETABS local Recipe = _G.Recipe local TECH = _G.TECH local TUNING = _G.TUNING local GetPlayer = _G.GetPlayer -- This is for the sanity aura Wolyo gains from "cute" things if _G.TheNet and _G.TheNet:GetIsServer() then AddPrefabPostInit("butterfly", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("bee", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("chester", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("glommer", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) AddPrefabPostInit("hutch", function(inst) if GetPlayer().prefab == "wolyo" then inst:AddComponent("sanityaura") inst.components.sanityaura.aura = TUNING.SANITYAURA_MED end end) end Tried the code and got the same result I attached both log files like you said, hope it helps! server_log_cave.txt server_log.txt client_log.txt Link to comment https://forums.kleientertainment.com/forums/topic/114787-mod-crashes-with-caves/#findComment-1296727 Share on other sites More sharing options...
Ultroman Posted January 5, 2020 Share Posted January 5, 2020 From the absolute bottom of your first server log: [string "../mods/wolyo/modmain.lua"]:64: attempt to index a nil value LUA ERROR stack traceback: ../mods/wolyo/modmain.lua(64,1) =(tail call) ? =[C] in function 'xpcall' scripts/mods.lua(161,1) in function 'mod' scripts/mainfunctions.lua(267,1) =[C] in function 'SpawnPrefab' scripts/mainfunctions.lua(306,1) in function 'SpawnPrefab' scripts/components/childspawner.lua(445,1) in function 'DoSpawnChild' scripts/components/childspawner.lua(472,1) in function 'SpawnChild' scripts/components/childspawner.lua(178,1) in function 'OnUpdate' scripts/components/childspawner.lua(200,1) in function 'fn' scripts/scheduler.lua(177,1) in function 'OnTick' scripts/scheduler.lua(371,1) in function 'RunScheduler' scripts/update.lua(180,1) [00:01:07]: Disabling wolyo (Wolyo) because it had an error. Since you've edited the code, I don't know what line 64 is now. But I'm guessing it's GetPlayer() which returns nil. This looks like DS code. What it wants to do doesn't make any sense in a multiplayer setting. It says: if the "the player" using a particular character, add an aura to the bees. It makes sense in DS, since there's only one player to be affected by the aura, and we know which character they are playing during worldgeneration and loading, but in DST we do not. I believe GetPlayer() on the client returns the character entity (client-shell version) of the current client, but since the postinits are only called on the server, there IS NO PLAYER TO CHECK. The code wants to give the player sanity when close to bees by adding a sanity aura to the bees. But the way it is done makes everyone be affected by the sanityaura. Additionally, you don't check if they already have a sanityaura component. Perhaps another mod has already added a sanityaura component, in which case your mod overwrites their sanityaura or their mod overwrites yours (I think). Always check if there is already an aurafn function, and if there is, extend it to do whatever extra thing you want it to do for certain "observers" (entities, i.e. players, monster, etc. with a sanity component). Otherwise, add a new aurafn which does what you want. I have done this in the topic here. Link to comment https://forums.kleientertainment.com/forums/topic/114787-mod-crashes-with-caves/#findComment-1296753 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