Mods / Integrated Mod Manager
- Tags:
- Author:
- YangWenLi
- Side:
- Both
- Created:
- Sep 1st at 4:08 AM
- Last modified:
- Sep 10th at 3:10 PM
- Downloads:
- 13813
-
Recommended download (for Vintage Story 1.22.0-pre.1 - 1.22.7):
integratedmodmanager.zip 1-click install
⠀
What The Heck Is The Integrated Mod Manager?

The Integrated Mod Manager is a utility mod for modders.
Allowing you to skip writing UI code and instead make a simple Json file which will be used to automatically generate a config UI for you!
The process is entirely non-invasive, you don't need to change a single line of your mod's code, or even mark IMM as a dependency. You can pull the plug at any time, no vendor lock-in like with other config mods.
But why stop there? On top of configuration, IMM lets you define a list of known incompatible mods and define an automatic fix for them, meaning that your end-users won't nag you about a bug caused by two incompatible mods ever again!
You have full granular control, whether you want to simply check against a modID, or check for a generic detail such as whether or not a recipe exists to craft a certain item. Your enthusiasm is the limit.
On-board with the idea? Great, let's get you started.
{
// assets/examplecodemod/config/imm.json
"Configuration":
[
{
"ConfigFile": "examplecodemod/myconfig.json", // Your config file in the ModConfig folder
// You can use sraw strings or "domain:key" localization entries for just about every text display.
// Description fields support VTML. Clickable links can use handbook://, handbooksearch://, https://, etc.
"ConfigLabel": "Server gameplay", // This'd be a raw string
"Description": "examplecodemod:imm-server-desc", // Here be a key lookup for localization
"ConfigSource": "ModConfig", // Optional. ConfigSource dictates if we're reading/writing to ConfigFile or IMM's own internal storage for patch settings. ModConfig is the default, see the patch example for the other value and how to use it.
"ConfigSide": "Server", // "Server" (default) or "Client", this dictates if the config file is being edited on the server or in the client. You can overwrite this on individual settings.
"ParseDescriptions": false, // Optional. If your mod has (Settingname)Description fields, set this to true.
"Settings":
[
{
"Type": "Boolean",
"Label": "Enable feature",
"Description": "Turns the feature on or off.",
"Map": "Gameplay.EnableFeature", // Newtonsoft JPath into the config Json.
},
{
"Type": "String",
"Label": "Some Text",
"Map": "Gameplay.ServerTitle",
},
{
"Type": "Integer", // Int32-range
"Label": "Maximum count",
"Map": "Gameplay.MaxCount",
},
{
"Type": "Decimal", // Double
"Label": "Damage multiplier",
"Map": "Gameplay.DamageMultiplier",
},
{
"Type": "Slider",
"Label": "Spawn chance",
"Map": "Gameplay.SpawnChance", // Integer targets need whole-number Min/Max/Step, decimals may use fractions.
"Min": 0,
"Max": 1,
"Step": 0.05, // Optional, defaults to 1.
},
{
"Type": "Dropdown",
"Label": "Difficulty preset",
"Map": "Gameplay.Difficulty",
"Options":
[
{ "Label": "Easy", "Value": "easy" }, // ModConfig dropdown values must be any non-null primitive.
{ "Label": "Normal", "Value": "normal" }, // This means that instead of a string for a value, you can use numbers too if you want.
{ "Label": "Hard", "Value": "hard" }, // Labels can use localization keys too of course.
],
},
{
"Type": "Array",
"Label": "Allowed dimensions",
"Map": "Gameplay.AllowedDimensions",
"ElementType": "String", // Boolean | Integer | Decimal | String.
},
{
"Type": "Boolean",
"Label": "Client preview",
"Map": "Ui.EnablePreview",
"ConfigSide": "Client", // Overrides the block side for this setting.
},
],
},
// You can have more than one config file in case you prefer having one for the server and one for the client. Optional of course, you can have it all one big beautiful file if you want.
{
"ConfigFile": "examplecodemod/myclientconfig.json",
"ConfigLabel": "Client interface",
"ConfigSource": "ModConfig",
"ConfigSide": "Client",
"ParseDescriptions": false,
"Settings":
[
{
"Type": "Boolean",
"Label": "Compact HUD",
"Map": "Hud.Compact",
},
{
"Type": "Slider",
"Label": "HUD scale",
"Map": "Hud.Scale",
"Min": 0.5,
"Max": 2.0,
"Step": 0.1,
},
],
},
],
"Dependencies":
[
{
"ModId": "examplecodemod", // Applicability gate, if this mod is present, then we check the criteria. The game domain, or your own domain, both mean it'll always check.
"Label": "Required library is missing!!!", // As before, this can be a loc entry instead of a literal string.
"Description": "This feature requires Required Library.",
"Severity": "Error", // Warning | Error.
"Criteria": // Criteria types: Setting | GridRecipeCount | HasModID | CollectibleBehavior | CollectibleAttribute.
[
{
"Type": "HasModID",
"Operator": "Equal", // HasModID only accepts Equal, the issue activates when Value is missing.
"Value": "requiredlibrary",
},
], // Multiple criteria use an AND gate, not an OR gate. An empty list makes the gate alone activate the issue.
"Resolution": // Optional. If you want to provide a fix. Otherwise this becomes just an information warning/error.
{
"Type": "InstallMod", // SetSetting | InstallMod | RunCommand.
"ModId": "requiredlibrary",
},
},
{
"ModId": "otheroverhaul",
"Label": "Overlapping gameplay systems",
"Description": "Both mods currently enable the same system.",
"Severity": "Warning",
"Criteria":
[
{
"Type": "Setting",
"Target":
{
"ConfigFile": "examplecodemod/myconfig.json",
"Map": "Gameplay.EnableFeature", // You can supply the ModId of another mod for a domain, omitted means this descriptor's mod. A Setting target may instead use { "ModId": "...", "PatchSetting": "Code" }.
},
"Operator": "Equal", // Equal | NotEqual | GreaterThan | LessThan.
"Value": true,
},
{
"Type": "Setting",
"Target":
{
"ModId": "otheroverhaul",
"ConfigFile": "otheroverhaul/otherconfig.json",
"Map": "Features.EnableSameSystem",
},
"Operator": "Equal",
"Value": true,
},
],
"Resolution": {
"Type": "SetSetting",
"Target":
{
"ConfigFile": "examplecodemod/myconfig.json",
"Map": "Gameplay.EnableFeature",
// SetSetting targets may also use ModId + PatchSetting.
},
"Value": false, // Must match the setting's primitive type.
},
},
{
"ModId": "game",
"Label": "Duplicate grid recipe output",
"Description": "More than one enabled grid recipe produces this item.",
"Severity": "Warning",
"Criteria":
[
{
"Type": "GridRecipeCount",
"Output": "game:stick", // Explicit asset domain required.
"Operator": "GreaterThan",
"Value": 1, // Can never be negative
},
],
"Resolution":
{
"Type": "RunCommand",
"Value": "/examplecodemod fixrecipes", // You can send both client and server commands
},
},
{
"ModId": "game",
"Label": "Stick lost its ground-storage behavior",
"Description": "Checks whether a runtime item/block has a registered collectible behavior.",
"Severity": "Warning",
"Criteria":
[
{
"Type": "CollectibleBehavior",
"Target":
{
"Class": "Item", // Item | Block.
"Code": "game:stick", // Exact collectible code, explicit asset domain required.
},
"Behavior": "GroundStorable",
"Operator": "NotExists", // CollectibleBehavior accepts Exists | NotExists and omits Value.
},
],
},
{
"ModId": "game",
"Label": "Unexpected stick ground-storage rotation",
"Description": "Checks values stored inside a collectible's Attributes tree.",
"Severity": "Warning",
"Criteria":
[
{
"Type": "CollectibleAttribute",
"Target":
{
"Class": "Item", // Item | Block.
"Code": "game:stick", // Exact collectible code, explicit asset domain required.
},
"Path": "groundStorageTransform/rotation/y", // Uses the same IMM content-path syntax as content patches.
"Operator": "NotEqual", // Equal | NotEqual | GreaterThan | LessThan | Exists | NotExists.
"Value": -13, // Omit Value for Exists / NotExists. Comparison paths must resolve exactly one value.
},
],
},
],
}
{
// assets/examplecontentmod/config/imm.json
"Constants": { // Non-null JSON values, names may not collide with PatchSetting Codes.
"GlobalScale": 1.25,
"MaximumValue": 100000,
"ExtraDrop": { "type": "item", "code": "game:stick", "quantity": 1 },
},
"Configuration": [
{
"ConfigLabel": "Server content settings",
"ConfigSource": "PatchSettings", // Content mods can't make config files due to not having code, so IMM provides its own file. Omitts ConfigFile and ParseDescriptions.
"ConfigSide": "Server", // Server | Client
"Settings": [
{
"Type": "Boolean",
"Label": "Enable custom behavior",
"Code": "Enabled",
"Default": true,
"Targets": [
{
"Asset": "examplecontentmod:config/content.json", // Exactly one of Asset / AssetPattern
"Path": "enabled", // Exactly one of Path / Paths
"Operation": "Replace", // Replace | Append
"Timing": "Auto", // Auto | Early | BeforePatches | AfterPatches
"ResultType": "Auto", // Auto | Boolean | Integer | Decimal | String | Json
"Side": "Auto", // Auto | Both | Server | Client
"Optional": false,
// No Expression/Value means "use this owning PatchSetting"
},
{
"Asset": "examplecontentmod:config/content.json",
"Path": "traits",
"Operation": "Append",
"ResultType": "String",
"Value": "example-trait",
"Condition": "Setting", // Optional. The target only runs when this evaluates to true, false means the target is skipped completely.
"Optional": true,
},
],
},
{
"Type": "Slider",
"Label": "Durability multiplier",
"Code": "DurabilityMultiplier",
"Default": 1.0,
"Min": 0.25,
"Max": 4.0,
"Step": 0.25,
"Targets": [
{
"AssetPattern": "game:itemtypes/tool/*.json", // * wildcard, leading @ makes the whole pattern a regex.
"Path": "durability",
"Operation": "Replace",
"Timing": "Auto", // Auto classifies compatibility -> Early, patches -> BeforePatches, everything else -> AfterPatches.
"ResultType": "Integer",
"Side": "Server",
"Expression": "clamp(round(Current * Setting * Constants.GlobalScale), 1, Constants.MaximumValue)",
"Optional": true,
},
],
},
{
"Type": "Dropdown",
"Label": "Extra drop preset",
"Code": "DropPreset",
"Default": { "type": "item", "code": "game:stick", "quantity": 1 },
"Options": [ // PatchSettings dropdown values may be arbitrary JSON, not only primitives.
{ "Label": "Stick", "Value": { "type": "item", "code": "game:stick", "quantity": 1 } },
{ "Label": "Stone", "Value": { "type": "item", "code": "game:stone-granite", "quantity": 1 } },
],
"Targets": [
{
"Asset": "examplecontentmod:config/content.json",
"Path": "dropPreset",
"ResultType": "Json", // Implicitly replaces with the selected object
},
],
},
{
"Type": "Array",
"Label": "Allowed variants",
"Code": "AllowedVariants",
"Default": [ "normal", "rare" ],
"ElementType": "String", // Boolean | Integer | Decimal | String
"Targets": [
{
"Asset": "examplecontentmod:config/content.json",
"Path": "allowedVariants",
"ResultType": "Json",
},
],
},
{
"Type": "Integer",
"Label": "Bonus amount",
"Code": "BonusAmount",
"Default": 2,
"Targets": [],
},
{
"Type": "Decimal",
"Label": "Secondary scale",
"Code": "SecondaryScale",
"Default": 0.75,
"Targets": [],
},
{
"Type": "String",
"Label": "Display suffix",
"Code": "DisplaySuffix",
"Default": "reinforced",
"Targets": [
{
"Asset": "examplecontentmod:config/content.json",
"Path": "displaySuffix",
"ResultType": "String",
},
],
},
],
},
{
"ConfigLabel": "Client visual settings",
"ConfigSource": "PatchSettings",
"ConfigSide": "Client",
"Settings": [
{
"Type": "Boolean",
"Label": "Enable client visuals",
"Code": "ClientVisuals",
"Default": true,
"Targets": [
{
"AssetPattern": "examplecontentmod:shapes/*.json",
"Path": "clientVisualsEnabled",
"Side": "Auto", // Auto on a Client PatchSetting is client-only. Server PatchSettings/standalone patches run on both.
"Optional": true,
},
],
},
],
},
],
"ContentPatches": [
{
"Asset": "examplecontentmod:config/content.json",
"Path": "staticFlag",
"Operation": "Replace",
"Timing": "AfterPatches",
"ResultType": "Boolean",
"Side": "Both",
"Value": true, // Standalone patches require exactly one of Expression / Value.
},
{
"Asset": "examplecontentmod:config/content.json",
"Path": "drops",
"Operation": "Append", // Target must resolve to a JSON array, appends one evaluated JSON value.
"ResultType": "Json",
"Expression": "Constants.ExtraDrop",
"Condition": "Settings.Enabled", // Conditions are also valid on standalone ContentPatches; Setting itself is only available inside an owning Targets entry.
},
{
"AssetPattern": "@^game:config/weather.*\\.json$", // Regex form. Still needs an explicit domain in the pattern text.
"Paths": [ // Each path becomes its own binding.
"patterns/[*]/weight",
"events/[0]/weight",
],
"Operation": "Replace",
"Timing": "Auto",
"ResultType": "Decimal",
"Side": "Both",
"Expression": "clamp(Current * Settings.SecondaryScale, 0, 1000)",
"Optional": true,
},
{
"Asset": "examplecontentmod:config/content.json",
"Path": "entries/[code=rare]/weight", // Path segments: property, ["quoted"], [N], [*], [A..B], [$key=glob], [property=value]; ~1=/ and ~0=~.
"Operation": "Replace",
"Expression": "Enabled && Current > 0 ? max(Current + BonusAmount, 1) : 0",
"ResultType": "Integer",
"Optional": true,
},
{
"Asset": "examplecontentmod:config/content.json",
"Path": "[\"property~1with~1slash\"]/value", // Quoted property name; ~1 decodes to "/" and ~0 to "~".
"Operation": "Replace",
"Value": { "nested": [ 1, 2, 3 ] },
"ResultType": "Json",
"Optional": true,
},
],
// Expressions:
// refs: Setting (only inside owning Targets), Current/value, Settings.Name or ["Name"], Constants.Name or ["Name"], or bare setting/constant names.
// ops/literals: ! + - * / % == != < <= > >= && || ?: ; true false null pi e.
// funcs: if, not, and, or, greater, lesser, equal, notequal, sin, cos, abs, sqrt, ceiling, floor, exp, log, round, sign, clamp, max, min.
// patch value precedence: Expression, then Value, then the owning Setting. Standalone ContentPatches therefore require Expression or Value.
// Condition uses the same expression language and setting/constant references, but Current/value is forbidden because conditions run before asset/path resolution.
// A false Condition skips the binding entirely, it does not append null/false/[] or otherwise modify the asset.
"Dependencies": [],
}
{
// Advanced entries are for advanced types, and most mods will not need them. Unless you're a hardcore programmer. Otherwise ignore this.
// Structural Advanced types: Object | Dictionary | Array | Tuple. / Primitive leaves: Boolean | String | Integer | Decimal | Slider | Dropdown.
"Configuration":
[
{
"ConfigFile": "exampleadvancedmod/myconfig.json",
"ConfigLabel": "Advanced ModConfig example",
"ConfigSource": "ModConfig",
"ConfigSide": "Server",
"Settings":
[
{
"Type": "Advanced",
"Label": "Advanced gameplay rule",
"Map": "Gameplay.AdvancedRule",
"Advanced":
{
"Type": "Object",
"Columns": 2, // Object fields are laid out in this many columns when space permits.
"Fields":
[
{
"Key": "Enabled", // Exact JSON property name. Label/Description are display-only.
"Type": "Boolean",
"Label": "Enabled",
},
{
"Key": "Threshold",
"Type": "Decimal",
"Label": "Threshold",
},
{
"Key": "OptionalNote",
"Type": "String",
"Label": "Optional note",
"Optional": true, // Optional is only valid for Object fields and allows the property to be absent.
"Nullable": true, // Nullable allows an explicit JSON null value.
"InitialValue": "", // Used when IMM has to construct a missing/null value.
"ColumnSpan": 2,
},
{
"Key": "Tags",
"Type": "Array", // Advanced Array may contain any explicitly-described Advanced element type.
"Label": "Tags",
"ColumnSpan": 2,
"Element": { "Type": "String" },
"MaxItems": 16, // MinItems/MaxItems are optional on Advanced Array and Dictionary.
},
{
"Key": "Overrides",
"Type": "Dictionary", // JSON object with dynamic string keys sharing one Value schema.
"Label": "Per-item overrides",
"ColumnSpan": 2,
"KeyLabel": "Asset code",
// "KeyPattern": "^[a-z0-9_-]+:[a-z0-9_./-]+$", // Optional regex validation for dictionary keys.
"Value": { "Type": "Decimal", "InitialValue": 1.0 },
},
{
"Key": "Position",
"Type": "Tuple", // Fixed-length heterogeneous JSON array, unlike Array it has no add/remove controls.
"Label": "Position",
"ColumnSpan": 2,
"Items":
[
{ "Type": "Decimal", "Label": "X" },
{ "Type": "Decimal", "Label": "Y" },
{ "Type": "Decimal", "Label": "Z" },
],
},
],
},
// Undeclared properties already present in an Object are preserved when IMM edits the declared fields.
},
],
},
// PatchSettings can also do advanced stuff
{
"ConfigLabel": "Advanced PatchSettings example",
"ConfigSource": "PatchSettings",
"ConfigSide": "Server",
"Settings":
[
{
"Type": "Advanced",
"Label": "Per-item rules",
"Code": "ItemRules",
"Default": {}, // Default must conform to the explicit Advanced schema.
"Advanced":
{
"Type": "Dictionary",
"KeyLabel": "Asset code",
"Value":
{
"Type": "Object",
"Columns": 2,
"Fields":
[
{ "Key": "Enabled", "Type": "Boolean", "Label": "Enabled" },
{ "Key": "Multiplier", "Type": "Decimal", "Label": "Multiplier", "InitialValue": 1.0 },
],
},
},
"Targets":
[
{
"Asset": "exampleadvancedmod:config/content.json",
"Path": "itemRules",
"ResultType": "Json", // The whole structured Advanced value can be written as JSON.
// Expressions can reference an Advanced PatchSetting as a whole value, nested property access is not part of the expression language.
},
],
},
],
},
],
}
A mod can only have one imm.json, but you can include both config changes as well as patches, the examples were just kept separate to make them easier to read.
For code mods, you can optionally subscribe to imm.<modid> in order to reload setting changes live. Eg. api.Event.RegisterEventBusListener(myfunctionforlivereload, filterByEventName: "imm.mymodid");.
This mod is brought to you by...

The Unofficial Vintage Story Modding Co-op, click here to join.
As modders, we can help each other make even better stuff. Plus we have dedicated channels for better organization.
| Mod Version | Mod Identifier | For Game version | Downloads | Released | Changelog | Download | 1-click mod install* |
|---|---|---|---|---|---|---|---|
| 1.1.3 | integratedmodmanager | 10495 | Sep 10th at 3:10 PM | integratedmodmanager.zip | 1-click install | ||
|
* Setting to supress the first time nudge. Only when there are no errors or warnings. | |||||||
| 1.1.2 | integratedmodmanager | 988 | Sep 10th at 12:52 PM | integratedmodmanager.zip | 1-click install | ||
|
* Support for Stratum & Optimum backend criteria. | |||||||
| 1.1.1 | integratedmodmanager | 506 | Sep 8th at 7:29 PM | integratedmodmanager.zip | 1-click install | ||
|
* Support for advanced types (see documentation for examples). | |||||||
| 1.1.0 | integratedmodmanager | 280 | Sep 7th at 9:51 PM | integratedmodmanager.zip | 1-click install | ||
|
* New mod updater feature to update all your mods from within IMM. Includes automatic modes. | |||||||
| 1.0.5 | integratedmodmanager | 603 | Sep 6th at 10:19 AM | integratedmodmanager.zip | 1-click install | ||
|
* Dependencies can now check for Collectible Behaviours and Attributes. | |||||||
| 1.0.4 | integratedmodmanager | 383 | Sep 5th at 8:53 AM | integratedmodmanager.zip | 1-click install | ||
|
* Added a search bar to the config window. The visuals will be improved in an upcoming update, focusing right now on priority bugfixes and UX improvements. | |||||||
| 1.0.3 | integratedmodmanager | 331 | Sep 4th at 8:28 PM | integratedmodmanager.zip | 1-click install | ||
|
* Improved UI feedback for auto-resolved conflicts. | |||||||
| 1.0.2 | integratedmodmanager | 227 | Sep 4th at 7:40 AM | Release Retracted | |||
Retraction Reason:Crashes can occur under very specific circumstances. Please update to 1.0.3 to avoid headaches. Changelog:│ 1.0.2 │
│ 1.0.0 │ | |||||||






is there any way to block notifications? I keep getting "warnings" for missing dependancies relating to Aldi's Classes, but it is the addon patch mods that I am not installing, I don't see any way to stop these from showing up, and it is a small but annoying issue for me.
Using IMM you can navigate to IMM's own settings and tell it to not bother you with warnings.
I don't know if this has been suggested yet but when I'm configuring multiple mods having to reopen the imm menu every time with the chat command can become a bit cumbersome. I think there should at the very least be a setting to reopen the menu when you close a mod config.
I'll consider it. Until then, do know that pressing the up arrow with the chat open lets you send your last message again. So you press T, then up arrow, and then enter to basically re-open IMM in just three button presses.
You should implement a reset to default button for each mod when you'll have time.
It is in the bucketlist. Not yet been able to get ahold of that elusive time.
Just get into a temporal displacement or smtn smh.
Haha, I wish I could.
if i were to install this (and auto IMM) does that mean i can ditch config lib and imgui wholesale despite those being dependency mods for some?
If it's a hard dependency then no, the game enforces checks and enforces these before the mods even load. Auto IMM is for "Typed Configs" (meaning configs that have an actual code class associated with it, not the
configlib-patchesfile system that configlib has for content only mods) these generally don't have a hard dependency in the first place (meaning you didn't really need configlib for those in the first place).IMM doesn't read the
configlib-patches` file either to my knowledge so any content only mod with optional configlib support would still require configlib (or configkit) to actually use the config.hmmm, so that means mods that use configlib and imgui to change settings do not automatically get those same options with IMM... darnit... ah well. probably only a matter of time until most/all mods have switched to this improved system.
Perhaps try this: https://mods.vintagestory.at/autoimm it just came out.
i mentioned that in the very first comment haha.
i tried, but the game crashes if i ditch configlib, so there's definitely a couple mods that need it. and IMM can't configure things as well either for some reason unless the mod has explicit support where using autoconfiglib and imgui does have settings.
like i said, probably only a matter of time until most/all mods have switched to this improved system and "then" configlib+autoconfiglib+imgui will be completely obsolete. someday IMM+autoimm will be king i hope. or configkit takes over, who knows...
This mod is great and I love it. Thanks for making it!
Thank you <3
Is there a way for it to display automatically what the default value for a config is? I'm working on making this compatible with a mod I'm making and I was just wondering if there's a better way than manually typing what the default is on each config label
In theory the default should be displayed in the form of the original value written onto the file. But I do plan to add explicit defaults and per-setting value resets in the future (no timeline because my life is a real mess right now).
Got an odd error on the linux version where updating my mods just deleted them? I manually reinstalled most of them but now have an error showing that I'm missing an entity called entitypsagent so I'm kinda lost on what that may be.
If you could DM me your logs via discord or something I can have a look and see what's going on.
I'm trying to add compatibility, but I get "[Client Error] [integratedmodmanager] Failed to load forcegroundstorage:config/imm.json: Descriptor was empty." My JSON:
Thanks!
Is adding the IMM file the only change to the mod? I'd like to know that for testing purposes.
Also if this is meant to be a client-side setting, you might want to add "ConfigSide": "Client",.
That's correct, my mod was working as expected, I just wanted to add IMM compat. And it is a server-side setting (to me that means that the config loads inside Start, rather than StartClientSide. Correct me if I'm wrong).
I'll have a look later tonight and get back to you.
Hi, I tested the IMM you sent, exactly what you posted, and it works just fine. Maybe you put it in the wrong folder? Or forgot to save the file contents?
It should be at /modid/assets/modid/config/imm.json
Suggestions:
1. Add a button "Update all", so that we don't have to click every single mod to update.
2. Let the window automatically jump to the next mod which has not been updated yet, after a mod has been reviewed and updated manually.
I'll take note and see if I can squeeze it into one of the upcoming updates.
Setting SuppressFirstTimeNudges to true doesn't work
I'll test and see what's gone wrong. Mind tell me what the nudge looked like that you saw? Did it have a warning or error, or was it just the regular gray one?
1 error and 2 warning. It's just the optional dependencies for the Transport Tycoon mod which I don't want to install quite yet. It's the locust one that's marked as error, in case you were wondering.
Yep that's working as intended then. SuppressFirstTimeNudges does not tamper with errors and warnings. You can set the nudge behaviour to "first time only" and then it'll supress it even if there's warnings.
I was looking at adding the trains mod to a server but im unsure of exactly how to use this mod or what things it might change on the server for users. could i get a quick tldr on what i would need to do or look for if i were to go through with it?
Using this mod is just typing .imm in chat to open the menu, and use it to check if YTT is reporting any conflicts, missing dependencies, or other issues. You can also use it to configure values like how fast fuel burns.
Okay i gave it a shot to test it out. I assume the W and E filters are for Warning and Errors? Also if i use it to update mods does it update them for the server or client only?
W and E are filters indeed. The mod updater will update on the server.
Looking at adding this to my long term server - does it allow for upgrading to the highest mod version that supports x game version? the server is currently on 1.22.5 and with 200+ mods it's a little hard to keep track of :D Cheers!
IMM is already tuned to look for the highest version that the server can handle, so it won't try to install mods that aren't compatible with your game version.
You are a gentleman and a scholar, ty! Will be adding this in in a few minutes!
maltiez found slumped over behind burger king dumpster
How does this perform on rather... extensive modlists?
Pretty well, particularly since right now most mods with IMM's haven't updated yet to include them
NGL This is terribly simple to integrate. Maybe I should change that patch I made to be able to toggle anything in the YTT and be able to be configured through IMM
Sure, go ahead 🤠
Any way to dissable the box appearing in the top left on world load?
Should only show up once per world, will be adding an option to disable it entirely soon.
Where can I find this elusive option to disable it?
.imm command, then select IMM, and select nudge mod for first time only, then toggle the setting that says to hide the first time nudge.
Done :D
Yippee!, now make worms hostile and chase you around
Does it support, or are you planning support for modlists per save file? That is the biggest issue I have with managing mods, remembering whish save used which combo.
Nope, mod management like that is outside of what mod code is allowed to do. I will say that from what I hear the vanilla game might support this soon anyway.
That sounds awesome
You can make copies of the game's shortcut with alternate data paths to use different mod lists and save files without having to do switcherous all the time.
Go to your shortcut -> Properties -> Target
After the blah\blah\blah\VintageStory.exe
add
--dataPath "whatever the path is to a folder you have created"
when you run that shortcut it will not use the VintageStoryData folder in your AppData, and will instead use the folder whose path you specified.
That is awesome to know, thank you!
Request to make it possible to only be able to open it for admins/creative mode?
I don't want people on server try to mess with things or abuse stuff.
Already admin only. Clients can only see client-side configs. If you are experiencing otherwise, tell me which mods are involved and I'll try to find out what's going on.
sorry if this is a silly question but how do I open it ingame? When I first opened a world with it installed it came up with a window with conflicts, and I've resolved them, but now I'd like to try the new auto-update feature but I can't see how. Thanks! :)
Type .imm in chat
thank you! i think i must've tried /imm, i was so close!
Hey what program do you use for you thumbnail art
I thought my mom was the only person to use this programm in this planet
Now all it needs is to tell you if a mod needs an update lol
I can probably add that functionality in tbh. Added to my todo list.
Done :)
Thank you milkmaster
cool! thank you for the easy guide/example
added to grassroots mods, ty for this mod the UI is pretty i like seeing the modicons
<3
Newest update fixed my crashes with world editting. Thanky you! :D
Very interesting
Hello Galadorion and Bonmpa, I've just published version 1.0.4 which is sure to fix the issue for certain. It'll repair the econding issues on the save file just load the world, save, re-start the game, and it'll work.
I've re-created this locally and tested it a few times and it seems to work reliably.
Thank you both for your patience in this.
Hi,
After repleacing new file and following instructions everything works perfectly !
Thank You ! :D
Hi,
Yeah everything works just fine with that update now, Thanks!
Hi,
I have same issue as Bonmpa. While trying to click world edit I got crash. Also after new version of mod .
Here is raport:
Does this happen on new worlds or only on older ones?
Any chance you could do something for particles plus. Its the only mod i Have that uses imgui/configlib. I don't know if they are still active but I haven't seen anyting from them yet.
I can make the file need for IMM to work with the mod on behalf of the author, but ultimately they have to make the decision to include it in the mod. If you get them to agree, sure!
They said no. Didn't want to do anyting for a mod only 4 days old. Brining it up becasue i wanted to make sure IMM won't cause any conflicts with ConfigLib if I have both installed.
IMM is safe to use alongside ConfigLib, and soon ConfigKit.
Oooh, let me know what I need to do to get my mods working with this!
All it takes is making a imm.json file similar to how config lib has a config file. In the desc I have a full example (split into two for readability).
I'll make one for a couple of your mods and send them to you via discord, they should make it easy to figuire out the rest.
For some reason every time i`ll try to edit my existing world the game crashes and this mod is the culprit.
Looking into it right away.
I think I found the cause. Gone head and published an update, please let me know if this fixes it.
Unfortunately, I'm getting the same crash and the newest update you pushed did not fix it. :(
Edited multiple times cause formatting issues, and pasting issues.
at Newtonsoft.Json.JsonTextReader.ParsePostValue(Boolean ignoreComments)
at Newtonsoft.Json.JsonTextReader.Read()
at Newtonsoft.Json.Linq.JContainer.ReadContentFrom(JsonReader r, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JContainer.ReadTokenFrom(JsonReader reader, JsonLoadSettings options)
at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JToken.ReadFrom(JsonReader reader, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JToken.Load(JsonReader reader, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JToken.Parse(String json, JsonLoadSettings settings)
at Newtonsoft.Json.Linq.JToken.Parse(String json)
at Vintagestory.Common.WorldConfig.loadFromSavegame(SaveGame savegame) in VintagestoryLib\Common\Config\WorldConfig.cs:line 61
at Vintagestory.Client.GuiScreenSingleplayerModify.initGui(SaveGame savegame) in VintagestoryLib\Client\MainMenu\Screens\Singleplayer\GuiScreenSingleplayerModify.cs:line 51
at Vintagestory.Client.GuiScreenSingleplayerModify.OnScreenLoaded() in VintagestoryLib\Client\MainMenu\Screens\Singleplayer\GuiScreenSingleplayerModify.cs:line 174
at Vintagestory.Client.ScreenManager.LoadScreen(GuiScreen screen) in VintagestoryLib\Client\ScreenManager.cs:line 999
at Vintagestory.Client.GuiScreenSingleplayer.OnClickCellRight(Int32 cellIndex) in VintagestoryLib\Client\MainMenu\Screens\Singleplayer\GuiScreenSingleplayer.cs:line 172
at Vintagestory.API.Client.GuiElementMainMenuCell.OnMouseUpOnElement(MouseEvent args, Int32 elementIndex) in VintagestoryApi\Client\UI\Elements\Impl\Misc\GuiElementMainMenuCell.cs:line 321
at Vintagestory.API.Client.GuiElementCellList`1.OnMouseUpOnElement(ICoreClientAPI api, MouseEvent args) in VintagestoryApi\Client\UI\Elements\Impl\Interactive\GuiElementCellList.cs:line 242
at Vintagestory.API.Client.GuiElement.OnMouseUp(ICoreClientAPI api, MouseEvent args) in VintagestoryApi\Client\UI\Elements\Impl\GuiElement.cs:line 743
at Vintagestory.API.Client.GuiComposer.OnMouseUp(MouseEvent mouse) in VintagestoryApi\Client\UI\GuiComposer.cs:line 448
at GuiScreen.OnMouseUp(MouseEvent e) in VintagestoryLib\Client\MainMenu\Screens\Special\GuiScreen.cs:line 206
at Vintagestory.Client.ScreenManager.OnMouseUp(MouseEvent e) in VintagestoryLib\Client\ScreenManager.cs:line 944
at Vintagestory.Client.NoObf.ClientPlatformWindows.Mouse_ButtonUp(MouseButtonEventArgs e) in VintagestoryLib\Client\ClientPlatform\Input.cs:line 217
at OpenTK.Windowing.Desktop.NativeWindow.OnMouseUp(MouseButtonEventArgs e)
at OpenTK.Windowing.Desktop.NativeWindow.MouseButtonCallback(Window* window, MouseButton button, InputAction action, KeyModifiers mods)
--- End of stack trace from previous location ---
at OpenTK.Windowing.Desktop.NativeWindow.RethrowCallbackExceptionsIfNeeded()
at OpenTK.Windowing.Desktop.NativeWindow.ProcessWindowEvents(Boolean waitForEvents)
at OpenTK.Windowing.Desktop.GameWindow.Run()
at Vintagestory.Client.ClientProgram.Start(ClientProgramArgs args, String[] rawArgs) in VintagestoryLib\Client\ClientProgram.cs:line 354
at Vintagestory.Client.ClientProgram.<>c__DisplayClass10_0.<.ctor>b__1() in VintagestoryLib\Client\ClientProgram.cs:line 131
at Vintagestory.ClientNative.CrashReporter.Start(ThreadStart start) in VintagestoryLib\Client\ClientPlatform\ClientNative\CrashReporter.cs:line 95
Followed with great interest! 👀 May your Drifters forever be milkable.
Followed. We will watch your career with great interest. Also thank you for creating an alternative as the more the better.
Thank you, Chad.
the goat 🥹
<3
I'll be the first to comment just to say that YES a search bar is planned. I just didn't get around to it. I promise it'll be added soon, just want to make sure I code it right.