bedrock-tool / bedrocktool

a mostly working minecraft bedrock tool for downloading server worlds, skins and others
GNU General Public License v3.0
188 stars 22 forks source link

Generated world crashes the game #213

Closed jedenastka closed 3 months ago

jedenastka commented 3 months ago

Describe the bug

A set of worlds generated by this tool crash the game on load. All of these worlds are coming from sub-servers, only the main server world from that server loads correctly.

To Reproduce

  1. Run the worlds subcommand and connect to the server (see packet capture)
  2. Go to a sub-server
  3. Disconnect
  4. Try loading the saved world

The game crashes.

Expected behavior

The game doesn't crash and the world loads correctly.

Screenshots

Not applicable.

Desktop (please complete the following information):

Additional context

Example crashing world (too big for GitHub, so this is an external link): https://cloud.stary.pc.pl/s/oJm55Y4EtgSnHTt

attach packets.log.gpg (not always necessary)

packets.log.gpg.txt (faux .txt suffix to trick GitHub, it says "format not supported" otherwise)

jedenastka commented 3 months ago

I had the idea to try loading the world with the BDS under gdb:

Thread 19 "bedrock_server" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffef2006c0 (LWP 88821)]
0x000055555cc2ee67 in LevelChunk::fetchBiomes(std::__1::vector<Biome const*, std::__1::allocator<Biome const*> >&) const ()
(gdb) bt
#0  0x000055555cc2ee67 in LevelChunk::fetchBiomes(std::__1::vector<Biome const*, std::__1::allocator<Biome const*> >&) const ()
#1  0x000055555cc2434a in LevelChunk::validateAndFixBiomeStates() ()
#2  0x000055555cc27d13 in LevelChunk::deserializeKey(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >) ()
#3  0x000055555cef51b8 in std::__1::__function::__func<DBChunkStorage::_loadChunkFromDB(LevelChunk&, LevelChunk&, ChunkViewSource&)::$_13, std::__1::allocator<DBChunkStorage::_loadChunkFromDB(LevelChunk&, LevelChunk&, ChunkViewSource&)::$_13>, void (std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)>::operator()(std::__1::basic_string_view<char, std::__1::char_traits<char> >&&, std::__1::basic_string_view<char, std::__1::char_traits<char> >&&) ()
#4  0x000055555ceeec12 in DBStorage::_read(std::__1::basic_string_view<char, std::__1::char_traits<char> >, DBHelpers::Category, std::__1::function<void (std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)> const&) const::$_32::operator()(std::__1::unique_ptr<leveldb::Iterator, std::__1::default_delete<leveldb::Iterator> > const&) const ()
#5  0x000055555ceee1ce in DBStorage::_read(std::__1::basic_string_view<char, std::__1::char_traits<char> >, DBHelpers::Category, std::__1::function<void (std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)> const&) const ()
#6  0x000055555cee328a in DBChunkStorage::_loadChunkFromDB(LevelChunk&, LevelChunk&, ChunkViewSource&) ()
#7  0x000055555cee4758 in DBChunkStorage::_loadAndBlendFromDB(LevelChunk&, LevelChunk&, ChunkViewSource&) ()
#8  0x000055555cee426c in DBChunkStorage::checkAndReplaceChunk(ChunkViewSource&, LevelChunk&) ()
#9  0x000055555c9c313a in ChunkSource::_checkForReplacementDataTask(LevelChunk&, ChunkViewSource&) ()
#10 0x000055555c9dac78 in std::__1::__function::__func<ChunkSource::_launchReplacementDataTask(std::__1::shared_ptr<LevelChunk> const&, std::__1::shared_ptr<ChunkViewSource> const&, bool)::$_47, std::__1::allocator<ChunkSource::_launchReplacementDataTask(std::__1::shared_ptr<LevelChunk> const&, std::__1::shared_ptr<ChunkViewSource> const&, bool)::$_47>, TaskResult ()>::operator()() ()
#11 0x000055555d87e31c in BackgroundTask<TaskResult, void>::run(ITaskExecutionContext const*) ()
#12 0x000055555d84b801 in BackgroundWorker::_runOneTask() ()
#13 0x000055555d84b4c0 in BackgroundWorker::_processNextTask() ()
#14 0x000055555d86f9e8 in void* std::__1::__thread_proxy[abi:v15007]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, BackgroundWorker::start()::$_4> >(void*) ()
#15 0x00007ffff7c4b6c2 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:447
#16 0x00007ffff7cc6128 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Seems like something to do with loading biomes...

olebeck commented 3 months ago

I have traced the same issue before, couldn't get the leveldb key of what data its trying to decode. if you can find the key and send the leveldb + what key it's reading that would be very helpful to fix this, thanks

jedenastka commented 3 months ago

Unfortunately, I don't know how to do debugging without debug information.

This world will not be available anymore in 2 days, but I have made a capture so hopefully in the future it can be reexported correctly. I also found that converting the world to JE using je2be-web yelds a working JE world, albeit without any addon features, so at least I know it isn't completely corrupted.

olebeck commented 3 months ago

it isn't the chunk block data that's the issue I was debugging this same issue on windows using windbg, annoyingly windbg doesn't seem to be able to get register values of stack frames past the erroring one, I will try it with bds on Linux, gdb probably handles it way better

olebeck commented 3 months ago

i think i found the issue, biomes have a feature where it can reference the previous subchunks biomes to save space, minecraft seems to have broken decoding that, disabled it and seems to work now. try with latest version to check it fixed the issue for you too please

jedenastka commented 3 months ago

It works. Thank you so much!

jedenastka commented 3 months ago

This (or a related change) also seems to fix a different issue where generating worlds based on certain captures (which seemed to be random) would just silently fail, not producing a world.

Now for these captures there is an error printed to the console, but the world seems to generate correctly anyways:

ERRO[0001] decode packet *packet.Event: 1 unread bytes left: 0x00  part=main

This might be completely unrelated, but I wanted to note this.