mojira.dev
MC-306569

Structure Void placed incorrectly when loading structure with Structure Block with "STRUCTURE_EDIT_MODE" debug property enabled

When loading a structure with a Structure Block with "STRUCTURE_EDIT_MODE" debug property enabled, there is an extra layer of Structure Void, that extends beyond structure bounding box.

Also, when the structure is rotated through Structure Block GUI, a box of Structure Void is placed in a completely wrong position, as if the structure isn’t rotated.

Steps to reproduce

  1. Launch the game with -DMC_DEBUG_ENABLED=true -DMC_DEBUG_STRUCTURE_EDIT_MODE=true appended to Java VM options

  2. Build a simple structure and save it with a Structure Block

  3. Place a Structure Block elsewhere to load the structure

  4. Place another Structure Block with “Show Invisible Blocks: ON“ to observe Structure Void placement

  5. Optionally, rotate the structure

  6. Load the structure

My test world is attached to the bug report.

Expected result

All Structure Void placed are inside structure bounds

Actual result

There is Structure Void placed outside of structure bounds and, if the structure is rotated, in an incorrect position

Code analysis (26.1-snapshot-9, Vineflower decompiler, no obfuscation)

The following code in StructureBlockEntity#placeStructure is responsible for placing Structure Void

if (SharedConstants.DEBUG_STRUCTURE_EDIT_MODE) {
    BlockPos.betweenClosed(pos, pos.offset(this.structureSize)).forEach(p -> level.setBlock(p, Blocks.STRUCTURE_VOID.defaultBlockState(), 2));
}

I’ve managed to fix the issue by replacing BlockPos.betweenClosed(pos, pos.offset(this.structureSize)) with BlockPos.betweenClosedStream(boundingBox) and calculating bounding box as template.getBoundingBox(placeSettings, pos), where placeSettings and pos are existing local variables.

Below is a snippet from my @WrapMethod mixin

@WrapMethod(method = "placeStructure(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate;)V")
public void placeStructure(ServerLevel level, StructureTemplate template, Operation<Void> original)
{
    // ...
        
    StructurePlaceSettings placeSettings = new StructurePlaceSettings()
            .setMirror(this.mirror)
            .setRotation(this.rotation)
            .setIgnoreEntities(this.ignoreEntities)
            .setKnownShape(this.strict);

    // ...
    
    BlockPos pos = this.getBlockPos().offset(this.structurePos);
    if (SharedConstants.DEBUG_STRUCTURE_EDIT_MODE) {
        BoundingBox boundingBox = template.getBoundingBox(placeSettings, pos);
        BlockPos.betweenClosedStream(boundingBox).forEach(p -> level.setBlock(p, Blocks.STRUCTURE_VOID.defaultBlockState(), Block.UPDATE_CLIENTS));
    }

    // ...
}

Structure Void placement no longer exceeds structure bounds and respects structure rotation.

Attachments

Comments 1

Thank you for helping us improve Minecraft! We saved your files:

[media][media][media][media][media]

denvalec

(Unassigned)

Unconfirmed

(Unassigned)

26.1 Snapshot 9

Retrieved