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-861f7616d084
master
Guangcong Luo 2010-04-06 13:54:56 +00:00 committed by Git SVN Gateway
parent f5a13e5ecc
commit af8f95ebcf
8 changed files with 136 additions and 21 deletions

View File

@ -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

View 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

View File

@ -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;
}

View File

@ -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 );

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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);