Welcome to Databind’s documentation!¶
Contents:
Getting Started¶
Get started with Databind.
Library¶
If you’re looking to use the Databind library in your own Rust project, then look at the docs hosted on docs.rs.
Installation¶
Databind is build and installed from source using cargo.
With cargo installed, run cargo install databind
to get the latest version.
If Rust is in your path, then you should be able to access the CLI by running
databind
in any command line.
Built binaries are also available on the GitHub releases page.
Creating a Project¶
To create a new project, use the databind create
command.
USAGE:
databind create [OPTIONS] <NAME>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
--description <DESCRIPTION> The pack description [default: A databind pack]
--path <PATH> The path to create the pack in
ARGS:
<NAME> The name of the project
Example use:
databind create my_project
to create a new project in a folder
called my_project
.
databind create --description "My first project" my_project
to create a new project with the description My first project
.
databind create --path . my_project
to create a new project
in the current directory. Only works if empty.
Writing Code¶
Below is the default main.databind
file. .databind
files
can only be used to contain function definitions.
func main
tag load
tellraw @a "Hello, World!"
end
First, a function named main is defined. The name can be changed, it doesn’t
have to be main. Then, it is tagged with load
. This tag is
normal to datapacks and means that a function will run when the datapack is
initially loaded. After that, an ordinary tellraw
, and then end
to close the function definition.
When compiled, this will create a file called main.mcfunction
that contains
the following:
tellraw @a "Hello, World!"
A load.json
file will also be generated in minecraft/tags/functions
to give the function a load tag.
Building¶
To build your project, run databind
in the root directory of your project.
Alternatively, you can run databind <PATH>
where <PATH>
is the path to
your project.
Additional Files¶
You are able to create as many .databind
files and as many namespaces as
you’d like. You are also able to mix normal .mcfunction
files with .databind
files, meaning you don’t have to have a project that only uses Databind. This
is helpful if you want to convert a normal datapack to a Databind project.
Databind files cannot contain anything other than function definitions, so something
such as this alone in a .databind
file:
say Hello, World!
Would not generate any output.
Syntax¶
Syntax |
Notes |
---|---|
|
Define a new variable |
|
Define a new scoreboard objective |
|
Set the value of an objective for a given target (eg. |
|
Update the value of an existing variable |
|
Used to test variables in |
|
Define a function. Generates a new mcfunction file |
|
Define a macro. See the macros page for more information |
|
Calls a macro. See the macros page for more information |
|
Ends a macro definition. See the macros page for more information |
|
Call a function. Can infer namespace based on directory (see function calling example) |
|
Starts an if statement |
|
Runs if an if statement’s condition was not true |
|
Create a while loop. Condition should be something passable to |
|
Close a function, while loop, or if statement |
|
Shorthand for |
|
Can be used with a scoreboard operation as such: |
|
Delete a variable or objective. Can be used interchangeably |
|
Used to escape keywords (eg. |
Assignment Operators |
|
|
Add to a variable |
|
Subtract from a variable |
|
Set the value of a variable |
Databind CLI¶
What Can Be Compiled¶
Databind compiles Databind projects (see Creating a Project).
Databind will look for included files (**/*.databind
by default) and
leave other files alone.
Note that the namespace inference used for func
assumes a proper
file structure (<datapack>/data/<namespace>/functions
for functions), but it
does not check if this is the case. A minecraft/tags/functions/
folder may
be generated in an unexpected place if an invalid folder is passed.
Using the CLI¶
USAGE:
databind [FLAGS] [OPTIONS] <PROJECT>
databind [FLAGS] [OPTIONS] <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
--ignore-config Ignore the config file. Used for testing
-V, --version Prints version information
OPTIONS:
-c, --config <FILE> Configuration for the compiler
-o, --out <DIRECTORY> The output file or directory [default: out]
ARGS:
<PROJECT> The Databind project to compile
SUBCOMMANDS:
create Create a new project
help Prints this message or the help of the given subcommand(s)
From an Installation¶
When installed, you can access the CLI by running databind
in any command line.
Running databind --help
will output the text above.
With cargo run
¶
After building Databind yourself, you can use cargo run
to run it. Everything
works almost the exact same. You just need to add two dashes (--
) after run
(eg. cargo run -- --help
).
Databind Configuration¶
Configuration File¶
Databind can be configured via the databind.toml
generated
in the project’s root. A config file can also be passed
with the -c
or --config
option.
This table represents the default values of the options if no config changes are made.
Option |
Notes |
---|---|
|
Specify what files to compile using globs |
|
Specify what files not to copy over/compile using globs |
|
The output file or folder |
Example Config¶
Below is a configuration file with all of the above settings.
inclusions = ["**/*.databind"]
exclusions = []
output = "out"
CLI Arguments¶
Most options that can be set in the databind.toml
file
can also be set using CLI arguments.
Example use:
databind -c config.toml -o ./target ./datapack
Macros¶
Macros in Databind are advanced functions that allow you to take arguments,
unlike traditional mcfunctions. All arguments must be surrounded
by double quotes ("
). Here is a macro that says “Hello” to a name you pass:
!def say_hello($name)
say Hello, $name!
!end
And here is how it would be called:
?say_hello("World")
The macro call above would become the following when compiled:
say Hello, World!
As you can see, the $name
in the body of the macro was replaced
with the "World"
string that was passed to it.
Macros that use Databind code¶
Macros are able to use Databind code just like any other place in a
.databind
file. Here is a macro that creates a variable with a name
that is passed to it, then announces a message to all players:
!def create_var($name)
var $name := 5
tellraw @a "A variable named $name was created."
!end
Macros that call other macros¶
Macros are also able to call other macros and pass arguments to them.
!def macro_1($name)
say Hello, $name!
!end
!def macro_2($name)
# There is a % before 'call' here because 'call' is a Databind keyword
# See the syntax table for info on escaping keywords
say I am about to %call macro_1
?macro_1("$name")
!end
Keep in mind that macro arguments must be surrounded by double quotes,
which is why macro_2
’s call of macro_1
is "$name"
instead of
just $name
.
Macros that define functions¶
Since macros can use any Databind code, this also means that they’re able to define functions. This makes it possible to create macros that set up a series of functions to avoid copy + pasting code.
!def create_toggle_function($funcname)
# This appends '_load' to the end of the function name
func $funcname_load
tag load
var $funcname_state := 0
var $funcname_toggled := 0
end
# This appends '_on' to the end of the function name
func $funcname_on
say $funcname has been enabled
var $funcname_state = 1
end
# This appends '_off' to the end of the function name
func $funcname_off
say $funcname has been disabled
var $funcname_state = 0
end
# This appends '_toggle' to the end of the function name
func $funcname_toggle
say Toggling $funcname
execute if tvar $funcname_state matches 1 run var $funcname_toggled = 1
execute if tvar $funcname_state matches 1 unless tvar $funcname_toggled matches 0 run call $funcname_off
execute if tvar $funcname_state matches 0 unless tvar $funcname_toggled matches 1 run call $funcname_on
var $funcname_toggled = 0
end
!end
This entire macro creates four functions per call:
A function that loads when the datapack is loaded (
$funcname_load
)A function that enables something (
$funcname_on
)A function that disables something (
$funcname_off
)A toggle function (calls
$funcname_on
when disabled and$funcname_off
when enabled)
These functions can all be created by running the following line:
?create_toggle_function("my_function")
Of course, creating functions that only say “Enabled” or “Disabled” isn’t useful in most situations. What would be useful is to be able to pass commands to run when the function is enabled, disabled, or toggled.
This is entirely possible using macros due to the fact that the arguments passed can be multiline.
If we change the macro above to look like this:
!def create_toggle_function($funcname, $on_cmds, $off_cmds)
# This appends '_load' to the end of the function name
func $funcname_load
tag load
var $funcname_state := 0
var $funcname_toggled := 0
end
# This appends '_on' to the end of the function name
func $funcname_on
var $funcname_state = 1
$on_cmds
end
# This appends '_off' to the end of the function name
func $funcname_off
var $funcname_state = 0
$off_cmds
end
# This appends '_toggle' to the end of the function name
func $funcname_toggle
execute if tvar $funcname_state matches 1 run var $funcname_toggled = 1
execute if tvar $funcname_state matches 1 unless tvar $funcname_toggled matches 0 run call $funcname_off
execute if tvar $funcname_state matches 0 unless tvar $funcname_toggled matches 1 run call $funcname_on
var $funcname_toggled = 0
end
!end
We’re now able to pass commands to run when the function is enabled and disabled. If we wanted a command that summoned an armor stand when enabled and killed it when disabled, we could call the macro like this:
# This formatting is not required, it's just to make the code
# easier to read
?create_toggle_function(
"astand",
"summon armor_stand ~ ~ ~
say Created armor stand",
"kill @e[type=armor_stand]
say Killed armor stand",
)
When compiled to a datapack, if we wanted to run our toggle function in-game, we could run the following:
/function namespace:astand_toggle
Files for macros¶
Any file whose name starts with an !
symbol is able to define macros
that work anywhere in the project. These files, if they only contain macros,
should generally be placed right in the src/
directory as opposed to
in a namespace’s functions/
directory, however you can place them wherever
you’d like.
It’s important to note that the reason the !
was chosen is that the compiler
goes through the src/
directory in alphabetical order. This means that if you,
for example, have two namespaces, abc
and xyz
, macros defined in xyz
will not be available in abc
. A good idea is to begin the names of any folders
containing macro definitions with an !
, similar to the files. That way, they are
always compiled first.
Macros that contain calls to other macros can be defined in any order. If you have the following two macros:
!def macro_1()
say Macro 1
!end
!def macro_2()
say Macro 2
?macro_1()
!end
You don’t have to define macro_1
before macro_2
; it’s only important that
they’re both defined before macro_2
is called. A project using macros might
have a file structure similar to this:
project_root
│ databind.toml
└───src
│ pack.mcmeta
├───!macros
│ !my_macro.databind
└───data
└───namespace
└───functions
main.databind
Global Vars¶
You can define global variables with a file called vars.toml
in the project root.
Keys and values aren’t put in a section of the .toml
, they’re just in the file. For example:
name="World"
This defines a global variable name
that can be used in your code.
Types¶
The TOML format supports datatypes other than just strings, such as
booleans and integers. Types that aren’t strings are converted to
strings. Booleans that are true
are turned into 1
, and
false
ones are turned into 0
. Floats like 1.0
are
truncated, but floats with non-zero decimals are left alone.
Using Global Vars¶
To use a global variable in your code, use an &
symbol followed
by the variable name. Like this:
say Hello, &name!
Which, with the vars.toml
defined above, becomes:
say Hello, World!
Instances of &varname
are directly replaced, meaning that
escaping them with a %
symbol doesn’t work. This means that
the following code:
say Hello, %&name!
won’t stop the replacement of &name
.
When to use¶
Global variables are useful to let users more easily configure aspects
of your datapack. This does mean that the project must be recompiled
whenever the configuration is changed, and that users must have Databind
downloaded to use the project. If you are only configuring number values,
eg. an amount of time to wait for something, then it might be easier for
people using your datapack to have a config.mcfunction
file somewhere in the
project that sets scoreboard values.
Folder Structure¶
How the folder structure of Databind works.
In a project started with databind create
, the file structure
might look something like this:
project_root
│ databind.toml
│ LICENSE
│ README.md
└──src
│ pack.mcmeta
│ pack.png
└───data
└───namespace
└───functions
main.databind
All of the Databind-related files (other than the configuration file) are contained in the src/ directory. Other files such as the project’s license and the README are just in the root. These files are not generated by default, but they’ve been added in the example to show where they might be placed.
It’s possible to create a project without using databind create
, but it’s
not ideal and bugs caused by it generally won’t be fixed.
Examples¶
Various examples on how to use Databind and its features.
Contents:
Function Examples¶
Examples using functions.
Contents:
Calling¶
Different ways to call a function.
function
command¶
Built into mcfunctions. Requires a namespace.
example/src/data/example/functions/main.databind
func example_func
say Hello, World!
end
func main
function example:example_func
end
call
(infer namespace)¶
Add namespaces to functions while compiling. Allows more freedom with directory names.
example/src/data/example/functions/main.databind
func example_func
say Hello, World!
end
func main
call example_func
end
Compiled, call example_func
becomes function example:example_func
.
call
(explicit namespace)¶
example/src/data/example/functions/main.databind
func example_func
say Hello, World!
end
func main
call example:example_func
end
Effectively the same as the function
command.
Simple Function¶
Example¶
A function that increments a counter and logs when it’s run.
example/src/data/example/functions/main.databind
func load
tag load
var counter := 0
end
func example
tellraw @a "Example_function run"
var counter += 1
end
Compiled¶
example/out/data/example/functions/load.mcfunction
scoreboard objectives add counter dummy
scoreboard players set --databind counter 0
example/out/data/example/functions/example.mcfunction
tellraw @a "Example_function run"
scoreboard players add --databind counter 1
If/Else Examples¶
Examples using if/else statements.
If statements use several files, so compiled output is not shown in the examples.
Contents:
Single If Statement¶
A lone if statement.
Example¶
example/src/data/example/functions/main.databind
func main
tag load
var test := 1
runif tvar test matches 1
say Test is equal to 1
end
end
If/Else¶
An if statement with an else
block.
Example¶
example/src/data/example/functions/main.databind
func main
tag load
var test := 1
runif tvar test matches 1
say Test is equal to 1
else
say Test is not equal to 1
end
end
Nested If Statements¶
Multiple if statements inside of each other.
example/src/data/example/functions/main.databind
func main
tag load
var i := 0
var j := 0
runif tvar i matches 0
runif tvar j matches 0
say i is 0 and j is 0
else
say i is 0 and j is not
end
end
end
Objective Examples¶
Examples using objectives.
Contents:
Create Objective¶
Create a scoreboard objective.
Example¶
# Create an objective points and set everyone's score to 100
obj points dummy
sobj @a points = 100
Compiled¶
scoreboard objectives add points dummy
scoreboard players set @a points 100
Deletion¶
Example¶
Define an objective and delete it.
obj objective dummy
delobj objective
# or
delvar objective
Compiled¶
scoreboard objectives add objective dummy
scoreboard objectives remove objective
Scoreboard Operations¶
Example¶
Define two objectives and use a scoreboard operation to multiply the first.
obj obj1
obj obj2
sobj @a obj1 = 5
sobj @a obj2 = 2
sbop @a obj1 *= @a obj2
Compiled¶
scoreboard objectives add obj1 dummy
scoreboard objectives add obj2 dummy
scoreboard players set @a obj1 5
scoreboard players set @a obj2 2
scoreboard players operation @a obj1 *= @a obj2
Variable Examples¶
Examples using variables.
Contents:
Create, Modify & Test¶
Example¶
# Create a variable called example and set it to 2
var example := 2
# Add 1 to example
var example += 1
# Subtract 2 from example
var example -= 2
# Set example to 1
var example = 1
# Say something if example is 1
execute if tvar example matches 1 run say Variable example is equal to 1!
Compiled¶
scoreboard objectives add example dummy
scoreboard players set --databind example 2
scoreboard players add --databind example 1
scoreboard players remove --databind example 2
scoreboard players set --databind example 1
execute if score --databind example matches 1 run say Variable example is equal to 1!
Deletion¶
Compiled¶
scoreboard objectives add variable dummy
scoreboard players set --databind variable 5
scoreboard objectives remove variable
Scoreboard Operations¶
Example¶
Define two variables and use a scoreboard operation to multiply the first.
var variable1 := 5
var variable2 := 2
sbop gvar variable1 *= gvar variable2
Compiled¶
scoreboard objectives add variable1 dummy
scoreboard players set --databind variable1 5
scoreboard objectives add variable2 dummy
scoreboard players set --databind variable2 2
scoreboard players operation --databind variable1 *= --databind variable2
While Examples¶
Examples using while loops.
Contents:
For Loop¶
A for loop-like while loop.
Example¶
example/src/data/example/functions/main.databind
func load
tag load
var i := 10
while tvar i matches 1..
tellraw @a "Variable i is above 0"
var i -= 1
end
tellraw @a "Variable i is at 0"
end
Compiled¶
When while loops are compiled, functions with random characters
at the end are created. In compiled examples, these characters
will be abcd
.
example/out/data/example/functions/load.mcfunction
scoreboard objectives add i dummy
scoreboard players set --databind i 10
function example:while_abcd
tellraw @a "Variable i is at 0"
example/out/data/example/functions/while_abcd.mcfunction
execute if score --databind i matches 1.. run function example:condition_abcd
example/out/data/example/functions/condition_abcd.mcfunction
tellraw @a "Variable i is above 0"
scoreboard objectives remove --databind i 1
function example:loop_abcd
Loop Until False¶
Use an integer as a boolean to loop until false.
Example¶
example/src/data/example/functions/main.databind
func load
tag load
var bool := 1
while tvar bool matches 1
tellraw @a "Bool is true"
end
end
Compiled¶
When while loops are compiled, functions with random characters
at the end are created. In compiled examples, these characters
will be abcd
.
example/out/data/example/functions/load.mcfunction
scoreboard objectives add bool dummy
scoreboard players set --databind bool 1
function example:while_abcd
example/out/data/example/functions/while_abcd.mcfunction
execute if score --databind bool matches 1 run function example:condition_abcd
example/out/data/example/functions/condition_abcd.mcfunction
tellraw @a "Bool is true"
function example:while_abcd