Tutorial: Adding Mining Resources (updated for Alpha 18)

First, some points to be aware of.

  • I’m going to assume some knowledge on the part of the reader for this tutorial, so it’s going to read as something of an intermediate topic. I will assume you know how to make a basic mod, including how to add simple items (furniture and decorations are the usual starting points). I will also assume that you understand what a mixinto is.
  • Throughout this tutorial, I will use some very specific aliases and nest files in some very specific folders. I do this because they are the same folders that the stonehearth mod uses and they are similar aliases to those used by the stonehearth mod. So if you want to go look for similar examples in the stonehearth mod, it’s pretty easy because it’s all in similar places. You don’t have to make such long aliases or nest your files in the same way, but I feel that it is good practice to do so!
  • Anywhere I use CAPITAL LETTERS in a piece of code, that’s your hint to replace that piece of text with your own thing.
  • Here are all the code snippets built into an example mod: RESOURCE_MOD.zip (10.5 KB)

. If you put it in your stonehearth mods folder and change the extension to .smod, it should just work.

1. The manifest

I want to talk about this first, because anything you don’t put in the manifest will not be active in the final mod. So it’s really a checklist of things to add.

Our example mod manifest looks like this:

manifest.json

{
   "info":
   {
      "name": "RESOURCE_MOD",
      "version": 3
   },
   
   "aliases":
   {
    "resources:RESOURCE"        : "file(entities/resources/RESOURCE/RESOURCE_THING)",
     "terrain:ui:RESOURCE_block" : "file(entities/terrain/ui/RESOURCE_block)"
   },

   "mixintos":
   {
    "stonehearth/data/biome/arctic_generation_data.json" : "file(data/biome/arctic_generation_data.json)",
    "stonehearth/data/biome/desert_generation_data.json" : "file(data/biome/desert_generation_data.json)",
    "stonehearth/data/biome/temperate_generation_data.json" : "file(data/biome/temperate_generation_data.json)",
    "stonehearth/data/terrain/terrain_blocks.json" : "file(data/terrain/terrain_blocks.json)",
    "stonehearth/services/server/mining/mining_loot_tables.json" : "file(services/server/mining/mining_loot_tables.json)",
    "stonehearth/scenarios/scenario_index.json" : "file(scenarios/scenario_index.json)",
    "stonehearth/data/resource_constants.json" : "file(data/resource_constants.json)"
   }
}

So what are all these bits for?

  • resources:RESOURCE is the actual item that can be used in recipes by your crafter hearthlings. Maybe it’s a new metal ore, a new stone or some kind of gem.

  • terrain:ui:RESOURCE_block is used to create a tooltip when you click on an vein of your resource in the world. If you don’t want to create veins of your resource in the world, you can leave this out!

  • stonehearth/data/biome/arctic_generation_data.json, stonehearth/data/biome/desert_generation_data.json and stonehearth/data/biome/temperate_generation_data.json are files that describe the way the world is generated depending on the type of map the player wants. Currently only the desert and temperate biomes are playable, but the arctic biome will come eventually (with the viking-type kingdom)! If you want veins of your resource in the world, you must define the color of that vein in each biome. If the color isn’t defined, it will appear as a bright red by default! If you don’t want to create veins of your resource in the world, you can leave this out!

  • stonehearth/data/terrain/terrain_blocks.json is a file that creates the data structures for veins of resources in the world. If you don’t want to create veins of your resource in the world, you can leave this out!

  • stonehearth/services/server/mining/mining_loot_tables.json is the file that determine the rate at which resources are found when mining out the various minable materials in the world. You’ll need this file if you want your resource to be minable in every biome, which means you’ll almost certainly need it in your mod.

  • stonehearth/scenarios/scenario_index.json is a list of a bunch of things that can be found in a world. One possibility is veins of resources. So you’ll only need this is you want veins of your resource in the world. This file itself points at another file, which we’ll get into later.

  • stonehearth/ui/data/constants.json is something you’ll need if you want to create a recipe that uses a generic resource rather than a specific item.

2. Adding a Generic Resource

2.1. The Item

This is the thing that a crafter can use. You’ll need 3 files to create a basic resource item.

  • RESOURCE.png is an image of the item that will appear in the inventory screens of the game and will also represent your new resource type in the crafing windows.
  • RESOURCE_THING.qb is the model for your resource and is the same as an “iconic” form for any other item. A resource is not placeable or wearable, so you’ll never need a ghost form or a wearable form.
  • RESOURCE_THING.json is the basic data of your resource. It will look like this:

RESOURCE_THING.json

{
   "mixins": "stonehearth:mixins:item_properties",
   "type": "entity",
   "components": {
      "model_variants": {
         "default": {
            "models": [
               "file(RESOURCE_THING.qb)"
            ]
         }
      }
   },
   "entity_data" : {
      "stonehearth:net_worth" : {
          "value_in_gold" : 5,
          "rarity" : "common",
          "shop_info" : {
              "buyable" : true,   
              "sellable" : true,
              "shopkeeper_level" : 1,
              "shopkeeper_type" : "caravan"
          }
      },
      "stonehearth:catalog": {
         "display_name": "i18n(RESOURCE_THING)",
         "description": "i18n(A RESOURCE DESCRIPTION.)",
         "icon": "file(../RESOURCE.png)",
         "is_item": true,
         "category": "resources",
         "material_tags": "RESOURCE_TYPE resource"
      }
   }
}

Let’s stop a moment to talk about the tag entry. You want this to be something unique because its going to be checked against later on. So “marble resource” or “amethyst resource”. It can’t be “stone resource” because stonehearth already uses that!

2.2. Adding it to a Loot Table

Next, we need some way for the hearthlings to find it in the world so they can use it. Since we are talking about mining resources, this will need to be through mining. For this, we mixinto the mining_loot_tables.json file.

Here is a basic example, which we’ll expand later on when we talk about veins:

mining_loot_tables.json

{
   "mineable_blocks" :
   {
      "rock" :
      {
         "entries": {
            "default": {
               "items": {
                 "UNIQUE_IDENTIFIER": { "uri" : "RESOURCE_MOD:resources:RESOURCE", "weight" : 0.200 }
               }
            }
         }
      }
   }
}

What does it mean? The chance of getting anything when you kill, harvest or mine something is given by a loot table. Loot tables work based on something called a weight.

Weights are a handy way to assign a probability of something without assigning a strict probability. A probability is a value between 0 (never happen) and 1 (always happens). So if you are using probability the numbers in your table have to add up to 1 always. So if you add something new or pull something out, you have to calculate your numbers all over again.

Weights are a bit different! A weight merely states how likely something is relative to something else. Say you want A to drop 5 times as often as B. B has an arbitrary weight of 2. Therefore A must have a weight of 10, 5 times as much as B. So currently, we have a total weight of 12. 2/12 times we see B and 10/12 times we see A. What if we want to add item C with a weight of 8 (4 times as common as B)? Now we have a total weight of 20, giving 10/20 times we’ll see A, 2/20 times we’ll see B and 8/20 times we’ll see C. The relative chance of each item dropping is preserved, but the chance of A and B dropping is now less than it was before. This is important.

Anyhow, this bit of data is telling us to add our resource to the “rock” loot table and give it a weight of 0.200. Check the numbers in stonehearth/services/server/mining/mining_loot_tables.json before adjusting this weight. If your number is too low, your resource will not drop much (if at all). If your number is too high, it will outweight every other resource and nothing else will drop!

There are other loot tables in the mining_loot_tables that you can add your resource to if you so desire. Rock is just the most logical one to start with.

The UNIQUE_IDENTIFIER should be replaced with a term that is unique to the resource you are adding. If you use a resource identifier that already exists in the loot table, it will overwrite that entry, causing that thing to no longer drop from that table! You can use the same UNIQUE_IDENTIFIER in different tables though.

NOTE: There exist files in the biomes folder called desert_mining_loot_table.json and temperate_mining_loot_table.json. These files are for any additional mining loot tables you want to add that are specific to that biome type only. Since the method for adding loot tables for these is exactly the same as for the generic file, there is really nothing extra to say about them.

2.3. Making your resource a material

So now we have our item dropping in the world when we mine in rock. How does we create a recipe with it as a requirement?

There are two choices.

  1. We can specify the exact item by using “URI” : “RESOURCE_MOD:resources:RESOURCE”.
  2. We can use anything that of a given material type. eg. “material” : “RESOURCE resource”

If we use the first choice, we don’t have to do anything special, but the second option does not happen automatically. You actually have to add some data for it. So why would we go to the effort? Well, maybe you’ve got multiple forms of the resource. Perhaps you’ve added amethysts, diamonds and rubies and they are all tagged “gem resource”. You want to make a recipe that could use amethysts, diamonds or rubies as one of its components. That’s when you use the second option with “material” : “gem resource”!

The information to enable this goes into data/resource_constants.json.

{
    "resources" : {
        "RESOURCE resource" : {
            "name" : "RESOURCE_THING",
            "icon" : "RESOURCE_MOD/entities/resources/RESOURCE/RESOURCE.png",
            "stacks" : 80,
            "default_resource": "RESOURCE_MOD:resources:RESOURCE"
        }       
    }
}

Now, anywhere you use “material” : “RESOURCE resource” as a requirement in a recipe, you’ll see your RESOURCE.png as the icon and the tooltip will show the name RESOURCE_THING.

NOTE: Not yet sure what default_resource does! If anyone knows…

Step 3: Resource Veins

So now you have a resource and it randomly drops when you dig through the rock just like the current metal ores do. Sometimes, you’ll also find motherloads of ore that are called ore veins. This is considerably more work, but it’s quite doable. Let’s take a look at all the bits you need!

3.1: Terrain Blocks

Our first step is to define what the vein will look like in the world. Here we need to mixinto data/terrain/terrain_blocks.json.

terrain_blocks.json

{
   "block_types" :
   {
      "RESOURCE" :       { "tag" : 501, "kind" : "RESOURCE_KIND" }
   },
   "selectable_kinds" :
   {
       "RESOURCE_KIND" : "RESOURCE_MOD:terrain:ui:RESOURCE_block"
   }
}

The “block_types” tag is an organisational element that stonehearth uses to define each block of terrain in the game. The “tag” number must be unique. Check the original file first to make sure you give it a unique tag!

RESOURCE_KIND is the identifying name for the kind of resource. It’s not necessarily the same as the RESOURCE name you’ve used elsewhere.

“selectable_kinds” are all the kinds of terrain in the world that you can click on and see a tooltip. So far, this is only ore veins. You need to use the RESOURCE_KIND you just defined in block_types and then point at the file that is going to describe your resource.

So next we need to create that descriptive file!

RESOURCE_block.json

{
   "mixins": "stonehearth/entities/terrain/ui/ore_block",
   "entity_data": {
      "stonehearth:catalog": {
         "display_name": "RESOURCE vein",
         "description": "Provides RESOURCE when mined."
      }
   }
}

As you can see, it has a mixin from the ore_block file, but we don’t need to worry about that. The important stuff is the display_name and description, which provides the tooltip text you see when you click on the ore vein.

The last part of defining the look of a vein is to define its colour. To do this, we are going to have to get stuck into the biome definition files. Currently, there are three of these: arctic_generation_data.json, desert_generation_data.json and temperat_generation_datae.json. Only desert_generation_data.json and temperate_generation_data.json are being used right now, but the artic one will be coming in a future alpha, so might as well be ready for them. In each of these files, there is a “palette” definition with a “spring” definition nested inside. For now, seasons aren’t implemented, so we only need to add something to the spring definition for each biome. I’ll just show one file, but you can just cut-and-paste to each file anyway, with the possible exception of the colour.

temperate.json

{
   "palettes" :
   {
      "spring" :
      {
         "RESOURCE" :               "#DEDEDE"
      }
   }
}

The RESOURCE here is the block_type you defined before. The information #DEDEDE is an RGB color in hexadecimal notation. Do pick your own color to give it a unique look! If you are lucky, you might be able to get away with using the same color for every biome. If you aren’t so lucky, a color that is plainly visible in one biome may blend into the colors of another biome. The color is defined per biome and per season so that you can fix problems like that on a case-by-case basis.

3.2. Defining the vein

We’ve pretty well defined what the vein looks like, now we can talk about how to make the vein appear in the world.

Veins are a kind of “scenario”, which is some things that can appear in the world in a specific place. Our first step is to mixinto scenarios/scenario_index.json.

scenario_index.json

{
   "static" :
   {
      "scenarios" :
      [
          "file(static/terrain/RESOURCE_vein/RESOURCE_vein.json)"
      ]
   }
}

This is basically a manifest file for scenarios with it’s own categories. Ore veins don’t move, so they go in the static category.

Now we can add the scenario definition that tells the game what the vein should be like in its own file.

RESOURCE_vein.json

{
   "mixins" : "/stonehearth/scenarios/static/terrain/ore_vein/ore_vein.json",
   "name" : "RESOURCE_vein",
   "kind" : "RESOURCE",
   "weight" : 200,

   "data" :
   {
      "num_veins_min" : 5,
      "num_veins_max" : 10,
      "vein_length_min" : 20,
      "vein_length_max" : 40,
      "vein_radius" : 3,
      "mother_lode_radius_min" : 5,
      "mother_lode_radius_max" : 7
   }
}

Again, RESOURCE must be the same as defined previously. This is the block_type defined in terrain_blocks.json.

The weight is the chance of this particular scenario spawning in the world. Common ore veins like iron and copper have a weight of 75, while gold is only 40. A large number like 200 or 500 is only appropriate for testing purposes. Make sure to adjust this number down after you are sure everything works!

Some of the entries in “data” affect how big your ore vein will be. Normally a vein is between vein_length_min and vein_length_max voxels long (horizontally) and vein_radius blocks high (should be 1-4). mother_lode_radius_min and mother_lode_radius_max determine how wide the widest part of the vein is.

3.3. Loot tables, part 2

Finally, we are ready to define the things you can get when you mine a block of your ore vein. We need to mixinto mining_loot_tables.json some more. Your mixinto file from part 2.2 above will now look like this:

mining_loot_tables.json

{
   "mineable_blocks" :
   {
      "rock" :
      {
         "entries": {
            "default": {
               "items": {
                 "ore": { "uri" : "RESOURCE_MOD:resources:RESOURCE", "weight" : 0.200 }
               }
            }
         }
      },
      "RESOURCE_KIND" :
      {
         "entries": {
            "default": {
               "num_rolls": 1,
               "items": {
                  "none": { "uri": "", "weight": 6 },
                  "ore": { "uri": "RESOURCE_MOD:resources:RESOURCE", "weight": 1 }
               }
            }
         }
      }
   }
}

This extra data tells the game to check the RESOURCE_KIND loot table when mining out one of your resource vein blocks. It then defines the loot table.

As you can see, I have “num_rolls” set to 1, which means the game checks once to see what item drops. Maybe you want to make it rain resources? You could set it to 10 and the game would check the loot table 10 times for each time your hearthlings mine out a block.

We also have two “items” listed in the RESOURCE_KIND loot table. The second one is your resource as expected. But what is the first? Because there is no item listed, it’s the chance that no item drops. So in the example, 6 out of 7 times, you’ll mine a block and nothing comes out. 1 out of 7 times you’ll get your resource. If you like, you can add more things to your resource vein loot table. Maybe it’s a gem vein and you have a chance to get a amethyst, diamond, emerald or nothing. You’d need four entries then.

17 Likes

very helpful, i dont have time to read the entire thing, or “test” it out, at the moment, but i will definitely be taking a further look at this later today!

1 Like

Super helpful, shame I had already figured it out myself. If I waited I could have avoided the headache of discovering the biome part…

2 Likes

Probably! This topic seems to be getting more complicated rather than less, which is why I felt there really needed to be an updated tutorial on the subject. It took me a while to puzzle out where the colours had gone to as well :sweat:

3 Likes

Updated the tutorial. Turns out there were a couple of places where I used the “kind” term instead of the “block_type” term and this was wrong. Which is wierd because the tag in which you must place the block_type in scenarios/static/terrain/RESOURCE_vein/RESOURCE_vein.json is labelled “kind”. Note: The block_type and kind are named exactly the same in all the stonehearth.mod resource veins…

@sdee @albert any chance of making this tag label a little more sensible? :wink:

2 Likes

To clarify (or perhaps confuse things further):

  • block_type defines the color of a terrain voxel.
  • kind defines the material of the terrain voxel.

For example, Kentucky Bluegrass and Crabgrass may be two block_types, but they both are treated as a grass kind for digging, planting, etc. Admittedly, for ore veins, it seems odd that you would have multiple colors for the same ore type, so I can see why there would be confusion between the two terms.

2 Likes

I’ve updated the example mod and the tutorial itself to reflect a recent change in one of the .json files that you must mixinto.

The mining_loot_table.json file now requires that all mineable blocks are nested inside a “mineable blocks” tag. Without the correct nesting, the items you want to drop from mining will not drop at all.

4 Likes

OK. I’ve updated this Tutorial for Alpha 18. Hopefully I haven’t introduced any new errors and have correctly gotten rid of any old information.

The RESOURCE_MOD example is also up to date.

Let me know if I got anything wrong!

1 Like

Apparently I did make an error. Updated the tutorial to fix it.

Any entry you add to the mining_loot_tables.json (or a biome specific loot table) should use an unique identifier, so as not to overwrite an entry in the original loot table. Unless that is what you want of course.

{
   "mineable_blocks" :
   {
      "rock" :
      {
         "entries": {
            "default": {
               "items": {
                 "UNIQUE_IDENTIFIER": { "uri" : "RESOURCE_MOD:resources:RESOURCE", "weight" : 0.200 }
               }
            }
         }
      }
   }
}
3 Likes

Well, time to add mythril :stuck_out_tongue:

2 Likes

In DoN mod, for better compatibility with all biomes (and moded biomes too) author make mithril craftable from silver. I think with graet count of mods it is a best way entering another ores.

Well to be fair biome compatability is relatively easy to do with ore spawning if I understand what I made right, it’s Basicly one or two, really small, files.

@ the devs though, instead of making things bright red if for a particular biome it’s undefined, can’t you make it default to what’s in the “default” biome? (the forest)

It is also possible to the mod adding the ore to add the colors to the biomes.
Just mixinto this into the desired biome generation file:

{
	"palettes": {
		"spring": {
			"your_ore": "#0099ff"
		}
	}
}
1 Like