[SaveEditor] WarBender - savegame editor [released/1.0.4]

Users who are viewing this thread

I've checked, and that slot is properly marked as referencing a troop in metadata, so you should be able to just pick the right person from the dropdown - no need to muck around with raw IDs.

Also, I made it omit the "slot_" prefix (since it's always there) - so it'll be just "troop_spouse".
 
True, I formulated my answer without taking into consideration the specifications of your tool, my fault. I was just pointing out how I would do the game if I had to give you a wife. If we focus on how your tool works, yes, it's exactly how you commented. :wink:
 
No worries! I just wanted to make sure drandonboss can find everything, in case they're not familiar with the inner structure of a save, and are just going based on what they see on the screen. Didn't mean it to sound as a criticism of your answer; my apologies about that!
 
Why didn't this get stickied or included in the Modder's Download Repository yet?

Edit: Would it be possible to calculate how much things like parties occupy in disk space and display it in the program?
 
When I launch the exe nothing happens and Warbender UI is just running in the background

Do I need to put the files in a specific location?

Edit: it fixed itself
 
KratosMKII said:
Edit: Would it be possible to calculate how much things like parties occupy in disk space and display it in the program?

It's possible to calculate how much any given record takes in the file, but it can be tricky to meaningfully translate it to higher-level stuff. For example, a single party record has tons of fields, but it just describes the party as a whole, not individual troops in it. Do we also count troops as part of the size? But then both troops and parties reference other stuff - e.g. a party has an associated party template and faction. Do those count? And so on... it's kinda hard to draw the line between "just parties" and "everything else" in a save, because of all the inter-dependencies.

Going strictly by records, it's pretty straightforward: so you'd get numbers like "X bytes used for party records, Y bytes used for troop records, ...". I'm not sure how useful that would be though. When does that stuff come in handy?
 
int19h said:
KratosMKII said:
Edit: Would it be possible to calculate how much things like parties occupy in disk space and display it in the program?

It's possible to calculate how much any given record takes in the file, but it can be tricky to meaningfully translate it to higher-level stuff. For example, a single party record has tons of fields, but it just describes the party as a whole, not individual troops in it. Do we also count troops as part of the size? But then both troops and parties reference other stuff - e.g. a party has an associated party template and faction. Do those count? And so on... it's kinda hard to draw the line between "just parties" and "everything else" in a save, because of all the inter-dependencies.

Going strictly by records, it's pretty straightforward: so you'd get numbers like "X bytes used for party records, Y bytes used for troop records, ...". I'm not sure how useful that would be though. When does that stuff come in handy?
Optimizing the save file size. 1257 for example has save files that start at 50MB but can grow up to 60-70MB. It would be interesting to know how much space does each thing occupy.
 
Alright, here we go! 1.0.4 is the new release, and now the property grid will show (SizeInBytes) property for any record or collection you might open. This includes any child records and collections that are physically embedded into the one that you're viewing, but not anything that it references by ID - e.g. for a party, its slots and stacks are counted, but the faction referenced by faction_id is not, nor are the troops referenced by troop_id in the stacks.

gZ6mQM7.png


In addition, I switched the project to .NET 4.6 - turned out to be much simpler than I expected. So, now this should work on Windows 8.x as well.
 
int19h said:
Alright, here we go! 1.0.4 is the new release, and now the property grid will show (SizeInBytes) property for any record or collection you might open. This includes any child records and collections that are physically embedded into the one that you're viewing, but not anything that it references by ID - e.g. for a party, its slots and stacks are counted, but the faction referenced by faction_id is not, nor are the troops referenced by troop_id in the stacks.

gZ6mQM7.png


In addition, I switched the project to .NET 4.6 - turned out to be much simpler than I expected. So, now this should work on Windows 8.x as well.
Thank you! Now i can know why my save game is so massive and take measures to reduce it.
But now i'm getting this error:
i6SiqkS.png
This started to happen suddenly on v1.0.3. The .inis are there but the program doesn't find them.
 
Are you sure that's the right folder? I mean, I'd expect it to have subfolders related to other things in the module (Data, Sounds, Textures etc) - and all folders always show up, regardless of the filename filter. This is what it looks like for me:
ewY1Npp.png


Can you check path on top of that open dialog? When you click on it, you should be able to copy-paste it, and open it in Explorer, to make sure it's correct.

One really weird possibility would be that the file and the folders are all marked as "hidden", and you have the setting to not show hidden files in Explorer (which is the default). But I can't imagine hiding all files in the folder accidentally.

Either way, if the file really is there but it doesn't show up, the workaround is to enter (or copy/paste) the full path to module.ini into the "File name:" field at the bottom. Even if it doesn't show in the file browser, clicking "Open" will try to load that exact path.

 
Another thing that's really weird on your screenshot, is that the open file dialog only shows "Desktop" and "Favorites" in the pane on the left. Note how there's no drive letters, no "Documents" etc. Is that something that you have set up intentionally that way, or is it unexpected?
 
int19h said:
Are you sure that's the right folder? I mean, I'd expect it to have subfolders related to other things in the module (Data, Sounds, Textures etc) - and all folders always show up, regardless of the filename filter. This is what it looks like for me:
ewY1Npp.png


Can you check path on top of that open dialog? When you click on it, you should be able to copy-paste it, and open it in Explorer, to make sure it's correct.

One really weird possibility would be that the file and the folders are all marked as "hidden", and you have the setting to not show hidden files in Explorer (which is the default). But I can't imagine hiding all files in the folder accidentally.

Either way, if the file really is there but it doesn't show up, the workaround is to enter (or copy/paste) the full path to module.ini into the "File name:" field at the bottom. Even if it doesn't show in the file browser, clicking "Open" will try to load that exact path.
Sorry for the delay in response. I was trying to find the ini in the savegame folder that's why it didn't work  :facepalm:.

By analyzing my savegame i found:
It seems that the items (1819) alone are occupying 28MB of the 60MB file due to a unnecessary (probably) amount of slots. Each has 2048 slots.
Parties (2096 total) occupy 10.6MB.
Troops (3937 total) occupy 19.65MB

Most of the occupied space is due to slots.

I was surprised by the results. I was told that party positions occupied the most space. There's 5636 map tracks but they occupy only 135kb.

Do you know if the amount of slots that a object has is hardcoded? Or is it dependent on the highest assigned slot id?
Nevermind. I opened another mod's save and the slot amount was different.

I guess it's time to cut out the unused slots in my end.

wMtIs3u.jpg
Is this intended? I noticed the program is occupying 170MB by opening a 3.3MB file. Maybe this is the cause?




 
The way it computes the amount something takes on disk is basically by writing it into memory as if it were writing it to disk, and then seeing how many bytes that took. On top of that, the writing logic is validated when you open the save by immediately "writing" the whole save into memory, then comparing the result byte-by-byte with what was read from disk; if WarBender can't write your save out exactly like it read it, even if there's just a single byte difference, it's going to give you an warning and ask if you really want to open that save, given that you're likely to corrupt data if you then try to save it back. So I'm fairly confident that the numbers it gives are accurate.

That the app uses a lot of memory is also not surprising - it's rather profligate with it, on the basis that everybody has a lot of it these days. :lol: Just to give one example, the aforementioned procedure to "write" data into memory is also used to validate any changes that you make to properties - i.e. every time you edit some property or slot, the entire save is "written" into memory, validating all object references, collection sizes etc as it goes. To see this in action, try opening any faction, then opening its "relations" using the [...] button on the right side of value, then click "Add", and press "OK". You should get an error message. If validation wasn't there, you'd end up with a corrupt save, because every faction should have exactly as many entries in its relations as there are factions in total - no more and no less. There are a few other places where there are inter-related collections like that in the save, and all of them are checked.

The memory used for all this validation is then immediately discarded, so it's not really used. But since .NET is a garbage-collected runtime environment, in practice it's going to keep it around until it thinks it's low on memory - so it can show as using quite a bit, even though in practice most of that is ready to be garbage-collected. I was really, really paranoid about data corruption when writing that code (due to bad experiences with some save editors for other games ruining my saves), so this is the trade-off - it could be much faster and more lean memory-wise, but then if something goes wrong, you might end up with a broken save without noticing. For the same reason, there's no "Save", only "Save As", and even then it automatically backs up your save if you try to overwrite an existing file - and all backups have unique names, so it won't overwrite a backup, either. It also writes saves out by first writing them into a temporary file, then moving the old file (if any) to the temp directory, then moving the new file that it wrote into its proper place, then finally deleting the old file - so even if you did something crazy like pull the power cord while it was saving, you will have either the old save intact, or the new save intact, but you will never lose both.

The "Parent" and "Raw" properties is just a display bug for the slots collection that I've missed when I added SizeInBytes. They're computed properties that don't reflect anything on the disk - "Parent" is the object to which those slots belong, and "Raw" is the actual integer values for the slots - i.e. before they get interpreted as references to other entities, or flags. I think I'll actually keep "Raw" around, since it might be useful occasionally to be able to view the raw slot values as numbers - just add parens around it, so it'll be "(Raw)". And "Parent" shouldn't be visible at all. I'll fix both in the next release - thank you for reporting it! Either way, these things don't affect the byte count in any way, so don't worry about them

Now, as far as the problem with the size of your saves. That slots take up so much space is not surprising, if you have a lot per object - every slot is 8 bytes (64-bit integer), and then the length of the slots collection is itself 4 bytes (32-bit integer). So if you have 2k slots per item, then each item is 16 kilobytes just for the slots alone. So, with 1819 items, that's 1819 * (4 + 2048 * 8 ) = 29809772 bytes, i.e. 28.5 megabytes - sounds like what you're seeing. So far as I can see, in Native, items don't have any slots at all, which is probably why items don't usually come up as space-consuming. So I think your mod is special in that regard because it has slots on items, and conventional wisdom might simply not apply here.

On the other hand, map tracks are stored as five 32-bit floating point numbers each - 3 floats for X/Y/Z coordinates, 1 for angle of the arrow, 1 for age of the track - plus one 32-bit integer for flags (not sure what it stores there exactly, but presumably part of that is the party ID? I'll need to research it some day), and they don't have slots. So one track is 6 * 4 = 24 bytes, and 5636 tracks is 5636 * 24 = 135264 bytes, or 132 kilobytes. Again, sounds like what you're seeing.


 
Oh, sorry. My technical knowledge is lacking  :ohdear:

I had very impressive results by ordering my constants file by slot type, renumbering all the slots and removing unnecessary gaps. My vanilla warband mod save size decreased by 2MB, while the 1257AD start file size decreased to 24MB from 58MB! Most of the gains were with items, which decreased to 1.86MB from 28MB. They now have 128 slots each.

Thank you so much for this!
 
Glad to hear that it was useful! I hoped that the tool would come in handy for the modders as well, and not just to answer the age-old question of how to marry Matheld :wink: But the idea of save size optimization never occurred to me (to be honest, I didn't even think it was a problem!).

Let me know if there's anything else that might come in handy. Something that I've been thinking about is export/import of saves as XML files. Not sure how useful that is, but in theory, it would allow to load them into e.g. Excel, or even a full-fledged database, and then run fancy queries on it, for example. Another idea would be to run such XML through XSLT transforms - that could be used to e.g. convert save files between different incompatible mod versions, by adding/removing/reordering slots and other things as needed (although writing those wouldn't be easy!).

Also, would you be interested in working on .wmmx definitions for your mods, to incorporate directly in the app, like it has now for Native? (take a look at Modules\Native.wmmx to see what I mean). I've been thinking of trying to cover at least a few more popular and actively maintained mods out of the box. Had Viking Conquest tentatively marked as the first in the pipeline - but it sure would be faster and nicer all around to work on something with the author involved, since that removes a lot of guesswork!
 
int19h said:
Glad to hear that it was useful! I hoped that the tool would come in handy for the modders as well, and not just to answer the age-old question of how to marry Matheld :wink: But the idea of save size optimization never occurred to me (to be honest, I didn't even think it was a problem!).

1. Let me know if there's anything else that might come in handy. 2. Something that I've been thinking about is export/import of saves as XML files. Not sure how useful that is, but in theory, it would allow to load them into e.g. Excel, or even a full-fledged database, and then run fancy queries on it, for example. Another idea would be to run such XML through XSLT transforms - that could be used to e.g. convert save files between different incompatible mod versions, by adding/removing/reordering slots and other things as needed (although writing those wouldn't be easy!).

3. Also, would you be interested in working on .wmmx definitions for your mods, to incorporate directly in the app, like it has now for Native? (take a look at Modules\Native.wmmx to see what I mean). I've been thinking of trying to cover at least a few more popular and actively maintained mods out of the box. Had Viking Conquest tentatively marked as the first in the pipeline - but it sure would be faster and nicer all around to work on something with the author involved, since that removes a lot of guesswork!
1. In the moment: make the program open the module directory by default when needed, so people wouldn't need to search for the folder every time they open the program.

2. That would involve a lot of work. You would need the slot values from the author and also need to modify the file every time a new update comes through.

3. I can provide you the necessary files. But those will be of v2.1 which may release in a few weeks. Sadly i cannot add them myself. I do not have the time.

 
KratosMKII said:
In the moment: make the program open the module directory by default when needed, so people wouldn't need to search for the folder every time they open the program.

That should already be the case. When opening a save, the default folder is set to M&B Savegames in Documents. And if you need to locate module.ini (which is only needed when it can't guess the module from save folder), that dialog should open in the directory that contains module subdirectories by default - i.e. "Modules" under wherever M&B is installed, which it gets from the registry. Where does it open for you?
 
int19h said:
KratosMKII said:
In the moment: make the program open the module directory by default when needed, so people wouldn't need to search for the folder every time they open the program.

That should already be the case. When opening a save, the default folder is set to M&B Savegames in Documents. And if you need to locate module.ini (which is only needed when it can't guess the module from save folder), that dialog should open in the directory that contains module subdirectories by default - i.e. "Modules" under wherever M&B is installed, which it gets from the registry. Where does it open for you?
It opens the savegame folder again after selecting the save file to load.
 
To know where the Modules folder is, it needs to be able to locate the game install folder in the registry ("HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\mount&blade warband", key "install_path"). Do you have yours installed via Steam or GoG or something? Or is it just a folder that has been copied around across several Windows reinstalls?
 
Side note: it can be fun playing with the raw data to get visualizations. Here's a chart I've made of lords' relations with each other, about 300 days into my game (click to open a zoomable SVG).





For each lord node, its background color is their current faction, and its border color is their original faction. Lines between nodes indicate relation - lower than -10 for red lines, higher than +10 for green lines. The brighter a given line is, the stronger the relation. Nodes were automatically positioned so as to group friendly lords together, and put hostile lords apart.

As you can see, this still has six clear clusters of friends at the edges, and the main trait that lords in those clusters share is their original faction (I think in practice this actually rather correlates with families, since they don't straddle faction boundaries initially). And then in the middle you find the lords that are hated by everyone, and aside from a gaggle of debauched and quarrelsome lords, it also has all the kings.
 
Back
Top Bottom