stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

Oignontom8283

@Oignontom8283

Joined July 4th, 2026

  • 11Devlogs
  • 2Projects
  • 1Ships
  • 0Votes
Blåhaj !!!
Open comments for this post

31m 9s logged

MechanicaSaveFix, a BepInEx mod that replaces Mechanica’s save system with a single archive per world.

Demo video : https://youtu.be/NF6xDftQVgA

This isn’t my first time getting into this game! I’ve been trying things out, doing little tweaks, etc. on the game for years now. But this is my first and biggest completed project aimed at modding this game!

There are no resources online about the game’s structure, how it works, etc. So I spent way more time searching and understanding than actually coding! Working without documentation is really annoying :)

My goal here is to get a big Blåhaj! Will I pull it off? I don’t know…

The problem?
Mechanica saves every object, robot, weld, link, etc. into its own little file, stored in nested folders. A small test world already makes hundreds of folders, and large worlds reach thousands of files. On large worlds, you run into what I call “Infinite Save Loading” (ISL). The save never finishes, you have to restart the game, and you lose your progress. I suspect the number of files is the cause, but I haven’t proven it, because these freezes are very hard to reproduce.
However, during my testing, I didn’t have the issue. So at best, it improves things! Which is already pretty neat :3

What does the mod do?
The mod doesn’t rewrite the game’s save system, which wasn’t designed to be replaced. It sits on top of it:
It intercepts the game’s calls to files (File, Directory, FileInfo, DirectoryInfo) using Harmony;
It redirects them to a Virtual File System (VFS) that keeps everything in memory;
It then writes the result into a single .msa (Mechanica Save Archive) file, which is actually a zip containing the original files and folders.

The game therefore continues to believe it is writing thousands of small files, while it is actually writing only one file to disk. On the first save, a classic world is converted to .msa. The original folder is not touched, and you can extract the archive to get back a standard save.

I also rewrote the world selection menu (it lists classic folders and archives) and the world creation flow. I added a confirmation window, a config file, a backup system, and an optional update check.

Difficulties encountered:

  • No centralized save code. Every system (objects, robots, welds, storage, links…) reads and writes its files in its own way. There was no single place to hook into;
  • Incremental saving and cleanup. The game only rewrites what has changed, then deletes any file absent from its list of valid paths, compared as exact strings. The mod must therefore keep everything in memory and reproduce paths identically: mix of / and , case, spaces. Early on, a bug like this caused all files to be deleted by cleanup;
  • Not everything goes through File/Directory. Some parts of the code use FileInfo/DirectoryInfo, which had to be intercepted separately;
  • Implicitly created folders. The game checks for the existence of folders that are sometimes legitimately empty. After a bug where object categories were duplicated on every reload, I added explicit folder tracking in the VFS, with entries for empty folders in the archive;
  • A very tangled save menu. It relies on dictionaries indexed by UI objects, with a large part of the interface hardwired in the Unity editor, so invisible in decompiled code. I had to inspect the layout at runtime and rewrite the menu entirely;
  • Architecture issues. It took me a while to decide where to place the world swap function (it’s in the VFS).
  • I think I didn’t forget anything :/

Unfortunately, I admit, this is just a band-aid on a gaping wound. It only improves or at best delays the problem. Not to mention the fact that other things like the game’s multiplayer are still completely broken ¯_(ツ)_/¯

0
0
30
Open comments for this post

3h 51m 44s logged

v0.12.0

Version v0.11.0 introduced a system that checks the GitHub repository for new versions of the mod.As for

v0.12.0 … I ended up finding a bug that was causing certain item categories to be duplicated whenever a save was reloaded. I spent quite a bit of time tracking down the issue and fixing it, and it ended up requiring some fairly significant changes to the VFS.(Nothing too crazy, though. I basically just added explicit directory tracking so that empty directories are still properly preserved.)

Anyway, it works now! :3

0
0
14
Open comments for this post

7h 16m 40s logged

v0.10.0

There we go! The mod is technically functional and usable. All that’s left is getting other people to test it and adding a couple more things, like an update check, and that’s it (:

What’s changed:

  • Added a configuration file for the mod.
  • Added several features driven by settings from the configuration file.
  • Patched the new world creation menu to directly create a save in the new format.
  • Reorganized a good chunk of the code in the larger files (Utils.cs, VirtualFS.cs, SaveMenu.cs).

Progress so far:

  • ✅ VFS (Virtual File System).
  • ✅ Write the fake System.IO functions.
  • ✅ Write/Read the .msa (Mechanica Save Archive) file.
  • ✅ Intercepting the system functions.
  • ✅ Write the triggers that will fire the capture/emission of virtual files.
  • ✅ Add display/support for the new save format in the world selection menu.
  • ✅ Config file
  • ❌ [Optional] Fix non-blocking base-game load/save errors that clutter the console.
0
0
8
Open comments for this post

5h 38m 21s logged

v0.8.1

I thought this step was going to be simple… Not at all!
It’s been a nightmare of an ordeal. The save selection menu’s code (its logic) was basically one flat, tangled plate of spaghetti.

The base game used a bunch of dictionaries to store data and look it back up. The functions tied to the buttons used the Rect object handed to the class to look up the data they needed. Why hand over an object to look up data through a dictionary when you can just pass the function what it needs directly…
I completely rewrote the menu’s behavior from scratch, cleanly, to support displaying and loading saves in their new archive form.

What’s changed:

  • Rewrote the save selection menu so it lists both classic save folders and the new .msa archives side by side.
  • Added a proper confirmation popup (reused for save deletion, and reusable for anything else later) instead of the base game’s tangled state.
  • Rebuilt the difficulty settings screen flow so it works the same way whether the save is a folder or an archive.
  • Deleting a save now works for both save folders and .msa archives.
  • Fixed thumbnails not showing for saves without a screenshot.
  • Hooked up unloading the virtual file system when leaving a world, so you can load another world without restarting the game.
  • Squashed a good number of bugs along the way (mixed up path separators, wrong field types, missing state resets) that only showed up once real saves were being loaded and listed.

Progress so far:

  • ✅ VFS (Virtual File System).
  • ✅ Write the fake System.IO functions.
  • ✅ Write/Read the .msa (Mechanica Save Archive) file.
  • ✅ Intercepting the system functions.
  • ✅ Write the triggers that will fire the capture/emission of virtual files.
  • ✅ Add display/support for the new save format in the world selection menu.
  • ❌ Add a config file, [deinitialize the VFS on world exit - Early Done], and other minor details/improvements (new)
  • ❌ [Optional] Fix non-blocking base-game load/save errors that clutter the console.
0
0
21
Open comments for this post

7h 15m 16s logged

0.6.0

It wasn’t as simple as expected… But it works now!
You can load a normal world, and on the first save it will be converted into a .msa archive. From then on, whenever you try to load a world that has an archived version, that version will be loaded instead of the other one.

What’s changed:

  • Fixed VirtualFS incorrectly normalizing the root save path, which caused it to no longer match the paths built by the game itself, breaking file lookups everywhere.
  • Fixed QueryEntries not sanitizing multi-level directory paths, which caused Directory.GetFiles/GetDirectories to return nothing for nested folders (welds, anchors, etc.).
  • Fixed reconstructed paths mixing / and \ separators, which broke the game’s own string comparisons (e.g. RemoveOldFiles deleting everything instead of only orphaned files).
  • Added patches for DirectoryInfo/FileInfo instance methods (GetFiles, GetDirectories, CreateSubdirectory, Exists), which weren’t covered by the static File/Directory patches.
  • Simplified VirtualFS‘s internal mode from three states (Idle/Capturing/Playback) down to two (Idle/Intercepting), since capture and playback behaved identically from the interception logic’s point of view.
  • Wrote the Save()/LoadSave() coroutine wrappers that trigger the capture/playback cycle and commit/load the .msa archive.

Progress so far:

  • ✅ VFS (Virtual File System).
  • ✅ Write the fake System.IO functions.
  • ✅ Write/Read the .msa (Mechanica Save Archive) file.
  • ✅ Intercepting the system functions.
  • ✅ Write the triggers that will fire the capture/emission of virtual files.
  • ❌ Add display/support for the new save format in the world selection menu.
  • ❌ Add a config file, deinitialize the VFS on world exit, and other minor details/improvements (new)
  • ❌ [Optional] Fix non-blocking base-game load/save errors that clutter the console. (new)
0
0
11
Open comments for this post

55m 14s logged

v0.5.1

I added the Harmony patches to intercept System.IO functions. It was long and repetitive 👍.

What’s changed:

  • Add src\Patches\io\Directory.cs for the directory-related function patches.
  • Add src\Patches\io\File.cs for the file-related function patches.
  • Removed old test files for writing/reading files.

Progress so far:

  • ✅ VFS (Virtual File System).
  • ✅ Write the fake System.IO functions.
  • ✅ Write/Read the .msa (Mechanica Save Archive) file.
  • ✅ Intercepting the system functions.
  • ❌ Write the triggers that will fire the capture/emission of virtual files.
  • ❌ Add display/support for the new save format in the world selection menu.

The next step should let me run the first tests, which will probably be followed by some bug fixes. Hopefully not 🤞.

0
0
10
Open comments for this post

1h 57m 48s logged

v0.4.1

I almost went CRAZY 😰 I ran into an architecture problem, and I was about two steps away from refactoring EVERYTHING to make it clean. I finally found a solution. It’s not the cleanest, but I didn’t have any other idea. So the world-swap function lives inside the VFS. In the end it’s just a matter of roles/responsibilities, nothing technically blocking really 😅.

What’s changed:

  • Add method to write the VFS to a zip archive.
  • Add method to load a zip archive into the VFS.
  • Add method to replace the world’s save with the new one and move the previous version to backup.
  • Improved the versioning system, and included build info (hash, time…).

Progress so far:

  • ✅ VFS (Virtual File System).
  • ✅ Write the fake System.IO functions.
  • ✅ Write/Read the .msa (Mechanica Save Archive) file.
  • ❌ Intercepting the system functions.
  • ❌ Write the triggers that will fire the capture/emission of virtual files.
  • ❌ Add display/support for the new save format in the world selection menu.
0
0
1
Open comments for this post

1h 34m 11s logged

Mostly environment/tooling additions and improvements.

What’s changed:

  • Add build.yml GitHub CI, to verify that commits and PRs compile.
  • Add release.yml GitHub CI, to build and attach the mod to releases.
  • Minor tweaks to the build script.
  • Add a VSCode task to build the project without running a command.

Progress so far (so no changes here ¯_(ツ)_/¯):

  • ✅ VFS (Virtual File System).
  • ✅ Write the fake System.IO functions.
  • ❌ Write/Read the .msa (Mechanica Save Archive) file.
  • ❌ Intercepting the system functions.
  • ❌ Write the triggers that will fire the capture/emission of virtual files.
  • ❌ Add display/support for the new save format in the world selection menu.
0
0
6
Open comments for this post

57m 57s logged

I finished the Forward component, which faithfully reproduces every System.IO function (the functions used to interact with the computer’s file system).

Why? : I need functions with the exact same API, since I’m going to intercept the game’s disk read/write functions to stop it from writing thousands of small files and folders.

What’s changed:

  • Add VirtualFS.DeleteFile()
  • Add VirtualFS.DeleteFileNoThrow() (System.IO‘s Delete function doesn’t throw an error, unlike VirtualFS.DeleteFile(), so I made an alternative to properly mimic Delete’s behavior.
  • Add Forward.cs

Progress so far:

  • ✅ VFS (Virtual File System).
  • ✅ Write the fake System.IO functions.
  • ❌ Write/Read the .msa (Mechanica Save Archive) file.
  • ❌ Intercepting the system functions.
  • ❌ Write the triggers that will fire the capture/emission of virtual files.
  • ❌ Add display/support for the new save format in the world selection menu.
0
0
5
Open comments for this post

7h 44m 42s logged

I have to admit I’ve been working on reverse-engineering / decompiling this game for a long time now, so getting set up was pretty quick.

I established the mod/patch structure, refactored it, refactored it again, until I landed on my current plan.
Right now I’ve only written VirtualFS.cs, which contains the virtual file system that will intercept System.IO requests to prevent them from writing to disk.

Next I’ll move on to writing the fake System.IO functions (write a file, read a file, etc.), the functions that will write and read the save in .zip format, the patches for the system functions, the triggers, and finally the interface.

Progress so far:

  • ✅ VFS (Virtual File System).
  • ❌ Write the fake System.IO functions.
  • ❌ Write/Read the .msa (Mechanica Save Archive) file.
  • ❌ Intercepting the system functions.
  • ❌ Write the triggers that will fire the capture/emission of virtual files.
  • ❌ Add display/support for the new save format in the world selection menu.

Markdown checkboxes don’t work… so I’m using good old emojis instead. ¯_(ツ)_/¯

0
0
9
Open comments for this post

7h 23m 40s logged

First of all, I would like to point out that I spent a huge amount of time (which is therefore not accounted for here) thinking through the structure of the project, its features, and overall architecture.

I’ve set up the command-line arguments here. In THEORY, I haven’t forgotten any. But there are no guarantees, and I might change some of the formats in the future. (I ran some tests with libraries; that time is included here.)

Here is a (simplified) diagram of the code architecture.

0
0
26

Followers

Loading…