Pseudo Instance
This page defines the runtime model for version-one site events. We use pseudo instance to mean a controlled, recoverable, cleanable site runtime built on top of a formal ruin record inside the original world. It is not a separate dimension, and it is not a larger version of a right-click interaction.
Adoption Boundary
Version one adopts a pseudo-instance instead of a separate dimension for only three reasons:
- We already have reusable host structures and do not need a brand-new dungeon map first.
- The first slice needs to prove activation, site pressure, objective progress, and recovery, not teleportation and isolated world space.
- A pseudo-instance is enough to support a ten-to-twenty-minute field action at much lower cost than a dimension solution.
That gives us the following boundary:
| Option | Used in version one | Conclusion |
|---|---|---|
| local pseudo-instance | yes | first formal vertical slice |
| local sealed ruin | no | add later if the pseudo-instance proves itself |
| separate dungeon dimension | no | expansion work, not version-one scope |
Ledger And Runtime Split
Pseudo-instance state must stay separate from the world ledger. SavedData carries long-term truth. The pseudo-instance carries short-lived runtime state.
| Layer | Key | Stores |
|---|---|---|
| cross-stage handoff | SiteRef | unified reference shared by formal survey, activation, and recovery |
| ruin ledger | SiteCoordinate | ruin identity, anchor, lifecycle, formal record |
| runtime registry | SiteCoordinate | active state, owner, current phase, local caches |
| chunk side index | long chunkKey | which chunks are currently covered by the site |
ActivationService resolves SiteRef back into the ledger record, then normalizes it to one SiteCoordinate. If long-term records and runtime state collapse into one layer, chunk unload, retreat resolution, and duplicate activation start corrupting each other.
Recommended runtime registry:
public final class SiteRuntimeRegistry {
private final Map<SiteCoordinate, ActiveSiteRuntime> runtimeBySite = new HashMap<>();
private final Map<Long, Set<SiteCoordinate>> sitesByChunk = new HashMap<>();
private final Map<UUID, SiteCoordinate> siteByOwner = new HashMap<>();
}runtimeBySiteanswers whether one ruin is active now.sitesByChunksupports local sync, cache cleanup, and coverage lookup.siteByOwnerprevents one player or team from occupying multiple formal ruins at once.
Coverage And Chunk Index
In gameplay, a pseudo-instance feels like one field event. In implementation, it is a set of covered chunks. Version one can build that directly on verified APIs:
| Use | Verified API | Role |
|---|---|---|
| primary chunk key | ChunkPos.asLong(BlockPos) | creates a stable chunkKey from the anchor |
| coverage expansion | ChunkPos.rangeClosed(ChunkPos, int) | expands chunk coverage from a chunk radius |
| unload cleanup | ChunkEvent.Unload | clears local caches only; does not delete the formal ruin |
Recommended order:
- Compute
primaryChunkKeyfrom the ruin anchor. - Convert event radius into
chunkRadius. - Expand
coveredChunkKeysfromnew ChunkPos(anchor)withChunkPos.rangeClosed(centerChunk, chunkRadius). - Register
coveredChunkKeysintositesByChunkfor sync and cleanup.
ChunkEvent.Unload should only clear temporary cache, local spawn indexes, and rendering hooks in that chunk. It should not delete the ruin and it should not rewrite ledger truth.
Activation Entry And Runtime Services
Activation can come from items, machines, or site devices, but those entry points should not each implement their own startup path. Version one routes all of them through ActivationService.
| Service | Owns | Does not own |
|---|---|---|
ActivationService | validates SiteRef, ownership, and activation conditions; creates runtime | does not re-evaluate ruin type |
PressureRuntimeService | pressure, guardians, and phase danger | does not write long-term records |
ObjectiveRuntimeService | objective nodes, progress conditions, completion checks | does not own recovery resolution |
SiteFeedbackService | fog, sound, hints, and local presentation | does not hold authority state |
RecoveryService | resolution, ledger write-back, runtime teardown | does not drive in-site phase progress |
This split fixes two rules:
- Activation sources can grow, but the runtime startup path stays singular.
- Runtime services operate on the same
ActiveSiteRuntimeinstead of maintaining second copies of the site state.
Lifecycle
The pseudo-instance lifecycle stays fixed at five steps:
- Formal survey writes
DiscoveredSiteRecordand returnsSiteRef. - Activation hands
SiteReftoActivationService, which validates ownership and site conditions. - The runtime registry creates
ActiveSiteRuntimeand registersruntimeBySite,sitesByChunk, andsiteByOwner. - Runtime services advance pressure, objectives, and feedback inside the coverage area until completion, retreat, or collapse.
RecoveryServiceresolves results, writes back to the ledger, unregisters runtime state, and clears local indexes.
When the runtime ends, we delete the runtime registration, not the ruin truth. Whether the ruin is completed, invalidated, or available again is still a ledger decision.
Out Of Scope
Version one explicitly excludes:
- teleporting into a separate dimension,
- world copying or temporary map instances,
- letting activation entry points decide ruin type,
- letting chunk events rewrite the formal ledger,
- mixing early discovery nodes into the formal site lifecycle.
Acceptance Criteria
- We can start one formal field event on an existing host structure without teleporting into a new dimension.
- Activation, runtime, and recovery stay anchored to the same
SiteRefandSiteCoordinate. - Coverage, sync, and cache cleanup are supported by chunk-side indexes instead of repeated world scans.
- When the event ends, runtime state is removed and the ledger record remains.