Taking Questions about Mixintos and Overrides

If anyone has any questions about how to use mixintos or overrides, I’d be happy to collect (and maybe answer!) them in this thread. We’re so deep into the code that it’s a little hard for us to get perspective on what Tom’s post from a few weeks ago doesn’t explicitly cover.

If you’ve got success stories, please post them here too!

Frequently Asked Questions:

Q: What exactly, is a mixinto?
A: A mixinto lets you inject additional content into an existing .json file. (.json data files hold almost all of Stonehearth’s mutable gameplay parameters) The easiest use for this is to replace values defined in existing json. The more complicated (less documented, stable, and supported) use case is to add wholly new content to existing .json files. (This is dangerous because the format of those json files is not yet finalized, so the section you’ve modified may change or go missing.)

Q: What, exactly, is an override?
A: An override lets you replace any file in the game with another file. Use to replace assets with other assets. If you use this to replace code files with other code files, Team Radiant is not responsible for the results, or the mantainability of the edits going forward.

Q: Can you use mixintos to modify a .json array?
A: Yes. The modifications are added to the top of the array, though this may change in the future.

Q: How do I know what files are possible json targets for mixintos, and how do I reference them? Should I use their alias, or filename, or what?
A: See this post

Q: Will you replace the term “mixinto” with “extension”?
A: Maybe. If we do, it will just by a syntax change

Q: What does file(…) do?
A: file(…) is a shortcut that makes it “easier” to declare filepaths in json.

  • First, it appends the mod directory to the path in the parenthesis. As @RepeatPan mentions, file(/foo) is equal to /my_mod/foo
  • file() can also be used to append the path to the current directory: file(mystuff.json) is equivalent to /my_mod/path/path1/path2/mystuff.json
  • Finally, if the path inside a file() statement ends with a folder, and not a file with an extension, it will automatically append a file of the similar name.json to the path. For example, file(/stuff) becomes /my_mod/stuff/stuff.json

Q: How do I get a smaller world for testing?
A: Try adding this to your user_settings.json:

"mods" : {
   "stonehearth" : {
       "world_generation" : {"method" : "tiny"}
    }
 },

Q: Can I get trees to drop wool?
A: Yes! The resource_node determines what is dropped by a tree or plan when it is permanently harvested. Change the inside a tree.json (like, oak_tree.json) change the resource from stonehearth:oak_log to stonehearth:wool_bundle:

"stonehearth:resource_node": {
     "resource": "stonehearth:wool_bundle", 
     "durability": 20
 }

Q: Can you use mixintos for html code?
A: No

14 Likes

i’ll let the modding elite from our ranks take a first pass… but a little birdie reminded me of where this feature could be of use with the existing journal system… :smile:

i hope to get around to playing with this over the weekend, and will perhaps pose a question or two based on my progress (or more likely, lack thereof)…

thanks! :+1:

3 Likes

I’ll just say - I haven’t started modding because it’s not quite ready yet. Not a knock by any means, just don’t want to learn it twice. But I can’t wait for the conversation that should come out of this thread.

2 Likes

Oh me! I have a question! :smiley:

With mininto, does it overwrite the entire section it mixes? or does it add to it?
For example, it is possible to add tags to an item without deleting the tags already in place (original or other modder’s?)?
Same with the carpenter’s recipe list, is it possible to add to the list without re-writing the entire thing?

2 Likes

based on the blog, I would say no… but I’m curious as well:

Mixintos are used to modify or enhance the content in a mod. An override will completely overwrite that asset.

@chimeforest as far as I understand the mixintos are allowing you to “inject” code into existing files. You can use it to “overwrite” something which is already included in the file into which you are adding code. This is done simply by using the same names (e.g. for variables) and assign new values to them. But this is more a selective overwriting which comes in addition to adding code.

The overrides are really overwriting a whole file.

1 Like

@chimeforest, @SteveAdamo and @voxel_pirate are correct–Mixintos are purely additive.

A note of caution: mod loading is currently nondeterministic. That means that if 2 mods both override the same thing, or both specify mixintos that alter the same property, Stonehearth currently does not guarantee which one will take effect.

2 Likes

so, it’s basically n3rd Thunderdome… “two mods enter, one mod leaves!”

I’ve been rereading the blog post, getting geared up for (hopefully) some brief forays into mixinto programming this weekend!

@voxel_pirate asked on the blog about the namespaces and aliases we use in Stonehearth. Copy-pasting my reply in here:

The first goal of mixintos and overrides is to let people do qb-file swaps, and to manipulate the gross properties of the entities that define them, so that’s what is definitely supported (as per the example with the trees). This is all the team is currently officially ready to assure people is possible. :wink:

However, if you don’t mind playing in unstable territory, you CAN also use mixintos and overrides to do a wide range of things we’re only beginning to fully explore, up to and including replacing whole files of any type. (Given the currently fluid state of the Lua, this is like playing with gunpowder, from a stability POV. It is obviously not sustainable across releases.)

So what’s up with the mod:alias-syntax?

Every file in stonehearth has it’s hard-drive address. From the POV of loading resources referenced from json, this path is rooted in the mods folder. So the berry bush’s model’s full address is:

 "stonehearth/entities/plants/berry_bush/berry_bush.qb"

If you happen to be referring to an entity within your own mod (ie, the mod that the json file is a part of) you can use the file() syntax to automatically add the mod name. If the parent folder of a .json file is the same name as the .json file you want, you can also exclude the last part. So if you look at the manifest.json file for stonehearth, berry_bush.json can be addressed like this:

 "file(entities/plants/berry_bush)"

Usually, models are not aliased, because they are only used in the definition of the entity they belong to, which in this case, is lives in berry_bush.json.

Because we’re always moving files around, it’s very cumbersome to use the full address of a file when referring to it. So the manifest.json of any mod has an “alias” section into which you can just map names to files. stonehearth’s manifest.json describes berry bushes like this:

 "berry_bush" : "file(entities/plants/berry_bush)"

And if you ever need to refer to that berry bush, you can call it by using the name of its mod (stonehearth), plus the alias. So in lua, we do things like this all the time:

--In NewGameCallHandler, places a berry bush beside the camp standard"
self:place_item('stonehearth:berry_bush', camp_x, camp_z+3, 'civ')

So, how does this apply to mixintos? Most entities (things that appear in the game) are aliased, in stonehearth. So that’s why, if you want to mix into a berry bush, with a file you’ve specially prepared, your manifest will look like this:

 "mixintos" : {
      "stonehearth:berry_bush" : [
           "file(/entities/lantern/lit_bushes.json)"
      ]
  }

However, if the file you’re trying to mixinto IS NOT aliased by its mod (like the recipes file), you instead need to use its full path name (and then maybe let us know you’d really like it to be aliased). So if berry bushes weren’t aliased, the same line above would look like this:

  "mixintos" : {
        "stonehearth/entities/plants/berry_bush/berry_bush.json" : [
           "file(/entities/lantern/lit_bushes.json)"
        ]
  },

To figure out if you need to use an alias or the filepath to get to a file in Stonehearth, check the manifest.json file to see if it’s in there. If it’s not, then you’ll want to use the full path, and perhaps let Team Radiant know that there’s a desire for that file in the modding community.

4 Likes

What if we want to append something to a list? For example adding another model variant to a human without affecting what’s already there.

The file stuff is only there to load files from the mod it’s in as well right? That is it’s only function?

1 Like

So, the team is going to replace mixintos with extensions because mixintos sounds too cute.

The only proper way to do something like that would be to introduce magic keys à file() - for example, “append(models)” : [ “foo”, “bar” ] But that’s not really satisfying either. Or is it? Edit: Simply defining an array will merge them, although the order seems to be (mixinto, old values).

file() works relative to the mod if used absolute (i.e. file(/foo) is equal to /my_mod/foo) and relative to the current dictionary otherwise.

1 Like

Isn’t that the idea of Mixintos?

I don’t quite think so… at least not in the sense that @Xavion is describing.
Since since in the male1.json “model” is the section, and if you write a mixinto to try and add to it, It’ll just overwrite the whole “model” section. In order to include the original models they will have to be in the mixinto file.

However, if it was the case of adding a new recipe to the carpenters list, since there are multiple categories, one could make a new category and add your items to it without writing over the other categories.

@sdee, Did I get that right?

I will try this one out, but my understanding is that mixintos only overwrite if you use the same variables. So it should be possible to add into files.

See Stephanie’s comment above…

… are correct–Mixintos are purely additive…

Let me know what you discover.
I hope I’m wrong, but I don’t think I am =[

I’m pretty sure “model” is the variable he would have to mess with…

It is not. They are additive, sure enough, but they work on an extending mechanism. If you want to have it in pseudo-code, it would be something like

function mixin(original_json, mixin_json)
	for key, value in mixin_json do
		if type(value) == 'object' and type(original_json[key]) == 'object' then
			mixin(original_json[key], value)
		elseif type(value) == 'array' and type(orginal_json[key]) == 'array' then
			original_json[key] = table.join(value, original_json[key])
		else
			original_json[key] = value
		end
	end
end

That means that keys are either added or overwritten. Keys that do not exist yet will be created whereas existing keys will be completely overwritten with whatever the mixinto (or, in the old version - not sure if this has changed, I really hope it did - the mixin) defines.

So if you have model_variants.models and you have a mixinto that defines model_variants.models, the mixinto will overwrite it - because it’s an array and therefore cannot be merged.

So as long as you are dealing with just a single mod, you could just copy the original over, add your stuff and define the whole thing as a mixinto?

As long as only one mod is dealing with it, yes. If two mods try to access the same array, however, you get into trouble.

Of course one of those mods maybe stonehearth and if gets updated everything can break so it’s still kind of limited. What we really need is an append to list feature, a non-overriding form might be useful as well, so it can create new attributes but not change existing ones. It could probably have uses when dealing with multiple mods covering the same subject or people who have multiple parts to their mod and only need one, it would need a stable load order though so it would be pretty much useless so far.