Hunger Artist Posted December 23, 2016 Share Posted December 23, 2016 OnSave always returning nil in GetPersistData(). What I'm doing wrong? Code in prefab file local function onsave(inst, data) if inst.pokemons then data.saved=true for k, v in pairs(inst.pokemons) do print("Saving GUID "..v.GUID) if data.pokemons == nil then data.pokemons = { v.GUID } else table.insert(data.pokemons, v.GUID) end end dumptable(data.pokemons) return data.pokemons end end Modified EntityScript:GetPersistData() for debugging purpose function EntityScript:GetPersistData() local references = nil local data = nil for k,v in pairs(self.components) do if v.OnSave then local t, refs = v:OnSave() if type(t) == "table" then if t and next(t) and not data then data = {} end if t and data then data[k] = t end end if refs then if not references then references = {} end for k,v in pairs(refs) do table.insert(references, v) end end end end if self.OnSave then if not data then data = {} end local refs = self.OnSave(self, data) if self.prefab=="trainerred" then print("OnSave GUIDs ") print(refs) print(dumptable(refs)) end if refs then if not references then references = {} end for k,v in pairs(refs) do if self.prefab=="trainerred" then print("Ref GUIDs "..v) end table.insert(references, v) end end end if (data and next(data)) or references then return data, references end end Log [00:03:15]: DoRestart: true [00:03:16]: Saving GUID 112230 [00:03:16]: K: 1 V: 112230 [00:03:16]: OnSave GUIDs [00:03:16]: nil [00:03:16]: [00:03:16]: Serializing user: session/47A546BD92005A26/KU_dAYvwZw3_/0000000003 Link to comment Share on other sites More sharing options...
Kzisor Posted December 23, 2016 Share Posted December 23, 2016 2 minutes ago, popitup said: OnSave always returning nil in GetPersistData(). What I'm doing wrong? Do you have the line 'inst.OnSave = onsave' in your prefab function? Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 23, 2016 Author Share Posted December 23, 2016 Yeap, otherwise log file won't contain strings like [00:03:16]: Saving GUID 112230 [00:03:16]: K: 1 V: 112230 Link to comment Share on other sites More sharing options...
Kzisor Posted December 23, 2016 Share Posted December 23, 2016 2 minutes ago, popitup said: Yeap, otherwise log file won't contain strings like [00:03:16]: Saving GUID 112230 [00:03:16]: K: 1 V: 112230 Okie dokie, although I see you're 'return data.pokemons' when it should be 'return data'. Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 23, 2016 Author Share Posted December 23, 2016 I will try, but not so sure about it because of local refs = self.OnSave(self, data) Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 23, 2016 Author Share Posted December 23, 2016 (edited) Still nil [00:03:11]: DoRestart: true [00:03:12]: Saving GUID 114814 [00:03:12]: K: 1 V: 114814 [00:03:12]: OnSave GUIDs [00:03:12]: nil [00:03:12]: [00:03:12]: Serializing user: session/395F1B81BACCF1F2/KU_dAYvwZw3_/0000000003 Edited December 23, 2016 by popitup nil Link to comment Share on other sites More sharing options...
Kzisor Posted December 23, 2016 Share Posted December 23, 2016 3 minutes ago, popitup said: Still nil [00:03:11]: DoRestart: true [00:03:12]: Saving GUID 114814 [00:03:12]: K: 1 V: 114814 [00:03:12]: OnSave GUIDs [00:03:12]: nil [00:03:12]: [00:03:12]: Serializing user: session/395F1B81BACCF1F2/KU_dAYvwZw3_/0000000003 You're gonna need to post your prefab that is trying to save. There isn't enough information in order to determine the true cause of the issue. Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 23, 2016 Author Share Posted December 23, 2016 (edited) local MakePlayerCharacter = require "prefabs/player_common" local assets = { Asset("SCRIPT", "scripts/prefabs/player_common.lua"), } -- Custom starting items local start_inv = { "trainercap", "pokeball", } -- When the character is revived from human local function onbecamehuman(inst) -- Set speed when reviving from ghost (optional) inst.components.locomotor:SetExternalSpeedMultiplier(inst, "trainerred_speed_mod", 1) end local function onbecameghost(inst) -- Remove speed modifier when becoming a ghost inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "trainerred_speed_mod") end -- When loading or spawning the character local function onload(inst,data) inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman) inst:ListenForEvent("ms_becameghost", onbecameghost) if inst:HasTag("playerghost") then onbecameghost(inst) else onbecamehuman(inst) end if data and data.pokemons then print("Pokemons GUIDs loaded") inst.datapokemons=data.pokemons end end -- This initializes for both the server and client. Tags can be added here. local common_postinit = function(inst) -- Minimap icon inst.MiniMapEntity:SetIcon( "trainerred.tex" ) inst:AddTag("TrainerRed") end local function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, deepcopy(getmetatable(orig))) else -- number, string, boolean, etc copy = orig end return copy end local function onsave(inst, data) if inst.pokemons then data.saved=true for k, v in pairs(inst.pokemons) do print("Saving GUID "..v.GUID) if data.pokemons == nil then data.pokemons = { v.GUID } else table.insert(data.pokemons, v.GUID) end end dumptable(data.pokemons) return data.pokemons end end local function OnLoadPostPass(inst, newents, savedata) print("OnLoadPostPass") dumptable(savedata) if savedata ~= nil and savedata.pokemons ~= nil then for k, v in pairs(savedata.pokemons) do print("Loading pokemons") local pokemon = newents[v] if pokemon ~= nil then pokemon.entity.trainer=inst end end end end -- This initializes for the server only. Components are added here. local master_postinit = function(inst) -- choose which sounds this character will play inst.soundsname = "wilson" -- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used -- inst.talker_path_override = "dontstarve_DLC001/characters/" -- Can eat monster meat inst.components.eater.strongstomach = false -- Stats inst.components.health:SetMaxHealth(150) inst.components.hunger:SetMax(150) inst.components.sanity:SetMax(200) -- Damage multiplier (optional) inst.components.combat.damagemultiplier = 0.5 -- Hunger rate (optional) inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE inst.OnSave = onsave --inst.OnLoadPostPass = OnLoadPostPass --doesn't work anyway inst.OnLoad = onload inst.OnNewSpawn = onload end return MakePlayerCharacter("trainerred", prefabs, assets, common_postinit, master_postinit, start_inv) Just changed back "return data.pokemons" after trying "return data" Edit: I'm trying to save references to mobs. But their GUIDs don't persist because of problem that I described. Edited December 23, 2016 by popitup Link to comment Share on other sites More sharing options...
Aquaterion Posted December 23, 2016 Share Posted December 23, 2016 What exactly would be the use of returning a value after saving, if you dont mind me asking? Link to comment Share on other sites More sharing options...
Kzisor Posted December 23, 2016 Share Posted December 23, 2016 5 minutes ago, popitup said: Just changed back "return data.pokemons" after trying "return data" How are you 'storing' the pokemon on the instance? I don't see that anywhere. If you're using 'table.insert(inst.pokemons, X)' then you could try: for k, v in ipairs(inst.pokemons) do instead of for k, v in pairs(inst.pokemons) do That is really the only thing I see wrong with your code, aside from the returning of data.pokemons; which you should return data because other data could be in the data table. Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 23, 2016 Author Share Posted December 23, 2016 (edited) This code isn't for storing. It's for labeling mobs as pokemon in the wild. Just now, Aquaterion said: What exactly would be the use of returning a value after saving, if you dont mind me asking? The only use of returning value is make GUIDs persistent. Currently I'm using saved data in this piece of code (since OnLoadPostPass doesn't fire at all so I commented it) local function trainerred_postinit(inst) inst:DoTaskInTime( 1, function() if inst.datapokemons then for k, v in pairs(inst.datapokemons) do local pokemon = GLOBAL.Ents[v] if pokemon ~= nil then pokemon.entity.trainer=inst end end end end ) end AddPrefabPostInit("trainerred", trainerred_postinit) I labeling them for multiple purpose. One of them is forbid to attack master. Edited December 23, 2016 by popitup Link to comment Share on other sites More sharing options...
Kzisor Posted December 23, 2016 Share Posted December 23, 2016 (edited) 13 minutes ago, popitup said: This code isn't for storing. It's for labeling mobs as pokemon in the wild. The only use of returning value is make GUIDs persistent. Currently I'm using saved data in this piece of code (since OnLoadPostPass doesn't fire at all so I commented it) local function trainerred_postinit(inst) inst:DoTaskInTime( 1, function() if inst.datapokemons then for k, v in pairs(inst.datapokemons) do local pokemon = GLOBAL.Ents[v] if pokemon ~= nil then pokemon.entity.trainer=inst end end end end ) end AddPrefabPostInit("trainerred", trainerred_postinit) I labeling them for multiple purpose. One of them is forbid to attack master. How are you populating 'inst.pokemons'?? You have to populate that table before you can save anything from it. Edited December 23, 2016 by Kzisor Changed to, to from, stupid auto correct. Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 23, 2016 Author Share Posted December 23, 2016 (edited) local function addpokemon(trainer, pokemon) if trainer.pokemons==nil then trainer.pokemons={} end table.insert(trainer.pokemons,pokemon) end pokemon is just instance of regular mob. Useful topic: OK if it doesn't work with prefab then I'll try save GUIDs with component. Edited December 23, 2016 by popitup Link to comment Share on other sites More sharing options...
Kzisor Posted December 23, 2016 Share Posted December 23, 2016 13 minutes ago, popitup said: local function addpokemon(trainer, pokemon) if trainer.pokemons==nil then trainer.pokemons={} end table.insert(trainer.pokemons,pokemon) end Did you try using ipairs instead of pairs in the onsave function? Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 23, 2016 Author Share Posted December 23, 2016 (edited) Yeap, still nothing. So what should happen that returning value become nil even if I returning a simple number. So calling OnSave from EntityScript:GetPersistData() local refs = self.OnSave(self, data) return nil even for this code local function onsave(inst, data) if inst.pokemons then data.saved=true for k, v in ipairs(inst.pokemons) do print("Saving GUID "..v.GUID) if data.pokemons == nil then data.pokemons = { v.GUID } else table.insert(data.pokemons, v.GUID) end end dumptable(data.pokemons) return 2345555 end return 2345555 end I'm a bit confused. Edited December 23, 2016 by popitup Link to comment Share on other sites More sharing options...
Aquaterion Posted December 23, 2016 Share Posted December 23, 2016 maybe the issue is with playercommon/classified also having onsave functions, and since they kind of override the player prefab's safe, ur return is getting lost in there Link to comment Share on other sites More sharing options...
Serpens Posted December 24, 2016 Share Posted December 24, 2016 did not read the full thread, but the first post looks like you want to save instances. In case there is a problem with it, maybe this thread helps, although you already use GUID: Link to comment Share on other sites More sharing options...
zUsername Posted December 24, 2016 Share Posted December 24, 2016 local function OnSave(inst, data) local pokemons = {} for k,v in pairs(inst.pokemons) do pokemons[k] = {} pokemons[k].GUID = v.GUID end data.pokemons = pokemons end local function OnLoad(inst, data) if data and data.pokemons then inst.pokemons = data.pokemons end end local master_postinit = function(inst) inst.pokemons = {} inst.OnSave = OnSave inst.OnLoad = OnLoad end Don't know if it's work for you or not. But above code works on my Warly mod: https://steamcommunity.com/sharedfiles/filedetails/?id=607654103 Link to comment Share on other sites More sharing options...
Hunger Artist Posted December 24, 2016 Author Share Posted December 24, 2016 Thanks for replies. Solution was found. So I made dummy prefab and spawning it once per world local assets = { } local function addguid(inst,guid,ownerid) table.insert(inst.guids,guid) inst.ownerlist[guid]=ownerid end local function onsave(inst, data) print("Dummy: onsave") local cleanguids={} local cleanownerlist={} for k, v in ipairs(inst.guids) do if Ents[v] then table.insert(cleanguids,v) cleanownerlist[v]=inst.ownerlist[v] end end if #cleanguids>0 then data.guids=cleanguids data.ownerlist=cleanownerlist print(dumptable(data.ownerlist)) return data.guids end end local function OnLoadPostPass(inst, newents, data) print("Dummy: OnLoadPostPass") for k, v in pairs(Ents) do --print(k) end if data and data.guids and data.ownerlist then for k, v in pairs(data.guids) do local poke = newents[v] print("Dummy: loading GUID "..v) if poke ~= nil then print("Dummy: owner "..data.ownerlist[v]) --poke.entity.trainerid=data.ownerlist[v] print("Dummy: Exist "..poke.entity.name) print("Dummy: newGUID "..poke.entity.GUID) if Ents[poke.entity.GUID] then print("Dummy: labeling it") Ents[poke.entity.GUID].trainerid=data.ownerlist[v] inst:addguid(poke.entity.GUID,data.ownerlist[v]) end end end end end local function fn() local inst = CreateEntity() inst.entity:AddTransform() inst.entity:AddNetwork() inst.entity:SetPristine() if not TheWorld.ismastersim then return inst end inst.ownerlist={} inst.guids={} inst.addguid = addguid inst.OnSave = onsave inst.OnLoadPostPass = OnLoadPostPass GUIDsHelper=inst return inst end return Prefab("guiddummy", fn, assets) In modmain GLOBAL.GUIDsHelper=nil local function trainer_postinit(inst) inst:DoTaskInTime( 0, function() for k, v in pairs(GLOBAL.Ents) do if v.trainerid and v.trainerid==inst.userid then print(v.name.." labeled") v.trainer=inst end end if GLOBAL.TheWorld.ismastersim and not GLOBAL.GUIDsHelper then print("Dummy spawned") GLOBAL.GUIDsHelper=GLOBAL.SpawnPrefab("guiddummy") end end ) end AddPlayerPostInit(trainer_postinit) There is no easy way to store references with players prefab. Hope devs will do something about it. 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