Language Overview
Scripts¶
Terracotta scripts use the extension .tc and contain code that is compiled to DiamondFire templates.
Unlike old Terracotta, a single script can now contain multiple events/functions/processes.
function send_centered_message(message: txt) {
allPlayers.sendMessage(message, align="Centered");
}
playerevent join {
send_centered_message(s"%default <green>has joined!");
}
Semantics¶
Terracotta is a non-whitespace-significant language that relies on semicolons to separate instructions. This means complex lines can be arbitrarily split up however you see fit because it's ultimately the semicolons that differentiate between them.
default.displayParticleEffect(par("Block",amount=10, material="diamond_block"), default.location);
default.displayParticleEffect(
par(
"Block",
amount=10,
material="diamond_block"
),
default.location
);
Anything that involves sectioning off chunks of code (like if statements or loops) does so with curly braces.
if (player.hasPlotPermission(permission="Owner")) {
player.sendMessage("You are the owner!");
}
while (default.attackCooldownTicks > 0) {
player.givePotionEffect(pot("Slowness"));
wait;
}
default.clearPotionEffects();
Expressions¶
Nearly every place in Terracotta that accepts a value accepts an expression. This means equations and even other action calls can be inlined, avoiding the need to use temporary variables.
function colored_particle_trail(hue: num) {
allPlayers.displayParticleEffect(
par(
var.setToRandom("Entity Effect","Dust"),
amount = num.random(1,5),
color = var.setToHSBColor(hue * 2,100,100)
),
default.location.shiftAllAxes(0,0.1,0)
);
}
Types¶
Terracotta's type system allows variables to keep track of what kinds of values they should be storing. Not only is this critical for using variables in expressions, but it also allows you to have a level of type-safety that normally doesn't exist in DiamondFire.
Some level of type inference does exist, but it's recommended to explicitly type variables when they're declared.
line test: num = 5 * 2;
// test's type will be inferred as 'num' if a type isn't provided
line test = 5 * 2;
Generic types are also supported. Type inference will NOT infer the subtypes of lists and dictionaries, so explicit typing is even more important here.
line numbers: list[num] = [5, 10, 15];
// if you didn't declare the type as list[num], you may encounter buggy behavior
line numbers = [5, 10, 15]; // numbers is typed as list[any] here
Use the declare keyword!
When you declare a global, saved, or local variable, that declaration will be limited to the file or event/function/process it is placed in. If you want to make a variable's type known to all files, put the declare keyword before its declaration.
// This coins variable will now be available for use in all files
declare saved "coins %uuid": num;
gameevent startup {
// Declaring inside events/functions/processes is useful when you need to
// initialize a variable right away but still have it be accessible everywhere
declare global config = /* ... */;
}
As long as you properly declare your variable's types you shouldn't run into any type issues, but if you ever need to tell the compiler to treat a variable a certain way you can use the as keyword.
line power; // will be typed as 'any'
player.launchUp(power as num); // this WOULD throw an error without the typecast
More detailed information on the type system can be found here.
Item Libraries¶
Item Libraries are Terracotta's solution for representing items with complex data. Library items can be imported from your Minecraft inventory, and can later be edited in-game and will be synced back to your project files live.

Saved items with complex nbt can be easily referenced in code with the litem() function.
More detailed information on Item Libraries can be found here.
Comments¶
Single-line comments start with //.
// Sends a message to the player
// TODO: Add color codes
player.sendMessage("Hello world!"); // End-of-line comment
// Code can be commented out to disable it:
//default.playSound(snd("Pling"));
Block comments are surrounded with /* and */.
/*
* Multi!
* Line!
* Comment!!!
*/
/*
the stars on the side
are also not necessary
*/
/* it can also be all on one line */
Adding an extra star to the start of a block comment (/**) turns it into a documentation comment.
/**
* This text will show up in test's autocomplete entry!
*/
function test(
/** This text will show up when you're calling test! */
wow: str
) {
print(wow);
}
Documentation comments can be applied to:
- Functions
- Processes
- Parameters
- Variable Declarations
- Dictionary keys (in variable declarations)
¶
Next: Read more on Expressions or Types, learn about Item Libraries, see how Actions and Variables work, or just start messing around and reference these docs as needed!