Virtual File System (VFS) is a lightweight C# framework that creates an in-memory virtual file system by merging folders and zip-archives in order, forming a unified hierarchy that overrides identical paths - ideal for seamless modding, DLC, and game content expansions.
$ dotnet add package TrimKit.VirtualFileSystemAs the name implies Virtual File System (VFS) is a framework to create a virtual file system which allow you to include ("mount") several folders or zipped archives in a specific order merging their file structure and creating a unified file hierarchy while (virtually) overriding any files that have the same paths.
It could be used as a basis for modding/DLC/addon system in your game where you (or people modding your game) can override existing files of the base game with updated versions or add new files into the existing hierarchy seamlessly.
Note on file overridding: if you include "mod1" that contains "folder1/file1.txt" and then include "mod2" which contains a different file but with with the same path "folder1/file1.txt" it will then be overriden since mod2 was included after mod1. Similar approach to modding is actually already present in a large number of games. Additionally, as stated above this approach can also be used not only for modding, but to allow loading of additional content (e.g. DLC) or any other extra data into the game.
Virtual File System supports both: folders and zipped archives, and is developed in pure C# with no external dependencies.
The goal of this framework is to make adding mod support to games as easy as it can possibly be. It offers a clean, minimalist, and fully documented API that is easy to learn and use.
Use provided nuget package or download the source.
:wrench: dotnet add package TrimKit.VirtualFileSystem
First, create a new vfs container and add any number of root folders (at least one is required).
// Create VFS and include several root containers
var vfs = new VFSManager();
vfs.AddRootContainer("Data/ModFolder1"); // folder with the name "ModFolder1"
vfs.AddRootContainer("Data/ModFolder2"); // folder with the name "ModFolder2"
vfs.AddRootContainer("Data/Mod3.pak"); // zip archive with the name "Mod3.pak"
Next... well, that's it! Now you can read files from the VFS as needed :)
// check if file exists
bool fileExists = vfs.FileExists(virtualPath);
// check if folder exists
bool folderExists = vfs.FolderExists(virtualPath);
// get file stream
Stream stream = vfs.GetFileStream(virtualPath);
// get all contents of the file as byte array
byte[] content = vfs.GetFileContents(virtualPath);
// or if it's a text file - get the text directly
string text = vfs.GetFileContentsAsText(virtualPath);
// you can get a list of all entry paths (virtual files)
List<string> allEntries = vfs.Entries;
// you can get a list of all folders
List<string> allFolders = vfs.Folders;
// you can also get all files in a specific folder
List<string> filesInFolder = vfs.GetFilesInFolder(virtualPath);
// same as above, but you can also filter by extension
List<string> filesInFolderWithExtension = vfs.GetFilesInFolder(virtualPath, "txt");
// in case you need FileInfo equivalent - it's there too. Inside are things like Name, Extension, Size, ContainerType, etc.
VirtualFileInfo fileinfo = vfs.GetFileInfo(virtualPath);
// ...and there are a few more functions you can call.
You can automate packing folders into VFS-compatible zip archives in your build script and use the resulting file in your application.
Additionally, you can also includes optional per-file obfuscation when packing. It's not a proper cryptographic encryption, but rather a simple obfuscation step which can deter casual inspection of packed assets.
// pack a folder into a single file usable with VFS
VFSManager.PackFolder("C://Path/to/Data/Folder/", "OutputFile.pak");
// the same, but with optional obfuscation
VFSManager.PackFolder("C://Path/to/Data/Folder/", "OutputFile.pak", "Password");
The library is very minimalist internally, so the overhead compared to just reading files from the disc or Zip archive directly is basically zero.
This library is part of the TrimKit collection - a set of small, focused C# libraries that make game development more enjoyable by reducing the need for boilerplate code and providing simple reusable building blocks that can be dropped into any project.
Each module is independent and can be used standalone or combined with others for a complete lightweight foundation.
Contributions are welcome!
You can start with submitting an issue on GitHub.
This library is released under the MIT License.