Skip to content

Helpers & Registries

Ceremony scripts have access to a set of built-in helpers and pre-wrapped Minecraft registries. These globals are available in every script without imports.


Vec3 provides 3D vector math for positions, directions, distances, and movement calculations. It supports both static operations (take values, return new values) and instance methods (operate on a Vec3Instance).

// From three numbers
const a = Vec3.of(10, 65, -30);
// From an object with x, y, z properties
const b = Vec3.of({ x: 10, y: 65, z: -30 });
// Zero vector constant
const origin = Vec3.ZERO; // (0, 0, 0)

Many Vec3 methods accept a Vec3Like parameter, which can be any of:

FormatExample
Vec3InstanceVec3.of(1, 2, 3)
Object with x, y, z{ x: 1, y: 2, z: 3 }
Array of three numbers[1, 2, 3]

This means you can pass player positions, block positions, or raw arrays interchangeably:

const playerPos = wrapPlayer(player).pos;
const distance = Vec3.distance(playerPos, [100, 65, 200]);

Static methods take Vec3Like parameters and return new Vec3Instance values.

MethodSignatureDescription
Vec3.of(x, y, z) or ({x, y, z})Create a new Vec3Instance
Vec3.add(a: Vec3Like, b: Vec3Like)Add two vectors
Vec3.subtract(a: Vec3Like, b: Vec3Like)Subtract b from a
Vec3.scale(v: Vec3Like, scalar: number)Multiply vector by scalar
Vec3.normalize(v: Vec3Like)Return unit vector (length 1)
Vec3.distance(a: Vec3Like, b: Vec3Like)Euclidean distance between two points
Vec3.distanceSq(a: Vec3Like, b: Vec3Like)Squared distance (faster, no sqrt)
Vec3.direction(from: Vec3Like, to: Vec3Like)Normalized direction from one point to another
Vec3.dot(a: Vec3Like, b: Vec3Like)Dot product
Vec3.cross(a: Vec3Like, b: Vec3Like)Cross product
Vec3.lerp(a: Vec3Like, b: Vec3Like, t: number)Linear interpolation (t=0 returns a, t=1 returns b)
Vec3.length(v: Vec3Like)Vector length/magnitude
const a = Vec3.of(0, 64, 0);
const b = Vec3.of(100, 70, 50);
const mid = Vec3.lerp(a, b, 0.5); // Midpoint
const dir = Vec3.direction(a, b); // Unit direction from a to b
const dist = Vec3.distance(a, b); // Distance between points
const offset = Vec3.add(a, [0, 10, 0]); // 10 blocks above a
const scaled = Vec3.scale(dir, 5); // 5 blocks in direction

Vec3Instance objects (returned by Vec3.of() and all static methods) have these methods:

MethodSignatureReturnsDescription
add(other: Vec3Like)Vec3InstanceAdd another vector
subtract(other: Vec3Like)Vec3InstanceSubtract another vector
scale(scalar: number)Vec3InstanceScale by a number
normalize()Vec3InstanceReturn unit vector
distanceTo(other: Vec3Like)numberDistance to another point
distanceToSqr(other: Vec3Like)numberSquared distance to another point
length()numberVector magnitude
dot(other: Vec3Like)numberDot product
cross(other: Vec3Like)Vec3InstanceCross product
lerp(other: Vec3Like, t: number)Vec3InstanceInterpolate toward another vector

Instance properties: x, y, z (all numbers, read-only).

const pos = Vec3.of(10, 65, 20);
const moved = pos.add([5, 0, 5]); // (15, 65, 25)
const dist = pos.distanceTo([100, 65, 100]); // Distance as a number
const dir = pos.subtract([0, 65, 0]).normalize(); // Direction from origin at y=65
const half = pos.scale(0.5); // (5, 32.5, 10)

Teleport player 5 blocks in the direction they are looking:

Events.on('useItem', (player, hand, stack, level) => {
const p = wrapPlayer(player);
const target = p.pos.add(p.lookAngle.scale(5));
p.teleport(target.x, target.y, target.z);
});

Check if a player is within 10 blocks of a point:

const shrine = Vec3.of(500, 72, -300);
Events.on('serverTick', (server) => {
// Only check every 20 ticks (1 second)
if (server.getTickCount() % 20 !== 0) return;
server.getPlayerList().getPlayers().forEach((player) => {
const p = wrapPlayer(player);
if (p.pos.distanceTo(shrine) < 10) {
p.sendActionBar('<light_purple>You feel a warm presence...');
}
});
});

The Java.type() function gives you direct access to Java classes from within scripts. This is the escape hatch for anything not covered by the built-in helpers.

const BlockPos = Java.type('net.minecraft.core.BlockPos');
const ResourceLocation = Java.type('net.minecraft.resources.ResourceLocation');
const BuiltInRegistries = Java.type('net.minecraft.core.registries.BuiltInRegistries');
const AABB = Java.type('net.minecraft.world.phys.AABB');
const MobEffectInstance = Java.type('net.minecraft.world.effect.MobEffectInstance');
const Component = Java.type('net.minecraft.network.chat.Component');
ClassImport PathUse Case
BlockPosnet.minecraft.core.BlockPosBlock coordinate positions
ResourceLocationnet.minecraft.resources.ResourceLocationRegistry identifiers
BuiltInRegistriesnet.minecraft.core.registries.BuiltInRegistriesAccess all registries
AABBnet.minecraft.world.phys.AABBAxis-aligned bounding boxes
MobEffectInstancenet.minecraft.world.effect.MobEffectInstanceEffect application
Componentnet.minecraft.network.chat.ComponentChat/text components
ItemStacknet.minecraft.world.item.ItemStackItem stack manipulation
CompoundTagnet.minecraft.nbt.CompoundTagNBT data

Java collections do not have JavaScript array methods. Use .size() and .get(i) to iterate:

const players = Server.getPlayerList().getPlayers();
// Iterate using size/get
for (let i = 0; i < players.size(); i++) {
const player = players.get(i);
wrapPlayer(player).sendMessage('<gray>Announcement: Server restart in 5 minutes');
}
const BlockPos = Java.type('net.minecraft.core.BlockPos');
const pos = new BlockPos(100, 65, 200);
const AABB = Java.type('net.minecraft.world.phys.AABB');
const box = new AABB(0, 0, 0, 100, 100, 100);
// Find entities in a bounding box
const level = Server.overworld();
const entities = level.getEntities(null, box);

The Logger global provides structured logging that writes to the server console with the [Ceremony] prefix.

MethodSignatureDescription
Logger.info(message: string, ...args: any)Informational message
Logger.warn(message: string, ...args: any)Warning message
Logger.error(message: string, ...args: any)Error message
Logger.debug(message: string, ...args: any)Debug message (only visible with debug logging enabled)

All methods support {} placeholders that are replaced by the additional arguments in order:

Logger.info('Player {} joined from dimension {}', player.getName().getString(), 'overworld');
// Output: [Ceremony] Player Steve joined from dimension overworld
Logger.warn('Low TPS detected: {}', server.getAverageTickTime());
Logger.error('Failed to load data for player {}', uuid);
Logger.debug('Tick count: {}, entities loaded: {}', tickCount, entityCount);

State is a global key-value store shared across all scripts. It lives in memory for the duration of the server session and is useful for cross-script communication and runtime flags.

MethodSignatureReturnsDescription
State.get(key: string)anyGet a value (returns undefined if not set)
State.set(key: string, value: any)voidSet a value
State.has(key: string)booleanCheck if a key exists
State.remove(key: string)voidDelete a key
State.keys()string[]Get all stored keys
// Script A: Set a global flag
State.set('event_active', true);
State.set('event_name', 'Double XP Weekend');
State.set('event_multiplier', 2);
// Script B: Read the flag
if (State.has('event_active') && State.get('event_active')) {
const multiplier = State.get('event_multiplier');
Logger.info('Event active: {} ({}x)', State.get('event_name'), multiplier);
}
boss-spawner.js
State.set('boss_alive', true);
State.set('boss_health', 500);
Events.on('entityDeath', (entity, source, amount) => {
if (entity.getName().getString() === 'World Boss') {
State.set('boss_alive', false);
State.remove('boss_health');
}
});
// rewards.js
Events.on('entityKilledOther', (level, killer, killed) => {
if (killed.getName().getString() === 'World Boss' && killer.isPlayer()) {
const p = wrapPlayer(killer);
p.sendMessage('<gold>You defeated the World Boss!');
p.giveItem('minecraft:nether_star', 1);
}
});
// announcer.js
let lastAnnounced = false;
Events.on('serverTick', (server) => {
if (server.getTickCount() % 200 !== 0) return;
const alive = State.get('boss_alive');
if (alive && !lastAnnounced) {
// Announce boss is alive
server.getPlayerList().getPlayers().forEach((p) => {
wrapPlayer(p).sendMessage('<red>A World Boss has appeared!');
});
lastAnnounced = true;
} else if (!alive) {
lastAnnounced = false;
}
});

Ceremony pre-wraps common Minecraft registries as global objects. These give you direct access to registry entries by name, avoiding the need to manually look up ResourceLocation keys.

GlobalDescriptionExample Values
ParticleTypesParticle type registryParticleTypes.FLAME, ParticleTypes.END_ROD, ParticleTypes.HEART
SoundEventsSound event registrySoundEvents.ENTITY_PLAYER_LEVELUP, SoundEvents.BLOCK_ANVIL_LAND
ItemsItem registryItems.DIAMOND, Items.IRON_SWORD, Items.GOLDEN_APPLE
BlocksBlock registryBlocks.STONE, Blocks.DIAMOND_ORE, Blocks.OBSIDIAN
MobEffectsMob effect (potion) registryMobEffects.SPEED, MobEffects.STRENGTH, MobEffects.NIGHT_VISION
EntityTypesEntity type registryEntityTypes.ZOMBIE, EntityTypes.ARMOR_STAND, EntityTypes.CREEPER
// Check if a broken block is diamond ore
Events.on('blockBreak', (player, pos, state, level) => {
if (state.getBlock() === Blocks.DIAMOND_ORE) {
const p = wrapPlayer(player);
p.sendMessage('<aqua>You found diamonds!');
p.playSound('minecraft:entity.player.levelup');
}
});
// Spawn particles at a location
const spawnParticles = (level, pos, particleType, count) => {
level.sendParticles(
particleType,
pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5,
count,
0.3, 0.3, 0.3, // spread
0.01 // speed
);
};
Events.on('useBlock', (player, pos, hand, hitResult, level) => {
spawnParticles(level, pos, ParticleTypes.FLAME, 20);
});

Registry keys use UPPER_SNAKE_CASE in the global objects. The names correspond to Minecraft’s internal names:

Minecraft IDRegistry Global
minecraft:diamondItems.DIAMOND
minecraft:stoneBlocks.STONE
minecraft:speedMobEffects.SPEED
minecraft:zombieEntityTypes.ZOMBIE
minecraft:entity.player.levelupSoundEvents.ENTITY_PLAYER_LEVELUP
minecraft:flameParticleTypes.FLAME

The Potions registry provides access to potion types for use with brewing and tipped arrows.

ConstantDescription
Potions.HEALINGInstant Health potion
Potions.STRONG_HEALINGInstant Health II
Potions.HARMINGInstant Damage potion
Potions.POISONPoison potion
Potions.REGENERATIONRegeneration potion
Potions.STRENGTHStrength potion
Potions.SPEEDSpeed potion
Potions.LONG_SPEEDSpeed (extended)
Potions.STRONG_SPEEDSpeed II
Potions.NIGHT_VISIONNight Vision potion
Potions.INVISIBILITYInvisibility potion
Potions.FIRE_RESISTANCEFire Resistance potion
Potions.WATER_BREATHINGWater Breathing potion
Potions.SLOW_FALLINGSlow Falling potion
Potions.TURTLE_MASTERTurtle Master potion
// Example: check what potion type a tipped arrow has
const potionType = Potions.HEALING;
Logger.info('Potion: ' + potionType);

The Attributes registry provides access to entity attribute types (health, speed, damage, etc.) for use with attribute modifiers.

ConstantDescription
Attributes.MAX_HEALTHMaximum health (default 20)
Attributes.MOVEMENT_SPEEDMovement speed (default 0.1)
Attributes.ATTACK_DAMAGEAttack damage (default 1.0)
Attributes.ATTACK_SPEEDAttack speed (default 4.0)
Attributes.ARMORArmor value
Attributes.ARMOR_TOUGHNESSArmor toughness
Attributes.KNOCKBACK_RESISTANCEKnockback resistance (0-1)
Attributes.LUCKLuck (affects loot tables)
Attributes.FOLLOW_RANGEMob follow range
Attributes.FLYING_SPEEDFlying speed (for flying mobs)
Attributes.SPAWN_REINFORCEMENTSZombie reinforcement chance
// Example: temporarily boost a player's max health
Events.on('playerJoin', (player) => {
const p = wrapPlayer(player);
const attr = player.getAttribute(Attributes.MAX_HEALTH);
Logger.info(p.name + ' max health: ' + attr.getValue());
});

These globals are always available in Ceremony scripts.

The MinecraftServer instance. Use it to access player lists, worlds, execute commands from the server console, and more.

// Get all online players
const players = Server.getPlayerList().getPlayers();
// Get the overworld
const overworld = Server.overworld();
// Execute a command as the server
Server.getCommands().getDispatcher().execute(
'say Hello from Ceremony!',
Server.createCommandSourceStack()
);
// Get current tick count
const tick = Server.getTickCount();

The Ceremony plugin API. Provides access to Ceremony-specific features like regions, displays, HUD, and more.

// Access the Ceremony API
const api = CeremonyAPI;
// Example: work with regions, displays, etc.
Logger.info('Ceremony API version: {}', Ceremony.getVersion());

The MoLang context object. Provides access to MoLang query, variable, temp, array, and math systems for integration with Journey’s MoLang-based features.

PropertyDescription
context.query / ctx.queryMoLang query functions
context.variable / ctx.variableMoLang variables
context.temp / ctx.tempMoLang temporary storage
context.array / ctx.arrayMoLang array access
context.math / ctx.mathMoLang math functions
// Read a MoLang variable
const level = ctx.query.player_level;
// Set a temp variable for MoLang expressions
ctx.temp.custom_value = 42;

Here is a complete script that uses Vec3, Logger, State, Java interop, and registries together to create a “sacred grove” area that heals players, spawns particles, and tracks visitors.

const groveCenter = Vec3.of(250, 68, -100);
const groveRadius = 15;
State.set('grove_visitors', 0);
Events.on('serverTick', (server) => {
if (server.getTickCount() % 40 !== 0) return; // Every 2 seconds
const overworld = Server.overworld();
const players = server.getPlayerList().getPlayers();
for (let i = 0; i < players.size(); i++) {
const raw = players.get(i);
const p = wrapPlayer(raw);
const dist = p.pos.distanceTo(groveCenter);
if (dist < groveRadius) {
// Heal the player
p.addEffect('minecraft:regeneration', {
duration: 60,
amplifier: 0,
visible: false
});
// Spawn particles around them
overworld.sendParticles(
ParticleTypes.HAPPY_VILLAGER,
p.pos.x, p.pos.y + 1, p.pos.z,
5, 1.0, 0.5, 1.0, 0.01
);
// Track unique visitors
if (!p.data.getBoolean('visited_grove')) {
p.data.set('visited_grove', true);
State.set('grove_visitors', State.get('grove_visitors') + 1);
p.sendMessage('<green>You discovered the Sacred Grove!');
p.playSound('minecraft:block.amethyst_block.chime', { pitch: 1.5 });
Logger.info('{} discovered the Sacred Grove (total visitors: {})',
p.name, State.get('grove_visitors'));
}
}
}
});

  • Use Vec3.distanceSq instead of Vec3.distance when you only need to compare distances — it avoids the square root calculation and is faster.
  • Registry globals are read-only lookups. You cannot add or modify registry entries at runtime.
  • State is great for runtime flags, but remember it resets on server restart. Use PlayerData for anything that needs to persist.
  • Keep Java.type() imports at the top of your script for readability, similar to import statements in other languages.
  • The Server global is not available during script loading — it is set once the server has started. Use the serverStarted event if you need to run initialization logic that depends on it.