Thread Safety: Using world.execute()
Each world has it's own thread in Hytale, and it's own world.execute() queue. Entity operations must run on the world thread. But, packet handlers, async callbacks, and some event listeners don't run on the world thread by default. If you modify entity state from the wrong thread, you'll get errors or undefined behavior. So, you have to schedule to the world thread correctly.
When You Need It
You're on the wrong thread when your code is triggered by:
- Packet handlers (
PlayerPacketFilter, PlayerPacketWatcher)
- Async operations (CompletableFuture callbacks, scheduled tasks)
- Cross-world operations (accessing entities in a different world)
You're already on the right thread when:
- Inside a command executor
- Inside most game event listeners
- Inside
world.execute() callbacks
How It Works
Ref<EntityStore> entityRef = playerRef.getReference();
if (entityRef == null || !entityRef.isValid()) {
return;
}
Store<EntityStore> store = entityRef.getStore();
World world = store.getExternalData().getWorld();
world.execute(() -> {
// Safe to modify entities here
});
What Can Go Wrong
From the wrong thread:
- Null components that shouldn't be null
- ConcurrentModificationException
- Silent failures (code runs but nothing happens)
- Inconsistent state (partially applied changes)
Quick Check
Not sure which thread you're on? Log it:
plugin.getLogger().at(Level.INFO).log("Thread: %s", Thread.currentThread().getName());
World threads are named after their world. Network threads say "Netty" or similar.