DarkScythe
Hunkalicious Holo
- Joined
- May 6, 2014
- Messages
- 804
TSL Serializer
Add-on component for use with TableSaverLoader
Available at the CivFanatics Download Database
Latest Version: v3 (Released: March 28, 2015)
Add-on component for use with TableSaverLoader
Available at the CivFanatics Download Database
Latest Version: v3 (Released: March 28, 2015)
What This Is:
This is an add-on component for use with Pazyryk's TableSaverLoader which remedies an issue that may result in potential data loss.
Pazyryk has been notified of this issue, but as he seems to have not been around very much lately, I decided to write up a workaround in the meantime, until he returns to resume work on TableSaverLoader, and can come up with a better solution.
What The Problem Is:
It is suggested that any mod which uses TableSaverLoader for persistence of its data include this component alongside it. As discussed in the thread here, there exists an issue with the fact that, for mods which rely on the Lua-only savegame interception system, we all have to define TableSave() with the details of the table we want saved, and then further define the Input Handler to call these functions.
However, When multiple mods which rely on this system are loaded, a conflict appears -- only one Input Handler can take control of any given input! The savegame interception relies upon capturing Ctrl+S and F11, but only the last input handler loaded will be able to take control of these keys. As well, clicking on the 'Save Game' or 'Quicksave' buttons in the menu is also tied to running each mod's customized savegame interception functions.
What ends up happening, then, is that only the last mod loaded will have its data saved when a manual game save is initiated this way.
Note that autosaves are unaffected! This only affects cases where autosaves run infrequently, and a player manually saves the game and exits or reloads. Any data from other mods since the last autosave will be lost.
What This Does:
This script is a work-around for the game's inherent limitation of the input handler system interfering with TableSaverLoader across multiple mods / contexts. It remedies the input handler limitation by invoking the use of LuaEvents to trigger all associated mods to execute a TableSave() from their own context. At the same time, it re-defines the interception functions to be more generic, so that it can be re-used across contexts.
How It Works:
This component is separated into two files: A "Core" file, and a "Client" file.
The Core file sets up the "TSL Master" for the TSL Serializer for the first mod which loads with this component. This Master handles communication among all of the "Clients" which set up listeners from the Client file.
The Clients request an ID from the Master when they load. This ID is used by the Master to keep track of how many contexts it needs to call. In doing so, Clients will also "register" their tables with the Master, which allows the Master to perform some basic logic to determine whether there are any issues with, conflicts between, or duplication of data among different mods and contexts.
The Client file also hooks up with TableSaverLoader, and adds a listener which waits to conduct a TableSave() when triggered by the Master.
Usage Notes / Requirements:
Both of the files must be included alongside any mod or context which relies on TableSaverLoader. By extension, TableSaverLoader must be present. This component does not include a copy of TableSaverLoader.
Both files must be imported into VFS.
The "Core" file must not be altered. It is already included within the Client file. No further action is necessary with the Core file beyond including it in VFS.
The "Client" file must be renamed. This is important, because the Client file must sit within the same context as the parent mod.
The Client should be included after TableSaverLoader has been loaded and global tables defined, but before the first Events.LoadScreenClose function.
For example:
Code:
...
include("TableSaverLoader016.lua")
gMyGlobalTable = {}
include("ModTSLSerializer.lua")
...
Implementation Specifics:
tableRoot and tableName must be defined, either inside the Client file, or as a global before it is included (in which case, delete / comment out tableRoot and tableName inside the Client file.)
tableRoot will be whatever is your mod's main global table. For those that have already implemented TableSaverLoader, this will be the first argument in your TableSave() function. It doesn't matter whether it points directly to the main table, or to a variable which references it, as long as it points to the table with all the data, and all the sub-tables.
For example, if you use the global MapModData table:
Code:
MapModData.gMyModTable
MapModData.gT.gMyModData
Simple global Lua tables are also valid:
Code:
gMyModDataTable = {}
If you have assigned to something to reference that table instead, you may also use it.
Code:
MapModData.gMyModTable
gMyModTable = MapModData.gMyModTable
gTable = gMyModDataTable
For these examples, these are valid tables to define tableRoot as:
Code:
tableRoot = MapModData.gMyModTable
tableRoot = MapModData.gT.gMyModData
tableRoot = gMyModTable
tableRoot = gTable
tableRoot = gMyModDataTable
AVOID USING 'MapModData' or 'MapModData.gT'!
These are default tables (the latter being a TSL-specific example) and may contain a whole lot of unrelated data which may cause weird issues if saved all into your table. As the client registers the defined table with the Master, the Master will warn you if you try to do this. It will, however, not fail or prevent you from using these tables.
tableName must be a string and will be the unique name for the table when written into the savegame database. Avoid duplicates! The Master will warn you if a duplicate tableName is submitted.
For those with existing TableSaverLoader hookups, tableName will be the same as the second argument provided in your TableSave() function.
Notes For Modders:
This script introduces a new LuaEvent which effectively replaces the default TableSave():
Code:
LuaEvents.TSLTableSave()
It sends a notice to the Master to trigger all contexts to conduct a TableSave() immediately.
The biggest usage for this is with TSL's savegame intercept functions, which have already been included.
All manual saves done by your script, as well as autosave need not be modified, although there is no harm in using the above LuaEvents replacement.
Once this component is added and included, it is important that existing TableSaverLoader hook-up code be deleted or commented out, except for OnModLoaded()!
This script already includes all of the standard TableSaverLoader hookup-code (except for OnModLoaded(),) for ease of use, especially the modified savegame interception functions which now call the new LuaEvents instead.
Leaving the original hook-up code in place may end up re-defining these functions back, and render this component useless. OnModLoaded() is not included, because implementations of this particular function vary between mods. In other words, this script only handles saving -- TableLoad() will still need to be called by your own script.
This script has been tested with a couple different mods, but by no means was it an exhaustive test, and so for the time being, consider this a potential Beta. However, I have not seen any issues arise in my tests. This has also only been tested with the latest version of TableSaverLoader as of current writing (v0.16) and may provide unexpected results when used in an environment with mixed versions, since TableSaverLoader v0.16 is incompatible with tables created with older versions of itself.
How To Use:
- Import Core & Client files into VFS.
- Rename the (non-Core) Client file into something unique.
- include() the Client file into your main Lua script.
- Ensure it's included after TableSaverLoader.
- Ensure that the global table has already been defined.
- Define tableRoot and tableName in, or before, the Client file.
- Delete or comment out existing TableSaverLoader hook-up code, EXCEPT for OnModLoaded()
- At the minimum, SaveGameIntercept() and QuickSaveIntercept() need to be removed, or commented out. Modified versions of those functions are included in this script.
- Every other TSL hook-up function has also been included, so it may duplicate autosaves if not removed.
- The only function not duplicated/included is the OnModLoaded() function, as different mods have different ways of defining this.
- If your mod has a modified InputHandler, ensure it retains the calls defined by TableSaverLoader's stock function, and leave it defined after the Client file include. It will overwrite the included function.
Download:
For the moment, please refer to the CivFanatics download database.
If need arises for an alternate download for some reason, I can provide it then.
Release History:
- v1 (Jan 13, 2015)
- Initial private beta testing release
- v2 (Jan 14, 2015)
- Separated the code into 'Core' and 'Client' files
- v3 (Mar 28, 2015)
- Fixed an issue causing the save game hotkeys to not work properly
- Added version checking to the Serializer
- Removed the need to delete tableRoot and tableName if they were already defined
- Hooked up the debug mode so it actually does something
- Switched standard save operation method with the previously-experimental debug method for speed
- Old method is activated by toggling MapModData.TSLMaster.debugMode to true
Mods Utilizing TSL Serializer:
Released:
- Fate/Stay Night: Archer's Japan [BNW] (by Vice Virtuoso)
- Madoka Magica: Wish for the World [BNW] (by Vice Virtuoso)
- Saints Row -- 3rd Street Saints Civilization [BNW/G&K] (by Vice Virtuoso)
- Lyrical Nanoha -- TSAB Civilization [BNW] (by Vice Virtuoso)
- Militaires Sans Frontieres Civilization: Subsistence [BNW] (by Vice Virtuoso)
- Knights Templar (by LeeS)
- Hulfgar's Modpack Complete Edition (by Hulfgar)
- CIV-Linked Great Generals (by LeeS)
- Jojo's Bizarre Adventure - Steel Ball Run: The United States of Valentine [BNW] (by Vice Virtuoso)
- Hyperdimension Neptunia: Leanbox [BNW] (by Vice Virtuoso)
- Hulfgar's Modpack Industrial Edition (by Hulfgar)
- Piety & Prestige (by JFD)
- Cultural Diversity (by JFD)
- Hyperdimension Neptunia: Lowee [BNW] (by Vice Virtuoso)
Planned / In Testing:
- Holo's Wolf and Merchant Empire (Spice and Wolf Civilization) (by DarkScythe)
- Holo's Spice and Wolf Civilization (BETA TEST) (by DarkScythe)
- Super Mario Bros. - The Lumas (by Typhlomence)
- Exploration Continued Expanded (by JFD)