Subnodes API
============

Subnodes API offers a universal way for both mods trying to add new subnode
kinds and mods trying to make their regular nodes have different shapes. For
the former, there's the subnode kind registration API, and for the latter
there's subnode registration API. This is to ensure that the conflicts and
function bloat present for existing solutions (like MTG `stairs` or MCLA/VL
`mcl_stairs` or MB Stairs+) is gotten rid of, replaced with a new standard way
of adding variety to regular nodes.

This document describes the various interfaces that Subnodes provides and
explains their usage. When in doubt, consult the source code.


Terminology
-----------

* A **regular node** is a full solid (walkable) node 1 m³ in size, e.g. Stone,
  Apple Tree or Glass.
* A **subnode** is a node that exists as a partial variant of a regular node,
  e.g. Stone Stair or Red Wool Slab.
* A **subnode kind** is a category of subnodes, a type of variation, e.g. stair
  or microblock.


Functions
---------

* `subnodes.register_kind(name, def)`: Register a new subnode kind
  * `name`: the kind name, formatted as `"modname:kind_name"`
  * `def`: a Kind Definition table
* `subnodes.register_subnodes(node_name, node_subnodes_def)`: Register subnodes
  for a regular node
  * `node_name`: the node itemstring, i.e. `"modname:node_name"`
  * `def`: a table containing node definition overrides for the registered
    subnodes, indexed by kind name (can be empty)
* `subnodes.make_name_subname(node_name, kind_name)`: Construct strings for
  subnode processing from parameters
  * `node_name`: the node itemstring, i.e. `"nodes:stone"`
  * `kind_name`: the kind name, i.e. `"subnodes:block"` (doesn't have to be
    registered)
  * Returns:
    * the non-modname part of the node itemstring, i.e. `"stone"`
    * what would be the registered subnode itemstring, i.e. `"nodes:block_stone`
    * the subnode itemstring with modname replaced, i.e. `"subnodes:block_stone"`
      (only to be used when implementing backwards compatibility)
* `subnodes.create_drop_kind(kind_name)`: Returns a `drop` callback for a Kind
  Definition table to drop the equivalent subnode of the passed kind name
* `subnodes.is_suitable(node_def)`: Return `true` if the passed node definition
  is suitable to be turned into a subnode as-is


Tables
------

* `subnodes.registered_kinds`: All registered subnode kinds, indexed by kind
  name and containing Kind Definition tables
* `subnodes.registered_subnodes`: All registered subnodes, indexed by itemstring
  and referencing their node definitions
* `subnodes.subnode_definitions`: All registered subnode definitions, indexed by
  regular node itemstring (used internally to resolve registration conflicts)


Kind Definition
---------------

All fields are optional on their own. Here, they are ordered by the time they
are first accessed during a subnode registration.

```lua
{
	node_override = {...}, -- node definition override to apply to a new subnode
	get_readable_name = function(node_description)
		return "" -- new description
	end,
	get_tiles = function(tiles, align_style)
		return {} -- new tiles table
	end,
	drop = "itemstring" or function(subnode_name, node_name)
		return "itemstring"
	end,
	on_register = function(subnode_name, subnode_def, node_name, node_def) end,
	get_crafts = function(subnode_name, node_name) -- as in "crafting recipes"
		return {output = subnode_name, recipe = {{node_name}}}, ...
	end,
	after_register = function(subnode_name, node_name) end, -- ideal for aliases
}
```
