World tests operate on a Hytale world instance, letting you spawn entities, place blocks, move objects, and verify world state. TheDocumentation Index
Fetch the complete documentation index at: https://docs.hrtk.frotty27.com/llms.txt
Use this file to discover all available pages before exploring further.
WorldTestContext provides direct access to the world, its ECS store, block operations, and tick-waiting primitives.
World testing is where ECS meets the game world. While ECS tests work with raw entities and components, world tests verify that entities spawn at the right coordinates, blocks are placed correctly, and the world ticks forward as expected.
Entity type names and block IDs used in examples (like
Kweebec, Soil_Dirt) are from Hytale’s default content. Replace them with your mod’s actual entity roles and block type IDs. The spawnEntity method tries NPCPlugin first and falls back to an empty entity if the role is not found. Block IDs use the asset name without a namespace prefix.Isolation Strategies for World Tests
World tests modify shared state - blocks, entities, positions. Without isolation, your tests could corrupt the live server or interfere with each other. HRTK provides two strategies:- DEDICATED_WORLD - Each suite gets a temporary void world that is destroyed after the suite. This is the recommended default for any test that places blocks or spawns entities.
- SNAPSHOT - The world state is captured before the suite and restored after. Useful when you need to test against existing world content.
Complete Example Suite
WorldTestContext Methods
| Category | Method | Description |
|---|---|---|
| World | getWorld() | Get the Hytale World object |
| Store | getStore() | Get the entity store |
getCommandBuffer() | Get a command buffer for deferred ops | |
flush() | Execute deferred command buffer operations | |
| Blocks | setBlock(x, y, z, typeId) | Set a block at coordinates |
getBlock(x, y, z) | Get the block type ID at coordinates | |
fillRegion(x1, y1, z1, x2, y2, z2, typeId) | Fill a region with blocks (batched in a single world-thread dispatch) | |
| Entities | spawnEntity(typeId) | Spawn typed entity at origin (uses NPCPlugin if available) |
spawnEntity(typeId, x, y, z) | Spawn typed entity at position (uses NPCPlugin if available) | |
spawnNPC(role, x, y, z) | Spawn a fully initialized NPC by role name | |
spawnNPC(role, variant, x, y, z) | Spawn NPC with a specific variant | |
putComponent(ref, type, comp) | Attach component to entity | |
removeComponent(ref, type) | Remove component from entity | |
entityExists(ref) | Check if reference is still valid | |
despawn(ref) | Remove entity from world | |
| Position | getPosition(ref) | Get entity position as [x, y, z] |
setPosition(ref, x, y, z) | Set entity position | |
| Ticks | waitTicks(n) | Block until N ticks elapse |
waitTicksAsync(n) | Non-blocking tick wait | |
awaitCondition(supplier, maxTicks) | Poll each tick until non-null | |
| Queries | findEntities(componentType) | Find entities with component |
countEntities(componentType) | Count entities with component | |
getComponent(ref, type) | Get component (null if absent) | |
hasComponent(ref, type) | Check if entity has component |
WorldAssert Methods
| Method | Description |
|---|---|
assertBlockAt(world, x, y, z, typeId) | Assert block at position is expected type |
assertBlockNotAt(world, x, y, z, typeId) | Assert block is NOT the given type |
assertEntityInWorld(world, ref) | Assert entity exists in world |
assertWorldExists(worldName) | Assert a named world exists |
Entity Spawning: spawnEntity vs spawnNPC
When you callspawnEntity(typeId) or spawnEntity(typeId, x, y, z), HRTK first attempts to spawn a fully typed entity using NPCPlugin.spawnNPC(). This produces an entity with all the components and behaviors defined for that NPC type (health, AI, model, etc.). If the NPCPlugin call fails or the type is not recognized, HRTK falls back to creating an empty entity with no components attached.
When you call spawnNPC(role, x, y, z), HRTK directly invokes NPCPlugin.spawnNPC() with the role name. This always produces a fully initialized NPC or fails explicitly - there is no fallback to an empty entity.
fillRegion Performance
fillRegion() batches all block placements into a single world-thread dispatch. This means the entire region is filled atomically within one tick, rather than issuing separate block placements per coordinate. This makes large fills significantly faster and ensures the region is consistent when you assert against it.
Next Steps
- ECS Testing - lower-level entity/component operations
- Stats & Combat - health and damage verification
- Async & Tick Waiting - tick-based timing