ID:138431
 
I've been working on new saving routines, struggled through the area and obj code on my own, but I just can't get my NPC loading code to work. Here it is:

area
Read(savefile/F)
var/V
var/obj/O
var/mob/M
var/thedir
var/thetype
var/list/dontload = new /list
dontload.Add("type","text","icon","icon_state") //... et cetera
for (V in src.vars)
if (dontload.Find(V) == 0) F[V] >> src.vars[V]



F.cd = "/[num2text(src.roomnumber)]/npcs"
for (thedir in F.dir)
F.cd = "/[num2text(src.roomnumber)]/npcs/[thedir]"
usr << "F.cd = [F.cd]."
F["type"] >> thetype
if (thetype != null)
M = new thetype(src)
M.Read(F)
F.cd = "..."


src.Atmosphere()

Write(savefile/F)
var/V
var/obj/O
var/mob/critter/M
var/whichnum = 0
var/list/dontsave = new /list
dontsave.Add("text","icon","icon_state") //... et cetera
for (V in src.vars)
if (dontsave.Find(V) == 0) F[V] << src.vars[V]

if (src.contents.len != 0)
for (M as mob in src)
if (M.npc > 0)
F.cd = "/[num2text(src.roomnumber)]/npcs/[M.name]"
usr << "Writing [M.name] in [F.cd]."
M.Write(F)
F.cd = "..."

mob
Read(savefile/F)
var/V
var/list/dontload = new /list
if (istype(src,/mob/player)) dontload.Add("npc","peaceful") // et cetera
dontload.Add("type","engaged") // et cetera
for (V in src.vars)
if (dontload.Find(V) == 0) F[V] << src.vars[V]


Write(savefile/F)
var/V
var/list/dontsave = new /list
if (istype(src,/mob/player)) dontsave.Add("npc","peaceful") et cetera
dontsave.Add("engaged","advantage") et cetera
for (V in src.vars)
if (dontsave.Find(V) == 0) F[V] << src.vars[V]

I took out the code for obj saving so this would be shorter, but it's almost exactly the same as the mob saving code, and it works fine. (Objs are saved at /[num2text(src.roomnumber)]/contents .)

When I run this code, saving *seems* to work fine, but loading dips into, say, /65/npcs/Abdul AND /65/npcs/npc and produces two mobs, both with all initial values. Just two duplicate prototype npcs. I just can't figure out what I'm doing wrong.

Z</<>
On 8/23/00 11:02 am Zilal wrote:

When I run this code, saving *seems* to work fine, but loading dips into, say, /65/npcs/Abdul AND /65/npcs/npc and produces two mobs, both with all initial values. Just two duplicate prototype npcs. I just can't figure out what I'm doing wrong.

I'm riding on very little sleep right now so I'm pretty incoherent, but one suggestion I can give would be to use the auto-object loading rather than recreating objects yourself. Eg, instead of:

F["type"] >> thetype
M = new thetype(src)
M.Read(F)

just do:

F >> M
M.loc = src

which will recreate the mob and load it at once.

However, I think your method should work too, so this is bothersome. If you have problems later today I'll take a look.
In response to Tom H.
On 8/23/00 12:43 pm Tom H. wrote:
just do:

F >> M
M.loc = src

which will recreate the mob and load it at once.

That generated the message "Cannot write to null.loc." for the second line, and no mobs. Removing that line had no effect but removing the error. Still no mobs.

I wasn't doing the F >> M thing because I remembered Deadron's letter in which he was saying I couldn't access the things I wanted from savefiles because that stored things differently than you would expect or something. And I wanted things to work like I expected. Does F >> M open up M.Read()? And shall I send you cerulea so you can take a look at it?

Z
In response to Zilal
On 8/23/00 2:07 pm Zilal wrote:
I wasn't doing the F >> M thing because I remembered Deadron's letter in which he was saying I couldn't access the things I wanted from savefiles because that stored things differently than you would expect or something. And I wanted things to work like I expected. Does F >> M open up M.Read()? And shall I send you cerulea so you can take a look at it?


The major limitation to auto-loading is that when you call F << M to save something, Byond does some special stuff.

While << and >> do call M.Write() and M.Read() to get the info, << doesn't store the data the normal way. That is, it doesn't create discrete subdirectories in the savefile for each variable. Instead it creates, near as I can tell, one "packet" of data that contains everything in a compact lump, and stores that.

This is very efficient and probably much faster to load -- but it means that if you want to poke into a directory to get a single value without loading the entire mob, you are out of luck.

Zilal's Loadable() verb wasn't working because she was attempting to get a mob name (or something like that) from the mob directory, but since she was using F << M to save the info, she couldn't actually get to the mob data without completely loading it.

Z, I happen to be up and awake (being a good boy, *I* went to bed at 2:30 AM, unlike that Tom guy), so if you want to send me the code I will check it out.
On 8/23/00 11:02 am Zilal wrote:
When I run this code, saving *seems* to work fine, but loading dips into, say, /65/npcs/Abdul AND /65/npcs/npc and produces two mobs, both with all initial values. Just two duplicate prototype npcs. I just can't figure out what I'm doing wrong.

I hadn't really thought about it, but I had a class of /mob/critter/npc with a variable also called npc... I changed the variable's name to "npcstatus," and now when I save and load, I just get one npc with initial values. Still no Abdul, though. It's weird. After I save him, I can access his saved variables--from either the saving or the loading proc--and they're fine. But somehow they're not getting applied to the mob I create.

Z
In response to Zilal
Apparently, I wasn't the only one who missed the bug below:

mob
Read(savefile/F)
var/V
var/list/dontload = new /list
for (V in src.vars)
if (dontload.Find(V) == 0) F[V] << src.vars[V]


Write(savefile/F)
var/V
var/list/dontsave = new /list
for (V in src.vars)
if (dontsave.Find(V) == 0) F[V] << src.vars[V]


The <<'s go the same way both times. Which is no good. Well, I changed it so the Read one is properly facing >>, but now we have another problem. Invoking this Read() proc causes the Dream Seeker to crash.

BUG: C\Windows\Desktop\dung\libdung\utils\fmem.c:0 Corrupt block header.
BUG: C\Windows\Desktop\dung\libdung\utils\fmem.c:282 Error reading fmem structure.
Dream Daemon: (C\Windows\Desktop\dung\libdung\server\sfile.c,493) error reading from file nodes

What now?

Z
In response to Zilal
On 8/23/00 9:41 pm Zilal wrote:

BUG: C\Windows\Desktop\dung\libdung\utils\fmem.c:0 Corrupt block header.
BUG: C\Windows\Desktop\dung\libdung\utils\fmem.c:282 Error reading fmem structure.
Dream Daemon: (C\Windows\Desktop\dung\libdung\server\sfile.c,493) error reading from file nodes

What now?

Hmm. That's embarrassing (and more so since the "dung" is still hanging around). I wonder if a bad savefile got created on one of the previous loads. Backup the .sav file (so we can test it later) and remove the original. Then try to save and load again. Hopefully that will work.
In response to Zilal
On 8/23/00 8:52 pm Zilal wrote:
On 8/23/00 11:02 am Zilal wrote:
I hadn't really thought about it, but I had a class of /mob/critter/npc with a variable also called npc... I changed the variable's name to "npcstatus," and now when I save and load, I just get one npc with initial values. Still no Abdul, though. It's weird. After I save him, I can access his saved variables--from either the saving or the loading proc--and they're fine. But somehow they're not getting applied to the mob I create.

I was wrong in my initial email to you -- the problem wasn't that you had a subclass named npc, it was that you never set the npc value for /mob/critter.

If you do:

mob
critter
npc = 2

It should cause more mobs to start saving.

And yes I'm embarrassed to have missed << in the wrong direction. But I did find the other problem!
In response to Deadron
On 8/23/00 11:46 pm Deadron wrote:
I was wrong in my initial email to you -- the problem wasn't that you had a subclass named npc, it was that you never set the npc value for /mob/critter.

If you do:

mob
critter
npc = 2

It should cause more mobs to start saving.

And yes I'm embarrassed to have missed << in the wrong direction. But I did find the other problem!

Poor Deadron. I just wrote to you that I had only been trying to save mobs with the npc value set to 2 already, so I won't embarrass you further by repeating it here! (It's my fault though, really; I should have made it more clear in my original letter.)

That means, though... at least I think it means... that the setup:

mob
var/npc = 0
critter
npc // the object /mob/critter/npc
npc = 2 // the variable

doesn't save well; saving a /mob/critter/npc created two entries for a /mob/critter/npc in the savefile. Or it just loaded two of them. I can't figure it out. So, kiddies, don't be oblivious like me and name a variable after a class of anything!

Z
In response to Tom H.
On 8/23/00 11:24 pm Tom H. wrote:
Hmm. That's embarrassing (and more so since the "dung" is still hanging around). I wonder if a bad savefile got created on one of the previous loads. Backup the .sav file (so we can test it later) and remove the original. Then try to save and load again. Hopefully that will work.

Yes, it worked! I don't know why I didn't think to do that myself. (I think I was late for the Survivor finale already.) Thank you, Tom. What should I do with this corrupt savefile?

Z
In response to Zilal
On 8/24/00 8:59 am Zilal wrote:
Poor Deadron. I just wrote to you that I had only been trying to save mobs with the npc value set to 2 already, so I won't embarrass you further by repeating it here! (It's my fault though, really; I should have made it more clear in my original letter.)


Um, I rest on my past bug-finding accomplishments.
In response to Zilal
On 8/24/00 9:18 am Zilal wrote:

Yes, it worked! I don't know why I didn't think to do that myself. (I think I was late for the Survivor finale already.) Thank you, Tom. What should I do with this corrupt savefile?

Good to hear. If you could, just hang on to that file for a couple of days in case we need to check it out. I doubt it will be necessary, as your code example and error report should suffice.