ID:139271
 
Code:
mob
verb
Save()
usr.Savinit()
proc
Savinit()
if(usr.chooseslot1)
var/savefile/F = new("[usr]1.sav")
Write(F)
if(usr.chooseslot2)
var/savefile/F = new("[usr]2.sav")
Write(F)
if(usr.chooseslot3)
var/savefile/F = new("[usr]3.sav")
Write(F)
Loadinit()
if(fexists("[usr]1.sav"))//This is somewhere else in the code but I figured it would be good for you to see
var/savefile/F = new("[usr]1.sav")
Read(F)
return
mob
Write(var/savefile/F)
var/thehash=md5("[style][moves][trainingmove][rank][fightmove1][fightmove2][fightmove3][fightmove4][attributemove][healthexp][healthexpmax][legdefexp][bodydefexp][headdefexp]")
F["thehash"]<<thehash
..()

Read(var/savefile/F)
var/style
var/list/moves //This is a list of all the moves, will they still all appear in here just the same?
var/trainingmove
var/rank
var/belttesting //A variable not in the md5 hashes, do I still need to define it in the write?
var/fightmove1
var/fightmove2
var/fightmove3
var/fightmove4
var/attributemove
var/healthexp
var/healthexpmax
var/legdefexp
var/bodydefexp
var/headdefexp
var/Hash1
F["style"] >> style
F["moves"] >> moves
F["trainingmove"] >> trainingmove
F["rank"] >> rank
F["belttesting"] >> belttesting
F["fightmove1"] >> fightmove1
F["fightmove2"] >> fightmove2
F["fightmove3"] >> fightmove3
F["fightmove4"] >> fightmove4
F["attributemove"] >> attributemove
F["healthexp"] >> healthexp
F["healthexpmax"] >> healthexpmax
F["legdefexp"] >> legdefexp
F["bodydefexp"] >> bodydefexp
F["headdefexp"] >> headdefexp
F["thehash"] >> Hash1
if(md5("[style][moves][trainingmove][rank][fightmove1][fightmove2][fightmove3][fightmove4][attributemove][healthexp][healthexpmax][legdefexp][bodydefexp][headdefexp]") != Hash1)
del(src)
else
..()


Problem description:
Well I'm messing around with md5 and stuff, I've double checked and am sure both hashes should be the same, but when I have them outputted, they come up different. Basically, even if I didn't cheat I get kicked off the game and I don't know why. I've found out that it's saving strings, but not numbers. I can output my style and get "Taekwondo" but when I output my healthexp I get nothing. Just blank. Null. Anyone know the problem?


I also get this error:
runtime error: Undefined operation: null / null
proc name: Stat (/mob/Stat)
source file: Stat.dm,12
usr: Ganing (/mob)
src: Ganing (/mob)
call stack:
Ganing (/mob): Stat()

Stat.dm 12 is this: var/percen1=usr.healthexp/usr.healthexpmax*100
Did some more testing and found out it is the numbers that are causing problem.
When saving I have:
Taekwondo/listWhite Belt010000
When loading it becomes:
Taekwondo/listWhite Belt

But why... >.>
You're loading those values into local vars, and apparently never assigning them to your mob.

There are a few other mistakes here. One is that you have no delimiter between items, nor are you escaping said delimiter, so one string can bleed right into the next; this might be decent for relatively simplistic hash checking but it is exploitable if a string nobody cares much about is put next to one that's much more important.

The other issue is that you're not hashing in a way that respects the datatypes. "1" is equivalent to 1 here, which might not be a big deal, but you're also trying to hash a list as just [list]. That will only output /list as you saw, which isn't useful to you because it doesn't tell you anything about the contents.

Lummox JR
In response to Lummox JR
You just went like expert++ on me haha. Anyway to newb that down? xD
In response to Lummox JR
I looked through the forums and found a example of Garthor's. I took it and made it into my own. But...

proc/hashify1(var/mob/M)
return md5("[M.style][M.moves][M.trainingmove][M.rank][M.fightmove1][M.fightmove2][M.fightmove3][M.fightmove4][M.attributemove][M.healthexp][M.healthexpmax][M.legdefexp][M.bodydefexp][M.headdefexp]")

mob/proc
Save()
if(usr.chooseslot1)
var/savefile/F = new("[usr.key]1.sav")
F["mob"] << usr
F["hash"] << hashify1(usr)
Load1()
var/savefile/F = new("[usr.key]1.sav")
F["mob"]>>usr
if(F["hash"] != hashify1(usr))
fdel("[usr.key]1.sav")
del(usr)
mob
Write(var/savefile/F)
..()
Read(var/savefile/F)
..()


Problem:
Whenever I load myself it loads everything but then has me logout and then login again... which brings up the New/Load options once again. So what do I do to make it so that I'm not logging off anymore? I've ran some tests and concluded that the line "F["mob"]>>usr" is causing it but I do not know why.
In response to Ganing
Your hashing a set of the users variables when you save and then your comparing against a hashed usr when you load and I wouldn't expect those things to be the same. Check to see if your in fact failing that check and deleting the usr?

ts
In response to Tsfreaks
The check has nothing to do with the user being deleted. If I take out the check, I'm still logged out and logged back in. :/
In response to Ganing
Ganing wrote:
Problem:
Whenever I load myself it loads everything but then has me logout and then login again... which brings up the New/Load options once again. So what do I do to make it so that I'm not logging off anymore? I've ran some tests and concluded that the line "F["mob"]>>usr" is causing it but I do not know why.

This is not a problem, it is the well-defined behavior of the Login() and Logout() procedures: when a client changes mobs, Logout() is called on their current mob (if it exists), and Login() is called on their new mob (if it exists). Loading a savefile (properly, at least) creates a new mob, and in the process of doing so, connects a client to that new mob. Therefore, Login() and Logout() are called.

The problem, therefore, lies in you thinking that Login() means "player has connected to my server". Obviously, this is a misconception. What you need to do is specify a mob type - such as /mob/login_mob - set world/mob to that, and never save a mob of that type. Then, you can accurately assume that any time /mob/login_mob/Login() is called, a player is connecting to your game.

Alternatively, you could use client/New() and client/Del(), but there are issues with that which crop up if you are holding the client there for a while (to solicit input, for instance) and so it's best to use a temporary mob unless the client can be processed immediately.
In response to Garthor
So I got it fixed. It works. Awesome right? Well one last thing I'm trying to do... make this client sided. Which didn't seem too hard at first, exporting it was simple. But now I've got to find a way to import, and let the system know which file to import.

client/proc
Save()
if(src.chooseslot1)
var/savefile/F = new("[src.key]1.sav")
F["mob"] << src.mob
F["hash"] << hashify1(src.mob)
src.mob.client.Export(F)
if(src.chooseslot2)
var/savefile/F = new("[src.key]2.sav")
F["mob"] << src.mob
F["hash"] << hashify1(src.mob)
src.mob.client.Export(F)
if(src.chooseslot3)
var/savefile/F = new("[src.key]3.sav")
F["mob"] << src.mob
F["hash"] << hashify1(src.mob)
src.mob.client.Export(F)
Load1()
// var/client_file = Import() <- How do I make it so that it will Import() the right one? As in the [src.key]1.sav instead of the [src.key]2.sav?
var/savefile/F = new("[src.key]1.sav")
F["mob"] >> src.mob
if(F["hash"] != hashify1(src.mob))
fdel("[src.key]1.sav")
del(src)


How do I make it import the right one? I want to be able to check if the right one is there, but I don't want it to import [src.key]2.sav when it's supposed to import [src.key]1.sav. I looked up Import() in the Reference and stuff and it didn't help me at all. If I was doing only one save file, this would be pretty simple... but since there are three...
In response to Ganing
You can only have one client-side savefile per hub, hence why you can't specify which one to load. You'll need to combine your savefiles into one file if you want multiple "slots".
In response to DarkCampainger
Well went with just one save then. But after I tried to save and load, it apparently attempted to load another games save... Got runtime errors dealing with leather pants and helmets...
In response to Ganing
You can have multiple characters saved into one savefile, by the way.
In response to Ganing
How you get around this depends on the interface involved when selecting which character to load. Most times you can just use a selection pop-up box that the player chooses which slot to load into, and then load that particular savefile using that chosen slot's value. Most of the time, you would see something like this...
switch(input(src,"Which slot do you want to load?","") as null|anything in list("1","2","3"))
if("1")
src.load_proc("saves/players/[src.key]1.sav")

...or something with a very similar effect.