27 lines
2.4 KiB
Markdown
27 lines
2.4 KiB
Markdown
# 0005. Namespaced content IDs
|
|
|
|
- **Status:** Accepted
|
|
- **Date:** 2026-06-27
|
|
|
|
## Context
|
|
|
|
Every single piece of registered content (blocks, items, recipes, biomes, entities, etc.) needs a perfectly stable identifier. This identifier has to be completely unambiguous across the engine, data packs, Lua mods, recipe references, and save files. First-party content and third-party content must be able to coexist without ever colliding, and these identifiers must be able to survive being written to disk and read back later.
|
|
|
|
## Decision
|
|
|
|
We identify all content using a **namespaced string** in the exact format `"namespace:id"`.
|
|
|
|
- We strictly reserve the `core:` namespace for first-party content (e.g., `"core:stone"`, `"core:iron_sword"`). Modders must choose their own short namespace (e.g., `"mymod:weird_dirt"`).
|
|
- This format is absolutely mandatory. A bare ID with no `:` is an **immediate error at registration or parse time**. We will never silently coerce it to `core:`. This exact rule applies everywhere: engine scripts, data packs, Lua mods, recipe references, and save files.
|
|
- **Charset rules:** Both the namespace and the ID must match `[a-z0-9_-]+` and have exactly one `:` sitting between them. We only allow lowercase ASCII. No uppercase letters, no Unicode, no spaces, no dots, and no slashes.
|
|
- At registration time, we intern each ID string into a small integer handle (for example, `BlockId(u32)`). All hot paths compare these integer handles for speed. We only keep the original string around for display purposes, save/load routines, and the Lua API.
|
|
|
|
Notice that the reserved namespace is deliberately called `core:` rather than naming it after the project itself. This ensures the namespace stays completely stable regardless of any future rebranding.
|
|
|
|
## Consequences
|
|
|
|
- Identifiers are highly greppable, inherently filesystem-safe, and totally unambiguous in both logs and save files.
|
|
- First-party and mod content simply cannot collide. By refusing to provide a silent default namespace, we ensure mistakes blow up immediately rather than silently corrupting data.
|
|
- We pay a tiny runtime cost at registration to intern the strings, but in exchange, we get lightning-fast handle comparisons on all hot paths.
|
|
- This strict formatting is a permanent contract. If we relaxed it later (for example, by defaulting bare IDs), we would fundamentally change the meaning of existing save files, making such a change effectively irreversible.
|