Dimension crash
Draylar opened this issue ยท 2 comments
This is a tricky one... not entirely sure where to start.
Summary: dimensions are crashing due to some sort of ID serialization/reading issue.
This started 2 weeks ago when I got an issue on Miner's Horizon about an odd crash. From experimenting (and eventually getting the user's world file), it seems like some worlds are bricked when you log out in custom dimensions because you are no longer able to log in. As I traced through the debug log, I gathered the following information:
- only occurs when the player logs out while inside a custom dimension and attempts to relog back in
- crashes at PlayerManager#onPlayerConnect at the getLevelProperties call because the ServerWorld is null
- ServerWorld is null because the dimension ID attached to the ServerPlayerEntity of the method is null/invalid
- dimension ID seems to be properly saved because loadPlayerData can see the ID.
One other odd thing that was noticed is DimensionType is serialized by rawId, which returns the ID - 1. I was curious as to whether or not this was responsible, but it doesn't seem to be related (as dims are retrieved by ID + 1).
After talking with Chloe for a bit, we came to a mixin solution that involved setting the dimension to the Overworld if it's null. This works and fixes worlds, but the issue still occurs (although it is being patched, so it appears to work).
At this stage I was still under the impression it was a Miner's Horizon issue... then Raphy contacted me and said they also had dimension crashes. Just the two of us, right? No; Jericho also experienced it today. Not a specific Miner's Horizon issue. I'm opening this issue because this is a bug that will, again, brick worlds. I do have a patch jar out, but it won't work in the long run.
Any clues or ideas would be appreciated.
Upon further investigation, it seems to be a bug related to how Mojang assumes dimensions will be registered. The 3 default dimensions and their IDs are:
- Nether, 0
- Overworld, 1
- End, 2
These are conveniently registered in the correct order, so no issues appear.
The problem is with custom IDs that don't follow in the typical ID order (eg. Miner's Horizon is 5 and does not work). This is because while dimensions are saved with their ID, they are also (on occasion-- not always!!) saved at the first available index in the dim Registry. The Dimension ID is saved to the player NBT, and when it's read, the dimension registry is asked for the dimension at index n. In the case of default dimensions, this works fine, because each is registered with an ID equal to their index in the registry (Nether is at index 0 with an ID of 0, etc). Custom dimensions with custom IDs do not match their index, so null is returned by the registry, which then causes a crash in PlayerManager#onPlayerConnect
. In other words, all dimensions with special IDs will break-- and I have no desire to figure out what happens once we have multiple dimensions with similar IDs.
That was my old theory while testing a broken world. Guess what happens when I load into a new one? The index is 5 and the dimension works. I have a testing world a user sent me that crashes, and the index is always 3 (which leads to null). Must've somehow been saved differently-- not sure.
Hope this makes sense. I don't have any sort of proposal for a fix (and can't even prove this is a full issue), but I will come back and post again after I've figured stuff out.