Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/BunnyNabbit/celaria-formats/llms.txt

Use this file to discover all available pages before exploring further.

Celaria uses two binary map formats: .cmap files are finalized maps used by the game server and contain medal times for timed runs, while .ecmap files are editor maps opened in Celaria’s built-in map editor and do not require medal times. Both formats are parsed with a static parse(buffer) method that returns a fully populated map instance.

Reading .cmap files

Use CelariaMap.parse(buffer) to load a finalized map. Pass a Node.js Buffer — typically read from disk with fs.readFileSync.
import fs from "node:fs"
import { CelariaMap } from "celaria-formats"

const buffer = fs.readFileSync("./myMap.cmap")
const map = CelariaMap.parse(buffer)

console.log(map.name)            // map name string
console.log(map.version)         // 0, 1, or 2
console.log(map.mode)            // 0 = freeRoam, 1 = timeTrial
console.log(map.instances)       // array of all map objects
console.log(map.checkpointOrder.toArray()) // checkpoints in sequence order
The mode property reflects the game mode: CelariaMap.gameModes.freeRoam (0) or CelariaMap.gameModes.timeTrial (1). The default is timeTrial. After parsing, every checkpoint and goal Block in the map has its medalTimes property populated with { platinum, gold, silver, bronze } values (in ticks).
Version differences are handled automatically by parse. In versions 0 and 1, positions and scales are stored as scaled integers; in version 2 they use 64-bit doubles. You always get consistent floating-point values regardless of the source version.

Reading .ecmap files

Use EditableCelariaMap.parse(buffer) to load an editor map. The API is identical to CelariaMap.parse.
import fs from "node:fs"
import { EditableCelariaMap } from "celaria-formats"

const buffer = fs.readFileSync("./myMap.ecmap")
const map = EditableCelariaMap.parse(buffer)

console.log(map.name)
console.log(map.instances)
console.log(map.checkpointOrder.toArray())
Unlike CelariaMap, an EditableCelariaMap does not store or require medal times — checkpoint and goal blocks will have medalTimes as undefined after parsing. Checkpoints are still ordered via checkpointOrder.
import fs from "node:fs"
import { CelariaMap } from "celaria-formats"

const map = CelariaMap.parse(fs.readFileSync("./myMap.cmap"))

// Medal times are available on checkpoint/goal blocks
for (const block of map.checkpointOrder.toArray()) {
  console.log(block.medalTimes.platinum) // ticks
  console.log(block.medalTimes.gold)
  console.log(block.medalTimes.silver)
  console.log(block.medalTimes.bronze)
}

Filtering instances by type

map.instances is a flat array containing every object in the map. You can filter it by instanceId to work with a specific type:
instanceIdClassDescription
0BlockSolid rectangular prism geometry
1SphereCollectible gem
2PlayerSpawnPointPlayer start position
3Barrier (wall)Invisible wall barrier
4Barrier (floor)Invisible floor barrier
128TutorialHologramTutorial hologram object
import { Block, Sphere, PlayerSpawnPoint, Barrier } from "celaria-formats"

// Filter by instanceId
const blocks = map.instances.filter(i => i.instanceId === 0)
const spheres = map.instances.filter(i => i.instanceId === 1)
const spawns = map.instances.filter(i => i.instanceId === 2)
const barriers = map.instances.filter(i => i.instanceId === 3 || i.instanceId === 4)

// Or filter by instanceof
const blocksByClass = map.instances.filter(i => i instanceof Block)
const spheresByClass = map.instances.filter(i => i instanceof Sphere)
Both approaches produce the same results. Filtering by instanceof is more readable when you have the class imported; filtering by instanceId avoids the import when you only need the number.

Build docs developers (and LLMs) love