SandroHc / schematic4j

Java parser for the .schem/.schematic/.litematic Minecraft formats. 🗺
MIT License
15 stars 3 forks source link

SchematicUtil.load switches up blocks, inserts extra blocks #1

Closed blackjackkent closed 11 months ago

blackjackkent commented 2 years ago

Hello! New to the Minecraft dev scene so bear with me, but I'm pretty bewildered here. :)

I'm working on a side project to try and implement a layer-by-layer blueprint viewer (a la Schematic2Blueprint) that works on .schem Sponge format schematic files, and am using this library as a dependency. With some schematics (I'm using Amulet to export them to .schem, if that makes any difference) it works fine, but with others, weird stuff starts to happen in the block ordering.

Case in point - I set up a big pile of many different block types in my creative world so I could test how my app behaves on all of them: image

The .schem file itself seems to be fine, because I can re-import it into Amulet or Litematica and all the blocks look correct. However, parsing it with SchematicUtil.load has some weird behavior.

The first level of blocks, for instance:

image

Going from north to south on one vertical Y value (if I understand correctly) should be

Schematic schematic = SchematicUtil.load(path);
int length = schematic.getLength();
int height = schematic.getHeight();
int width = schematic.getWidth();
for (int i = 0; i < height; i++) {
    for (int j = 0; j < length; j++) {
        for (int k = 0; k < width; k++) {
            SchematicBlock block = schematic.getBlock(k, i, j);
        }
    }
}

which is what I am doing in my application. Given the row above, the result I would expect would be

minecraft:stone
minecraft:granite
minecraft:polished_granite
minecraft:diorite
minecraft:polished_diorite
minecraft:andesite
minecraft:polished_andesite
minecraft:deepslate
minecraft:cobbled_deepslate

Instead, what I get is

minecraft:stone
minecraft:granite
minecraft:polished_granite
minecraft:polished_blackstone_brick_stairs
minecraft:grass_block
minecraft:mossy_stone_bricks
minecraft:grass_block
minecraft:yellow_stained_glass
minecraft:grass_block

As you can see, it starts off correct and then kind of goes off the rails from there. The rest of the parsing gives much the same result - some blocks are listed as being where they are supposed to be, while others seem to have been swapped in from wildly different parts of the schematic, or just slotted in at random. (The grass_block is a repeated offender.)

Am I doing something wrong in how I'm using the library? Or is there a sneaky bug lurking around here? I've attached the .schem file in question here: palette-lvl1.zip; please let me know if there's other info that would be helpful! :)

(Thanks very much for this tool, also! Assuming I can figure out what the issue is here, it's been awesome in all other regards. :) )

tigerdan2 commented 1 year ago

Hey, late response for other people who might want to use this api

The issue arises due to incorrect handling of the BlockData format The Sponge format specifies varint encoding for block data. Meaning multiple bytes may repesent a larger integer

The Sponge schematic Parser in thisnproject does not handle varint decoding, wich results in wrong decoding of schematic with a block pallet that require multiple bytes to be represented in the BlockData byte array.

So the api is the problem.

RyanLandDev commented 11 months ago

Hey, late response for other people who might want to use this api

The issue arises due to incorrect handling of the BlockData format The Sponge format specifies varint encoding for block data. Meaning multiple bytes may repesent a larger integer

The Sponge schematic Parser in thisnproject does not handle varint decoding, wich results in wrong decoding of schematic with a block pallet that require multiple bytes to be represented in the BlockData byte array.

So the api is the problem.

I'm facing the same issue, the API appears to mess up with bigger palettes. Worth noting it works perfectly fine for small schematics with smaller block palettes.

This is how my schematic should look: image

However, when I rebuild the schematic using my program with this library, I get this (screenshot taken from the same location): image

It seems like it works correctly for the first few layers and kind of fails from there. The issue is not on my end (I think) since I tried putting a random location inside Schematic#getBlock(x, y, z), which returns the wrong block aswell.

RyanLandDev commented 11 months ago

@blackjackkent @tigerdan2 A bit late, but I was able to successfully resolve this issue in #2

SandroHc commented 11 months ago

The fix from #2 is now available in schematic4j 1.0.1.

Are you able to upgrade to that version to confirm if the issue has been fixed?

RyanLandDev commented 11 months ago

The fix from #2 is now available in schematic4j 1.0.1.

Are you able to upgrade to that version to confirm if the issue has been fixed?

Just upgraded to the new version. The issue has been resolved

SandroHc commented 11 months ago

I'll mark this issue as resolved. Thanks once again for the fix!