OpenLoco / OpenLoco

An open source re-implementation of Chris Sawyer's Locomotion
https://openloco.io/
MIT License
1.26k stars 155 forks source link

Crash with "Shinkansen Land 1970" scenario #2613

Open shusaura85 opened 2 weeks ago

shusaura85 commented 2 weeks ago

Version information:

Describe the bug Game crashes when starting the Shinkansen scenario.
In 24.09, it crashes every time (caused by random landscape generation bug).
In 24.05 to 24.08, it crashes if the ObjData files SHINKT0.DAT and SHINKF0.DAT are missing and need to be installed by the scenario.
In this case, it crashes after saving the first object,
then it crashes after saving the second object,
3rd attempt will load the scenario successfully.

To Reproduce

  1. If object files SHINKT0.DAT and SHINKF0.DAT are present in Locomotion ObjData folder, remove them.
  2. Start new game
  3. , Select scenario "Shinkansen Land 1970".
  4. Crashes and creates dump file
  5. See error

Expected behaviour Doesn't crash

Additional context In 24.09 it crashes when "Generating landscape..."

Attached dump from 24.08 as 24.09 has another bug with random landscape generation

b372fe7c-36ad-44b4-a847-713c222a27af(OpenLoco, v24.08 (40e9b7bf on master)).zip

AaronVanGeffen commented 2 weeks ago

I believe this is due to a small mistake in the generateTerrainAroundCliffs function. That function was implemented as part of #2383, which was merged for v24.04. This too will be fixed by #2615.

shusaura85 commented 2 weeks ago

Still crashes in 24.09.1 if the ObjData files are not present. This bug doesn't appear to be fixed

Dump files give the same error:
FAILURE_BUCKET_ID: NULL_CLASS_PTR_READ_c0000005_openloco.dll!Unknown ExceptionAddress: 6205cdcb (openloco+0x000acdcb) ExceptionCode: c0000005 (Access violation)

1st crash - both objdata files missing.zip 2nd crash - 1 file missing (SHINKF0.DAT).zip

Cgettys commented 1 week ago

I can still repro this on c71cd567f104ef2dcb55cded95f9a36cd0b1e33a

Also looks like Snowy Heights can repro the terrain generation bug.

I think this is really two bugs: one with ObjData installation (that would only repro with custom scenario installation that installs objects, e.g. specifically "Shinkansen Land 1970"

And a second bug which appears to be a deterministic crash when deallocating the height map:

unmap_chunk(): invalid pointer

Thread 1 "OpenLoco" received signal SIGABRT, Aborted.
0xf7fc7579 in __kernel_vsyscall ()
(gdb) bt 20
#0  0xf7fc7579 in __kernel_vsyscall ()
#1  0xf731af97 in ?? () from /lib/i386-linux-gnu/libc.so.6
#2  0xf72c80b5 in raise () from /lib/i386-linux-gnu/libc.so.6
#3  0xf72af2bf in abort () from /lib/i386-linux-gnu/libc.so.6
#4  0xf72b037d in ?? () from /lib/i386-linux-gnu/libc.so.6
#5  0xf73268dd in ?? () from /lib/i386-linux-gnu/libc.so.6
#6  0xf7326bdb in ?? () from /lib/i386-linux-gnu/libc.so.6
#7  0xf732b2b5 in free () from /lib/i386-linux-gnu/libc.so.6
#8  0xf759715c in operator delete(void*) () from /lib/i386-linux-gnu/libstdc++.so.6
#9  0xf759718c in operator delete(void*, unsigned int) () from /lib/i386-linux-gnu/libstdc++.so.6
#10 0x0117981d in std::__new_allocator<unsigned char>::deallocate (this=0xffffc8dc,
    __p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037  \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\032\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., __n=147456) at /usr/include/c++/13/bits/new_allocator.h:172
#11 0x011719ea in std::allocator<unsigned char>::deallocate (__n=147456,
    __p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037  \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\032\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., this=0xffffc8dc) at /usr/include/c++/13/bits/allocator.h:210
#12 std::allocator_traits<std::allocator<unsigned char> >::deallocate (__n=147456,
    __p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037  \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\032\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., __a=...) at /usr/include/c++/13/bits/alloc_traits.h:517
#13 std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_deallocate (this=0xffffc8dc,
    __p=0x4342710 "\030\030\030\030\030\030\030\030\031\032\033", '\034' <repeats 12 times>, "\033\032\031\034\035\036\037  \037\036\035\034\033\032\031\030\027\026\025\024\023\022\023\024\025\025\025\025\025\026\027\030\031\032\032\032\0--Type <RET> for more, q to quit, c to continue without paging--
32\031\030\031\032\033\033\032\031\030\027\026\025\024\020\021\023\024\025\026\027\030\031\032\033\032\031\031\030\027\026\025\024\024\025\024\024\024\023\022\021\020\020\020\020", '\017' <repeats 11 times>, "\020\021\022\023\024\025\026\027\026\025\024", '\023' <repeats 45 times>, "\022\021\020\021\022\023\024\025\026\027\030\031\032\033\033\032\031\030\027\026\025\024\021\021\021\021\021\024"..., __n=147456) at /usr/include/c++/13/bits/stl_vector.h:390
#14 0x0116d495 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::~_Vector_base (this=0xffffc8dc,
    __in_chrg=<optimized out>) at /usr/include/c++/13/bits/stl_vector.h:369
#15 0x0116c97f in std::vector<unsigned char, std::allocator<unsigned char> >::~vector (this=0xffffc8dc,
    __in_chrg=<optimized out>) at /usr/include/c++/13/bits/stl_vector.h:738
#16 0x01278ba0 in OpenLoco::World::MapGenerator::HeightMap::~HeightMap (this=0xffffc8dc, __in_chrg=<optimized out>)
    at /openloco/src/OpenLoco/src/Map/MapGenerator/HeightMap.h:11
#17 0x01277d1b in OpenLoco::World::MapGenerator::generate (options=...)
    at /openloco/src/OpenLoco/src/Map/MapGenerator/MapGenerator.cpp:1046
#18 0x0130ef64 in OpenLoco::Scenario::generateLandscape () at /openloco/src/OpenLoco/src/Scenario.cpp:252
#19 0x0130f72f in OpenLoco::Scenario::start () at /openloco/src/OpenLoco/src/Scenario.cpp:362
Cgettys commented 1 week ago

Exact crash isn't perfectly deterministic - sometimes I get this message:

free(): invalid size which implies a good old fashioned memory corruption most likely Unfortunately, I can't get it to run under valgrind, I'm sure I'm doing something stupid.

valgrind ./OpenLoco
==9114== Memcheck, a memory error detector
==9114== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==9114== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==9114== Command: ./OpenLoco
==9114==
OpenLoco, v24.09.1-1 (c71cd567 on master, DEBUG)
X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  4 (X_DestroyWindow)
  Resource id in failed request:  0x2e00002
  Serial number of failed request:  139
  Current serial number in output stream:  139
==9114==
==9114== HEAP SUMMARY:
==9114==     in use at exit: 580,429 bytes in 2,516 blocks
==9114==   total heap usage: 22,302 allocs, 19,786 frees, 2,855,546 bytes allocated
==9114==
==9114== LEAK SUMMARY:
==9114==    definitely lost: 0 bytes in 0 blocks
==9114==    indirectly lost: 0 bytes in 0 blocks
==9114==      possibly lost: 0 bytes in 0 blocks
==9114==    still reachable: 580,429 bytes in 2,516 blocks
==9114==         suppressed: 0 bytes in 0 blocks
==9114== Rerun with --leak-check=full to see details of leaked memory
==9114==
==9114== For lists of detected and suppressed errors, rerun with: -s
==9114== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
duncanspumpkin commented 1 week ago

@AaronVanGeffen this is a progress bar issue. When installing an object it unloads all objects the progress bar then tries to render but with objects unloaded it crashes.

Cgettys commented 1 week ago

I don't think so?

I tried commenting out the relevant progress updates

        {
            HeightMap heightMap(kMapColumns, kMapRows);

            generateHeightMap(options, heightMap);
            //updateProgress(25);

            generateRivers(options, heightMap);
            //updateProgress(30);

            generateLand(heightMap);
            //updateProgress(35);

            generateWater(heightMap);
            //updateProgress(45);

            generateTerrain(heightMap);
            //updateProgress(55);
        }

        generateSurfaceVariation();
        //updateProgress(175);

And recompiled of course.

It seems to be a double free or other memory corruption (and the error messages agree):

double free or corruption (out)

at line 1046

When HeightMap heightMap(kMapColumns, kMapRows); leaves scope and thus is destroyed. What I can't work out, is what's going wrong...

Cgettys commented 1 week ago
 {
            HeightMap heightMap(kMapColumns, kMapRows);

            //generateHeightMap(options, heightMap);
            //updateProgress(25);

            //generateRivers(options, heightMap);
            //updateProgress(30);

            //generateLand(heightMap);
            //updateProgress(35);

            //generateWater(heightMap);
            //updateProgress(45);

            //generateTerrain(heightMap);
            //updateProgress(55);
        }

This works "fine" as long as one wants to live on a perfectly flat world. The minute one uncomments generateHeightMap, things go boom.

So my theory (haven't found the exact point yet) is that somewhere along the line, the pointer to heightMap::_height is freed. Possibly by existing assembly code? or by C++ code I haven't found yet.

Which results in a 100% deterministic double free crash when heightMap leaves scope.

Cgettys commented 1 week ago

Yeah, definitely looks to be the case

        {
            // Intentional leak... someone else is freeing the heightMap._height
            HeightMap* heightMap = new HeightMap(kMapColumns, kMapRows);

            generateHeightMap(options, *heightMap);
            updateProgress(25);

            generateRivers(options, *heightMap);
            updateProgress(30);

            generateLand(*heightMap);
            updateProgress(35);

            generateWater(*heightMap);
            updateProgress(45);

            generateTerrain(*heightMap);
            updateProgress(55);
        }

Also works fine and actually generates terrain! (but leaks the wrapper struct, but not the big array probably)

Cgettys commented 1 week ago

Theory somewhat busted:

            HeightMap* heightMap = new HeightMap(kMapColumns, kMapRows);

            generateHeightMap(options, *heightMap);
            generateHeightMap(options, *heightMap);

Would crash if that pointer was being freed But I'm pretty confused.

Cgettys commented 1 week ago

Given that I have a workaround (leak the heightmap), I think that's enough debugging for me for one day... hope the data helps.

Cgettys commented 1 week ago

Oh... ok, so that's even more fun. If I try to leak it, it generates fine. But quitting to the menu now deterministically crashes instead. What cursed (arena based?) memory management shenanigans am I overlooking here?

free(): invalid next size (normal)

Thread 1 "OpenLoco" received signal SIGABRT, Aborted.
0xf7fc7579 in __kernel_vsyscall ()
(gdb) bt 20
#0  0xf7fc7579 in __kernel_vsyscall ()
#1  0xf731af97 in __pthread_kill_implementation (threadid=threadid@entry=4137756608, signo=signo@entry=6,
    no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:43
#2  0xf731b01f in __pthread_kill_internal (signo=6, threadid=4137756608) at ./nptl/pthread_kill.c:78
#3  0xf72c80b5 in __GI_raise (sig=6) at ../sysdeps/posix/raise.c:26
#4  0xf72af2bf in __GI_abort () at ./stdlib/abort.c:79
#5  0xf72b037d in __libc_message_impl (fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:132
#6  0xf73268dd in malloc_printerr (str=str@entry=0xf7456cf8 "free(): invalid next size (normal)")
    at ./malloc/malloc.c:5772
#7  0xf73288bb in _int_free_merge_chunk (av=av@entry=0xf74bd760 <main_arena>, p=p@entry=0x432c1b8,
    size=size@entry=129488) at ./malloc/malloc.c:4684
#8  0xf7328c20 in _int_free (av=av@entry=0xf74bd760 <main_arena>, p=0x432c1b8, have_lock=<optimized out>,
    have_lock@entry=0) at ./malloc/malloc.c:4646
#9  0xf732b267 in __GI___libc_free (mem=0x432c1c0) at ./malloc/malloc.c:3398
#10 0x012c83f7 in OpenLoco::ObjectManager::unload (header=...)
    at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:567
#11 0x012c9527 in operator() (__closure=0xffffc8eb, handle=...)
    at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#12 0x012ca168 in OpenLoco::ObjectManager::forEachLoadedObject<OpenLoco::ObjectManager::unloadAll()::<lambda(const OpenLoco::LoadedObjectHandle&)> >(struct {...} &&) (func=...) at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.h:210
#13 0x012c9554 in OpenLoco::ObjectManager::unloadAll () at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#14 0x013151a0 in OpenLoco::Title::start () at /OpenLoco/src/OpenLoco/src/Title.cpp:154
#15 0x011ce2f5 in OpenLoco::Game::returnToTitle () at /OpenLoco/src/OpenLoco/src/Game.cpp:263
#16 0x011e00b5 in OpenLoco::GameCommands::loadSaveQuit (args=..., flags=1 '\001')
    at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:64
#17 0x011e0112 in OpenLoco::GameCommands::loadSaveQuit (regs=...)
    at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:77
#18 0x011deb4d in OpenLoco::GameCommands::callGameCommandFunction (command=21, regs=...)
    at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:354
#19 0x011ded5f in OpenLoco::GameCommands::loc_4313C6 (esi=21, regs=...)
    at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:416
(More stack frames follow...)
(gdb) bt 40
#0  0xf7fc7579 in __kernel_vsyscall ()
#1  0xf731af97 in __pthread_kill_implementation (threadid=threadid@entry=4137756608, signo=signo@entry=6,
    no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:43
#2  0xf731b01f in __pthread_kill_internal (signo=6, threadid=4137756608) at ./nptl/pthread_kill.c:78
#3  0xf72c80b5 in __GI_raise (sig=6) at ../sysdeps/posix/raise.c:26
#4  0xf72af2bf in __GI_abort () at ./stdlib/abort.c:79
#5  0xf72b037d in __libc_message_impl (fmt=<optimized out>) at ../sysdeps/posix/libc_fatal.c:132
#6  0xf73268dd in malloc_printerr (str=str@entry=0xf7456cf8 "free(): invalid next size (normal)")
    at ./malloc/malloc.c:5772
#7  0xf73288bb in _int_free_merge_chunk (av=av@entry=0xf74bd760 <main_arena>, p=p@entry=0x432c1b8,
    size=size@entry=129488) at ./malloc/malloc.c:4684
#8  0xf7328c20 in _int_free (av=av@entry=0xf74bd760 <main_arena>, p=0x432c1b8, have_lock=<optimized out>,
    have_lock@entry=0) at ./malloc/malloc.c:4646
#9  0xf732b267 in __GI___libc_free (mem=0x432c1c0) at ./malloc/malloc.c:3398
#10 0x012c83f7 in OpenLoco::ObjectManager::unload (header=...)
    at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:567
#11 0x012c9527 in operator() (__closure=0xffffc8eb, handle=...)
    at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#12 0x012ca168 in OpenLoco::ObjectManager::forEachLoadedObject<OpenLoco::ObjectManager::unloadAll()::<lambda(const OpenLoco::LoadedObjectHandle&)> >(struct {...} &&) (func=...) at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.h:210
#13 0x012c9554 in OpenLoco::ObjectManager::unloadAll () at /OpenLoco/src/OpenLoco/src/Objects/ObjectManager.cpp:829
#14 0x013151a0 in OpenLoco::Title::start () at /OpenLoco/src/OpenLoco/src/Title.cpp:154
#15 0x011ce2f5 in OpenLoco::Game::returnToTitle () at /OpenLoco/src/OpenLoco/src/Game.cpp:263
#16 0x011e00b5 in OpenLoco::GameCommands::loadSaveQuit (args=..., flags=1 '\001')
    at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:64
#17 0x011e0112 in OpenLoco::GameCommands::loadSaveQuit (regs=...)
    at /OpenLoco/src/OpenLoco/src/GameCommands/General/LoadSaveQuit.cpp:77
#18 0x011deb4d in OpenLoco::GameCommands::callGameCommandFunction (command=21, regs=...)
    at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:354
#19 0x011ded5f in OpenLoco::GameCommands::loc_4313C6 (esi=21, regs=...)
    at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:416
#20 0x011deaf7 in OpenLoco::GameCommands::doCommandForReal (
    command=OpenLoco::GameCommands::GameCommand::loadSaveQuitGame, company=0, regs=...)
    at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:346
#21 0x011de95f in OpenLoco::GameCommands::doCommand (command=OpenLoco::GameCommands::GameCommand::loadSaveQuitGame,
    regs=...) at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.cpp:306
#22 0x011cf8e4 in OpenLoco::GameCommands::doCommand<OpenLoco::GameCommands::LoadSaveQuitGameArgs> (args=...,
    flags=1 '\001') at /OpenLoco/src/OpenLoco/src/GameCommands/GameCommands.h:138
#23 0x014188e9 in OpenLoco::Ui::Windows::ToolbarTop::Game::loadsaveMenuDropdown (
    window=0x1a1b0f4 <OpenLoco::Ui::WindowManager::_windows+5428>, widgetIndex=0 '\000', itemIndex=8)
    at /OpenLoco/src/OpenLoco/src/Windows/ToolbarTop.cpp:261
#24 0x01419c84 in OpenLoco::Ui::Windows::ToolbarTop::Game::onDropdown (window=..., widgetIndex=0 '\000', itemIndex=8)
    at /OpenLoco/src/OpenLoco/src/Windows/ToolbarTop.cpp:714
#25 0x0133dd1b in OpenLoco::Ui::Window::callOnDropdown (this=0x1a1b0f4 <OpenLoco::Ui::WindowManager::_windows+5428>,
    widgetIndex=0 '\000', itemIndex=8) at /OpenLoco/src/OpenLoco/src/Ui/Window.cpp:1101
#26 0x0123f942 in OpenLoco::Input::dropdownRegisterSelection (item=8)
    at /OpenLoco/src/OpenLoco/src/Input/MouseInput.cpp:894
#27 0x0124018f in OpenLoco::Input::stateWidgetPressed (button=OpenLoco::Input::MouseButton::leftReleased, x=63,
    y=115, window=0x1a1d0c2 <OpenLoco::Ui::WindowManager::_windows+13570>,
    widget=0x1a1d950 <OpenLoco::Ui::WindowManager::_windows+15760>, widgetIndex=0 '\000')
    at /OpenLoco/src/OpenLoco/src/Input/MouseInput.cpp:1076
#28 0x0123e120 in OpenLoco::Input::handleMouse (x=63, y=115, button=OpenLoco::Input::MouseButton::leftReleased)
    at /OpenLoco/src/OpenLoco/src/Input/MouseInput.cpp:380
#29 0x0131b3e6 in OpenLoco::Ui::handleInput () at /OpenLoco/src/OpenLoco/src/Ui.cpp:899
#30 0x012d6d1c in OpenLoco::sub_431695 (var_F253A0=1) at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:302
#31 0x012d71dd in OpenLoco::tick () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:448
#32 0x012d819c in OpenLoco::variableUpdate () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:731
#33 0x012d836f in OpenLoco::update () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:771
#34 0x012d83ab in OpenLoco::run () at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:786
#35 0x012d8811 in OpenLoco::main (options=...) at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:881
#36 0x012d8b8f in OpenLoco::main (argv=...) at /OpenLoco/src/OpenLoco/src/OpenLoco.cpp:902
#37 0x01270601 in main (argc=1, argv=0xffffd144) at /OpenLoco/src/OpenLoco/src/Main.cpp:28
AaronVanGeffen commented 1 week ago

Duncan is talking about a different set of progress bars. The object loading happens during the S5 import routines, not the map generation.

Cgettys commented 1 week ago

Oh - I see. He's talking about the scenario loading bug Whereas I was talking about the other bug that also impacts Shinkansen Land - the landscape generation one. Would it help if I opened a separate issue to track that?

AaronVanGeffen commented 3 days ago

Shinkansen Land 1970 generates fine for me, provided the objects are present. I can reproduce a crash on Snowy Heights, though. As randomness is involved, luck can sway either way, though. I'll look into it.

shusaura85 commented 3 days ago

Shinkansen Land 1970 generates fine for me, provided the objects are present. I can reproduce a crash on Snowy Heights, though. As randomness is involved, luck can sway either way, though. I'll look into it.

This issue was supposed to be about the crash when saving the objects inside the scenario. Looks like it got hijacked for terrain generation bugs

AaronVanGeffen commented 3 days ago

This issue was supposed to be about the crash when saving the objects inside the scenario. Looks like it got hijacked for terrain generation bugs

Don't worry, we have not forgotten the issue with object extraction.