#define _GNU_SOURCE
#include <errno.h>
#include <stdlib.h>
#include "data.h"
#include "login.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
int deserialize_player(FILE* fp, player_t *plr);
int serialize_player(player_t* plr, FILE* fp);
int try_make_data_dirs() {
int err = 0;
err = mkdir("data", S_IRWXU);
err = mkdir("data/players", S_IRWXU);
return err;
}
int try_load_plr(char *player_name, playerc_t *plr) {
int err = 0;
printf("Trying to make data directories...\n");
err = try_make_data_dirs();
if (err) {
switch (err) {
// Now the errors that continue will be from I/O, which we can use to
// figure out if the file exists in login
case EACCES: /* No permissions***************************************/
printf("No permissions to create directories\n");
return -1;
default: /* Do nothing because this is fine****************************/
break;
}
}
printf("Done, opening file.\n");
char *fname;
asprintf(&fname, "data/players/%s.plr", player_name);
FILE *fp;
if (fp = fopen(fname, "rb")) {
printf("Got fp\n");
if (deserialize_player(fp, &plr->plr)) {
printf("Couldn't deserialize player\n");
return -1;
}
} else {
printf("Couldn't open file: %d\n", errno);
printf("%s", strerror(errno));
return -1;
}
printf("Read file into plr\n");
fclose(fp);
return err;
}
int try_write_plr(player_t *plr) {
int err = 0;
err = try_make_data_dirs();
if (err) {
switch (err) {
// Now the errors that continue will be from I/O, which we can use to
// figure out if the file exists in login
case EACCES: /* No permissions***************************************/
printf("No permissions to create directories\n");
return -1;
default: /* Do nothing because this is fine****************************/
break;
}
}
char *fname;
asprintf(&fname, "data/players/%s.plr", plr->name);
FILE *fp = fopen(fname, "wb");
char* buf = malloc(sizeof(player_t) + 1);
serialize_player(plr, fp);
printf("serialized as: %s\n");
fprintf(fp, "%s", buf);
fclose(fp);
return err;
}
/*
* Ugh
*
* serialize_player takes in a `player_t` struct and a buffer and does some
* magic to write out the player in a format that can be easily parsed back
* including strings
*
* because we can't have nice things
*
* this function is sensitive to player struct updates so if things break but
* don't fail to compile this is probably the reason
*/
int serialize_player(player_t *plr, FILE* fp) {
int err = 0;
err = fprintf(fp, "%d,%d,%d,%d,%d,%s,%s", plr->xp, plr->hp, plr->max_hp, plr->level, plr->location_id, plr->pw_hash, plr->name);
return err;
}
/*
* deserialize_player reverses the results of serialize_player.
*
* because even when we're gay we can't have nice things
*
* this function is *also* sensitive to player struct updates (no shit) so if
* things break but still compile it's probably this thing
*/
int deserialize_player(FILE* fp, player_t* plr) {
int err = 0;
if (fp == NULL) {
perror("can't open player file");
return -1;
}
int c;
enum ParsePlayerState state = ReadingData;
enum ParsePlayerType type = Xp;
char* buf = malloc(1 << 10);
printf("Allocated buf\n");
while ((c = getc(fp) != EOF)) {
if (c == ',') {
state = Comma;
printf("Found comma");
}
switch (state) {
case ReadingData:
strncat(buf, c, 1);
break;
case Comma:
switch (type) {
case Xp: ;
int xp = atoi(buf);
plr->xp = xp;
state = ReadingData;
type = Hp;
memset(buf, 0, strlen(buf));
break;
case Hp: ;
int hp = atoi(buf);
plr->hp = hp;
state = ReadingData;
type = MaxHp;
memset(buf, 0, strlen(buf));
break;
case MaxHp: ;
int max_hp = atoi(buf);
plr->max_hp = max_hp;
state = ReadingData;
type = Level;
memset(buf, 0, strlen(buf));
break;
case Level: ;
int level = atoi(buf);
plr->level = level;
state = ReadingData;
type = LocationId;
memset(buf, 0, strlen(buf));
break;
case LocationId: ;
int location_id = atoi(buf);
plr->location_id = location_id;
state = ReadingData;
type = PwHash;
memset(buf, 0, strlen(buf));
break;
case PwHash: ;
plr->pw_hash = malloc(1 << 5);
strcpy(plr->pw_hash, buf);
state = ReadingData;
type = Name;
memset(buf, 0, strlen(buf));
break;
case Name: ;
plr->name = malloc(1 << 5);
strcpy(plr->name, buf);
// we're done here
free(buf);
return 0;
}
}
}
return err;
}