naev 0.12.6
save.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "physfs.h"
11
12#include "naev.h"
14
15#include "save.h"
16
17#include "array.h"
18#include "conf.h"
19#include "dialogue.h"
20#include "load.h"
21#include "log.h"
22#include "mission.h"
23#include "ndata.h"
24#include "nxml.h"
25#include "player.h"
26#include "plugin.h"
27#include "shiplog.h"
28#include "start.h"
29
30int save_loaded = 0;
31
32/*
33 * prototypes
34 */
35/* externs */
36/* player.c */
37extern int
38player_save( xmlTextWriterPtr writer );
39/* event.c */
40extern int events_saveActive( xmlTextWriterPtr writer );
41/* news.c */
42extern int news_saveArticles( xmlTextWriterPtr writer );
43/* nlua_var.c */
44extern int var_save( xmlTextWriterPtr writer );
45/* faction.c */
46extern int pfaction_save( xmlTextWriterPtr writer );
47/* hook.c */
48extern int hook_save( xmlTextWriterPtr writer );
49/* economy.c */
50extern int
51economy_sysSave( xmlTextWriterPtr writer );
52/* unidiff.c */
53extern int
54diff_save( xmlTextWriterPtr writer );
55/* static */
56static int save_data( xmlTextWriterPtr writer );
57
64static int save_data( xmlTextWriterPtr writer )
65{
66 /* the data itself */
67 if ( diff_save( writer ) < 0 )
68 return -1; /* Must save first or can get cleared. */
69 if ( player_save( writer ) < 0 )
70 return -1;
71 if ( missions_saveActive( writer ) < 0 )
72 return -1;
73 if ( events_saveActive( writer ) < 0 )
74 return -1;
75 if ( news_saveArticles( writer ) < 0 )
76 return -1;
77 if ( var_save( writer ) < 0 )
78 return -1;
79 if ( pfaction_save( writer ) < 0 )
80 return -1;
81 if ( hook_save( writer ) < 0 )
82 return -1;
83 if ( space_playerSave( writer ) < 0 )
84 return -1;
85 if ( economy_sysSave( writer ) < 0 )
86 return -1;
87 if ( shiplog_save( writer ) < 0 )
88 return -1;
89 return 0;
90}
91
97int save_all( void )
98{
99 return save_all_with_name( "autosave" );
100}
101
108int save_all_with_name( const char *name )
109{
110 char file[PATH_MAX];
111 const plugin_t *plugins = plugin_list();
112 xmlDocPtr doc;
113 xmlTextWriterPtr writer;
114 const char *err;
115
116 /* Do not save if saving is off. */
117 if ( player_isFlag( PLAYER_NOSAVE ) )
118 return 0;
119
120 /* Create the writer. */
121 writer = xmlNewTextWriterDoc( &doc, 0 );
122 if ( writer == NULL )
123 goto err_ret;
124
125 /* Set the writer parameters. */
126 xmlw_setParams( writer );
127
128 /* Start element. */
129 xmlw_start( writer );
130 xmlw_startElem( writer, "naev_save" );
131
132 /* Save the version and such. */
133 xmlw_startElem( writer, "version" );
134 xmlw_elem( writer, "naev", "%s", naev_version( 0 ) );
135 xmlw_elem( writer, "data", "%s", start_name() );
136 xmlw_endElem( writer ); /* "version" */
137
138 /* Save last played. */
139 xmlw_saveTime( writer, "last_played", time( NULL ) );
140
141 /* Save plugins. */
142 xmlw_startElem( writer, "plugins" );
143 for ( int i = 0; i < array_size( plugins ); i++ )
144 xmlw_elem( writer, "plugin", "%s", plugin_name( &plugins[i] ) );
145 xmlw_endElem( writer ); /* "plugins" */
146
147 /* Save the data. */
148 if ( save_data( writer ) < 0 ) {
149 WARN( _( "Trying to save game data" ) );
150 goto err_writer;
151 }
152
153 /* Finish element. */
154 xmlw_endElem( writer ); /* "naev_save" */
155 xmlw_done( writer );
156
157 /* Write to file. */
158 if ( PHYSFS_mkdir( "saves" ) == 0 ) {
159 snprintf( file, sizeof( file ), "%s/saves", PHYSFS_getWriteDir() );
160 WARN( _( "Dir '%s' does not exist and unable to create: %s" ), file,
161 _( PHYSFS_getErrorByCode( PHYSFS_getLastErrorCode() ) ) );
162 goto err_writer;
163 }
164 snprintf( file, sizeof( file ), "saves/%s", player.name );
165 if ( PHYSFS_mkdir( file ) == 0 ) {
166 snprintf( file, sizeof( file ), "%s/saves/%s", PHYSFS_getWriteDir(),
167 player.name );
168 WARN( _( "Dir '%s' does not exist and unable to create: %s" ), file,
169 _( PHYSFS_getErrorByCode( PHYSFS_getLastErrorCode() ) ) );
170 goto err_writer;
171 }
172
173 /* Back up old saved game. */
174 if ( !strcmp( name, "autosave" ) ) {
175 if ( !save_loaded ) {
176 char backup[PATH_MAX];
177 snprintf( file, sizeof( file ), "saves/%s/autosave.ns", player.name );
178 snprintf( backup, sizeof( backup ), "saves/%s/backup.ns",
179 player.name );
180 if ( ndata_copyIfExists( file, backup ) < 0 ) {
181 WARN( _( "Aborting save…" ) );
182 goto err_writer;
183 }
184 }
185 save_loaded = 0;
186 }
187
188 /* Critical section, if crashes here player's game gets corrupted.
189 * Luckily we have a copy just in case... */
190 xmlFreeTextWriter( writer );
191 snprintf( file, sizeof( file ), "%s/saves/%s/%s.ns", PHYSFS_getWriteDir(),
192 player.name, name ); /* TODO: write via physfs */
193 if ( xmlSaveFileEnc( file, doc, "UTF-8" ) < 0 ) {
194 goto err;
195 }
196 xmlFreeDoc( doc );
197
198 return 0;
199
200err_writer:
201 xmlFreeTextWriter( writer );
202err:
203 xmlFreeDoc( doc );
204err_ret:
205 err =
206 _( "Failed to write saved game! You'll most likely have to restore it "
207 "by copying your backup saved game over your current saved game." );
208 WARN( err );
209 dialogue_alert( "%s", err );
210 return -1;
211}
212
216void save_reload( void )
217{
218 /* Should be refreshed already when menu is opened (load_refresh). */
219 const nsave_t *ns = load_getList( player.name );
220 if ( array_size( ns ) <= 0 ) {
221 WARN( _( "Unable to reload save for '%s'!" ), player.name );
222 return;
223 }
224 load_game( &ns[0] );
225}
Provides macros to work with dynamic arrays.
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:179
void dialogue_alert(const char *fmt,...)
Displays an alert popup with only an ok button and a message.
Definition dialogue.c:130
int load_game(const nsave_t *ns)
Actually loads a new game based on save structure.
Definition load.c:1272
const nsave_t * load_getList(const char *name)
Gets the array (array.h) of loaded saves.
Definition load.c:612
int save_loaded
Definition save.c:30
int missions_saveActive(xmlTextWriterPtr writer)
Saves the player's active missions.
Definition mission.c:1348
Header file with generic functions and naev-specifics.
const char * naev_version(int long_version)
Returns the version in a human readable string.
#define PATH_MAX
Definition naev.h:57
int ndata_copyIfExists(const char *file1, const char *file2)
Copy a file, if it exists.
Definition ndata.c:358
void xmlw_setParams(xmlTextWriterPtr writer)
Sets up the standard xml write parameters.
Definition nxml.c:59
Player_t player
Definition player.c:77
const char * plugin_name(const plugin_t *plg)
Tries to tget the name of a plugin.
Definition plugin.c:315
static plugin_t * plugins
Definition plugin.c:26
const plugin_t * plugin_list(void)
Returns the list of all the plugins.
Definition plugin.c:396
int player_save(xmlTextWriterPtr writer)
Save the freaking player in a freaking xmlfile.
Definition player.c:3404
int var_save(xmlTextWriterPtr writer)
Saves the mission variables.
Definition nlua_var.c:65
void save_reload(void)
Reload the current saved game.
Definition save.c:216
int save_all_with_name(const char *name)
Saves the current game.
Definition save.c:108
int save_all(void)
Saves the current game.
Definition save.c:97
int pfaction_save(xmlTextWriterPtr writer)
Saves player's standings with the factions.
Definition faction.c:2208
static int save_data(xmlTextWriterPtr writer)
Saves all the player's game data.
Definition save.c:64
int events_saveActive(xmlTextWriterPtr writer)
Saves the player's active events.
Definition event.c:839
int economy_sysSave(xmlTextWriterPtr writer)
Saves what is needed to be saved for economy.
Definition economy.c:1094
int diff_save(xmlTextWriterPtr writer)
Saves the active diffs.
Definition unidiff.c:1960
int hook_save(xmlTextWriterPtr writer)
Saves all the hooks.
Definition hook.c:1261
int space_playerSave(xmlTextWriterPtr writer)
Saves what is needed to be saved for space.
Definition space.c:4166
const char * start_name(void)
Gets the module name.
Definition start.c:182
A naev save.
Definition load.h:25