Skip to content
This repository has been archived by the owner on Aug 1, 2021. It is now read-only.

Database format

Krzysztof Zych edited this page May 23, 2013 · 20 revisions

The database consists of a tree of files under the db directory. Every file in that subtree is loaded and parsed. Order doesn't matter - once loading is complete, any undefined items used in recipes are reported. The files are YAML files, with some custom structure on top.

A file must have a cluster declaration, and any of primitives, crafts, processing, defaults and equivalents sections. The sections can occur in any order, and exactly once per file, though it's recommended to put the cluster declaration first.

Cluster

cluster: redpower2

Declares that items and crafts found in this file belong to a named group. There are no restrictions on number of groups; a group can span many files. Group names are identifiers - they can contain letters, numbers and underscores. They are used for consistency-checking purposes, and restricting sets of available items.

Primitives

primitives:
- wool: 5
- water:
    cost: 1
    stacks: false
- snowball:
    cost: 1
    stacks: 16

This section contains declarations of items deemed primitive, that is for which we don't specify any crafting recipes. Typically those items are only acquired by mining or harvesting. What is considered primitive can vary from person to person, and probably from server to server. Are diamonds primitive? Yes, until you install IndustrialCraft and enable the UU-Matter crafting recipe. Is UU-Matter primitive? Maybe - there is no crafting recipe for it, but it is made in a machine. Regardless, an item declaration is either short-form (like wool in the example above), or long-form.

Short form is simply item name: cost, where cost is a positive integer. Cost is used to determine the cheapest crafting path from one item to another down in it's tree of requirements. The exact value of cost isn't important, but it is significant in relation to other items, and determines the cost of crafts involving that item. For example, you can craft an IndustrialCraft iron furnace from either 8 iron ingots, or 5 iron ingots and a regular furnace. Since iron is considered more valuable than cobblestone, we'd set cost of one iron ore higher than one cobblestone. When asked to craft an iron furnace, the program should then point us to the latter recipe.

Long form allows specifying more properties: so far the only one recognized is stacks, any others are stored, but not used for calculations (they can however be used for formatting output). Stacks is a positive integer, telling the program how large a single stack of the item is, and is used to nicely tally the input requirements. If not declared, stacks defaults to 64, as for most items in the game. If specified as either 1 or false, the item does not stack, and the required item numbers are shown without stacking.

Crafts

- cell:
    makes: 16
    ingredients: [tin ingot*4]
    shape: |
      ~ t ~
      t ~ t
      ~ t ~
- lava cell: [cell, lava]
- 30K coolant cell:
  - coolant cell*3
  - tin ingot*6
- dense copper plate:
  machine: compressor
  ingredients:
    - copper ingot*8
- uranium cell: [cell, uranium fuel ingot]
- uranium cell: [re-enriched uranium cell, coal dust]
- retriever:
    ingredients:
      - brass*2
      - leather
      - ender pearl*2
      - iron*2
      - blue alloy ingot
      - filter
    shape: |
      br le br
      en fi en
      ir bl ir

Crafting recipes are declared in the crafts section. There can be many recipes for one item, possibly in many files. There is no limit to the number of crafting recipes per file, or across all files. A recipe can use any items not defined in the same file.

Again, a definition is either short-form or long-form. Short-form in this case is item name: list-of-ingredients, using any YAML list notation for the ingredients. In the example above, lava cell and uranium cells are specified in the short form using flow (compact) list representation; and the 30K coolant cell using the block (line enumerated) form.

Long-form, as used above by dense copper plate and cell allows specifying more properties. All, except ingredients are optional:

  • makes: a positive integer describing how many of the resulting item are crafted using this recipe; when not specified, defaults to 1
  • machine: for recipes not using the crafting grid or crafting table, specify which machine is needed for the recipe.
  • ingredients: list of required items, as described below
  • shape: describes how to lay out items on the crafting grid, also described below
  • compatible: to avoid name conflicts, crafts for the same item that are not in the same cluster as its first definition, need to declare compatibility
  • tag: gives this recipe an internal tag, to allow advanced definitions like overrides
  • overrides: points to another recipe that is to be overriden by this one
  • all other properties are stored, but not used for calculation (but may be used for other purposes)

Ingredients

An ingredient list simply enumerates all the necessary items for crafting. When more than one of an item is required, it can either be listed many times, or with an asterisk (multiplier) and the number required. There should be no spaces between the asterisk and both name and number.

Shape

Used to display a hint how to lay out items on the crafting grid. While the example shows it in a YAML block string form, the newlines are not significant and shape can be equivalently described by a simple string (of 9 or less items). For example, the shape for a retriever could be written as br le br en fi en ir bl. In this form, quotes are optional, while in the longer block form, quotes should not be used at all

  • any letter, or sequence of letters that is a unique prefix of any item on the ingredient list. In the example above, crafting a cell requires only tin ingots, so it suffices to use t for describing one. The retriever is more complicated, but we could use single letters for anything but brass and blue alloy ingots - both of these start with B, so more letters are necessary (at least two in this case)
  • when that's insufficient, items in the ingredient list can be prefixed by a shape specifier, which is any sequence of letters followed by a vertical bar, such as D|diamond pickaxe*2. Those shape specifiers take precedence over unique prefixes.
  • a ~ signifies a blank space on the grid
  • spaces and newlines are ignored, but useful for describing the grid layout

The shape specifier syntax is reminiscent of conventions used in Java code to add crafting recipes. Note that when using multi-ingredient expansions, their usage is undefined.

Compatible and name conflicts

Two different clusters cannot define the same item, unless flagged for compatibility. For example, Buildcraft, IndustrialCraft and Redpower2 all define an item called "pump". While similar in purpose (pumping liquids into containers or pipes), each one is crafted differently. Without checking for name conflicts, the program would get confused, fuse the three recipes together, and decide on the cheapest one. The user would be unable to choose which specific pump to craft.

To avoid this, the program detects such conflicts, and exits with an error. To resolve it, either all items must be renamed (for example to "pump", "electric pump" and "blulectric pump" respectively), or, when the crafts are indeed for the same item, declared compatible. For example, both vanilla Minecraft and Pam's Harvestcraft define recipes for mushroom stew:

cluster: vanilla

crafts:
- mushroom stew: [red mushroom, brown mushroom, bowl]
cluster: harvestcraft

crafts:
- mushroom stew:
    ingredients: [white mushroom, white mushroom, bowl]
    compatible: vanilla
- mushroom stew: 
    ingredients: [white mushroom, brown mushroom, bowl]
    compatible: vanilla
- mushroom stew: 
    ingredients: [white mushroom, red mushroom, bowl]
    compatible: vanilla

With the compatible declarations, there is no name conflict, there is exactly one mushroom stew, crafted with all mushroom combinations. Any other mods adding mushroom stew recipes will also need to state compatibility.

However, when multiple clusters add crafts for the same items (many mods that add ore processing, such as IndustrialCraft, GregTech, Factorization, Thermal Expansion), it is often convenient to mark an item forward-compatible with any mods. Note: this effectively turns off conflict detection for this item. For example - gold ingots:

- gold ingot:
    machine: furnace
    ingredients: [gold ore]
    compatible: all

The compatibility declaration may be added in any cluster defining the item, but may not refer to itself (the cluster, that is).

Tags and overrides

cluster: railcraft

crafts:
- gold plate gear:
    ingredients: [gold nugget*4, stone gear]
    overrides: railcraft/without-buildcraft
- gold plate gear:
    ingredients: [gold nugget*4, cobble]
    tag: without-buildcraft

It is possible that some pairs of clusters will need to override one another's recipes. The override mechanic provides a declarative solution. In the example above, Railcraft adds two recipes for gold plated gear. The first one should be used only if Buildcraft is available, otherwise the program should use the second one.

When Buildcraft is excluded and unavailable, the first recipe will not solve, but the second one will. When Buildcraft is available, both recipes will solve, and the program would pick the second one as it takes fewer items to craft, which is undesirable. To avoid this, we declare the Buildcraft recipe as overriding the other one.

Now, with Buildcraft available, the second recipe will not be considered. On the other hand, the override will not be active if Buildcraft is not available, and because the first recipe is now unsolvable, the other one will be used.

This example uses tags, to perform overrides within the same cluster. Forcing overrides across clusters is even easier; consider the following example:

cluster: vanilla

crafts:
- track:
    ingredients: [iron*6, stick]
    makes: 16
cluster: railcraft

crafts:
- track:
    ingredients: [standard rail*6, wooden railbed]
    makes: 16
    compatible: vanilla
    overrides: vanilla

In this case, we need to disable the vanilla track recipe when Railcraft is used. While it is sufficient to use only cluster names here, the recipe needs to be flagged as compatible to avoid name conflict errors (because two distinct clusters define the same item, see above). This form of override deactivates all crafts for the same item in another cluster, as opposed to specific crafts when using tags.

Processing

Processing is an alternative syntax for crafts, slightly more compact and suited for simpler recipes. It is especially useful for describing processing (hence the name) items of one kind into another, such as smelting ore.

processing:
- inputs: [iron ore]
  machine: furnace
  outputs: [iron]

crafts:
- iron:
  machine: furnace
  ingredients: [iron ore]

The above two definitions are completely equivalent. Inputs are converted to an ingredient list, machine and makes retain their meaning, and outputs are used as crafted item names. When there's exactly one output item listed, there is no ambiguity - it's exactly equivalent to a craft. For more than one output item, currently the recipe expands to an identical craft for each of the output items listed. As the engine doesn't support multi-output recipes yet, this is a non-ideal approximation of those.

Templates

Both craft and processing sections can make use of templates. Templates may be freely mixed with regular crafts and processing definitions, and are automatically recognized when used.

crafts:
- $(color) pipe wire:
    machine: assembly table
    ingredients: [redstone, iron, $(color) dye]
    color: [red, blue, green, yellow]
- $(material) transport pipe:
    ingredients: [$(material)*2, glass]
    makes: 8
    material: [wooden/wood, stone, cobblestone/cobble, sandstone, iron, golden/gold ingot, obsidian, emerald]

processing:
- vars: [metal]
  inputs: [$(metal)]
  outputs: [$(metal) dust]
  metal:
    - iron
    - copper/copper ingot
    - tin/tin ingot
    - gold/gold ingot
    - bronze

Templates are used wherever there are many recipes differing only by a single, or few elements, both in name and ingredient list. If a crafted item's name includes a substitution variable, it's treated as a template. Alternatively, if the definition includes a vars entry, it is also treated as a template. In the craft examples above, $(color) and $(material) are substitution variables, and the color: and material: lines are their expansion lists, respectively.

Variables

A single variable template expands to as many crafts as were on the expansion list. Each recipe has the substitution variable replaced with another item on the expansion list, both in name and ingredient list (and shape, if defined). In the example above, there will be 4 pipe wire recipes, and 8 pipe recipes. It is completely equivalent to specifying each of those in a separate craft definition.

It is possible to include nulls (~) in the substitution list. When expanding, a null value is omitted both in name and ingredient list. If, in the above recipe for pipe wires there was an additional null in the expansion list, it would have expanded to 5 recipes, the additional one named simply "pipe wire", listing redstone and iron as ingredients.

When using multiple substitution variables, every combination of substitution variables is expanded, except for one consisting of only nulls.

crafts:
- $(peripheral) $(tool) turtle:
    ingredients: [$(peripheral), turtle, $(tool)]
    shape: ~ ~ ~ $(tool) turtle $(peripheral) ~ ~ ~
    tool: [~, mining/diamond pickaxe, farming/diamond hoe, melee/diamond sword, felling/diamond axe, digging/diamond shovel]
    peripheral: [~, crafty/crafting table, wireless/wireless modem]

This template expands to 17 (has 6 tools * 3 peripherals - 1 all nulls) turtles. 5 of them are equipped only with tools, 5 with tools and a crafting table, another 5 with a tool and wireless modem. The remaining two have either a modem or a crafting table. There is no limit to the number of substitution variables in a template, however one or two should suffice for 99% cases.

Two-part expansions

It may happen that an item's name cannot be exactly represented by simply replacing the substitution variable. For example, wood-en pipe and gold-en pipes can't be expressed that way, when listed together with other pipes, and would require their own separate crafts. In that case, each item on the expansion list can have two components: the name expansion and the ingredient expansion, separated by a slash chracter (and no spaces). In the example above, three pipes use that syntax: wooden, golden and cobblestone pipes. In the turtles template, a mining (name expansion) turtle uses a diamond pickaxe (ingredient expansion). If there's no slash character present, the name and ingredients are equal.

Multi-ingredient expansions

An alternative, richer version of two-part expansions. Might make them obsolete in the future. Items on the expansion list are specified as a keyword, which becomes the name expansion, and a list of one or more ingredients (ingredient expansion). All are concatenated into the final output. The two styles may be mixed within one file and even one recipe. For example:

- $(flavor) donut:
    ingredients: [$(flavor), donut]
    flavor:
    - chocolate/chocolate bar
    - powdered/powdered sugar
    - jelly/grape jelly
    - jelly/strawberry jam
    - frosted: [sugar, red dye, yellow dye, green dye]

All donuts except the frosted donut are crafted with two ingredients - a donut and the appropriate flavor item, while the frosted donut needs sugar and the coloured dyes. Note also that jelly donut is defined twice - these are simply alternative recipes.

YAML tricks: anchors, references and merges

colors: &colors
    color: [black, red, green, brown, blue, purple, cyan, light gray, gray, pink, lime, yellow, light blue, magenta, orange, white]

crafts:
- $(color) lumar:
    ingredients: [redstone, glowstone, $(color) dye*2]
    makes: 2
    <<: *colors
- inverted $(color) lamp:
    ingredients: [glass pane*6, $(color) lumar*2, redstone torch]
    <<: *colors

Consider the example above. Instead of inserting the color list each time (in the lumar and inverted lamp templates), we used what is called a YAML anchor and a merge. The <<: *colors is a merge that tells the YAML parser to include the contents of specified anchors (that is, colors) into the currently constructed object. That anchor is specified above in the pseudo-section colors (a pseudo-section because it's ignored by the application, and thus merely a serialization detail. In fact there can be any number of such sections in a file). The final effect is intuitive: declare a common substitution list exactly once, and use it where applicable.

Equivalents

This section is akin to the Forge Ore Dictionary. It allows both aliasing many items under a common name, and listing them as equivalents, hence the name.

equivalents:
- [pulverized silver, silver dust]
- [pulverized copper, copper dust]
- [electrum blend, electrum dust]
- [silver, silver ingot]
- [white dye, bonemeal]
- [blue dye, lapis, indigo dye]
- [rose red, red dye]
- [dandelion yellow, yellow dye]

Pulverized silver is declared equivalent to silver dust, silver is an alias for silver ingot. Recipes can list white dye instead of bonemeal, and blue dye is lapis or indigo dye, when defined.

It is customary, though not necessary, to list equivalents in a separate file, named forge.yml.

The names listed need not be defined, and can be later filled by other files, or not filled at all. When referenced by crafts, any name that does not resolve to an item will be exchanged for another one on the list which is defined. If any unresolved items are left when parsing is complete, the loader will throw an error.

Equivalents defined across multiple files are concatenated and resolved at the same time. The intended purpose is to extend existing definitions, for example when a mod adds a new alternative dye, or processed ore, it should list them as alternatives to already defined items or aliases, and use these aliases in its recipes.

Defaults

This section is most useful for files that list many processing recipes for a single machine, though it's not restricted to that scenario. Keys defined in a defaults section are used by processing and crafts sections in places they're not defined. For example: if we add a machine key in defaults, all recipes in the file that do not specify a machine, use that one. To avoid that behavior, a recipe has to explicitly specify machine as null. Keys from a recipe always take priority over the defaults section.

defaults:
    machine: furnace

crafts:
- iron:
    ingredients: [iron ore]
- iron block:
    ingredients: [iron*9]
    machine: ~

In the above example, iron is smelted in a furnace, as declared in the defaults section. Iron blocks are crafted by hand - the default has been overridden.