Skip to content

fix entity archetype positions - #4303

Open
whimxiqal wants to merge 1 commit into
SpongePowered:api-12from
whimxiqal:whimxiqal/fix-entity-archetype-positions
Open

fix entity archetype positions#4303
whimxiqal wants to merge 1 commit into
SpongePowered:api-12from
whimxiqal:whimxiqal/fix-entity-archetype-positions

Conversation

@whimxiqal

Copy link
Copy Markdown

Fix entity archetype positions in archetype volumes

Problem

ServerWorld#createArchetypeVolume throws whenever any entity stands in the minimum-x, -y, or -z plane of the requested region:

java.lang.IllegalArgumentException: EntityArchetype position is out of bounds:
  Found (-0.5, 130.5, 14.5) but is outside bounds ((0, 0, 0), (15, 383, 15))
    at ObjectArrayMutableEntityArchetypeBuffer.addEntity(ObjectArrayMutableEntityArchetypeBuffer.java:110)
    at SpongeArchetypeVolume.addEntity(SpongeArchetypeVolume.java:232)
    at VolumeApplicators.lambda$applyEntityArchetypes$15(VolumeApplicators.java:221)
    at SpongeVolumeStream.lambda$apply$7(SpongeVolumeStream.java:218)
    ...
    at net.minecraft.world.level.Level.createArchetypeVolume(Level.java:1912)

Reproduced on SpongeVanilla 1.21.1-12.0.4-RC0 by copying a single chunk column (min = (-16, -64, 16), origin = min) that contained an entity at block (-16, 67, 31) — squarely inside the region, on its minimum-x face.

Root cause

createArchetypeVolume pairs VolumePositionTranslators.offset(Vector3i) with VolumeApplicators.applyEntityArchetypes(). offset(Vector3i) delegates to offset(min.toDouble().add(BLOCK_OFFSET)), so every element position becomes pos - min - 0.5. That half-block bias is a block-space convention: applyBlocks, applyBiomes and applyBlockEntityArchetypes all call element.position().round().toInt(), and Math.round(-0.5) == 0, so it cancels out. applyEntityArchetypes() does not round — it stores the raw position — and ObjectArrayMutableEntityArchetypeBuffer#addEntity bounds-checks with entry.position().toInt(), which floors. floor(-0.5) == -1, hence the exception.

Two consequences beyond the crash:

  • Every entity that doesn't throw is stored half a block negative on all three axes.
  • SpongeArchetypeVolume#applyToWorld has the same mismatch mirrored: relativeTo(Vector3i) also subtracts BLOCK_OFFSET, which the block applicators undo by rounding and applyEntityArchetype() does not. A save → paste round trip therefore lands entities a full block off, not half.

Separately, AbstractReferentArchetypeVolume#addEntity flattened positions through Vector3i before delegating, discarding sub-block precision that entityArchetypesByPosition() on the same class preserves.

Fix

All three changes are implementation-side; SpongeAPI is untouched.

  • LevelMixin_API#createArchetypeVolume — entity leg switched to the Vector3d overload of relativeTo, so entities are placed at storedPosition + placement.
  • SpongeArchetypeVolume#applyToWorld — entity leg switched to the Vector3d overload of relativeTo, so entities are placed at storedPosition + placement.
  • AbstractReferentArchetypeVolume#addEntity — transforms the position as a Vector3d instead of flattening it to a block coordinate.

This settles the convention that the rest of the codebase already assumes: an entity archetype's position is a real position relative to the volume origin, not a block position. SchematicTranslator writes entry.position() straight into the schematic's Pos doubles and reads them back unchanged, and StructureTemplateMixin_API#addEntity converts the position to a Vec3 and floors it separately for the BlockPos. The -0.5 was only ever meaningful for block-shaped elements.

Testing

./gradlew compileJava passes for SpongeCommon and SpongeVanilla. I haven't added an automated test — the failure is in a Level mixin and needs a live world; VolumeTransformationTest is the nearest existing harness and doesn't reach this path. Verified by hand: chunk copies that previously threw now succeed, and entities land on their original blocks on paste.

Notes

Written against api-12, but api-13 through api-16 carry the identical offset(origin) + applyEntityArchetypes() pairing and need the same fix.

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.

1 participant