Lephisto/src/save.c
2014-03-04 00:19:56 +00:00

231 lines
6.1 KiB
C

#include <stdio.h> /* remove() */
#include "lephisto.h"
#include "log.h"
#include "xml.h"
#include "player.h"
#include "toolkit.h"
#include "dialogue.h"
#include "menu.h"
#include "lfile.h"
#include "hook.h"
#include "save.h"
#define LOAD_WIDTH 400
#define LOAD_HEIGHT 300
#define BUTTON_WIDTH 50
#define BUTTON_HEIGHT 30
/* Externs. */
extern int player_save(xmlTextWriterPtr writer); /* A lot of stuff. */
extern int player_load(xmlNodePtr parent);
extern int missions_saveActive(xmlTextWriterPtr writer); /* Active missions. */
extern int missions_loadActive(xmlNodePtr parent);
extern int var_save(xmlTextWriterPtr writer); /* misn var. */
extern int var_load(xmlNodePtr parent);
extern int pfaction_save(xmlTextWriterPtr writer); /* Faction data. */
extern int pfaction_load(xmlNodePtr parent);
extern int hook_save(xmlTextWriterPtr writer); /* Hooks. */
extern int hook_load(xmlNodePtr parent);
extern int space_sysSave(xmlTextWriterPtr writer); /* Space stuff. */
extern int space_sysLoad(xmlNodePtr parent);
extern int diff_save(xmlTextWriterPtr writer);
extern int diff_load(xmlNodePtr parent);
extern void menu_main_close(void);
/* Static. */
static int save_data(xmlTextWriterPtr writer);
static void load_menu_close(unsigned int wdw, char* str);
static void load_menu_load(unsigned int wdw, char* str);
static void load_menu_delete(unsigned wdw, char* str);
static int load_game(char* file);
/* Save all the game data. */
static int save_data(xmlTextWriterPtr writer) {
/* The data itself. */
if(diff_save(writer) < 0) return -1; /* Must save first or can get cleared. */
if(player_save(writer) < 0) return -1;
if(missions_saveActive(writer) < 0) return -1;
if(var_save(writer) < 0) return -1;
if(pfaction_save(writer) < 0) return -1;
if(hook_save(writer) < 0) return -1;
if(space_sysSave(writer) < 0) return -1;
return 0;
}
/* Save the current game. */
int save_all(void) {
char file[PATH_MAX];
xmlDocPtr doc;
xmlTextWriterPtr writer;
writer = xmlNewTextWriterDoc(&doc, 0);
if(writer == NULL) {
ERR("testXmlwriterDoc: Error creating the xml writer.");
return -1;
}
xmlw_start(writer);
xmlw_startElem(writer, "lephisto_save");
/* Save the version or something.. */
xmlw_startElem(writer, "version");
xmlw_elem(writer, "lephisto", "%d.%d.%d", VMAJOR, VMINOR, VREV);
xmlw_elem(writer, "data", dataname);
xmlw_endElem(writer); /* Version. */
if(save_data(writer) < 0) {
ERR("Trying to save game data");
xmlFreeTextWriter(writer);
xmlFreeDoc(doc);
return -1;
}
xmlw_endElem(writer); /* lephisto_save. */
xmlw_done(writer);
if(lfile_dirMakeExist("saves") < 0) {
WARN("Aborting save...");
xmlFreeTextWriter(writer);
xmlFreeDoc(doc);
return -1;
}
snprintf(file, PATH_MAX, "%ssaves/%s.ls", lfile_basePath(), player_name);
/* Critical section, if crashes, the players save game gets screwed!!!
* HAHAHAHAHA!!!!! -- NOT!
*/
xmlFreeTextWriter(writer);
xmlSaveFileEnc(file, doc, "UTF-8");
xmlFreeDoc(doc);
return 0;
}
/* Open the load game menu. */
void load_game_menu(void) {
unsigned int wid;
char** files;
int lfiles, i, len;
/* Window. */
wid = window_create("Load Game", -1, -1, LOAD_WIDTH, LOAD_HEIGHT);
/* Load the saves. */
files = lfile_readDir(&lfiles, "saves");
for(i = 0; i < lfiles; i++) {
len = strlen(files[i]);
/* No save extension. */
if((len < 6) || strcmp(&files[i][len-3], ".ls")) {
free(files[i]);
memmove(&files[i], &files[i+1], sizeof(char*) * (lfiles-i-1));
lfiles--;
i--;
}
else /* Remove the extension. */
files[i][len-3] = '\0';
}
/* Again.. What if there is no files? */
if(files == NULL) {
files = malloc(sizeof(char*));
files[0] = strdup("None");
lfiles = 1;
}
window_addList(wid, 20, -50,
LOAD_WIDTH-BUTTON_WIDTH-50, LOAD_HEIGHT-90,
"lstSaves", files, lfiles, 0, NULL);
/* Buttons. */
window_addButton(wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnBack", "Back", load_menu_close);
window_addButton(wid, -20, 30 + BUTTON_HEIGHT, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnLoad", "Load", load_menu_load);
window_addButton(wid, -20, 20+2*(10+BUTTON_HEIGHT), BUTTON_WIDTH, BUTTON_HEIGHT,
"btnDelete", "Del", load_menu_delete);
/* Default action. */
window_setAccept(wid, load_menu_load);
}
static void load_menu_close(unsigned int wdw, char* str) {
(void)str;
window_destroy(wdw);
}
static void load_menu_load(unsigned int wdw, char* str) {
(void)str;
char* save, path[PATH_MAX];
int wid;
wid = window_get("Load Game");
save = toolkit_getList(wid, "lstSaves");
if(strcmp(save, "None")==0)
return;
snprintf(path, PATH_MAX, "%ssaves/%s.ls", lfile_basePath(), save);
load_game(path);
load_menu_close(wdw, NULL);
menu_main_close();
}
static void load_menu_delete(unsigned int wdw, char* str) {
(void)str;
char* save, path[PATH_MAX];
int wid;
wid = window_get("Load Game");
save = toolkit_getList(wid, "lstSaves");
if(strcmp(save, "None") == 0)
return;
if(dialogue_YesNo("Permanently Delete?",
"Are you sure you want to permanently delete '%s'?", save) == 0)
return;
snprintf(path, PATH_MAX, "%ssaves/%s.ls", lfile_basePath(), save);
remove(path); /* Remove is more portable and will call unlink on Linux. */
/* Need to reload the menu. */
load_menu_close(wdw, NULL);
load_game_menu();
}
/* Load a new game. */
static int load_game(char* file) {
xmlNodePtr node;
xmlDocPtr doc;
doc = xmlParseFile(file);
node = doc->xmlChildrenNode; /* Base node. */
if(node == NULL) {
WARN("Savegame '%s' invalid!", file);
return -1;
}
diff_load(node); /* Must load first to work properly. */
player_load(node);
var_load(node);
missions_loadActive(node);
pfaction_load(node);
hook_load(node);
space_sysLoad(node);
/* Need to run takeoff hooks since player just "took off". */
hooks_run("takeoff");
hooks_run("enter");
xmlFreeDoc(doc);
xmlCleanupParser();
return 0;
}