Regions
How region ownership works, what a cross-region call costs, and when a plugin needs the compatibility bridge.
A region is the unit of ownership in Aurora. It is not a world, a dimension, or a thread pool worker. It is a set of chunks with a single owner thread, and that owner is the only thread allowed to mutate its state.
What a region is
Regions are formed from world topology and runtime configuration. The exact split is a runtime decision; do not hard-code assumptions about a region’s shape into a plugin. What is stable is the ownership rule: a region has one owner, and the owner is the mutation boundary.
Ownership rules
- A region’s chunks, entities, and block state are mutated by its owner thread.
- A write from a non-owner is refused, not silently serialized onto the owner.
- Global lifecycle work stays global; it does not become a region mutation by accident.
- A region does not inherit another region’s lock, thread-local, or plugin state.
The runtime would rather return an owned refusal than accept a race. If a plugin sees a refusal, it has reached a boundary that must be made explicit.
Crossing regions
Cross-region work has an explicit path. Depending on the operation, it is scheduled on the target region, bridged through a bounded compatibility path, or refused with an owned message. The caller never becomes the owner of the target region.
Compatibility bridge
Some Paper plugins assume a single main thread and call across the world without scheduling. The compatibility bridge exists for those plugins, but it is opt-in and off by default. It is still being qualified, and it does not make the core runtime single-threaded.
- The bridge is a compatibility path, not the supported architecture.
- Bridged calls are bounded and observed; a plugin cannot hang shutdown indefinitely.
- Build 48.4 refuses a synchronous chunk load from the region shutdown thread with an owned message.
- Enable it deliberately, test the plugin’s behavior, and remove it when the plugin is region-aware.
What this means for plugins
A plugin that only reads state may be safe. A plugin that mutates chunks or entities from a scheduler callback must know which region owns the target. A plugin that assumes “the server thread” is the only thread needs either a region-aware change or the bridge.
| Pattern | Status |
|---|---|
| Region-aware API call | Supported path. Route through the API and let the scheduler own the execution. |
| Legacy sync callback | Bounded compatibility path. Verify the plugin; do not assume global ordering. |
| Direct NMS mutation | Unsafe unless the caller owns the region. A refusal is a correctness signal. |
| Canvas plugin API | Removed. Use dev.iyanz.sourbycraft.api; legacy names read with warnings until Build 50. |
Failure modes
- Owned refusal: the caller tried to mutate a region it does not own. Fix the scheduling; do not suppress the message.
- Cross-region wait: the caller is waiting on another region. Check the deadline and the target region’s health.
- Shutdown refusal: a plugin tried to load a chunk after the region stopped. The load is refused instead of hanging the stop.
- Bridge warning: a legacy path is being used. Treat it as a migration signal.
Continue
Observability explains how to see region deadlines and stalls. sourbyapi covers the supported plugin surface.