The official MCA compiler outputs an intermediatery language called MCIL (Minecraft Intermediate Language). This allows compilation results to be converted to various different formats. This language provides a list of branches, which are made up of multiple nodes. Nodes are instructions, such as to run a command, wait a certain amount of time, or start another branch.

While MCIL is typically generated by an MCA compiler, it can also be written by hand if required.

An MCIL file should be formatted as JSON in a .mcil or .mcl file, or in the MessagePack format in a .mcib or .mcb file.

Basic Structure

The root of an MCIL file is an array containing one or more sub-arrays. Each of these sub-arrays represents a branch, and the branches ID is determined from its index in the root array, where the index start from 0 (i.e. the branch with ID 0 is the first branch, ID 1 is the second, etc).

When an MCIL program is executed, the first branch (with ID 0) should be executed. Other branches are accessed with the branch node (more on this later).

Nodes

Each branch array contains zero or more 'node' objects. All of these objects have a type property, which specifies the type of the node. When 'executing' a branch, execution should start at the first node (i.e with index 0), and continue until the end of the branch.

command type

This node contains a Minecraft command to be executed. It contains the following properties:

  • string node.command - The name of the command to execute, without a slash (e.g. say, testfor, etc).
  • string node.params - The parameters to pass to the command, separated by a space. If no parameters are supplied, the string will be empty.
  • optional string node.name - The name of the command block - this is typically used in commands such as say before the provided text. If not provided, it should be #.

Some commands allow relative positions to be provided in the parameters. These relative commands should always be relative from the same location (e.g. ~1 ~2 ~3 in one command should end up using the same location as another command that contains the same coordinates). To aid this transformation, MCIL supports some "relative position flags".

To calculate the new values for relative commands, it is first necessary to figure out which relative positions relate to which coordinates. By default, the first coordinate should be assumed to be on the X-axis, the second on the Y-axis, the third on the Z-axis, the fourth on the X-axis, the fifth on the Y-axis, etc.

If a relative position ends with an asterisk (*), the position should not be changed and should be used as-is. This is called an 'absolute' flag. Additionally, there are three similar flags that can be used to force a certain axis. If a relative position ends with an x character, it should be assumed to be on the X-axis. If it ends with a y character, the Y-axis should be used. If it ends with a z character, the Z character should be used. All of these should be case insensitive.

When an axis flag is used (x, y, or z), the 'axis counter' should be updated. That is, if a y flag is used for one coordinate, the next should be assumed to be on the Z-axis, and the next to be on the X-axis, etc. This does not apply for the absolute flag (that is, the 'axis counter' should increment normally - ~5 ~2* ~3 should use the X-axis for ~5, not change ~2, and use the Z-axis for ~3).

wait type

This node instructs the executor to wait a certain number of 'redstone ticks' before continuing, where one 'redstone tick' is approximately 0.1 seconds. This node has the following properties:

  • number node.duration - The number of redstone ticks to wait

branch type

This node starts executing another branch. The current branch should continue executing if it has any nodes remaining. This node contains the following properties:

  • number node.id - The ID of the branch to switch to.
  • optional object node.test - A test command node

The test property can be used to start executing the new branch conditionally. It contains a node with command type, which should be executed before branching. If the command is successfully executed, the branch should start.

sync type

This node is used to synchronise two branches. When encountered in a branch, execution on the branch should halt until a corresponding endsync node is encountered in the referenced branch. The node contains the following properties:

  • number node.id - The ID of the branch to sync with.

When sync is encountered, the current branch should be halted until the referenced branch has its 'resumeable' flag set for the current branch. If so, the flag should be disabled for the current branch, and execution should continue on this branch.

endsync type

This node is used to signify when a synced branch can continue. This node contains the following properties:

  • number node.id - The ID of the branch to end syncing with.

When this node is encountered, the 'resumeable' flag for the referenced branch should be enabled. This means that if an endsync node is encountered in one branch before a sync node in another, the sync will immediately resume.

Branch Execution Priority

The MCIL documentation does not specify the priority for executing branches. As a result, branch execution can occur in any order (e.g. branch 1 triggers branch 2, branch 1 finished, then branch 2 is executed, or branch 1 triggers branch 2, branch 2 is executed and finished, then branch 1 is finished), interpolated (e.g. one command block from branch 1, one from branch 2, etc), or even simultaneously. As a result, sync should be used if any operations in one branch depend on another branch's completion.