ID:138694
 
(See the best response by Keeth.)
Code:
runtime error: Maximum recursion level reached (perhaps there is an infinite loop)
To avoid this safety check, set world.loop_checks=0.
proc name: Savee (/mob/proc/Savee)
usr: Muvuca (/mob)
src: Muvuca (/mob)
call stack:
Muvuca (/mob): Savee()
Muvuca (/mob): Logout()
Muvuca (/mob): ToRead()
Muvuca (/mob): Login()
ToRead()
Login()
ToRead()
Login()
ToRead()
Login()
...
Login()
Login()
Login()
Login()
Login()
Login()
Login()
Login()
Login()


mob/proc/Savee()
var/savefile/F = new("[usr.ckey].sav")
F["savedx"] << x
F["savedy"] << y
F["savedz"] << z
F["contents"] << contents //this is where the problem is, for some reason I can't save and load a list, any help?


Problem description:
Happens every time I have something in contents and log out then log in again.

If I have nothing in contents, the problem does not happens.

PS: BTW the obj in contents usually are attached to a list.
Best response
That seems to be a lot of calls to Login(). I'm going to go out on a limb and assume this has to do with saving an object that contains a reference to your mob, resulting in your mob being saved. Then, when you load up your character, it creates an entirely new separate copy of your mob in the world. When it does this, it also (by default) loads up key data. When it does this, the game world will automatically assign that mob to you, logging you out of your current mob and logging you into your new one.

This is easily confirmed if you want to show your Login()/Logout()/ToRead() functions. And to confirm what object in your contents, if any, contains a reference to your mob -- savefile.ExportText() will return (or print to a file) a human readable form of your savefile data. All you need to do then is look for an object that saves a mob.
If you are still having issues, please post the relevant code and we'll get back with ya!
Keeth appears to be correct, some kind of reference save loop is happening here. I recommend reading my savefile how-to article for more information as to why this happens and how to prevent it.
Additionally, you can try fixing it for now by adding this to your code:
mob/Read() return

While that would stop the runtime error, it would entirely break his loading system. Finding the cause of the error and resolving it is the best way to handle this.
He doesn't seem to be saving/loading the mob itself, just the contents and location. Unless it's something I'm missing?
Right, but there's a good chance this is just a 'figuring it out' system that will be expanded to save more later and I doubt he's gonna want to save and load each variable one-by-one. Utilizing Read() and Write() via << and >> is a very good way of saving large amounts of data.
Yep, that's why I said 'fixing it for now' :p
Down the road when he's trying to expand his save system and can't figure out why the examples he's reading just aren't working I imagine it'll be more tricky trying to figure out why than fixing this issue. Just hiding the error doesn't fix it. =P
Thx for reply, I made many changes and the problem change, its not looping anymore, but probably is the same reason.

Problem Description: Keep in mind that it is a card game, wverything works fine, but when I duel and after logout, the problem happens.

runtime error: cannot append to list
proc name: ToRead (/mob/proc/ToRead)
usr: Muvuca (/mob)
src: Muvuca (/mob)
call stack:
Muvuca (/mob): ToRead()
Muvuca (/mob): Login()

Here are the codes you asked for:
mob/proc/Savee()
var/savefile/F = new("[usr.ckey].sav")
F["sx"] << x
F["sy"] << y
F["sz"] << z
F["contents"] << contents

mob/proc/ToRead()
if(fexists("[usr.ckey].sav"))
var/savefile/F = new("[usr.ckey].sav")
F["sx"] >> x
F["sy"] >> y
F["sz"] >> z
F["contents"] >> contents

mob/Login()
usr.pixel_y=10
usr.ToRead()

mob/Logout()
src.Savee()
del(src)

//BONUS: THIS IS THE VERB WHICH PROBABLY IS THE REASON OF THE PROBLEM.

mob
verb
LigarDisco()
if(usr.deckescolhido==0)
return
if(usr.discoligado==1)
return
src.frozen=1
world << "<font color = white><font align=center>[usr.nome] raised the disk."
for(var/obj/cartas/O in usr.deck)
O.dir = SOUTH
O.icon = O.iconoriginal
O.icon_state = O.iconstateoriginal
O.name = O.nomeoriginal
O.owner=usr
O.setado=0
O.emdef=0
O.ematk=0
O.nodeck=1
O.nocampo=0
O.nograve=0
O.narfg=0
O.namao=0
src.layer=1000
usr.discoligado=1
winset(usr,"button5","is-visible=false")
var/obj/zones/mz1/a = new/obj/zones/mz1
var/obj/zones/mz2/b = new/obj/zones/mz2
var/obj/zones/mz3/c = new/obj/zones/mz3
var/obj/zones/mz4/d = new/obj/zones/mz4
var/obj/zones/mz5/e = new/obj/zones/mz5
var/obj/zones/stz1/f = new/obj/zones/stz1
var/obj/zones/stz2/g = new/obj/zones/stz2
var/obj/zones/stz3/h = new/obj/zones/stz3
var/obj/zones/stz4/i = new/obj/zones/stz4
var/obj/zones/stz5/j = new/obj/zones/stz5
a.owner=usr
b.owner=usr
c.owner=usr
d.owner=usr
e.owner=usr
f.owner=usr
g.owner=usr
h.owner=usr
i.owner=usr
j.owner=usr
if(usr.dir==NORTH)
a.loc=locate(usr.x-2,usr.y+2,usr.z)
b.loc=locate(usr.x-1,usr.y+2,usr.z)
c.loc=locate(usr.x,usr.y+2,usr.z)
d.loc=locate(usr.x+1,usr.y+2,usr.z)
e.loc=locate(usr.x+2,usr.y+2,usr.z)
f.loc=locate(usr.x-2,usr.y+1,usr.z)
g.loc=locate(usr.x-1,usr.y+1,usr.z)
h.loc=locate(usr.x,usr.y+1,usr.z)
i.loc=locate(usr.x+1,usr.y+1,usr.z)
j.loc=locate(usr.x+2,usr.y+1,usr.z)
for(var/mob/E in world)
if(E.discoligado==1)
if(E.loc==locate(usr.x,usr.y+6,usr.z))
usr.Embaralhar()
E.Embaralhar()
E.client:eye=locate(E.x,E.y-3,E.z)
usr.client:eye=locate(usr.x,usr.y+3,usr.z)
usr.oponente=E.nome
E.oponente=usr.nome
var/mob/y=usr.oponente
world << "<font color = white><b><font align=center>[y.nome] vs [usr.nome]"
usr.chavededuelo="[usr][usr.oponente]"
E.chavededuelo="[usr][usr.oponente]"
if(usr.dir==WEST)
a.loc=locate(usr.x-2,usr.y-2,usr.z)
b.loc=locate(usr.x-2,usr.y-1,usr.z)
c.loc=locate(usr.x-2,usr.y,usr.z)
d.loc=locate(usr.x-2,usr.y+1,usr.z)
e.loc=locate(usr.x-2,usr.y+2,usr.z)
f.loc=locate(usr.x-1,usr.y-2,usr.z)
g.loc=locate(usr.x-1,usr.y-1,usr.z)
h.loc=locate(usr.x-1,usr.y,usr.z)
i.loc=locate(usr.x-1,usr.y+1,usr.z)
j.loc=locate(usr.x-1,usr.y+2,usr.z)
for(var/mob/E in world)
if(E.discoligado==1)
if(E.loc==locate(usr.x-6,usr.y,usr.z))
usr.Embaralhar()
E.Embaralhar()
E.client:eye=locate(E.x+3,E.y,E.z)
usr.client:eye=locate(usr.x-3,usr.y,usr.z)
usr.oponente=E.nome
E.oponente=usr.nome
var/mob/y=usr.oponente
world << "<font color = white><b><font align=center>[y.nome] vs [usr.nome]"
usr.chavededuelo="[usr][usr.oponente]"
E.chavededuelo="[usr][usr.oponente]"
if(usr.dir==EAST)
a.loc=locate(usr.x+2,usr.y+2,usr.z)
b.loc=locate(usr.x+2,usr.y+1,usr.z)
c.loc=locate(usr.x+2,usr.y,usr.z)
d.loc=locate(usr.x+2,usr.y-1,usr.z)
e.loc=locate(usr.x+2,usr.y-2,usr.z)
f.loc=locate(usr.x+1,usr.y+2,usr.z)
g.loc=locate(usr.x+1,usr.y+1,usr.z)
h.loc=locate(usr.x+1,usr.y,usr.z)
i.loc=locate(usr.x+1,usr.y-1,usr.z)
j.loc=locate(usr.x+1,usr.y-2,usr.z)
for(var/mob/E in world)
if(E.discoligado==1)
if(E.loc==locate(usr.x+6,usr.y,usr.z))
usr.Embaralhar()
E.Embaralhar()
E.client:eye=locate(E.x-3,E.y,E.z)
usr.client:eye=locate(usr.x+3,usr.y,usr.z)
usr.oponente=E.nome
E.oponente=usr.nome
var/mob/y=usr.oponente
world << "<font color = white><b><font align=center>[y.nome] vs [usr.nome]"
usr.chavededuelo="[usr][usr.oponente]"
E.chavededuelo="[usr][usr.oponente]"
if(usr.dir==SOUTH)
a.loc=locate(usr.x+2,usr.y-2,usr.z)
b.loc=locate(usr.x+1,usr.y-2,usr.z)
c.loc=locate(usr.x,usr.y-2,usr.z)
d.loc=locate(usr.x-1,usr.y-2,usr.z)
e.loc=locate(usr.x-2,usr.y-2,usr.z)
f.loc=locate(usr.x+2,usr.y-1,usr.z)
g.loc=locate(usr.x+1,usr.y-1,usr.z)
h.loc=locate(usr.x,usr.y-1,usr.z)
i.loc=locate(usr.x-1,usr.y-1,usr.z)
j.loc=locate(usr.x-2,usr.y-1,usr.z)
for(var/mob/E in world)
if(E.discoligado==1)
if(E.loc==locate(usr.x,usr.y-6,usr.z))
usr.Embaralhar()
E.Embaralhar()
E.client:eye=locate(usr.x,usr.y+3,usr.z)
usr.client:eye=locate(usr.x,usr.y-3,usr.z)
usr.oponente=E.nome
E.oponente=usr.nome
var/mob/y=usr.oponente
world << "<font color = white><b><font align=center>[y.nome] vs [usr.nome]"
usr.chavededuelo="[usr][usr.oponente]"
E.chavededuelo="[usr][usr.oponente]"
winset(usr,"button6","is-visible=true")
winset(usr,"button7","is-visible=true")
winset(usr,"button8","is-visible=true")
winset(usr,"button9","is-visible=true")
winset(usr,"button10","is-visible=true")
winset(usr,"button11","is-visible=true")
winset(usr,"watch","is-visible=false")
usr.Embaralhar()


PS: Every time I use that verb and then reconnect the problem happens. (the problem appear only when I reconnect.)
PS²: THERE IS ONLY ONE OBJECT IN USR.CONTENTS and probably it is not the cause of the issue, but if necessary I can put it here for you to see...
PS³: As you can see, english is not my first language so sorry for bad english.
I'm pretty sure cannot append to list errors refer specifically to putting non-movable atoms inside of the contents list, since the contents list is one of few lists that only accept a certain type of entry.

In short, you somehow are trying to add something to your contents list that is not of the type /atom/movable. From what I can see, that particular function is NOT adding anything to your contents. Embaralhar() might be doing it, but I don't know.

As a side note, consider separating some of your code into separate functions. You seem to be duplicating a lot of code, especially when it comes to the whole...
if(usr.dir==EAST)
...
else if(usr.dir==WEST)
...
etc...

...thing.

Let's not get into that here, though... I just felt like I had to say something because this code is hard to follow, and unnecessarily long.

PS: Stop using usr in procs, such as /mob/proc/Savee() and /mob/proc/ReadTo.
Thx for advice, I got rid of contents and now im using a list called allthings to be my inventory. The "cannot append to list" thing stopped, but the strange loop came back. I noticed that as Keeth said, the game created another copy of me like i was 2 times in the same server.

So... Now back to the loop problem, what can I do?

I'll post the obj code here:

obj
deck
icon='deck.dmi'
icon_state="rednormal"
cor="red"
name=""
DblClick()
if(usr.discoligado==1)
return
if(usr.jaescolheu==0)
var/r=length(src.decklist)
if(r<40)
alert("Você não pode escolher um deck com menos de 40 cartas.")
return
usr.deck-=usr.deck
usr.deck+=src.decklist
usr.cartasnodeck=length(usr.deck)
src.icon_state="[src.cor]uso"
src.escolhido=1
usr.deckescolhido=src
usr.jaescolheu=1
return
if(usr.jaescolheu==1)
var/obj/y=usr.deckescolhido
y.escolhido=0
y.icon_state="[y.cor]normal"
usr.deck-=usr.deck
usr.cartasnodeck=0
usr.deckescolhido=""
usr.deck+=src.decklist
usr.cartasnodeck=length(usr.deck)
src.icon_state="[src.cor]uso"
src.escolhido=1
usr.deckescolhido=src
return
verb
// a lot of verbs that I didn`t use when I got the problem


Bump... Any help?
Bump... Any help?