Desktop Tuesday, a peek inside the modding API

Hi guys. W’e’re just a few weeks into Alpha, but some of you are already going hog wild producing mods. That’s great, but there’s a downside. Our modding APIs are still very much in flux, so our poor modders are having to guess at which parts of the interface are meant for modding, and which ones should be hands off.

In the next release, we’ll start the process of exposing and documenting the more solidified modding interfaces. Here’s a sneak preview of how we will address one of the more immediate modding concerns: how to get your content into the game without hacking up the default Stonehearth mod.

Note: This is the way things will work in the next Alpha release (next week? maybe later…). If you’ve already been modding, you may notices some discrepancies with the way things work today. The stuff in here is correct (or rather, will be, when the next release is out 😉

How Mods are Written Today

First, a quick explanation of how modders are changing the game today. The Stonehearth game content is stored in the “stonehearth.smod” file in your installation directory. This is just a renamed zip file. You can unzip it and get a peek at all the images, models, and data files within. To mod the game modders unzip the file, find a particular game asset, and overwrite it with their own version. This works, but it has lots of problems…

  1. It requires changing files that the game installer owns. If you install a newer version of the game, it will blow away the changes that the mod has made
  2. It’s difficult to manage multiple mods that are all trying to overwrite different pieces of the Stonehearth mod.
  3. Multiple mods can’t make changes to the same game object. They’re both trying to overwrite the same file, and only one can win.

So, here’s our plan for addressing the current state of affairs.

Anatomy of a Mod

A Stonehearth mod consist of:

  1. A directory with the mod files
  2. A manifest.json file in the directory describing the mod

A Stonehearth mod is just a file or directory that sits in the “mods” directory in your Stonehearth installation directory. If the game sees a directory or .smod file (which is just a renamed zip file of a directory!) it will try to load it as a mod when the game starts. If a file and directory have the same name (like /foo vs foo.smod), the game chooses to load the directory, not the file.

The Manifest

The manifest is a list of all the assets and code in the mod. Here’s a massively abbreviated version of the Stonehearth mod’s manifest file.

{
   "info" : {
      "name" : "Stonehearth"
   },
   "aliases" : {
      "medium_oak_tree" : "file(entities/trees/oak_tree/medium_oak_tree)",
      "mixins:tree" : "file(mixins/tree)"
   }
}

The aliases block declares a new game object “medium_oak_tree” and lists the file path to get to the data file that describes that game object. (Modders, the syntax here is shorthand for “entities/trees/oak_tree/medium_oak_tree/medium_oak_tree.json”).  Here’s what that file looks like:

entities/trees/oak_tree/medium_oak_tree/medium_oak_tree.json

{
   "mixins": "stonehearth:mixins:tree", 
   "type": "entity", 
   "components": {
      "model_variants": [
         {
            "models": [
               {
                  "type": "one_of",
                  "items": [
                     "file(medium_oak_tree.qb)", 
                     "file(medium_oak_tree_2.qb)", 
                     "file(medium_oak_tree_3.qb)"
                  ]
               }
            ]
         }
      ], 
      "unit_info": {
         "name": "Medium Oak Tree", 
         "description": "Sturdy, in the prime of life."
      }, 
      "stonehearth:resource_node": {
         "resource": "stonehearth:oak_log", 
         "durability": 12
      }
   }
}

We’ve talked about our entity/component framework in previous blogs. This file defines a new entity and the components for that entity: which model to use when rendering it, what to call it in game, the fact that it is a resource node that produces logs, etc.

Now notice the “mixin” line at the top of the file. Using mixins you can define common data parameters and re-use them across multiple entity definitions. Notice that we refer to the mixin by the alias specified in the manifest. Here’s the definition of the tree mixin.

mixins/tree/tree.json

{
   "type" : "entity",
   "components" : {
      "stonehearth:commands" : {
         "commands" : [
            "file(/data/commands/chop_tree)"
          ]
      },
      "render_info" : {
         "scale" : 1
      },
      "destination" : {
         "region" : [
            {
               "min" : { "x" : -3, "y" : 0, "z" : -3 },
               "max" : { "x" :  4, "y" : 1, "z" :  4 }
            }
         ]
      }
   }
}

Ok, so all of this has been in the game since Alpha 1 r1. Here’s what we’re adding to make your modding life easier.

 

Introducing Mixintos and Overrides

Using Mixintos and Overrides, you’ll be able to modify content in the Stonehearth mod (or any mod actually) without tampering with the mod’s internal files.  Both mixintos and overrides are specified in your mod’s manifest.

The Mixinto

Remember, a mixin allows an entity definition to pull  in content from the mixin file. A “mixinto” is the same thing but it’s a push rather than a pull. An outside mod (like your mod!) specifies what content to push into a destination data file. Here’s an example and it’s effect on the game. In our sample mod called “flagstone”…

flagstone/manifest.json

{
   "info" : {
      "name" : "Flagstone"
   },
   "mixintos" : {
      "stonehearth:medium_oak_tree" : [
         "file(/mixintos/big_tree.json)"
      ]
   }
}

Here the mixinto block specifies the target asset to modify by alias (notice the mod:alias syntax to refer to an asset in another mod!) and the data to mix into that asset. I could have defined an alias for big_tree.json and used that instead of the file path.

Here’s what the mixinto looks like.

flagstone/mixintos/big_tree.json

{
   "components" : {
      "unit_info" : {
         "name" : "GIANT tree"
      },
      "render_info" : {
         "scale" : 2
      }
   }
}

The mixinto changes the name and the scale of the tree model. Here’s what the game looks like with our flagstone mod loaded. Big trees!

 alt=

The Override

Mixintos are used to modify or enhance the content in a mod. An override will completely overwrite that asset. Here’s the syntax for adding an override:

{
   "info" : {
      "name" : "Flagstone"
   },

   "mixintos" : {
      "stonehearth:medium_oak_tree" : [
         "file(/mixintos/big_tree.json)"
      ]
   },

   "overrides" : {
      "stonehearth/entities/trees/oak_tree/medium_oak_tree/medium_oak_tree.qb" :"flagstone/models/cube.qb"
   }
}

In the override I need to explicitly define the file within the mod I want to change, and the replacement file. Here I’m replacing the medium oak tree model with a cube model from within my mod. And here’s what it looks like in game with both the mixinto and override working in tandem.

cube_giant_trees

Other Notes to Modders

Modders, here are a few other things to avoid when writing your mods. We’ll have real APIs for dealing with these issues eventually, so just be aware that doing any of the following will not be supported long term.

  1.  Don’t hook into an change the definition of functions in the Lua code. There will be an official events mechanism that you can hook into get notified when significant things happen in game (like entities being added to the world).
  2. The Lua I/O library is going away, for obvious reasons.

 

 

 

  • SgtOj

    Is it possible to get updated graphics. The current screenshots and pictures are not loading.

    • SgtOj

      Nvm… I am dumba$$.