Skip to content

Worlds and Resources

override suspend fun createGameWorldSuspend(): GameWorld =
worlds.pooled(getStartPlayers())

Available acquisition helpers:

worlds.pooled(players, slot = "main")
worlds.flat(generatorSettings, players, slot = "main")
worlds.map(resourceId = "arena_one", players, slot = "main")

worlds.map(...) accepts either a zipped world map resource or a schematic resource. Schematic resources are pasted into a blank game world when the world is acquired. Paper uses WorldEdit for schematic loading; Fabric reads Sponge .schem palette data natively.

Utility helpers:

val spawns = worlds.spawnsCircle(center, count = players.size, radius = 12.0)
worlds.teleport(players.map { it.id }, world, spawns)

GameWorld abstracts platform world operations:

world.spawnPos = pos(world, 0.0, 80.0, 0.0)
world.worldTime = 6000L
world.storm = false
world.naturalRegeneration = false
world.blockAt(0, 79, 0).type = "grass_block"
world.fill(pos(world, -5.0, 79.0, -5.0), pos(world, 5.0, 79.0, 5.0), "stone")
world.playSound(world.spawnPos, "entity.player.levelup")
world.spawnParticle("happy_villager", world.spawnPos, count = 20, spreadX = 1.0, spreadY = 1.0, spreadZ = 1.0)

It also supports item drops, TNT priming, containers, and simple block ray tracing.

Use @GameResource for typed resources:

@GameResource(
type = GameResourceType.MAP,
path = "maps/arena_one.zip",
id = "arena_one",
checksum = "sha256:...",
autoExtract = true,
)
@GameResource(
type = GameResourceType.SCHEMATIC,
path = "schematics/arena_two.schem",
id = "arena_two",
)
@GameResource(
type = GameResourceType.DATAPACK,
path = "datapacks/fast_loot.zip",
id = "fast_loot",
)
class ArenaGame : SettingsGameTemplate()

For the compact @Game.resources form, use .toMap(), .toSchematic(), or .toDatapack():

@Game(
name = "Arena",
resources = ["schematics/arena_two.schem.toSchematic()"],
)
class ArenaGame : SettingsGameTemplate()

Use legacy @GameMap for map-only declarations:

@GameMap(
id = "pillars_classic",
zipPath = "maps/pillars_classic.zip",
worldFolderName = "pillars_classic",
)
class PillarsGame : SettingsGameTemplate()
private lateinit var zones: AreaSet
override fun setup(players: List<GamePlayer>) {
val world = gameWorld ?: return
zones = areas {
box("finish", pos(world, 10.0, 80.0, 10.0), pos(world, 14.0, 84.0, 14.0)) {
onEnter {
endGame(player)
}
whileInside {
player.send(ActionBar("<gold>Finish zone!"))
}
}
}
}
override fun configureEvents(events: EventsScope) {
events.onPlayerMove {
if (requireAlive()) zones["finish"].update(player, to)
}
}

Use emitOutline while debugging zone boundaries.

Routes interpolate positions along a path:

val rail = route {
point("start", pos(world, 0.0, 80.0, 0.0))
point("middle", pos(world, 20.0, 84.0, 0.0))
point("finish", pos(world, 40.0, 80.0, 0.0))
}
val cartPos = rail[progress]
if (rail.passed(progress, "middle")) {
// Trigger a mid-route event.
}

Use routes for races, moving objectives, escort paths, minecart tracks, parkour progress, and timed animations.