ID:264438
 
Code:
client
Del()
mob.SaveSave(mob)
..()


mob
proc
LoadSave(mob/M)
if(!fexists("[M.ckey].sav"))
return 0
var/savefile/F=new("[M.ckey].sav")
Read(F)

SaveSave(mob/M)
var/savefile/F=new("[M.ckey].sav")
Write(F)


Problem description:
The code is obviously a very simple saving/loading code. It works and does what it needs to do, and it does not need to do anything else.
However, for some strange reason, when it attempts to save a lot of objs in the mobs contents (I am testing with 300), I get the following error message, and I am quoting this directly from Dream Daemon.

Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.
Shutting down after encountering too many critical errors.

I have tried various libraries as well. They all output the same problem (give or take 100 critical errors or so).
Strangely enough, the save file looks normal and even loads as it should.

Anyone have any ideas why this might be happening, and how to fix it? Or is BYOND incapable of saving large amounts of objects?
(Oh yeah, don't try and be witty and say something like I don't need to save 300 objects or whatever, if I did not need to save 300 I wouldn't attempt it)
Are you referencing the loaded mob on any of those objects?
In response to Falacy
No, and any variables that reference any mob or obj are tmp variables and should not be saved anyway.
In response to The Magic Man
mob/Login()
if(fexists("[src.ckey].sav")) src.LoadSave(src)
else
for(var/i=0;i<=500;i++) src.contents+=new/obj
src<<"Added Objects"

client
Del()
mob.SaveSave(mob)
..()

mob
proc
LoadSave(mob/M)
if(!fexists("[M.ckey].sav"))
return 0
var/savefile/F=new("[M.ckey].sav")
Read(F)
M<<"Loaded"

SaveSave(mob/M)
var/savefile/F=new("[M.ckey].sav")
Write(F)
M<<"Saved"


Seems to work fine for me. And your procs are setup weird <.<
In response to Falacy
After closing and opening Dream Daemon, I stopped getting just critical error spam, and got tons of infinite loops apparently.

I have no idea how because the infinite loops are apparently related to the Write proc, and I have not even touched or altered the Write proc in anyway at all.
There is also nothing else calling the write proc. Just what the hell is happening here!??
In response to The Magic Man
What's the exact error and what's it pointing to?
In response to Garthor
A log file outputs...

runtime error: Maximum recursion level reached (perhaps there is an infinite loop)
To avoid this safety check, set world.loop_checks=0.
proc name: Write (/atom/Write)
usr: Poor Long Sword (/obj/Items/Weapons/Long_Sword)
src: Poor Long Sword (/obj/Items/Weapons/Long_Sword)
call stack:
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
...
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Poor Long Sword (/obj/Items/Weapons/Long_Sword): Write(themagicman.sav (/savefile))
Magician (/mob/PC): Write(themagicman.sav (/savefile))
Magician (/mob/PC): SaveSave(Magician (/mob/PC))
Magician (/mob/PC): Logout()

A lot of times. This is in debug mode, and nowhere in the log does it point to a specific line of code that could be causing this.

I have no idea exactly how the write proc works, but from what I can see, write is being either called by all the objects in the mobs contents, or write ir calling write, which is calling write and so on and so on.
But I don't see how either of these could be happening (and there is definately no variables in any of the objects referencing another mob or obj).

Here is what is output for all the objs vars for.

skill blacksmith 2
InContainer 0
Construction /list
IsLiquid 0
desci
Collapsed 1
MatsNeeded 1 Armor Chain
1 Armor Plate
MaxAmount 1
Amount 1
Weight 1.8
BaseWeight 1.8
Damage 1d2
DamageType
Defence 20
Ranged
AmmoType
CanCraft 1
Quality 1
Material
Condition 110
MaxCondition 110
Equipped
Heavy 1
Hands 1
permname
Constructlist
ToolList
CanSmelt
SmeltTimer
animate_movement 1
loc Magician
x 0
y 0
z 0
screen_loc
pixel_step_size 0
type /obj/Items/Armor/Feet/Greaves
parent_type /obj/Items/Armor/Feet
tag
name Greaves
desc
suffix
text [
icon
icon_state
overlays /list
underlays /list
dir 2
visibility 1
luminosity 0
opacity 0
density 0
layer 3
gender neuter
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer 1
mouse_drop_zone 0
verbs /list
vars /list
contents /list
invisibility 0
infra_luminosity 0
pixel_x 0
pixel_y 0

The only thing that is referencing another obj or mob is loc, but I would assume that is natural provided the object is in a mobs contents.
Most of the /lists (if not all) are empty as well, contents, verbs, overlays, underlays, are all empty. The list Construction is simple list of several types (in this case /obj/Items/Materials/Armor_Chain and /obj/Items/Materials/Armor_Plate).

Also, even if this error occurs, the savefile looks normal when opened as a txt file, and it even loads perfectly fine.
In response to The Magic Man
How about showing us whatever Write() procs you have between /atom and /obj/Items/Weapons/Long_Sword? Oh, and any /mob/Write() and /mob/Magician/Write() you might have.

Circular references are NOT the issue. Savefiles already resolve those.

And I just noticed: SaveSave() shouldn't have an argument. Just use src throughout rather than mixing up src and the argument. But that's not causing this problem.
In response to Garthor
Ugh, this is great, I just found the problem.
I don't make use of Write(), but a library (SwapMaps) I am using does. Coincidentally, as soon as I untick the include box for said library, this problem dissapears.

I don't know whether this is a good or bad thing, but thanks for the help.
In response to The Magic Man
Well, now I'm really curious. Do you think you could post the ExportText() of the savefile?
In response to Garthor
http://www.byond.com/members/TheMagicMan/files/Saves.rar

You'll find various save files and some logs in there. They all causes an infinite loop crash and all loaded and worked just fine.
In response to The Magic Man
Oh wow, that is a gigantic mess...

I can't figure out EXACTLY what's causing the error (I can't manage to reproduce it), but I'm pretty damn sure that the solution is for you to change Write(F) to F << src. That'll let you include SwapMaps again.

Note that even when not using SwapMaps, you still have mangled savefiles as a result of calling Write() directly. And now I know for sure that doing so is actually wrong, rather than a "difference in style".
In response to Garthor
Garthor wrote:
Note that even when not using SwapMaps, you still have mangled savefiles as a result of calling Write() directly. And now I know for sure that doing so is actually wrong, rather than a "difference in style".

No, now you're just spouting nonsense without knowing what you're talking about again, actually. The fact is, calling Write() and Read() directly works perfectly fine and doesn't produce any supposed "mangled savefiles". If he has such a problem here, then it's not because of the above.
EDIT: This may very well be a case where a property save isn't suitable, though. But that method of saving is valid.
In response to Kaioken
Actually, working on this a bit more, it seems to be an issue with SwapMaps when it's saving a contents list with over ~150 objects with a list variable. I missed the part where you said you were saving hundreds of objects.

And Kaioken, please tell me which one of these is correct:

. = object("//.0")
.0
type = /mob
myobj = object(".0")
.0
type = /obj
owner = object("../../..")
name = "Garthor"
gender = "male"
contents = list(object("../myobj/.0"))
key = "Garthor"


myobj = object(".0")
.0
type = /obj
owner = object(".0")
.0
type = /mob
myobj = object("../../..")
name = "Garthor"
gender = "male"
contents = list(object("../../.."))
key = "Garthor"
name = "Garthor"
gender = "male"
contents = object("//myobj/.0/owner/.0/contents",0)
key = "Garthor"


Even if you aren't familiar with the format of ExportText(), you should notice that the second example - which called Write() directly - has all the data pertaining to the mob written twice. Furthermore, when trying to load the mangled savefile, Read() does not behave as expected: the duplicate data entries results in a copy of the mob being created. That's "mangled", not "different".
In response to Garthor
Garthor wrote:
Even if you aren't familiar with the format of ExportText(), you should notice that the second example - which called Write() directly - has all the data pertaining to the mob written twice. Furthermore, when trying to load the mangled savefile, Read() does not behave as expected: the duplicate data entries results in a copy of the mob being created. That's "mangled", not "different".

Which seems to be due to the fact that you're referencing the mob on the obj, which is what I said was most likely the problem in my first post, but he claimed he wasn't doing it.
In response to Falacy
Saving the mob on the obj isn't the issue (except for it causing direct calls to Write() to mangle the savefile, as I've already mentioned). The issue is that there's something about writing lists that is going wrong and making it quasi-recursive, and triggering the infinite recursion checker. If Write() is left alone, it's protected from this. But, if you even do so much as:

atom/Write()
..()


it'll trigger and crash.

Setting world/loop_checks = 0 fixes this... but aside from that there doesn't seem to be a solution.
In response to Garthor
Garthor wrote:
Saving the mob on the obj isn't the issue (except for it causing direct calls to Write() to mangle the savefile, as I've already mentioned). The issue is that there's something about writing lists that is going wrong and making it quasi-recursive, and triggering the infinite recursion checker. If Write() is left alone, it's protected from this.

Saving the mob on the obj may not be 100% of the issue here, but it explains why "the duplicate data entries results in a copy of the mob being created". It could also explain the infinite loops. If the mob is saving the obj, then the obj is saving the mob, then repeat forever. The same thing could happen on load. Only thing I'm not sure about is why overwriting the write() proc with only a parent call would trigger this, when using the built-in one doesn't.
In response to Garthor
I really don't know how the heck you're testing this and in what kind of messed up environment, but again I'm not getting anything like your results, which make no sense. I don't think you're fabricating the results, but make sure to test correctly. Clearly the first bunch of data in your second box was not saved by directly calling Write(), as that only does a property save, which only saves the vars directly, without saving the 'object()' header or the type. You've messed the testing up and accidentally included both types of saving in the savefile or the results, apparently.
FYI, these are the results my testing produced:
Saving with direct-Write():
a = 3
b = 4
name = "Kaioken"
icon_state = "sp2"
dir = 1
gender = "male"
contents = list(object(".0"))
.0
type = /mob
contents = list(object(".0"))
.0
type = /obj
key = "Kaioken"


Saving with <<:
. = object("//.0")
.0
type = /mob
a = 3
b = 4
name = "Kaioken"
icon_state = "sp2"
dir = 1
gender = "male"
contents = list(object(".0"))
.0
type = /mob
contents = list(object(".0"))
.0
type = /obj
key = "Kaioken"

As you can see, no duplicate data is generated by directly calling Write() (in fact, it generates less data than the full instance save, naturally). Both methods also reload the mob correctly as expected; Read() into the current object, and >> into a new one.

Also, I again add that you're not arguing against me here, but against how DM works and is documented. The above are results of an actual test, and everything I'm saying about using Write()&Read() directly working fine and being a different method of object saving from using the operators has been well known as well as documented in the DM Guide (see chapter 12 section 4.4) for years. I would like you to remember your point you've made recently about how you shouldn't strive to stubbornly insist on trying to "win" arguments and to know the truth instead of being deluded. Of course, it would also benefit you to read the DM Guide instead of only pointing others to it, especially when trying to prove someone who knows what he's talking about wrong.
I apologize in advance if the paragraph above may feel overstressed, overly blunt or insulting in any way; I added it in good heart in order to settle the matter and try to prevent inflating the topic with uselessly repetitive, offtopic chain posts.
In response to Falacy
Granted, I haven't read the entire topic in full, but I think the potential reason for the problem here you're mentioning has already been legitimately debunked.

Falacy wrote:
[...]If the mob is saving the obj, then the obj is saving the mob, then repeat forever.

DM's internal object saving system prevents this; when an object that is already in the savefile is about to be saved again, it just saves a reference to the part of the savefile where it was already saved instead of saving the whole object in full again, etc, so this isn't an issue. Garthor mentioned this already:

Garthor wrote:
Circular references are NOT the issue. Savefiles already resolve those.
In response to Kaioken
I suppose I should've posted my test case. It was this (or something very similar):

obj/thing
var/mob/owner

mob
var/obj/thing/mything
New()
..()
mything = new()
mything.owner = src

verb/test()
var/savefile/F = new()
Write(F)
src << F.ExportText()


The key is that there is some reference to the mob being saved along with the mob. When using Write(), it does not save a full object, and so when it comes to the reference to the mob, there's no previous reference in the savefile and so it creates a new one.

And I've found errors in the DM Guide and Reference before. This one goes up there with the abuse of usr: it USUALLY works, but then breaks under certain not-too-uncommon circumstances.
Page: 1 2