Last updated: December 10th, 2018. Latest version here.

Entities and components

All things in Stonehearth are made of entities and components.

Entities

An entity is an object that exists in the world. Every thing you see in Stonehearth (that isn't a piece of UI) is an entity. Ex: trees, hearthlings, rabbits, logs.

The entities.lua file in Stonehearth\mods\radiant\modules describes a lot of what you can do with an entity. However, entities contain very little data about themselves in themselves. They store almost all of their behavior inside components.

You can find all the entities from the game inside the mods\stonehearth\entities directory. Some are inside the mods\stonehearth\jobs directory (such as the workbenches or the different jobs outfits).

An entity is represented by a text file containing JSON describing that entity. This file describes which components should be added to the entity. The entity may inherit other components if it has mixins, etc. Here's an excerpt from small_boulder.json :

  {
     "type": "entity",
     "mixins": "stonehearth:mixins:boulder",
     "components": {
        "model_variants": {
           "default": {
              "models": [
                 "file(small_boulder_1.qb)"
              ]
           }
        },
        "stonehearth:resource_node": {
           "durability": 1
        },
        "mob": {
           "model_origin": { "x": -0.5, "y": 0, "z": 0.5 },
           "region_origin": { "x": -0.5, "y": 0, "z": 0.5 },
           "align_to_grid": [
              "x",
              "z"
           ]
        },
     },
     "entity_data": {
        "stonehearth:catalog": {
           "display_name": "i18n(stonehearth:entities.boulders.small_boulder.display_name)",
           "description": "i18n(stonehearth:entities.boulders.small_boulder.description)"
        },
        "stonehearth:appeal": {
           "appeal": -1
        }
     }
  }

These are the different keys or nodes that we can find in these JSON files:

  • "type" : "entity"
    This indicates what this JSON file is describing. In this case, it's an entity. Other files might contain a "type" of "index", "mixin", or "job", for example. When the file is consumed by our code, our code will thus know how to interpret the rest of it.

  • "mixins" : "stonehearth:mixins:boulder"
    This key lets you refer to another JSON file. All keys from that other file are incorporated into this one, and duplicate keys are merged together. So if both files have a "components" key, the final file will have the child components from both files. More on mixins in the next section of the guide.

Components

  • "components" : { ... }
    All components associated with an entity by default are declared inside the "components" key.

Here's a simple example from arch_backed_chair.json :

  {
     "mixins": "file(arch_backed_chair_ghost.json)",
     "components": {
        "stonehearth:entity_forms": {
           "iconic_form" : "file(arch_backed_chair_iconic.json)",
           "ghost_form" : "file(arch_backed_chair_ghost.json)",
           "placeable_on_ground" : true
        },
        "region_collision_shape": {
           "region": [
              {
                 "min" : { "x" : 0, "y" : 0, "z" : 0 },
                 "max" : { "x" : 1, "y" : 2, "z" : 1 }
              }
           ]
        }
     },
     "entity_data": {
        "stonehearth:net_worth": {
          "value_in_gold": 6,
          "rarity": "common",
          "shop_info": {
             "buyable": true,
             "sellable": true,
             "shopkeeper_level": 1,
             "shopkeeper_type": "caravan"
          }
        }
     }
  }

In this case, both "stonehearth:entity_forms" and "region_collision_shape" are components that will be added to the entity when it is created. Others will be added based on whatever is in the mixin arch_backed_chair_ghost.json.

Different components can be added/removed from the file as we add/remove functionality from the entity. Writing Stonehearth is very much an exercise in defining and implementing the reusable components that describe the many interactions in the game.

So, when thinking about your mods, think about the entities you want to add and the pieces of functionality that belong to each item you want to add to the game. Can they be broken down into generic, re-usable components? What data is required for each?

The component's name will change based on its mod, and whether it's implemented in C++ or Lua. For modding, we can only create components in Lua. How to create your own components will be covered in advanced sections of the guide.

Entity data

Entity Data can be added to an entity via its JSON file. It is a way to attach read-only, always-true-across-all-instances data to an entity.

  "entity_data" : { ... }

The data can then be accessed again in Lua via get_entity_data(). This allows components and other Lua scripts to make use of it:

  foo = radiant.entities.get_entity_data(my_chair, "stonehearth:net_worth").value_in_gold