ID:148667
 
I need to remove an object from a list within a savefile. This is the savefile for a mob, and I don't want to create a temp mob to do this, incase the owner tries to login. Any suggestions?
Xooxer wrote:
I need to remove an object from a list within a savefile. This is the savefile for a mob, and I don't want to create a temp mob to do this, incase the owner tries to login. Any suggestions?

If the owner tries to log in, then screwing with the savefile may be moot anyway. But I believe something like this would work:
proc/RemoveFromList(savefile/S,path,object)
var/list/L
S.cd=path
if(S.cd!=path)
world.log << "RemoveFromList(): [path] not found in [S.name]"
return
S.cd=S.dir[1] // assume the first save under this path is the mob
S["thelist"] >> L
L-=object
S["thelist"] << L
Care would have to be taken to be sure the object reference is correct of course, but there you go. The "path" would refer to whatever subdirectory the mob is stored under, which is probably something like ".0".

Lummox JR
In response to Lummox JR
Ok, I'll give that a go.

RemoveFromList(): .0 not found in ./chatters/trix

LummoxJR wrote:
The "path" would refer to whatever subdirectory the mob is >stored under, which is probably something like ".0".

Ok, so ".0" (with quotes, correct?) isn't the subdirectory. I don't know what it should be. How would I find out?

In response to Xooxer
Is there any documentation on how "things" (atoms, lists, associative lists, datums, etc.) are actually stored in savefiles? I suppose I may be able to experiment a little to find out, but no need to go through the trouble if it has already been documented.
In response to English
I just found something Deadron wrote on savefiles. It's worth a read.

http://www.deadron.com/Games/ByondBasicSavefiles.html
You COULD use my savefile editor, just a suggestion.
In response to Xooxer
Xooxer wrote:
Ok, I'll give that a go.

RemoveFromList(): .0 not found in ./chatters/trix

LummoxJR wrote:
The "path" would refer to whatever subdirectory the mob is >stored under, which is probably something like ".0".

Ok, so ".0" (with quotes, correct?) isn't the subdirectory. I don't know what it should be. How would I find out?

Hrm. Forgive the error in my above statement; this is what I get for writing late.

The path to the mob would actually be a character path, like in xooxer.sav you might have a character named Throlox the Large, so the path to him would be "/throloxthelarge" (ckey(name)). The ".0" under that would be the mob itself, as saved.
The dir[1] entry in my piece of code actually will find that ".0" or whatever, the first entry under that path (which is expected to be the mob), and go to that. So the path to your list might be "/throloxthelarge/.0/thelist".

Lummox JR
In response to Lummox JR
Lummox JR wrote:
Hrm. Forgive the error in my above statement; this is what I get for writing late.

Understandable.

The path to the mob would actually be a character path, like in xooxer.sav you might have a character named Throlox the Large, so the path to him would be "/throloxthelarge" (ckey(name)). The ".0" under that would be the mob itself, as saved.
The dir[1] entry in my piece of code actually will find that ".0" or whatever, the first entry under that path (which is expected to be the mob), and go to that. So the path to your list might be "/throloxthelarge/.0/thelist".

Ok, I believe I understand now. But there is still a problem, most likely something I'm not seeing. I recieve this runtime error:


runtime error: type mismatch
proc name: remove chan from savefile (/mob/proc/remove_chan_from_savefile)
source file: uops.dm,290
usr: Xooxer (/mob/chatter)
src: Xooxer (/mob/chatter)
call stack:
Xooxer (/mob/chatter): remove chan from savefile(./chatters/trix (/savefile), "/trix/.0", the trixylvainia (/obj/channel))
Xooxer (/mob/chatter): delchan("trixylvainia")
Xooxer (/client): Topic("src\[0x300000a];action=del_cha...", /list (/list), null)

Line 290 points to the line that removes the object from the list:

L -= object

I call the proc like so:

remove_chan_from_savefile(S,"/[ckey(CHANNEL.founder)]/.0",CH ANNEL)

where CHANNEL is the object to remove, and CHANNEL.founder is the name of the founder of that channel, which is the same as the founder's key. I don't allow renaming of mobs. Any ideas?

~X
In response to Xooxer
Xooxer wrote:
Ok, I believe I understand now. But there is still a problem, most likely something I'm not seeing. I recieve this runtime error:


runtime error: type mismatch
proc name: remove chan from savefile (/mob/proc/remove_chan_from_savefile)
source file: uops.dm,290
usr: Xooxer (/mob/chatter)
src: Xooxer (/mob/chatter)
call stack:
Xooxer (/mob/chatter): remove chan from savefile(./chatters/trix (/savefile), "/trix/.0", the trixylvainia (/obj/channel))
Xooxer (/mob/chatter): delchan("trixylvainia")
Xooxer (/client): Topic("src\[0x300000a];action=del_cha...", /list (/list), null)

Line 290 points to the line that removes the object from the list:

L -= object

I call the proc like so:

remove_chan_from_savefile(S,"/[ckey(CHANNEL.founder)]/.0",CH ANNEL)

where CHANNEL is the object to remove, and CHANNEL.founder is the name of the founder of that channel, which is the same as the founder's key. I don't allow renaming of mobs. Any ideas?

The problem is you're including that ".0" in the path. That's part of the full path to the list, but not what you should provide to the proc. The access to dir[1] takes care of that ".0" part, so all you have to do is point it to the character itself. Your path should be "/[ckey(CHANNEL.founder)]", nothing more.

Lummox JR
In response to Nadrew
Savefile editor? I'm interested!
In response to Xooxer
Funny, I think I've read that before but I must have glanced over/missed the part near the end about the autosaving behavior and how all the vars are saved.

That should make it very easy to modify a single saved variable :)

It doesn't really explain exactly how lists are saved though.
In response to Lummox JR
Originally, it was "/[ckey(CHANNEL.founder)]", but I recieved that runtime error, and so I added the .0 with the same error as a result. I don't think it has anything to do with the path, but then again, what do I know about savefile structure! :P

CHANNEL is a refernce to the object, and the list contains the same reference. The proc that calls this one is supposed to remove a channel object from the world (an admin feature), and does this with no problem. The reason I need to access savefiles is incase the founder is not online, I need to remove his/her reference to the channel they own. If I don't, then when they log back in, the channel will exsist in their channels list, but not in the world, causing all sorts of problems.

I know the CHANNEL is a valid reference, as it successfully removed the channel object from the world. I know the list exists in the savefile somewhere, as it's not tmp, global or const, just mob/var/list/channels, and is loaded into the mob when they log in after being saved.

In your snippet, the lines need to look like so, right?:

S["channels"] >> L
L-=object // line 290, where the error occurs.
S["channels"] << L

So, why is there a type-mismatch?

Ok, I added this line right before line 290:

world << "S\[\"channels\"\]: [L]"

and recieved this upon execution:

S["channels"]:

??? "channels" does not exist? I know it does! What am I missing here?

~X
How lists are saved:
listname = list(object(".0"),object(".1"))
.0
type = typehere
//other values here
.1
type = typehere
//other values here

In response to Hazman
In response to Xooxer
Xooxer wrote:
Originally, it was "/[ckey(CHANNEL.founder)]", but I recieved that runtime error, and so I added the .0 with the same error as a result. I don't think it has anything to do with the path, but then again, what do I know about savefile structure! :P

Well the .0 is definitely wrong; it shouldn't be included in the path you send to the proc.

CHANNEL is a refernce to the object, and the list contains the same reference. The proc that calls this one is supposed to remove a channel object from the world (an admin feature), and does this with no problem. The reason I need to access savefiles is incase the founder is not online, I need to remove his/her reference to the channel they own. If I don't, then when they log back in, the channel will exsist in their channels list, but not in the world, causing all sorts of problems.

This is actually fudgable by removing the invalid channel at load time.

I know the CHANNEL is a valid reference, as it successfully removed the channel object from the world. I know the list exists in the savefile somewhere, as it's not tmp, global or const, just mob/var/list/channels, and is loaded into the mob when they log in after being saved.

The question of the hour now is: How exactly are you saving people's files?
I was working on the assumption that each key has its own file, something like "[client.ckey].sav", and that in it is a list of characters like in an RPG, each accessed through a specific path. You're using this for a chat, however, where there are no separate characters.

This being the case, is your mob being saved to the path "/[ckey]" within their file, or are they in fact just being saved directly to it? If the latter is the case, then the path you should use with this proc is "/", not anything with their name tacked on. If the path you're giving the proc doesn't exist in the savefile, there's your problem.

In your snippet, the lines need to look like so, right?:

S["channels"] >> L
L-=object // line 290, where the error occurs.
S["channels"] << L

So, why is there a type-mismatch?

This will happen if the list can't be loaded, and is null. Which an invalid path would cause.

Lummox JR
In response to Lummox JR
Lummox JR wrote:

Well the .0 is definitely wrong; it shouldn't be included in the path you send to the proc.

It's removed now.

I need to remove his/her reference to the channel they own.

This is actually fudgable by removing the invalid channel at load time.

I realise this, but I'd really like to do this when the channel is deleted. Besides, it's a good learning experience.

The question of the hour now is: How exactly are you saving people's files?
I was working on the assumption that each key has its own file, something like "[client.ckey].sav", and that in it is a list of characters like in an RPG, each accessed through a specific path. You're using this for a chat, however, where there are no separate characters.

This being the case, is your mob being saved to the path "/[ckey]" within their file, or are they in fact just being saved directly to it? If the latter is the case, then the path you should use with this proc is "/", not anything with their name tacked on. If the path you're giving the proc doesn't exist in the savefile, there's your problem.

I'm using:

mob/Logout()
var/savefile/C = new("./chatters/[ckey(name)]")
C << src

which just saves the entire mob to the file automaticly. I changed the path to "/" as you suggested, and I still recieved the runtime error. I may just have to do it at runtime, though I'd really like to keep it all in one proc.

~X
In response to Xooxer
I'm not sure if this could be related to the problem but I ran this little test program just to verify how objects are saved:

mob
var/test1 = 0
var/test2 = 0
verb
saveprint()
var/savefile/F = new("./subdir/[ckey]")
usr << F.dir.len
for(var/temp in F.dir)
usr << ": [temp]"
savecreate()
var/savefile/F = new("./subdir/[ckey]")
test1 = 1
test2 = 2
F << usr

I created new variables and changed them from their initial values so they should have been created as subdirectories (as Deadron described, if I understood him correctly). However, when you use saveprint, it says there are no subdirectories in the savefile (and you can't access test1 through F["test1"]) so it seems to be consistent with F["channels"] being null.

Maybe I'm headed in the wrong direction, but I thought it might be worth pointing out/investigating.
In response to English
Interesting. I wonder if Nadrew had any problems like this with his Savefile Editor....

~X
In response to Xooxer
These are the text results from Nadrew's savefile editor:

. = object("//.0")
.0
type = /mob
test1 = 1
test2 = 2
name = "English"
gender = "male"
key = "English"
english = object(".0")
.0
type = /mob
name = "English"
gender = "male"
key = "English"

so why aren't any directories showing up? :(