Contains executable files or external scripts. Ensure you trust the creator and apply your own security measures.
Drop a .var, .vaj, or folder — every item gets your plugin auto-loaded in VaM.
Plugin Injector is a Windows desktop tool for VaM creators who package hair or clothing as
What it does for every item it processes
Useful when your hair pack depends on a custom shader, when your clothing needs a specific physics or material plugin to look right, or any time you would rather have "load look, plugin runs" than tell users to install something separately.
The window has three action cards (Inject Plugin, Fix for Release, Fix Item Gender), a plugin selector row up top, a drop zone, and the VaM Root setting tucked under a collapsible section.
Install
First-time setup: VaM Root
Click the VaM Root header to expand it, then drop your VaM folder (the one with
What this is for: when you later run Fix for Release, the tool walks your disk looking for
If your
The Inject Plugin and Fix Item Gender flows do not use this at all. They work the same whether VaM Root is set or empty.
Settings persist across runs, including your saved plugin presets and which one is active.
Other header buttons
Main workflow: Inject Plugin
1. Set up your plugin
Drop your plugin onto the top Drop to load plugin zone. It takes
Save it as a named preset using the disk icon next to the input. Once saved, you can grab it later from the PRESETS dropdown.
2. Drop a target onto Inject Plugin
Drop a target onto the Inject Plugin card. Three input types are accepted:
The toolbar gives you:
The action bar at the bottom shows Inject into N files.
3. Inject
Click Inject into N files. The file list is replaced by a result panel that reports what happened to each
For each
Headline (top of the per-file card):
Sub-notes (under the headline):
And one final line per package: Package saved. (logged against
4. Where the output goes
The new
Drop the new file into VaM's
5. History
The History panel keeps every inject and fix run as a session you can expand. Handy when you want to look back and check what you did to which package.
The trash icon at the top wipes everything. Expanding a session brings back the per-file detail.
The other two cards
Fix for Release
Drop a
Output lands in the same
Fix Item Gender
Drop a
Common errors
Common errors and fixes
Notes
Credits
Plugin Injector is a Windows desktop tool for VaM creators who package hair or clothing as
.var files. It bakes a plugin preset into your package so that whenever a user loads your item, the plugin is already attached with the parameters you set. Nobody has to touch the Plugins tab.What it does for every item it processes
- Makes sure the
MVRPluginManagercomponent is listed in the item's.vaj, adding it if it is missing. - Adds or updates a plugin storable in the
.vajwhoseidis the item's own UID (read from the matching.vam) for clothing, or the hard-codedCustomScalpid for hair. The storable'splugins.plugin#0field is set to your plugin path. - Saves the modified package as a new
.varinside aPluginInjectorFixed/subfolder. The original file is left alone.
Useful when your hair pack depends on a custom shader, when your clothing needs a specific physics or material plugin to look right, or any time you would rather have "load look, plugin runs" than tell users to install something separately.
The window has three action cards (Inject Plugin, Fix for Release, Fix Item Gender), a plugin selector row up top, a drop zone, and the VaM Root setting tucked under a collapsible section.
Install
- Download the attached
plugin-injector.zipand extractplugin-injector.exefrom it. - Put the exe anywhere. Single-file Tauri build, no installer, no extra DLLs.
- Double-click to run.
First-time setup: VaM Root
Click the VaM Root header to expand it, then drop your VaM folder (the one with
VaM.exe and AddonPackages\ in it) onto the input. Typing or pasting the path works too.What this is for: when you later run Fix for Release, the tool walks your disk looking for
.clothingplugins preset files that match the plugins inside the package, and bundles the matches into the output. The lookup is rooted at this path. For each .vaj in the package at, say, Custom/Clothing/Female/lulu/myitem/, it checks <VaM Root>/Custom/Clothing/Female/lulu/myitem/ on disk.If your
.var already lives inside your VaM install (a .var under AddonPackages\), the tool auto-derives the root by walking up to find a Custom/ folder, so you can usually leave this empty. Set it explicitly when you process .var files from outside your VaM tree, for example a build or dist folder.The Inject Plugin and Fix Item Gender flows do not use this at all. They work the same whether VaM Root is set or empty.
Settings persist across runs, including your saved plugin presets and which one is active.
Other header buttons
- Dark / Light: theme toggle.
- History: side panel with past inject and fix runs.
- Pin: keep the window on top while you work in VaM.
- 中文 / EN: UI language.
Main workflow: Inject Plugin
1. Set up your plugin
Drop your plugin onto the top Drop to load plugin zone. It takes
.cs, .cslist, or a .var that contains plugins. There is also a SRC field on the right if you would rather paste a path.Save it as a named preset using the disk icon next to the input. Once saved, you can grab it later from the PRESETS dropdown.
2. Drop a target onto Inject Plugin
Drop a target onto the Inject Plugin card. Three input types are accepted:
- A packaged
.var— the tool reads every.vajinside. - A loose
.vajfile — processed directly. - A folder — every
.vajfound inside (recursively) is processed.
The toolbar gives you:
- Select all / None to flip everything at once.
- A Clothing / Hair filter to narrow by category.
- Clicking a single row to toggle just that entry.
The action bar at the bottom shows Inject into N files.
3. Inject
Click Inject into N files. The file list is replaced by a result panel that reports what happened to each
.vaj. These are the same messages that end up in the History panel.For each
.vaj you will see one headline plus a couple of sub-notes:Headline (top of the per-file card):
- Injected successfully. — the
.vajwas actually changed. - Already up to date. — nothing needed changing. This is what you see on a clean re-run with the same preset.
Sub-notes (under the headline):
- Added MVRPluginManager component. — the item did not have it yet.
- MVRPluginManager component already present. — the item already had it.
- Added plugin storable. — no existing storable for this plugin, a fresh one was added.
- Updated existing storable. — a storable was there but with different parameters; it got overwritten. This is a real change, not a no-op.
- Storable ID & plugin path are correct. — existing storable matched exactly, left alone.
- Fixed JSON formatting (trailing commas removed). — the original
.vajhad non-strict JSON that got cleaned up while being rewritten.
And one final line per package: Package saved. (logged against
Author.Package.Version.var)4. Where the output goes
The new
.var is written to a PluginInjectorFixed/ subfolder next to the original. So if you drop F:\my-stuff\lulu.fgqy.1.var, you get F:\my-stuff\PluginInjectorFixed\lulu.fgqy.1.var. Same filename, same Author.Package.Version. The original is not touched.Drop the new file into VaM's
AddonPackages\ to test, or share it directly.5. History
The History panel keeps every inject and fix run as a session you can expand. Handy when you want to look back and check what you did to which package.
The trash icon at the top wipes everything. Expanding a session brings back the per-file detail.
The other two cards
Fix for Release
Drop a
.var onto this card before you publish. It does two cleanup passes:- Namespaces every
Custom/*path in.vajand.vapfiles toAuthor.Package.latest:/Custom/*. Skip this and the package will quietly fall back to the user's localCustom/folder, which breaks for anyone who does not happen to have the same files already installed. Note the.latestpart: the rewrite always useslatest, never the exact version number from the filename. That way, when you ship version 2 of the package, existing references still resolve to whichever version the user has installed. - Bundles any
.clothingpluginspreset files it finds on disk that reference plugins already used in the package's.vajfiles. The disk lookup is rooted at the VaM Root setting (see First-time setup). The summary at the top of the result panel always echoes which root was actually used, so you can verify it was the one you expected.
Output lands in the same
PluginInjectorFixed/ subfolder.Fix Item Gender
Drop a
.var (or a folder) here to fix the itemType field inside .vam files so it matches the gender of the directory it lives in (Female or Male). The case that bites people: an item ended up in the wrong gender folder during export, and now VaM's category filter is hiding it.Common errors
Common errors and fixes
| Message | Cause | Fix |
|---|---|---|
Invalid .var filename: expected Author.Package.Version | File is not named Author.Package.Version.var | Rename to VaM's convention before processing |
Cannot open .var: / Couldn't open .var file. | File is locked, missing, or unreadable | Close VaM (it might be holding the file), then check the path |
Cannot read .var as zip: / Couldn't read .var as ZIP. | Not a valid zip, or corrupt | Re-export the .var from VaM's Package Builder |
No .vam file found in <path> | Package contains no recognized hair or clothing .vam | Wrong package type. The tool only handles hair and clothing |
Not a hair/clothing .vam — skipped. | The selected item is not hair or clothing | Pick a different item |
No "storables" array in .vaj. | The .vaj is malformed (missing a required field) | Re-save the item in VaM to regenerate a valid .vaj |
Invalid .vap file. / Missing "storables" property. | The preset file is broken, or was not saved from VaM | Re-save the .vap from the item's Plugins Preset tab |
Invalid UTF-8 in .vap / .vam / .clothingplugins. | File contains non-UTF-8 bytes (rare, usually a bad text editor) | Re-save from VaM, or convert to UTF-8 without BOM |
Couldn't serialize .vam. / Couldn't write .vap / .vam file. | Disk write failed | Check disk space and write permissions on the output directory |
Couldn't create output directory. / Couldn't create output .var. / Failed to finalize output .var. | Output cannot be created | Check write permissions, or try a different output location |
Failed to inject plugin. / Injection failed. | Generic injection failure | The real reason is on the line above this one. Read that |
Failed to process .vaj. | One specific .vaj blew up mid-process | Other items in the package still finish. Inspect that one .vaj |
Skipped — id does not match any storable/plugin in .vaj files. | The targeted id is not in any .vaj | Check the preset was saved against the same item you are injecting into |
Couldn't read .clothingplugins. | An existing .clothingplugins inside the package is malformed | Open the package, delete the bad .clothingplugins, retry |
Cannot determine config directory | The app cannot find a writable settings folder | Run as the same Windows user that owns VaM. Check %APPDATA% access |
Notes
- The original
.varis never modified. Output always goes into aPluginInjectorFixed/subfolder next to the source. - Running it twice on the same package with the same preset is a no-op. The headline becomes Already up to date. and nothing is written into the storable. Updated existing storable. means something actually changed (the storable was there but with different parameters and got overwritten), so use that as a signal that this re-run was not idempotent.
- The plugin code still has to ship somewhere. The injector adds a reference, not the code itself. The
.csor.cslistshould be inside the same.var(best), or in a dependency.varthe package references. - The VaM Root setting only matters for namespacing. The inject flow works fine without it.
Credits
Contains executable files or external scripts. Ensure you trust the creator and apply your own security measures.