Tutorial 02: Variables and Types
Difficulty: Beginner
Time: ~25 minutes
Prerequisites: Tutorial 01
Goal
Learn how to store values with let and const, then work with the most important beginner-friendly types: int, double, string, and bool.
let and const
Use let for mutable variables:
let score: int = 0
let running: bool = trueUse const for compile-time constants:
const MAX_ROUNDS: int = 5
const GREETING: string = "Welcome!"The practical difference:
letcan change laterconstcannot change and must be a literal constant
int
int is the default numeric type for counters, timers, rounds, health-like values, and scoreboard-oriented logic.
let lives: int = 3
let wave: int = 1
wave = wave + 1Use int first unless you know you need fractional values or higher precision.
double
double is useful when you need floating-point precision.
let gravity: double = 9.81
let launch_angle: double = 45.0 as doubleRedScript does not do implicit numeric conversion. Cast intentionally:
let count: int = 5
let precise: double = count as doubleIf you only need whole numbers, stick with int. It is simpler and usually cheaper.
string
Use string for names, messages, and IDs.
let player_name: string = "Alex"
let item_id: string = "minecraft:golden_apple"For output, prefer f-strings:
let score: int = 12
say(f"Current score: {score}")bool
bool stores true or false.
let running: bool = false
let debug_mode: bool = trueBooleans work naturally in conditions:
if (debug_mode) {
say("Debug mode is enabled")
}Type Inference
You do not always have to write the type if the initializer is obvious:
let coins = 10
let title = "Shop"
let enabled = trueFor tutorials and early learning, explicit annotations are often clearer.
Arrays, Selectors, and Optional Values
The first four scalar types are enough for simple scripts, but most real datapacks also use three container/boundary types.
Arrays
Arrays hold repeated values of one type:
let rewards: int[] = [5, 10, 20]
let names: string[] = ["Lobby", "Arena", "Finale"]
let first_reward: int = rewards[0]
let reward_count: int = rewards.lenUse arrays when the set is small and known, or when you want to loop over a table of values later.
Selectors
Selectors represent Minecraft entity targets such as all players, the current executor, or filtered entities:
let everyone: selector = @a
let self: selector = @s
let nearby_zombies: selector = @e[type=zombie,distance=..10]They become most useful with foreach and execute context in later tutorials.
Option<T>
Use Option<T> when a value may be absent:
let found_score: Option<int> = Some(42)
let missing_score: Option<int> = NoneYou will handle options with if let Some(x) = value in the control-flow tutorial.
Small State Example
namespace tutorial02
const START_LIVES: int = 3
let lives: int = START_LIVES
let level_name: string = "Training Grounds"
let active: bool = false
let spawn_x: double = 12.5
@load
fn setup() {
active = true
say(f"Loaded {level_name}")
say(f"Lives: {lives}")
}This example shows a common pattern:
- constants for stable config
- mutable variables for game state
- strings for readable messages
- booleans for mode flags
- doubles for exact positions or calculations when needed
Updating Variables
@on_trigger("lose_life")
fn lose_life() {
if (lives > 0) {
lives = lives - 1
say(f"Lives left: {lives}")
}
}Casting Between int and double
fn average(total: int, players: int) -> double {
return total as double / players as double
}The explicit casts matter. They tell the compiler exactly which arithmetic model you want.
Full Example
namespace tutorial02
const START_LIVES: int = 3
const PACK_NAME: string = "Training Pack"
let lives: int = START_LIVES
let active: bool = false
let accuracy: double = 0.95
@load
fn setup() {
active = true
say(f"{PACK_NAME} loaded")
say(f"Accuracy target: {accuracy}")
}
@on_trigger("status")
fn status() {
tell(@s, f"Lives: {lives}")
tell(@s, f"Active: {active}")
}
@on_trigger("lose_life")
fn lose_life() {
if (lives > 0) {
lives = lives - 1
tell(@s, f"Lives left: {lives}")
}
}Practice
- Add a
const PACK_VERSION: string. - Add a
doublefor movement speed or radius. - Add a
boolthat toggles a debug message.