Skip to content

fix(folia): use entity scheduler for getState() to avoid off-region t…#61

Closed
wizzoh wants to merge 1 commit intoFreshSMP:feature/foliafrom
wizzoh:claude/fix-island-copy-error-J6jb3
Closed

fix(folia): use entity scheduler for getState() to avoid off-region t…#61
wizzoh wants to merge 1 commit intoFreshSMP:feature/foliafrom
wizzoh:claude/fix-island-copy-error-J6jb3

Conversation

@wizzoh
Copy link

@wizzoh wizzoh commented Mar 14, 2026

…hread errors

On Folia, every entity is owned by a specific region thread. The previous implementation used regionScheduler.run(location, ...) to schedule entity state access, but this targets the region that contains the given location rather than the region that owns the entity. In edge cases (chunk boundary transitions, region re-assignments) these can differ, causing:

IllegalStateException: Accessing entity state off owning region's thread

Two bugs are fixed:

  1. Switch from Bukkit.getServer().getRegionScheduler().run(location, task) to entity.getScheduler().execute(plugin, task, retired, delay). The EntityScheduler always dispatches on the entity's actual owning region thread, regardless of the entity's current location.

  2. Force-evaluate the lazy NBT tag (base.getNbt()) while still inside the entity scheduler callback. LazyBaseEntity.getNbt() delegates to TaskManager.sync(), which on Folia short-circuits and runs the supplier directly on the calling thread. Without this eager evaluation the supplier would run later on an async copy thread, also off the owning region.

Also remove the now-unused import org.bukkit.Bukkit statement.

…hread errors

On Folia, every entity is owned by a specific region thread. The previous
implementation used `regionScheduler.run(location, ...)` to schedule entity
state access, but this targets the region that *contains the given location*
rather than the region that *owns the entity*. In edge cases (chunk boundary
transitions, region re-assignments) these can differ, causing:

  IllegalStateException: Accessing entity state off owning region's thread

Two bugs are fixed:

1. Switch from `Bukkit.getServer().getRegionScheduler().run(location, task)`
   to `entity.getScheduler().execute(plugin, task, retired, delay)`.
   The EntityScheduler always dispatches on the entity's actual owning
   region thread, regardless of the entity's current location.

2. Force-evaluate the lazy NBT tag (`base.getNbt()`) while still inside
   the entity scheduler callback. `LazyBaseEntity.getNbt()` delegates to
   `TaskManager.sync()`, which on Folia short-circuits and runs the supplier
   directly on the calling thread. Without this eager evaluation the supplier
   would run later on an async copy thread, also off the owning region.

Also remove the now-unused `import org.bukkit.Bukkit` statement.

https://claude.ai/code/session_01LCRiqfY5a3h2Ccmonp6Jpn
@wizzoh wizzoh closed this Mar 14, 2026
@wizzoh wizzoh deleted the claude/fix-island-copy-error-J6jb3 branch March 14, 2026 14:07
@wizzoh wizzoh restored the claude/fix-island-copy-error-J6jb3 branch March 14, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants