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/sound/audio.h"
|
||||
#include "lib/sound/audio_id.h"
|
||||
#include "modding.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);
|
||||
}
|
||||
|
||||
// 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
|
||||
typedef struct save_game
|
||||
{
|
||||
GAME_SAVE_V35;
|
||||
GAME_SAVE_V38;
|
||||
} SAVE_GAME;
|
||||
|
||||
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)
|
||||
{
|
||||
return deserializeSaveGameV35Data(fileHandle, (SAVE_GAME_V35*) serializeGame);
|
||||
return deserializeSaveGameV38Data(fileHandle, (SAVE_GAME_V38*) serializeGame);
|
||||
}
|
||||
|
||||
#define TEMP_DROID_MAXPROGS 3
|
||||
|
@ -4424,6 +4457,16 @@ bool gameLoadV(PHYSFS_file* fileHandle, unsigned int version)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
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
|
||||
// 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));
|
||||
}
|
||||
|
||||
//version 38
|
||||
sstrcpy(saveGame.modList, getModList());
|
||||
|
||||
status = serializeSaveGameData(fileHandle, &saveGame);
|
||||
|
||||
// Close the file
|
||||
|
|
|
@ -78,10 +78,11 @@ extern "C"
|
|||
#define VERSION_34 34 //saves AI names for multiplayer (.gam file)
|
||||
#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_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
|
||||
#define KEEPOBJECTS true
|
||||
|
|
47
src/init.c
47
src/init.c
|
@ -234,11 +234,15 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
|||
wzSearchPath * curSearchPath = searchPathRegistry;
|
||||
char tmpstr[PATH_MAX] = "\0";
|
||||
|
||||
if ( mode != current_mode || force )
|
||||
if (mode != current_mode || force ||
|
||||
(use_override_mods && strcmp(override_mod_list, getModList())))
|
||||
{
|
||||
current_mode = mode;
|
||||
if (mode != mod_clean)
|
||||
{
|
||||
rebuildSearchPath( mod_clean, false );
|
||||
}
|
||||
|
||||
rebuildSearchPath( mod_clean, false );
|
||||
current_mode = mode;
|
||||
|
||||
// Start at the lowest priority
|
||||
while( curSearchPath->lowerPriority )
|
||||
|
@ -258,9 +262,10 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
|||
// Remove maps and mods
|
||||
removeSubdirs( curSearchPath->path, "maps", NULL );
|
||||
removeSubdirs( curSearchPath->path, "mods/music", NULL );
|
||||
removeSubdirs( curSearchPath->path, "mods/global", global_mods );
|
||||
removeSubdirs( curSearchPath->path, "mods/campaign", campaign_mods );
|
||||
removeSubdirs( curSearchPath->path, "mods/multiplay", multiplay_mods );
|
||||
removeSubdirs( curSearchPath->path, "mods/global", NULL );
|
||||
removeSubdirs( curSearchPath->path, "mods/campaign", NULL );
|
||||
removeSubdirs( curSearchPath->path, "mods/multiplay", NULL );
|
||||
removeSubdirs( curSearchPath->path, "mods/autoload", NULL );
|
||||
|
||||
// Remove multiplay patches
|
||||
sstrcpy(tmpstr, curSearchPath->path);
|
||||
|
@ -301,10 +306,10 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
|||
PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );
|
||||
|
||||
addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false );
|
||||
addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, global_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, global_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, NULL, true );
|
||||
addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, campaign_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true );
|
||||
addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods?override_mods:campaign_mods, true );
|
||||
if (!PHYSFS_removeFromSearchPath( 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 );
|
||||
addSubdirs( curSearchPath->path, "maps", 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", PHYSFS_APPEND, global_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, NULL, true );
|
||||
addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, multiplay_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
|
||||
addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true );
|
||||
addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods?override_mods:multiplay_mods, true );
|
||||
PHYSFS_removeFromSearchPath( curSearchPath->path );
|
||||
|
||||
// Add multiplay patches
|
||||
|
@ -379,6 +384,15 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
|||
debug(LOG_ERROR, "Can't switch to unknown mods %i", mode);
|
||||
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
|
||||
PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir());
|
||||
|
@ -388,6 +402,11 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force )
|
|||
printSearchPath();
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef struct _wzSearchPath
|
|||
struct _wzSearchPath * higherPriority, * lowerPriority;
|
||||
} 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 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
|
||||
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 * 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 * mod_list = NULL;
|
||||
int num_loaded_mods = 0;
|
||||
|
@ -225,6 +229,36 @@ void printSearchPath( void )
|
|||
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)
|
||||
{
|
||||
char * mod = strdup(modname);
|
||||
|
|
|
@ -51,6 +51,10 @@ extern char * global_mods[MAX_MODS];
|
|||
extern char * campaign_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
|
||||
}
|
||||
#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 printSearchPath( void );
|
||||
|
||||
void setOverrideMods(char * modlist);
|
||||
void clearOverrideMods(void);
|
||||
|
||||
void addLoadedMod(const char * modname);
|
||||
void clearLoadedMods(void);
|
||||
char * getModList(void);
|
||||
|
|
Loading…
Reference in New Issue