Modding:InheritFrom

From Vintage Story Wiki

This page was last verified for Vintage Story version 1.20.0-pre.13.


1.20.0 added the inheritFrom property for json files. This allows one json file to inherit the properties from another json file. Similar to json patching, the inheritFrom property should point to the json file that the current asset should inherit from. It may be prefixed with a game domain.

It is currently only used by "roughhewnfence-fsnow.json" in the base game. Here is how it inherits from the "assets/survival/blocktypes/wood/woodtyped/roughhewnfence-free.json" file.

{
	inheritFrom: "blocktypes/wood/woodtyped/roughhewnfence-free",
...
}

The inheritFrom property is supported on items, entities, and blocks. Recursive inheritance is supported (a file can inherit from a parent, which itself inherits from a grandparent).

Merging

The child file's json is merged with the parent file's json. If they both contain a dictionary property, then the entries in the dictionary are merged. Otherwise if they both contain the same integer/boolean/string/array property, then the child property replaces the parent property.

The following examples come from "roughhewnfence-fsnow.json" (the child), which inherits from "roughhewnfence-free.json" (the parent).

No child override

The parent has the class property.

	class: "BlockFence",

The child does not specify the class property. So the child inherits this field from the parent, for a result of:

	class: "BlockFence",

Child specifies new array value

The parent has this array value for the variantgroups property.

	variantgroups: [
		{ code: "wood", states: ["aged"], loadFromProperties: "block/wood" },
		{ code: "type", states: ["empty", "n", "e", "s", "w", "ne", "ns", "nw", "es", "ew", "sw", "nes", "new", "nsw", "esw", "nesw"] },
		{ code: "cover", states: ["free"] }
	],

The child has this replacement value:

	variantgroups: [
		{ code: "wood", states: ["aged"], loadFromProperties: "block/wood" },
		{ code: "type", states: ["empty", "n", "e", "s", "w", "ne", "ns", "nw", "es", "ew", "sw", "nes", "new", "nsw", "esw", "nesw"] },
		{ code: "cover", states: ["snow"] }
	],

Because arrays are replaced, the final value is the child's override. The parent's values are not merged in.

	variantgroups: [
		{ code: "wood", states: ["aged"], loadFromProperties: "block/wood" },
		{ code: "type", states: ["empty", "n", "e", "s", "w", "ne", "ns", "nw", "es", "ew", "sw", "nes", "new", "nsw", "esw", "nesw"] },
		{ code: "cover", states: ["snow"] }
	],

Child specifies new dictionary

The parent has this array value for the creativeinventory property.

	creativeinventory: { "general": ["roughhewnfence-*-ew-free"], "decorative": ["roughhewnfence-*-ew-free"] },

The child attempts to override it (as of 1.20.0-pre.13).

	creativeinventory: { },

However, creativeinventory is a dictionary. So the dictionaries are merged together. The child's override ends up doing nothing. This is the merged result:

	creativeinventory: { "general": ["roughhewnfence-*-ew-free"], "decorative": ["roughhewnfence-*-ew-free"] },

The only reason the "roughhewnfence-*-*-snow" blocks do not show up in the creative inventory (what the creativeinventory controls) is because the parent's wildcard does not match the child blocks.

Limitations

The inheritFrom processing is purely done at the JSON level. Notably it is done before the variant processing. So a JSON file can only inherit from another JSON file. It cannot inherit one registry object variant from a file. For example, "roughhewnfence-fsnow.json" cannot inherit from just the "game:roughhewnfence-aged-ew-free" block, but it does inherit from the "roughhewnfence-free.json" file that defines that variant.

When inheriting from a file in a different domain (for example a mod that inherits from a vanilla JSON file), for any asset properties, the domain defaults to the child's domain, even when parsing fields inherited from the parent file. For example, let's say "customfence.json" in "mymod" inherits from "roughhewnfence-free.json". Notice that the "game:" prefix is necessary to find the JSON file, because the default domain in "mymod:blocktypes/customfence.json" is "mymod".

{
	inheritFrom: "game:blocktypes/wood/woodtyped/roughhewnfence-free",
}

"roughhewnfence-free.json" points to the shape file "block/wood/fence/roughfence/empty". When the parent parses this property, the domain defaults to "game". So it correctly finds the "game:block/clutter/fence/roughfence/empty.json" shape file ("assets/survival/shapes/block/clutter/fence/roughfence/empty.json" in the game folder).

	shapebytype: {
		"*-empty-free": { base: "block/wood/fence/roughfence/empty" },
...
    }

However, when "customfence.json" tries to parse this, it instead tries to find "mymod:block/clutter/fence/roughfence/empty.json", which probably does not exist, and the mod's block has a red question mark.