Mordachai
Squire
I'm wicked stoked!
I always hated that modifying code runs the huge risk of adding new globals, or (even more likely) changing the order in which they're first referenced, which then breaks saves.
So, I figured there must be a way to force the order of reference, outside of the module code itself, so that changing ones module_*.py files doesn't risk your saves... and there IS!
The module system compiles a list of global variables and writes it out to variables.txt. This file defines the order of the globals in a saved game. So when you open the save later, the order things were saved at that time need to match up with the order that the variables.txt file claims it is now.
So, the trick is to keep that order consistent. What I've done is to have the process_global_variables.py read the old variables.txt file before starting processing your module files, which means that the order of the variables will be forced to be the same as last time, and any new variables you added will go on the end, and any change in order of reference won't alter the order they're read from the save file (or written). Viola! Save game compatible!
To add this for yourself, you need to modify the end of the process_global_variables.py.
Replace the final two lines, which normally look like:
With these lines instead:
The first time you compile, this code will copy the resulting variables.txt into your module system folder. That file will be overwritten every time you build after that.
And since this seems to be neglected often, I realized that its quite easy to also automatically have your module.ini update when you build your code (and it makes it easy to keep your source in a source control system, with all of the source properly stored in your build folder).
Just add this at the end of process_global_variables.py file (after the above changes):
Finally, I wanted to add another layer of protection, so I could see when / if I added globals, so I made a few changes to build_module.bat to force it to backup to 10 files deep a copy of variables.txt. This is not strictly necessary, but I feel better having it (place at the top of the file, just after the @echo off):
Note: Adding presentations does NOT break save compatibility.
I hope that this brings a whole new level of save-game compatibility to the whole modding community!
I always hated that modifying code runs the huge risk of adding new globals, or (even more likely) changing the order in which they're first referenced, which then breaks saves.
So, I figured there must be a way to force the order of reference, outside of the module code itself, so that changing ones module_*.py files doesn't risk your saves... and there IS!
The module system compiles a list of global variables and writes it out to variables.txt. This file defines the order of the globals in a saved game. So when you open the save later, the order things were saved at that time need to match up with the order that the variables.txt file claims it is now.
So, the trick is to keep that order consistent. What I've done is to have the process_global_variables.py read the old variables.txt file before starting processing your module files, which means that the order of the variables will be forced to be the same as last time, and any new variables you added will go on the end, and any change in order of reference won't alter the order they're read from the save file (or written). Viola! Save game compatible!
To add this for yourself, you need to modify the end of the process_global_variables.py.
Replace the final two lines, which normally look like:
Code:
compile_all_global_vars(variables, variable_uses, triggers, dialogs, game_menus, mission_templates, scripts, simple_triggers)
save_variables(export_dir, variables, variable_uses)
Code:
#MORDACHAI - Preserve previous global variable order, for save-game compatibility...
try:
file = open("variables.txt","r")
var_list = file.readlines()
file.close()
for v in var_list:
vv = string.strip(v)
if vv:
variables.append(vv)
variable_uses.append(0)
except:
print "Variables.txt not found. No attempt to maintain save game compatibility will be made for this build."
compile_all_global_vars(variables, variable_uses, triggers, dialogs, game_menus, mission_templates, scripts, simple_triggers)
save_variables(export_dir, variables, variable_uses)
#MORDACHAI - write out the new version of variables.txt to our module system folder, so we can maintain compatibility with it...
file = open("variables.txt","w")
for i in xrange(len(variables)):
file.write("%s\n"%variables[i])
file.close()
And since this seems to be neglected often, I realized that its quite easy to also automatically have your module.ini update when you build your code (and it makes it easy to keep your source in a source control system, with all of the source properly stored in your build folder).
Just add this at the end of process_global_variables.py file (after the above changes):
Code:
#MORDACHAI - copy our module.ini to the target folder too (if there is one)
try:
file = open("module.ini","r")
contents = file.readlines()
file.close()
file = open(export_dir + "module.ini","w")
for i in xrange(len(contents)):
file.write("%s"%contents[i])
file.close()
print "Module.ini updated."
except:
print "Module.ini not found. Skipping..."
Finally, I wanted to add another layer of protection, so I could see when / if I added globals, so I made a few changes to build_module.bat to force it to backup to 10 files deep a copy of variables.txt. This is not strictly necessary, but I feel better having it (place at the top of the file, just after the @echo off):
Code:
@echo backing up our previous variables.txt...
if not exist "variables.txt" goto nobackup
if exist "variables backup 9.txt" del "variables backup 9.txt" > nul
if exist "variables backup 8.txt" ren "variables backup 8.txt" "variables backup 9.txt" > nul
if exist "variables backup 7.txt" ren "variables backup 7.txt" "variables backup 8.txt" > nul
if exist "variables backup 6.txt" ren "variables backup 6.txt" "variables backup 7.txt" > nul
if exist "variables backup 5.txt" ren "variables backup 5.txt" "variables backup 6.txt" > nul
if exist "variables backup 4.txt" ren "variables backup 4.txt" "variables backup 5.txt" > nul
if exist "variables backup 3.txt" ren "variables backup 3.txt" "variables backup 4.txt" > nul
if exist "variables backup 2.txt" ren "variables backup 2.txt" "variables backup 3.txt" > nul
if exist "variables backup 1.txt" ren "variables backup 1.txt" "variables backup 2.txt" > nul
@rem I want to ensure that the file time stamp is what it was, not now...
ren "variables.txt" "variables backup 1.txt" > nul
copy "variables backup 1.txt" "variables.txt" > nul
:nobackup
Note: Adding presentations does NOT break save compatibility.
I hope that this brings a whole new level of save-game compatibility to the whole modding community!