Registries and compiled areas
A compact quest community has two world-side owners with different streaming jobs:
AlwaysLoaded sector
worldCommunityRegistryNode
communitiesData[]
worldCommunityRegistryItem
communityId
entriesInitialState[]
template -> communityCommunityTemplateData
Quest sector
worldCompiledCommunityAreaNode_Streamable
sourceObjectId
area -> communityArea
entriesData[] -> phasesData[] -> timePeriodsData[] -> spotNodeIds[]
The registry describes what the community can spawn. The compiled area places the community source in the streamed world and binds its entry/phase periods to world AI-spot identities. Neither substitutes for the other.
Registry responsibility
The inspected mod-owned shape places a worldCommunityRegistryNode in an
AlwaysLoaded sector. Its decisive properties are:
| Property | Responsibility |
|---|---|
communitiesData | Holds one or more worldCommunityRegistryItem records. |
communityId.entityId.hash | Selects the matching compiled community source. |
entriesInitialState | Gives each named entry its initial active state and initial phase. |
template | Embeds communityCommunityTemplateData for the entries available to this registry item. |
workspotsPersistentData | Retains spot identities and initial enabled/placement data in the inspected compact shape. |
An AlwaysLoaded registry is a useful mod-owned arrangement because the
definition remains reachable before the local quest sector finishes streaming.
It does not make the actor AlwaysLoaded. The compiled area and AI spots still
belong to their streamed sector, and activation still requires quest logic when
entryActiveOnStart is false.
Do not elevate the sector category to a universal schema rule. It is the retained, tested arrangement used by this section and must still be checked in the exact new package.
Compiled-area responsibility
The local Quest sector contains a
worldCompiledCommunityAreaNode_Streamable. Its communityArea mirrors the
spawn topology using world identities rather than character records:
entryName
-> entryPhaseName
-> periodName + isSequence
-> spotNodeIds[]
The registry side names spotNodeRefs; the compiled-area side names
spotNodeIds. Those values must resolve to the same placed AI spots. A
community can therefore be internally well-formed yet still fail because the
area points at a different spot identity than the registry template.
Important compiled-area fields in the retained shape are:
| Property | Responsibility |
|---|---|
sourceObjectId | Supplies the community/source identity that joins the area to the registry item. |
area.entriesData[].entryName | Mirrors one registry entry CName. |
phasesData[].entryPhaseName | Mirrors one spawn phase CName. |
timePeriodsData[].periodName | Mirrors the selected period such as Day. |
timePeriodsData[].isSequence | Mirrors whether the period uses its spot set as a sequence. |
timePeriodsData[].spotNodeIds | Names the world-global AI-spot identities used by the period. |
streamingDistance | Participates in when the compiled area is available; it does not guarantee actor readiness at scene start. |
Placement still uses the ordinary streaming-sector chain described in Sector
nodes and placement: one concrete node,
one matching nodeData record, a registered NodeRef where the arrangement uses
one, and the block descriptor that mounts the sector beneath the intended
quest-prefab root.
The three identity joins
Derive each world identity from its own canonical full NodeRef; do not mint
numbers from labels or from a neighbouring identity:
community/source ID
<- RED4 NodeRef hash(full community NodeRef)
registry-node ID
<- RED4 NodeRef hash(full community NodeRef with `_registry`
appended to the final community name)
AI-spot global ID
<- RED4 NodeRef hash(full AI-spot NodeRef)
The hash operation must understand RED4 NodeRef aliases and segments. The #
marker is NodeRef hierarchy/alias syntax and is skipped as a marker by that
operation; it is not an ordinary byte to feed into a generic hash. Do not use
plain FNV-1a over a debug label, the last #name, or the printed full path as a
substitute. When a numeric value must be audited outside normal WolvenKit
serialization, use RED4-aware NodeRef logic such as WolvenKit’s NodeRef
implementation and retain the originating full string beside the result.
Reject zero results and reject every collision across the source, registry, and spot sets before cooking. Equality is required only at the documented source join below; a source/registry collision, source/spot collision, registry/spot collision, or sibling-spot collision is an authoring error.
Community/source identity
In the retained compact shape, these represent one community/source identity and therefore match:
compiled area NodeRef-derived identity
== worldCompiledCommunityAreaNode_Streamable.sourceObjectId.hash
== worldCommunityRegistryItem.communityId.entityId.hash
This equality joins the registry item to its streamed source. It does not mean every nearby 64-bit ID should reuse the same value.
Registry-node identity
The worldCommunityRegistryNode is a separate world node and needs a separate
world-node identity. The historical crashing arrangement reused the
community/source value for that registry node. The repaired candidate assigned
a distinct identity and rejected future collisions.
The rule is not “add one” or “hash the debug name.” Preserve typed values and
derive the registry identity from the canonical full community NodeRef with
_registry appended to its final community name. Let the same RED4-aware
NodeRef path produce all related forms. Record the full synthetic registry
string as well as the serialized number so a review can explain where the
identity came from.
AI-spot identity
Every worldAISpotNode has its own registered world identity. It appears in at
least three roles in the retained shape:
registry template: spotNodeRefs[] full NodeRef
compiled area: spotNodeIds[] worldGlobalNodeID
registry node: workspotsPersistentData[].globalNodeId
That spot identity must be distinct from the community/source identity, the registry-node identity, and every sibling spot. Array position and visible debug text are not identity joins.
Standalone .community resources are comparison sources
The vanilla depot also contains communityCommunityTemplate CR2W resources.
For example:
base\open_world\minor_activities\westbrook\japantown\
ma_wbr_jpn_13\community\ma_wbr_jpn_013_claws_com.community
Observed in vanilla: that resource’s root owns
communityCommunityTemplateData with three communitySpawnEntry objects,
their character records, phases, appearances, time periods, quantities, and
local spot references.
Use it to study template semantics. Do not infer that the inspected mod-owned
worldCommunityRegistryItem.template is a soft path to this file: in the
retained compact registry it is embedded template data. Copying a vanilla
.community resource into a mod archive would also redistribute extracted
game content and preserve identities intended for another activity. Extract
your own reference and author a mod-owned registry instead.
Focused WolvenKit review
For a mod-owned community, inspect these joins without pasting a complete sector into your notes:
- record the full compiled-area NodeRef and its derived source identity;
- confirm the registry item’s
communityIdmatches that source identity; - derive the registry node identity from the full community NodeRef plus
_registry, and confirm it is different; - list each entry and initial phase once;
- derive each world-global AI-spot ID from that spot’s full NodeRef and list both forms;
- confirm the registry
spotNodeRefs, areaspotNodeIds, and persistent spot rows describe the same set; - reject zero values and every source/registry/spot/sibling collision;
- confirm the block mounts both the AlwaysLoaded registry sector and the Quest area/spot sector;
- confirm the questphase declares the prefab root required for its local community reference.
Do not use a numerical sort of the JSON arrays as a shortcut. The decisive
links are NodeIndex, typed IDs, entry/phase names, and NodeRefs.
Common failures
| Symptom | Inspect first |
|---|---|
| Activation node runs but no community appears | Area sector streaming, sourceObjectId/communityId equality, prefab root, and entry initial state |
| One community affects another | Reused community/source identity or copied vanilla identity |
| Loading near the area crashes | Registry-node collision, malformed handles, bad spot IDs, or another resource activated at the same boundary |
| Registry looks correct but the actor never gets a place | Area entriesData/phase/period mirror and exact spotNodeIds |
| Spot exists but is not persistent or enabled as expected | Registry workspotsPersistentData and the spot’s world-global identity |
| Old behavior survives a corrected archive | Return to a save made before any version of the community was installed |