ID:2003116
 
(See the best response by Ter13.)
Code:
mob
proc
Save()
var/savefile/S = new("Saves/[copytext(src.ckey,1,2)]/[src.ckey]")
S["x"] << src.x
S["y"] << src.y
S["z"] << src.z
src.Write(S)

Load()
if(fexists("Saves/[copytext(src.ckey,1,2)]/[src.ckey]"))
var/savefile/S = new("Saves/[copytext(src.ckey,1,2)]/[src.ckey]")
src.Read(S)
src.loc = locate(S["x"],S["y"],S["z"])

Logout()
usr.Save()
del usr


Problem description:
I am a little confused because it will create a save file but it won't save until the second time I play. What have I done wrong?

Edit: Forgot to mention the New and Load button are turf with Click() all they do is usr.Load() and new moves the player off the main menu to the map.
Also on the note of this code I attempted to just write S<>usr but that also didn't work so I attempted to save and load just x,y,z. :-/
</<usr>
 mob
proc
Save()
var/savefile/S = new("Saves/[copytext(src.ckey,1,2)]/[src.ckey]")
S["x"] << src.x
S["y"] << src.y
S["z"] << src.z
src.Write(S)

Load()
if(fexists("Saves/[copytext(src.ckey,1,2)]/[src.ckey]"))
var/savefile/S = new("Saves/[copytext(src.ckey,1,2)]/[src.ckey]")
S["x"] >> src.x
S["y"] >> src.y
S["z"] >> src.z
src.Read(S)
src.loc = locate(src.x , src.y , src.z)

Logout()
src.Save()
del src

Login()
if(fexists("Saves/[copytext(src.ckey,1,2)]/[src.ckey]"))
src.Load()
src.Save()
else
world.log << "hi"
src.Save()

Okay changed them all to src but why do I call save at login? Seems like it would just overwrite the save?
excuse my indentation my phone is being strange.
and no it shouldnt , save should be a regulatory called proc in my opinion idk but call save however you want.
Hmm... I don't care for the idea of having to call the save at login just to solve the issue it seems like a hack n slash patch. I guess I will need to figure out how to make it save another way. I don't like the idea of calling the save proc at login even though it would solve that issue.

Thank you for the info and help. :-)
im sorry saving and stuff isnt my strong point in programming but , no problem.
Hebrons, where are you getting this code example?

I keep seeing people spreading and using it, and it's badly wrong. Where are you getting it from?
that's how i learned saving i never really focused on saving so at the time it was simple enough idk ill have to learn more about saving i never got to brushing up on it but how would you approach this?
that's how i learned saving i never really focused on saving so at the time it was simple enough idk ill have to

Well, I mean, it's line for line identical to one that I've been trying to warn people to stay away from for years.
Best response
http://www.byond.com/developer/Ralphie_leo/SavingDemo I think that is what you are looking for?
I trashed the whole script I am going to attempt to approach it from another way. Though any input would be a great help. :-)

Edit: Followed your trail Ter13 I see what is wrong with it though I am not sure this is how I wish to handle it now. :-)
I am not sure this is how I wish to handle it now. :-)

Why not? We can talk about initial login/character creation logic a bit more and add information to my breadcrumb trail for people walking it in the future.
Well from what I was able to take away from most of the posts. I don't want to call Read or Write manually one thing I can't seem to understand is. When I call the save proc manually using a verb I get a bad output the first time.

Originally I had used this but it didn't work.
mob
proc
Save()
var/savefile/S = new("Saves/[copytext(src.ckey,1,2)]/[src.ckey]")
S << src

Load()
if(fexists("Saves/[copytext(src.ckey,1,2)]/[src.ckey]"))
var/savefile/S = new("Saves/[copytext(src.ckey,1,2)]/[src.ckey]")
S >> src

So I went hunting for a demo to see what I was doing wrong.

Edit: It's a little late at night for me sorry. The reason I felt like this wasn't how I wanted to handle the save was because I don't wish to manually output every var. I want it to just save the whole mob. Though I don't think that's possible using this above script at all.
When I call the save proc manually using a verb I get a bad output the first time.

Yep, it's a standing BYOND bug that I haven't been able to get fixed. I've reported it a few times. A temporary workaround is to export something to a savefile on world initialization and then delete the savefile manually.

world
New()
. = ..()
var/savefile/S
try
var/obj/o = new()
S = new("workaround.sav")
S << o
catch(exception/e)
S = S //blank instruction to ignore error
if(S)
S = null
fdel("workaround.sav")


That will get you around the bad output runtime for the time being.
That gives exception and e as undefined var then makes it a bad catch. :-P I have no idea why so I won't even attempt to correct it. Hah that being said is this the most efficient way of handling saves or would you recommend another way?

Edit:
I just removed the exception/e because even if I make it a var it goes unused anyway.

world
New()
. = ..()
var/savefile/S
try
var/obj/o = new()
S = new("workaround.sav")
S << o
catch()
S = S //blank instruction to ignore error
if(S)
S = null
fdel("workaround.sav")
In response to Ter13
Ter13 wrote:
Hebrons, where are you getting this code example?

I keep seeing people spreading and using it, and it's badly wrong. Where are you getting it from?

uhh keep in mind i went off directly from his code and just added on to it lmao , so maybe it just happened to look the same idk all i added on to was Load() and changes a few things in loc lol.
Why in the world does src nor usr save the current mobs x,y,z? I was under the impression that they were part of the default list of vars created for a mob.

Edit: Just answered my own question by looking over the other posts.
Why in the world does src nor usr save the current mobs x,y,z? I was under the impression that they were part of the default list of vars created for a mob.

I'm going to need to explain a few things here to you to adjust your thinking.


What is a proc/verb?

A proc or a verb are actually the same thing. They are tasks. In language, we sometimes refer to a complex set of actions as a single entity.

For instance, "taking out the trash" is a phrase we use to describe a series of individual actions. In order to take out the trash, you need to do a series of individual things:

1) Remove the lid from the garbage can.
2) Remove the full bag from the garbage can.
3) Place a new bag in the garbage can.
4) Place the lid back on the garbage can.
5) Take the full bag out to the dumpster.
6) Throw the full bag into the dumpster.

"Taking out the trash" isn't an action it's a series of actions.

So what is a verb or a proc anyway? A verb or a proc are a series of instructions. Instructions are sort of like actions. You are taking small steps to achieve a larger goal.

Now a proc and a verb differ slightly in theory despite being functionally the same thing. A proc is an action that "src" can do. A verb, however, is a proc that "usr" can do to "src". Sometimes, however, "usr" is "src". Verbs are different from procs because verbs are a series of procs that the player is allowed to tell their character or the things nearby their character to do.


What is src?

This is a fairly complex idea that too many people try to make too simple. Src is something called a label. In language, there's a similar label that you use every day that means the exact same thing you mean to imply when you write "src" in your code. "I".

Src is the same word as "I". It refers to the object doing the proc or verb. Depending on the context of the action, "I" can refer to different things. "I" is not you. It is a label for you. Similarly, "You" is not you. It is a label for you. We can use these words to reference you, but these words are just labels for you.

Similarly, src is a label that references an object in the context of a proc or verb.

What is usr?

Usr is a contextual label that is associated with the player that began an action. Sometimes, the object referred to by "usr" is the same as the object referred to by "src". This means that the verb is a self-instruction. It's something the player instructs their own object to do.

Sometimes, however, the object referred to by usr is not the same as src. This happens when the player is telling an object contexually within reach of the player to do something. This means that the player is telling something else to do something.

Usr is only valid after a player (the person, not the object they control) has initiated an action using the user interface. This means that sometimes, non-verb procs can use usr and not have any problems.

However, usr is inspecific. The label doesn't fully describe the object it references, so it may give us incomplete information.

mob
var
health = 100
verb
punch()
set src in oview(1) //context
health -= usr.strength //error!
player
var
strength = 10


In the above example, we want all mobs to be punchable if you are in a view distance of 1 of them. The problem is that usr doesn't have a strength variable defined. That's because usr is typecast as /mob. strength is defined under /mob/player. usr will in our case, always be a type of /mob/player, but since the label only knows that it is a /mob, we can't use any behavior specific to /mob/player. To do this, we'd have to fix it with typecasting. Essentially, we're creating a new label that refers to the same object as usr, but gives us more information about that object:

mob
verb
punch()
set src in oview(1) //context
var/mob/player/p = usr
health -= p.strength


This example works because we know that all players are interacting with the world through /mob/player instances, and the only thing that will use verbs are players using the GUI.

That leads us to your question:

Why in the world does src nor usr save the current mobs x,y,z? I was under the impression that they were part of the default list of vars created for a mob.

src may be "I", but usr may not be "I" at all in the context of a proc, and the "I" in usr may not be the same "I" in src in the context of a verb.

The context of a proc is how it is used. BYOND doesn't have private/public/protected access restrictions for functions, so any and all functions should always specify the correct arguments and labels, and not rely on usr at all (...Except for procs that act as verbs).

Any verb that does rely on usr, you should never call manually unless you are already inside of a function that relies on usr.

What the above tells us, is that we should not use usr in Save()/Load() because Save()/Load() describe an action taken by the object being loaded, therefore usr is invalid because it can either lead to the wrong object being used, or it is a less specific label than "src".

Also, "src" can be omitted anywhere it would be followed by a "." or ":" because it is implied. Usr is never implied, and thus cannot be omitted in any case where it is intended.

http://www.byond.com/forum/?post=1898575#comment16044933

In the above example, the reason that usr isn't used is because Read() and Write() are procs, not verbs, and aren't called from the context of a verb. You should almost always avoid usr in a proc. The reason src isn't used is because src is implied by "x, y, z".

When you use a label, the compiler attempts to find the scope for that label in this order:

1) local variables
2) if no local variable found, src instance variables
3) if no src variable found, global variables

Since we haven't defined "x" as a local variable, the compiler instead interprets "x" as "src.x". This happens during compilation, though, so it's not faster or slower at runtime to type "src.x" or just "x". It's whatever you prefer.
Page: 1 2