Skip to content

Fix errors and warnings #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Fix errors and warnings #5

wants to merge 17 commits into from

Conversation

ShayBox
Copy link

@ShayBox ShayBox commented Feb 2, 2025

No description provided.

@VilleOlof
Copy link
Owner

Really appreciate all the small changes with clippy and updating and fixing a bunch of small stuff.
The only thing i could nitpick is the use of fastanvil. I have my own create mca that does the same job and it would make a lot of sense for my own crate to use my other crate for that too (it didnt exist when i wrote this)

@ShayBox
Copy link
Author

ShayBox commented Feb 2, 2025

How does mca compare to fastanvil in performance?

@VilleOlof
Copy link
Owner

I quickly tried adding fastanvil to my existing benchmark that was against mca_parser (here)

The benchmark is a fairly simple one where it just parses the region and gets the decompressed data from the 0,0 chunk
Do note that i did edit the benchmark do also decompress the data on mca-parser and mca since fastanvil automatically gives the decompressed data with its read_chunk.

Crate mca mca_parser fastanvil
Mean 29.792 µs 77.383 µs 53.957 µs

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

I was finally able to test Sculk, trying to Chunk::from_bytes I get Missing field: structures

Samples.zip

use anyhow::Result;
use mca::RegionReader;
use sculk::chunk::Chunk;
use tokio::{fs::File, io::AsyncReadExt};
use tokio_stream::{wrappers::ReadDirStream, StreamExt};

const PATH: &str = "...";

#[tokio::main]
async fn main() -> Result<()> {
    let read_dir = tokio::fs::read_dir(PATH).await?;
    let mut read_dir_stream = ReadDirStream::new(read_dir);
    while let Some(Ok(entry)) = read_dir_stream.next().await {
        let path = entry.path();
        let mut data = Vec::new();
        let mut file = File::open(&path).await?;
        file.read_to_end(&mut data).await?;
        println!("Path: {path:?}");

        let region = RegionReader::new(&data)?;
        for x in 0..32 {
            for z in 0..32 {
                let Some(raw_chunk) = region.get_chunk(x, z)? else {
                    println!("1");
                    continue;
                };

                let bytes = raw_chunk.decompress()?;
                let chunk = Chunk::from_bytes(&bytes)?;
                for section in chunk.sections {
                    let Some(block_states) = section.block_states else {
                        println!("3");
                        continue;
                    };

                    for palette in block_states.palette {
                        println!("{palette:?}");
                    }
                }
            }
        }
    }

    Ok(())
}

@VilleOlof
Copy link
Owner

Is that from 2b2t lol? Anyhow, where that the structures field is missing. My test region files that are from the same DataVersion of 3955 does always include a "structures" region for every chunk.

While your samples doesnt ever have them, i guess thats a byproduct of upgrading old chunks into newer ones (instead of being generated in newer versions from the start)

I guess making

pub structures: Structures,

into

pub structures: Option<Structures>,

In chunk/mod.rs would fix that since apparently it just doesnt exist in weird old>new chunks

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

Yeah it's from the new world download from a few days ago, after changing that it looks like there's no further issues reading chunks.

EDIT: Spoke too soon, Error: Unsupported block entity: minecraft:hanging_sign

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

I'm not sure how to find the NBT to add to BrushableBlock

EDIT: This seems to be the last error, It finishes scanning without problem, I did have a decompression error once but I can't replicate that anymore.

@VilleOlof
Copy link
Owner

You can find the nbt data on the wiki here, this is from suspicious sand (but gravel would also work) and under "Data Values" and then "Block Data" you got all the data it has.

But if it was only these small errors for a good real world example to scan it. I'm pretty damn happy with that

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

I got the error again

Error: Zlib Decompression failed: Adler32 checksum mismatch

Caused by:
    Adler32 checksum mismatch

EDIT: I've just realized that BrushableBlock already exists as SuspiciousBlock, but do I make a generic BlockEntityKind::BrushableBlock/SuspiciousBlock?

@VilleOlof
Copy link
Owner

Oh right the suspicious block, yeah that looks fine.

And with the zlib error
Do you have exactly which region file is causing this? What are you doing in the code? Does it error out upon decompressing the region file?

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

I'm able to scan every chunk without failure, it seems to be random when it happens, I'll see if I can loop the program and find if it's the same chunk/region every time or not

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

I ran it a few times and got these files, but when I run it on these files they work fine, so I think it's just random when it fails.

test.zip

@VilleOlof
Copy link
Owner

That is really weird that its random

The only ever lines of code for zlib in mca is

miniz_oxide::deflate::compress_to_vec_zlib(&data, 4)
// and
miniz_oxide::inflate::decompress_to_vec_zlib(&data)?

so its like something weird with your files, because it feels weird for miniz_oxide to have such an error (may be).
But at the same time its so so weird that its random

If you really wanted to, you could try and pull mca locally, update miniz_oxide to 0.8.3 (from 0.8.0) and see if it happens again, doubt it will fix it but i cant really see any other area that could impact it (other than the internals of miniz_oxide)

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

After updating I got a slightly different error message but it's still not consistent

Error: r.48.9.mca

Caused by:
    0: Zlib Decompression failed: Invalid input data
    1: Invalid input data

Process finished with exit code 1

I can just try again if it fails, chances are it won't fail twice
EDIT: Is there a way to iterate over blocks, e.g. to read signs?

I found it, chunk.block_entities :)

@VilleOlof
Copy link
Owner

Sure, while retrying a failed chunk probably works for 99% of cases. But it working sometimes and sometimes not is really annoying.

I wonder if you ran it with newly generated chunks, if it work ever fail then. Because i dont personally recall ever getting any of these errors. And just maybe, it is the old new chunks but even then its weird that its random

@ShayBox
Copy link
Author

ShayBox commented Feb 3, 2025

I'll generate a new large vanilla world with Chunky while I'm gone today and see if it happens on that

EDIT: It seems double-decompressing doesn't work, maybe the data coming from RegionReader is randomly invalid?

@ShayBox
Copy link
Author

ShayBox commented Feb 4, 2025

It seems 1.21.4 has renamed a lot of things, more than just the furnace, but we should keep the old parsing to support old versions, what should I do?

image

Switch to the new names and parse the old names or keep the old names and parse the new names?

@VilleOlof
Copy link
Owner

I myself have no intention to work on newer versions.
But if someone goes through the entire crate, and updates every single new change to the newest version i will probably test it and stuff and merge it in.

double-decompressing

That doesnt sound right, how / when is a chunk ever double compressed in the first place?
And RegionReader cant really have invalid data inside it since its just a wrapper around a regions &[u8] data (and never changed or mutated). Then the data from before the RegionReader have to be invalid

@ShayBox
Copy link
Author

ShayBox commented Feb 4, 2025

I mean trying to raw_chunk.decompress() a second time after the first time fails, both fail, which leads me to believe the raw chunk from the region reader is what is randomly failing/invalid and can't be decompressed, but I'm probably wrong about that

@ShayBox
Copy link
Author

ShayBox commented Feb 5, 2025

I tried with new 1.20.4 regions and it also happens, but the same code and regions works flawlessly for my friend, so I'm inclined to believe it's my CPU/RAM corrupting. If I retry get_chunk and decompress when decompress fails it usually works after a number of attempts, but the chunks following also fail at the same rate, but eventually it will clear up when it reaches the next region.

I also tried without sculk code, which reduces the load on my CPU to half and makes it entirely IO bound, and it basically never fails, at a much, much lower rate (I added 10TB to my SSDs reads before it failed), so this seems to be instability with my computer under heavy CPU load.

This issue isn't sculk related and I think this PR is complete for now, if I decide to add 1.21.4 support I'll make a new PR.

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