Apply patch #1746 - new savegame format; load savegames using the mod they were saved with. (refs #1746)
git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@10497 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
f5a13e5ecc
commit
af8f95ebcf
57
src/game.c
57
src/game.c
|
@ -40,6 +40,7 @@
|
||||||
#include "lib/script/script.h"
|
#include "lib/script/script.h"
|
||||||
#include "lib/sound/audio.h"
|
#include "lib/sound/audio.h"
|
||||||
#include "lib/sound/audio_id.h"
|
#include "lib/sound/audio_id.h"
|
||||||
|
#include "modding.h"
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
|
@ -1467,20 +1468,52 @@ static bool deserializeSaveGameV35Data(PHYSFS_file* fileHandle, SAVE_GAME_V35* s
|
||||||
return deserializeSaveGameV34Data(fileHandle, (SAVE_GAME_V34*) serializeGame);
|
return deserializeSaveGameV34Data(fileHandle, (SAVE_GAME_V34*) serializeGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store loaded mods in savegame
|
||||||
|
#define GAME_SAVE_V38 \
|
||||||
|
GAME_SAVE_V35; \
|
||||||
|
char modList[modlist_string_size]
|
||||||
|
|
||||||
|
typedef struct save_game_v38
|
||||||
|
{
|
||||||
|
GAME_SAVE_V38;
|
||||||
|
} SAVE_GAME_V38;
|
||||||
|
|
||||||
|
static bool serializeSaveGameV38Data(PHYSFS_file* fileHandle, const SAVE_GAME_V38* serializeGame)
|
||||||
|
{
|
||||||
|
if (!serializeSaveGameV35Data(fileHandle, (const SAVE_GAME_V35*) serializeGame))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (PHYSFS_write(fileHandle, serializeGame->modList, modlist_string_size, 1) != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool deserializeSaveGameV38Data(PHYSFS_file* fileHandle, SAVE_GAME_V38* serializeGame)
|
||||||
|
{
|
||||||
|
if (!deserializeSaveGameV35Data(fileHandle, (SAVE_GAME_V35*) serializeGame))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (PHYSFS_read(fileHandle, serializeGame->modList, modlist_string_size, 1) != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Current save game version
|
// Current save game version
|
||||||
typedef struct save_game
|
typedef struct save_game
|
||||||
{
|
{
|
||||||
GAME_SAVE_V35;
|
GAME_SAVE_V38;
|
||||||
} SAVE_GAME;
|
} SAVE_GAME;
|
||||||
|
|
||||||
static bool serializeSaveGameData(PHYSFS_file* fileHandle, const SAVE_GAME* serializeGame)
|
static bool serializeSaveGameData(PHYSFS_file* fileHandle, const SAVE_GAME* serializeGame)
|
||||||
{
|
{
|
||||||
return serializeSaveGameV35Data(fileHandle, (const SAVE_GAME_V35*) serializeGame);
|
return serializeSaveGameV38Data(fileHandle, (const SAVE_GAME_V38*) serializeGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool deserializeSaveGameData(PHYSFS_file* fileHandle, SAVE_GAME* serializeGame)
|
static bool deserializeSaveGameData(PHYSFS_file* fileHandle, SAVE_GAME* serializeGame)
|
||||||
{
|
{
|
||||||
return deserializeSaveGameV35Data(fileHandle, (SAVE_GAME_V35*) serializeGame);
|
return deserializeSaveGameV38Data(fileHandle, (SAVE_GAME_V38*) serializeGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEMP_DROID_MAXPROGS 3
|
#define TEMP_DROID_MAXPROGS 3
|
||||||
|
@ -4424,6 +4457,16 @@ bool gameLoadV(PHYSFS_file* fileHandle, unsigned int version)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (version <= VERSION_37) // versions 35-37 use the same save game format
|
||||||
|
{
|
||||||
|
//if (PHYSFS_read(fileHandle, &saveGameData, sizeof(SAVE_GAME_V35), 1) != 1)
|
||||||
|
if (!deserializeSaveGameV35Data(fileHandle, (SAVE_GAME_V35*) &saveGameData))
|
||||||
|
{
|
||||||
|
debug(LOG_ERROR, "gameLoadV: error while reading file (with version number %u): %s", version, PHYSFS_getLastError());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (version <= CURRENT_VERSION_NUM)
|
else if (version <= CURRENT_VERSION_NUM)
|
||||||
{
|
{
|
||||||
if (!deserializeSaveGameData(fileHandle, &saveGameData))
|
if (!deserializeSaveGameData(fileHandle, &saveGameData))
|
||||||
|
@ -4448,6 +4491,11 @@ bool gameLoadV(PHYSFS_file* fileHandle, unsigned int version)
|
||||||
debug(LOG_ERROR, "Skirmish savegames of version %u are not supported in this release.", version);
|
debug(LOG_ERROR, "Skirmish savegames of version %u are not supported in this release.", version);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/* Test mod list */
|
||||||
|
if (version >= VERSION_38)
|
||||||
|
{
|
||||||
|
setOverrideMods(saveGameData.modList);
|
||||||
|
}
|
||||||
|
|
||||||
// All savegames from version 34 or before are little endian so swap them. All
|
// All savegames from version 34 or before are little endian so swap them. All
|
||||||
// from version 35, and onward, are already swapped to the native byte-order
|
// from version 35, and onward, are already swapped to the native byte-order
|
||||||
|
@ -4966,6 +5014,9 @@ static bool writeGameFile(const char* fileName, SDWORD saveType)
|
||||||
strcpy(saveGame.sPlayerName[i], getPlayerName(i));
|
strcpy(saveGame.sPlayerName[i], getPlayerName(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//version 38
|
||||||
|
sstrcpy(saveGame.modList, getModList());
|
||||||
|
|
||||||
status = serializeSaveGameData(fileHandle, &saveGame);
|
status = serializeSaveGameData(fileHandle, &saveGame);
|
||||||
|
|
||||||
// Close the file
|
// Close the file
|
||||||
|
|
|
@ -79,9 +79,10 @@ extern "C"
|
||||||
#define VERSION_35 35 //uses the (de)serialization API for saving/loading games and is big-endian instead of little-endian
|
#define VERSION_35 35 //uses the (de)serialization API for saving/loading games and is big-endian instead of little-endian
|
||||||
#define VERSION_36 36 //saves beacon properly
|
#define VERSION_36 36 //saves beacon properly
|
||||||
#define VERSION_37 37 //dpid changes; this had better be the last version
|
#define VERSION_37 37 //dpid changes; this had better be the last version
|
||||||
|
#define VERSION_38 38 //mod list!
|
||||||
|
|
||||||
|
|
||||||
#define CURRENT_VERSION_NUM VERSION_37
|
#define CURRENT_VERSION_NUM VERSION_38
|
||||||
|
|
||||||
//used in the loadGame
|
//used in the loadGame
|
||||||
#define KEEPOBJECTS true
|
#define KEEPOBJECTS true
|
||||||
|
|
47
src/init.c
47
src/init.c
|
@ -234,11 +234,15 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
||||||
wzSearchPath * curSearchPath = searchPathRegistry;
|
wzSearchPath * curSearchPath = searchPathRegistry;
|
||||||
char tmpstr[PATH_MAX] = "\0";
|
char tmpstr[PATH_MAX] = "\0";
|
||||||
|
|
||||||
if ( mode != current_mode || force )
|
if (mode != current_mode || force ||
|
||||||
|
(use_override_mods && strcmp(override_mod_list, getModList())))
|
||||||
|
{
|
||||||
|
if (mode != mod_clean)
|
||||||
{
|
{
|
||||||
current_mode = mode;
|
|
||||||
|
|
||||||
rebuildSearchPath( mod_clean, false );
|
rebuildSearchPath( mod_clean, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
current_mode = mode;
|
||||||
|
|
||||||
// Start at the lowest priority
|
// Start at the lowest priority
|
||||||
while( curSearchPath->lowerPriority )
|
while( curSearchPath->lowerPriority )
|
||||||
|
@ -258,9 +262,10 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
||||||
// Remove maps and mods
|
// Remove maps and mods
|
||||||
removeSubdirs( curSearchPath->path, "maps", NULL );
|
removeSubdirs( curSearchPath->path, "maps", NULL );
|
||||||
removeSubdirs( curSearchPath->path, "mods/music", NULL );
|
removeSubdirs( curSearchPath->path, "mods/music", NULL );
|
||||||
removeSubdirs( curSearchPath->path, "mods/global", global_mods );
|
removeSubdirs( curSearchPath->path, "mods/global", NULL );
|
||||||
removeSubdirs( curSearchPath->path, "mods/campaign", campaign_mods );
|
removeSubdirs( curSearchPath->path, "mods/campaign", NULL );
|
||||||
removeSubdirs( curSearchPath->path, "mods/multiplay", multiplay_mods );
|
removeSubdirs( curSearchPath->path, "mods/multiplay", NULL );
|
||||||
|
removeSubdirs( curSearchPath->path, "mods/autoload", NULL );
|
||||||
|
|
||||||
// Remove multiplay patches
|
// Remove multiplay patches
|
||||||
sstrcpy(tmpstr, curSearchPath->path);
|
sstrcpy(tmpstr, curSearchPath->path);
|
||||||
|
@ -301,10 +306,10 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
||||||
PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );
|
PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );
|
||||||
|
|
||||||
addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false );
|
addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false );
|
||||||
addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, global_mods, true );
|
addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||||
addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, global_mods, true );
|
addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||||
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, NULL, true );
|
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true );
|
||||||
addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, campaign_mods, true );
|
addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods?override_mods:campaign_mods, true );
|
||||||
if (!PHYSFS_removeFromSearchPath( curSearchPath->path ))
|
if (!PHYSFS_removeFromSearchPath( curSearchPath->path ))
|
||||||
{
|
{
|
||||||
info("* Failed to remove path %s again", curSearchPath->path);
|
info("* Failed to remove path %s again", curSearchPath->path);
|
||||||
|
@ -342,10 +347,10 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
||||||
PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );
|
PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );
|
||||||
addSubdirs( curSearchPath->path, "maps", PHYSFS_APPEND, NULL, false );
|
addSubdirs( curSearchPath->path, "maps", PHYSFS_APPEND, NULL, false );
|
||||||
addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false );
|
addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false );
|
||||||
addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, global_mods, true );
|
addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||||
addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, global_mods, true );
|
addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||||
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, NULL, true );
|
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true );
|
||||||
addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, multiplay_mods, true );
|
addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods?override_mods:multiplay_mods, true );
|
||||||
PHYSFS_removeFromSearchPath( curSearchPath->path );
|
PHYSFS_removeFromSearchPath( curSearchPath->path );
|
||||||
|
|
||||||
// Add multiplay patches
|
// Add multiplay patches
|
||||||
|
@ -379,6 +384,15 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
||||||
debug(LOG_ERROR, "Can't switch to unknown mods %i", mode);
|
debug(LOG_ERROR, "Can't switch to unknown mods %i", mode);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (use_override_mods && mode != mod_clean)
|
||||||
|
{
|
||||||
|
if (strcmp(getModList(),override_mod_list))
|
||||||
|
{
|
||||||
|
debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list);
|
||||||
|
}
|
||||||
|
clearOverrideMods();
|
||||||
|
current_mode = mod_override;
|
||||||
|
}
|
||||||
|
|
||||||
// User's home dir must be first so we allways see what we write
|
// User's home dir must be first so we allways see what we write
|
||||||
PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir());
|
PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir());
|
||||||
|
@ -388,6 +402,11 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
||||||
printSearchPath();
|
printSearchPath();
|
||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
}
|
}
|
||||||
|
else if (use_override_mods)
|
||||||
|
{
|
||||||
|
// override mods are already the same as current mods, so no need to do anything
|
||||||
|
clearOverrideMods();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ typedef struct _wzSearchPath
|
||||||
struct _wzSearchPath * higherPriority, * lowerPriority;
|
struct _wzSearchPath * higherPriority, * lowerPriority;
|
||||||
} wzSearchPath;
|
} wzSearchPath;
|
||||||
|
|
||||||
typedef enum { mod_clean=0, mod_campaign=1, mod_multiplay=2 } searchPathMode;
|
typedef enum { mod_clean=0, mod_campaign=1, mod_multiplay=2, mod_override=3 } searchPathMode;
|
||||||
|
|
||||||
void cleanSearchPath( void );
|
void cleanSearchPath( void );
|
||||||
void registerSearchPath( const char path[], unsigned int priority );
|
void registerSearchPath( const char path[], unsigned int priority );
|
||||||
|
|
|
@ -677,7 +677,10 @@ BOOL levLoadData(const char* name, char *pSaveName, GAME_TYPE saveType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuildSearchPath(psNewLevel->dataDir, false);
|
if (!rebuildSearchPath(psNewLevel->dataDir, false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// reset the old mission data if necessary
|
// reset the old mission data if necessary
|
||||||
if (psCurrLevel != NULL)
|
if (psCurrLevel != NULL)
|
||||||
|
|
34
src/main.c
34
src/main.c
|
@ -108,6 +108,10 @@ char * global_mods[MAX_MODS] = { NULL };
|
||||||
char * campaign_mods[MAX_MODS] = { NULL };
|
char * campaign_mods[MAX_MODS] = { NULL };
|
||||||
char * multiplay_mods[MAX_MODS] = { NULL };
|
char * multiplay_mods[MAX_MODS] = { NULL };
|
||||||
|
|
||||||
|
char * override_mods[MAX_MODS] = { NULL };
|
||||||
|
char * override_mod_list = NULL;
|
||||||
|
bool use_override_mods = false;
|
||||||
|
|
||||||
char * loaded_mods[MAX_MODS] = { NULL };
|
char * loaded_mods[MAX_MODS] = { NULL };
|
||||||
char * mod_list = NULL;
|
char * mod_list = NULL;
|
||||||
int num_loaded_mods = 0;
|
int num_loaded_mods = 0;
|
||||||
|
@ -225,6 +229,36 @@ void printSearchPath( void )
|
||||||
PHYSFS_freeList( searchPath );
|
PHYSFS_freeList( searchPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setOverrideMods(char * modlist)
|
||||||
|
{
|
||||||
|
char * curmod = modlist;
|
||||||
|
char * nextmod;
|
||||||
|
int i=0;
|
||||||
|
while ((nextmod = strstr(curmod, ", ")) && i<MAX_MODS-2)
|
||||||
|
{
|
||||||
|
override_mods[i] = malloc(nextmod-curmod+1);
|
||||||
|
strlcpy(override_mods[i], curmod, nextmod-curmod);
|
||||||
|
override_mods[i][nextmod-curmod] = '\0';
|
||||||
|
curmod = nextmod + 2;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
override_mods[i] = strdup(curmod);
|
||||||
|
override_mods[i+1] = NULL;
|
||||||
|
override_mod_list = modlist;
|
||||||
|
use_override_mods = true;
|
||||||
|
}
|
||||||
|
void clearOverrideMods(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
use_override_mods = false;
|
||||||
|
for (i=0; i<MAX_MODS && override_mods[i]; i++)
|
||||||
|
{
|
||||||
|
free(override_mods[i]);
|
||||||
|
}
|
||||||
|
override_mods[0] = NULL;
|
||||||
|
override_mod_list = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void addLoadedMod(const char * modname)
|
void addLoadedMod(const char * modname)
|
||||||
{
|
{
|
||||||
char * mod = strdup(modname);
|
char * mod = strdup(modname);
|
||||||
|
|
|
@ -51,6 +51,10 @@ extern char * global_mods[MAX_MODS];
|
||||||
extern char * campaign_mods[MAX_MODS];
|
extern char * campaign_mods[MAX_MODS];
|
||||||
extern char * multiplay_mods[MAX_MODS];
|
extern char * multiplay_mods[MAX_MODS];
|
||||||
|
|
||||||
|
extern char * override_mods[MAX_MODS];
|
||||||
|
extern char * override_mod_list;
|
||||||
|
extern bool use_override_mods;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif //__cplusplus
|
#endif //__cplusplus
|
||||||
|
|
|
@ -30,6 +30,9 @@ void addSubdirs( const char * basedir, const char * subdir, const bool appendToP
|
||||||
void removeSubdirs( const char * basedir, const char * subdir, char * checkList[] );
|
void removeSubdirs( const char * basedir, const char * subdir, char * checkList[] );
|
||||||
void printSearchPath( void );
|
void printSearchPath( void );
|
||||||
|
|
||||||
|
void setOverrideMods(char * modlist);
|
||||||
|
void clearOverrideMods(void);
|
||||||
|
|
||||||
void addLoadedMod(const char * modname);
|
void addLoadedMod(const char * modname);
|
||||||
void clearLoadedMods(void);
|
void clearLoadedMods(void);
|
||||||
char * getModList(void);
|
char * getModList(void);
|
||||||
|
|
Loading…
Reference in New Issue