Summary
MfFactionMapCommand reads sender.world from inside the Runnable handed to runTaskAsynchronously, at src/main/kotlin/com/dansplugins/factionsystem/command/faction/map/MfFactionMapCommand.kt:65:
val map = renderMap(faction, mapType, sender.world, senderChunkX - 10, senderChunkZ - 4, senderChunkX + 10, senderChunkZ + 4)
The chunk coordinates immediately above it are handled correctly — sender.location.chunk is read at line 46, on the main thread, before dispatching, and only the resulting x/z ints cross into the task. The world reference was not given the same treatment.
Why it matters
Two consequences follow, mirroring the ones described in #2006:
- The world is sampled at task time, not at command time. A player who changes world between issuing
/faction map and the task running is rendered a map of claims in the world they arrived in, indexed by chunk coordinates taken from the world they left. The rendered grid is then a mix of two worlds and shows claims that are not where the player is standing.
- The read itself is off-main-thread Bukkit API access.
Player.getWorld() is not documented as thread-safe, and the returned World is passed straight into claimService.getClaim(world, x, z) for every cell of a 21x9 grid.
Suggested fix
Snapshot the world alongside the chunk coordinates that are already snapshotted, and have the task use the snapshotted reference:
val senderChunk = sender.location.chunk
val senderWorld = senderChunk.world
val senderChunkX = senderChunk.x
val senderChunkZ = senderChunk.z
That keeps the world and the coordinates consistent with one another, since both are then taken from the same Location read.
Provenance
This was noticed while surveying the command package for PR #2019, which closes #2006. It is not covered by that issue's inventory, so it was filed separately rather than folded into that changeset.
This issue was filed during a Gardener session (https://github.com/Stephenson-Software/gardener).
Summary
MfFactionMapCommandreadssender.worldfrom inside theRunnablehanded torunTaskAsynchronously, atsrc/main/kotlin/com/dansplugins/factionsystem/command/faction/map/MfFactionMapCommand.kt:65:The chunk coordinates immediately above it are handled correctly —
sender.location.chunkis read at line 46, on the main thread, before dispatching, and only the resultingx/zints cross into the task. The world reference was not given the same treatment.Why it matters
Two consequences follow, mirroring the ones described in #2006:
/faction mapand the task running is rendered a map of claims in the world they arrived in, indexed by chunk coordinates taken from the world they left. The rendered grid is then a mix of two worlds and shows claims that are not where the player is standing.Player.getWorld()is not documented as thread-safe, and the returnedWorldis passed straight intoclaimService.getClaim(world, x, z)for every cell of a 21x9 grid.Suggested fix
Snapshot the world alongside the chunk coordinates that are already snapshotted, and have the task use the snapshotted reference:
That keeps the world and the coordinates consistent with one another, since both are then taken from the same
Locationread.Provenance
This was noticed while surveying the command package for PR #2019, which closes #2006. It is not covered by that issue's inventory, so it was filed separately rather than folded into that changeset.
This issue was filed during a Gardener session (https://github.com/Stephenson-Software/gardener).