Skip to content

proposal: Custom dimensions API #23

Description

@PyXiion

Summary

Add a core lib for custom dimensions — create, open, manage, and delete
dimensions from Lua. Dimensions persist at world/dimensions/<ns>/<path>,
survive script removal and reloads, and compose with the existing mc.world,
world-wrapper, and player:teleport APIs.

local dimension = require "core:dimension"

local arena = dimension.register("mypack:arena", {
  type = "void",
  seed = 42,
  own_rules = true,
})

dimension.get("mypack:arena"):teleport(player)

mc.on("player_changed_dimension", function(player, from, to)
end)

Related: worldgen proposal, #7, #13 (lifecycle), #20.

API

Core lib require "core:dimension".

Registration

dimension.register(id, opts?) -> Dimension
Key Type Default Meaning
type string "overworld" Preset (overworld,nether,end,flat,void), vanilla dimension-type id, or worldgen-registered type
seed number world seed Used only on first creation; ignored after the world has chunks
own_rules boolean true true — independent game rules; false — shares rules live with the overworld
  • Idempotent. Re-registering the same id returns the existing handle.
    Config is frozen on first creation — a conflicting declaration logs a
    warning and returns the existing dimension.
  • Never auto-deleted. Removing a script, reloading, or hot-reloading
    never deletes dimension data. Only delete removes a dimension.
  • minecraft:* ids are reserved.
  • The returned handle has a live .world immediately.

Discovery

dimension.get(id)      -> Dimension | nil
dimension.list()       -> { Dimension, ... }

Deletion

dimension.delete(id, force?)
  • Teleports all players out first. Removes region files from disk.
  • force defaults to false (confirmation required, like Multiverse's
    confirm prompt); force = true skips it. Irreversible.

Dimension handle

dim.id           -- "mypack:arena"
dim.world        -- existing World wrapper (all block/entity/weather APIs)
dim:teleport(player, pos?)  -- enter the dimension; defaults to world.spawn
dim:delete(force?)

Events

mc.on("player_changed_dimension", function(player, from, to)
end)

from / to are dimension id strings, or nil when entering/leaving
the server.

World spawn (companion change)

The existing world wrapper gains world.spawn — a read/write {x, y, z}
property. dim:teleport(player) resolves to world.spawn (or
{0, 64, 0} if not set).

Registration & lifecycle

  • Dimensions are opened at game time during module-level script load.
    Runtime ServerWorld creation is proven on 1.21.8–1.21.11 by the
    Multiverse mod (Fabric, server-side, using Arcade's dimensions module).
  • On /ignis reload: commands, events, the scheduler, regions, holograms
    etc. all clear — but the dimension registry is additive and persistent.
    Existing worlds stay open. Changed configs are ignored (warn). Removed
    scripts do not delete worlds.
  • Data lives at world/dimensions/<ns>/<path> — same layout as vanilla
    datapack dimensions.

Non-goals (v1)

  • Defining custom dimension types from Lua — see the worldgen proposal.
  • Portal-linked custom overworld/nether/end triples.
  • Per-dimension tick rate.
  • Unloading a world without deleting it.

Acceptance criteria

  • Every preset and worldgen-registered type produces a live, reachable world.
  • dim:teleport(player) and player:teleport(x,y,z,id) work.
  • The full world wrapper works inside custom dimensions.
  • mc.world(id) returns the custom world.
  • own_rules = true isolates gamerules; own_rules = false mirrors the
    overworld live.
  • Chunks persist across restarts and reloads.
  • Reloading/removing a script never deletes or crashes a dimension.
  • Reserved / duplicate / bad-type ids error clearly.
  • delete removes the world, its region files, and evicts players safely.

Open questions

  • Should the seed be mutable before the first chunk generates?
  • Should dimension.list() include on-disk-only worlds that aren't currently
    open?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions