ID:179520
 
I have looked over Deadron's demos and libraries all on character handling and saving, but since I cannot simply use his in my world (I need to know how it works in order to change it for my world, and I don't), I need to learn how to use savefiles on my own.

Upon log in, I would like to:

1 - Ask for a player's name (Done)
2 - Check to see if the name exists in the
file 'world.sav' (having trouble)

I won't put the rest of what I want to do yet, because I haven't gotten past step 2. What I *have* done, is included the procedures below for loading and saving when necessary (this is how the names get into 'world.sav' in the first place). Once this works, however, I will use some kind of 'if' statement to determine whether to ask for a password next, or to ask them if they typed the name correctly. (Side Note: I would rather not work on the client level to use keys to detemine accounts, even though this seems to be reccomended, because I cannot understand /client to save my life!)

var/savefile/Savefile = new("world.sav")
mob
proc/savechar()
var/chardir = src.ckey
Savefile.cd = "/players"
Savefile.cd = chardir
src.Write(Savefile)

proc/loadchar()
var/chardir = src.ckey
Savefile.cd = "/players"
Savefile.cd = chardir
src.Read(Savefile)
return 1

I don't even really know why there is a return 1 at the bottom, but it was in the example. Also, I could not get this command to work anywhere in my code, even though it was in the example I followed:

Savefile.Find(chardir)

BYOND tells me that .Find is not a valid procedure, go figure. If I need to use a different format for saving to a file, let me know that first. If this format works, but I just need to learn how to search for information in files, please show me how to do that. After this problem is solved, I will post all the steps to my log in procedure.

-- John
Felegar wrote:
I have looked over Deadron's demos and libraries all on character handling and saving, but since I cannot simply use his in my world (I need to know how it works in order to change it for my world, and I don't), I need to learn how to use savefiles on my own.

I would suggest ignoring the various demo code for my savefile stuff and just looking directly at the CharacterHandling code. There's not that many lines, and it shows you how to check for an existing character name and all that.

What you want to do is exactly what the library does...so you might be served by looking over the library in some detail. Any explanations I offer would simply be pasting code from the library.

Which I can do if necessary, but I don't have access to the code right now.
In response to Deadron
Okay, I see the code I think I need to use, but it needs a little explaining. This first set creates a menu list and takes information gathered from another proc to get it:

proc/ChooseCharacter()
var/list/available_char_names = client.base_CharacterNames()
var/list/menu = new()
menu += available_char_names

(There should be an indent in the second line, but it won't fit) Why can't the code above just be:

var/list/menu = client.base_CharacterNames()

Anyway, it's the procedure 'base_CharacterNames' that must be the important one, right? Here it is:

proc/base_CharacterNames()
var/list/names = new()
var/savefile/F = base_PlayerSavefile()

F.cd = "/players/[ckey]/mobs/"
var/list/characters = F.dir
var/char_name
for (var/entry in characters)
F["[entry]/name"] >> char_name
names += char_name
return names

Since this proc calls another proc, I might as well add it here, too:

proc/base_PlayerSavefile()
if (!_base_player_savefile)
var/start = 1
var/end = 2
var/first_initial = copytext(ckey, start, end)
var/filename = "players/[first_initial]/[ckey].sav"
_base_player_savefile = new(filename)
return _base_player_savefile

I understand what all this does, but I don't quite get how it does it, and I lose the whole directory hierarchy of the savefile somewhere along the way. The most confusing aspect of this does DM know what 'ckey' is since the player hasn't even logged in yet! In fact, I couldn't find the mob/Login() proc anywhere in the character handling library anyway. Is it in the BaseCamp library? I am totally confused :-P If you could somehow explain from Login() all the procs that are used it would be greatly helpful.

I know this message is dragging on, but I would like to add that an explanation of savefile hierarchy would help too, as the help files seem to contradict each other(I know they don't). One help file I read said that it was all done inside the file and did not involve actual directories, but I have used a very simple savefile proc and it created directories and instead of simply creating a 'world.sav' like I thought I had instructed it to, it saved it into 'character_name.sav'

-- John
In response to Felegar
Felegar wrote:
proc/ChooseCharacter()
var/list/available_char_names = client.base_CharacterNames()
var/list/menu = new()
menu += available_char_names

(There should be an indent in the second line, but it won't fit) Why can't the code above just be:

var/list/menu = client.base_CharacterNames()

If you look at the code right after that, you'll see that it uses the available_char_names list in a few places to see how many characters are available. Since other items are added to the menu, the list needed to be kept separate for the checks using available_char_names to work.


I understand what all this does, but I don't quite get how it does it, and I lose the whole directory hierarchy of the savefile somewhere along the way.

Since you are approaching this carefully and actually trying to learn (a refreshing approach!), I'll point you to the savefile tutorial I wrote which I don't think is publically listed anymore. It was confusing people who were trying to use it just for character saving without actually wanting to learn savefiles, so I created the character handling library and stopped pointing to it. But if you ignore the character saving part, it has a pretty good explanation of savefile hierarchy:

http://www.deadron.com/Games/ByondBasicSavefiles.html

The most confusing aspect of this does DM know what 'ckey' is since the player hasn't even logged in yet!

The client has a key and ckey before the player is hooked up to a mob. The client represents the player.


In fact, I couldn't find the mob/Login() proc anywhere in the character handling library anyway.

It's there right toward the top. Actually more than once, but the one you want looks like this:

mob/BaseCamp/ChoosingCharacter
Login()
spawn()
ChooseCharacter()
return ..()



If you could somehow explain from Login() all the procs that are used it would be greatly helpful.

Read through the savefile tutorial above, then look at the code again and see if anything is cleared up for you. Let me know of any questions after that.

If you haven't already, I strongly suggest buying the Blue Book (link on the left), as someone as curious as you will gain a lot from it.
In response to Deadron
Wow! Thanks a lot for the helpful tutorial, it really clears things up for me. Now I can actually go code some and come back with a different problem. I did have one question for now about this piece here:

SaveCharacter(char_name)
var/savefile/F = new("players.sav")
var/safe_name = ckey(char_name)
-> F.cd = "/[ckey]/[safe_name]"
F["full_name"] << char_name

About the line with the arrow, how does DM know what ckey is? Does it assume it to be client.ckey? It can't be /mob/player.ckey because that hasn't been assigned yet, right? I still am not sure how DM tells the difference between a client's info and a mob's info, since there doesn't seem to be a tutorial on clients, but I will assume the difference is that a mob's info is dynamic.

Thanks a lot for your help deadron!

-- John
In response to Felegar
Felegar wrote:
About the line with the arrow, how does DM know what ckey is?

The client always has the player's key and ckey. That is copied to the mob when they are connected to a mob.


I still am not sure how DM tells the difference between a client's info and a mob's info, since there doesn't seem to be a tutorial on clients, but I will assume the difference is that a mob's info is dynamic.

Think of it this way:

A player is a client. When the player logs in, the first thing they get is a client, which represents them and is unique to them.

Everything after that is connected to the client...the mob is hooked up to the client, etc.

A player mob is actually client.mob...their mob is a attribute (variable) of their client.

In your game for convenience you'll be sending text to the mob and thinking of the player as the mob, but what's really happening underneath is that that stuff is going to the client.

An important point about this is if you want information or verbs to stay with the player no matter what mob they have, then you store it with the client. You can give verbs to the client, for example, and the player will have those verbs no matter what mob they get hooked up to.

The client/player can be hooked up to different mobs throughout the game. In my code, clients are first given an admin mob for purposes of choosing their character, then given the character mob when that has been created or loaded, and later they might jump to another mob for one reason or another. During all this the client stays the same.
Well,heres a Save File you shall use it works i tryed it:

mob/verb/Save()
var/savefile/F = new("[usr.ckey].sav")
Write(F)
mob/verb/Load()
var/savefile/F = new("[usr.ckey].sav")
Read(F)

Nadrew gave it to me so kind of Thank him