mojira.dev
MC-197860

Deleting a custom dimension in a datapack deletes Nether and End

I was using online examples to set up custom dimensions for my datapack when I suddenly lost access to the nether and end dimensions in my vanilla world. They existed inside the world file, but were inaccessible. I could not run 'execute in' for any dimension aside from overworld, and portals could not teleport me.

How to reproduce

  1. Load a datapack that has a custom dimension using the default namespace

  2. Open world

  3. Close world

  4. Delete the datapack containing the custom dimension

  5. Open world

Video Example

 Depending on the resource location of the dimension, both nether and end could be gone or only one of them.

I was able to reproduce this bug multiple times, including on worlds generated in older versions like 1.15. The world does not have to be generated with the datapack–it can be added later. This process does not cause deletion of vanilla dimensions when custom dimensions use namespaces that are not 'minecraft.' This is a datapack I found online for free use, I did not create it. My client is unmodded. I also tested this in 1.16.2-rc2, at which the same bug occurred–though I was not able to mark it on here for some reason.

One last thing I noticed is that you do not even have to load the custom dimension, and the deletion of the 'dimensions' folder I did in the video is not required either for the bug to occur. Merely load the datapack in the world once, close the world, delete the datapack, and load the world again.

That is all I believe. I will try to monitor this thread if further information is needed. Thanks!

Linked issues

Attachments

Comments 10

The "minecraft" namespace is not necessary to reproduce the dimension going missing. This will also occur with any namespace as this datapack and video shows:

Video: https://streamable.com/o3cnq8
Datapack: 

[media]

 

URL of datapack in case link breaks or something: https://bugs.mojang.com/secure/attachment/334226/334226_test.zip 

 

Once the dimension goes missing, putting the datapack back on will not restore the missing nether/end dimension.

A friend looked into it and seems to be dependent on the order of the dimensions processed in this line of code in GeneratorOptions.CODEC (yarn names. Let me know if I should convert it to mojmap)

SimpleRegistry.createCodec(Registry.DIMENSION_OPTIONS, Lifecycle.stable(), DimensionOptions.CODEC).xmap(DimensionOptions::method_29569, Function.identity()).fieldOf("dimensions")

Here, the vanilla dimensions are returned missing when DimensionOptions#method_29569 is called it seems. The codec here might be the issue. The desired behavior is that the codec reads all the dimensions that exists and skips the ones that do not exist in the DIMENSION_OPTIONS registry instead of failing and removing dimensions that should still exist.

I've taken a closer look at this issue. Here are my findings into it:

How the Nether and End Dimensions are Removed

The removal of the nether and end relate to the:

  • Dimension Registration Order

  • Logic used to remove erroring dimensions in SaveFormat#getServerLifecyclePair

    • (These are MCP names, let me know if you need the mojmap name).

Dimension Registration Order

When the Dynamic<T> dynamic = nbt.get("WorldGenSettings").orElseEmptyMap();  in SaveFormat#getServerLifecyclePair is being constructed, the order of dimension registration is as follows:

  1. Overworld

  2. Datapack loaded custom dimensions

  3. Nether

  4. End

Logic used to remove erroring Dimensions

TelepathicGrunt is correct that the DimensionGeneratorSettings CODEC (GeneratorOptions.CODEC in Yarn names) will return missing dimensions.

However, that is only half of the story. The Dynamic<T> that is parsed into the DimensionGeneratorSettings CODEC originates from SaveFormat#getServerLifecyclePair.

When the custom dimension is removed, DimensionGeneratorSettings.CODEC fails to fully parse the Dynamic<T>, so the DataResult<DimensionGeneratorSettings> only return the Either#Right part of the result, which only includes the Overworld.

The crucial aspect is the Pair that is returned to the method uses the DataResult#resultOrPartial method, whose PartialResult which removes ALL objects AFTER the erroring objects, in addition to the erroring object.

i.e. The data result removes the erroring custom dimension, the Nether and the End, leaving only the Overworld.

 

When these two factors are put into effect, the subsequent ServerWorldInfo, which defines the settings for the World, will use the incorrect data. This is why the Nether and End dimensions become "missing".

Why the Nether and End Dimensions do not show after reinstating the missing datapack

When the world is loaded after the datapack is reinstated, by this time the Dynamic<T> no longer includes the nether and end in its list of dimensions. Hence, only the Overworld is parsed to the DataResult<DimensionGeneratorSettings> alongside the custom dimension.

For what it's worth, https://github.com/Mojang/DataFixerUpper/pull/55 seems to fix this issue as per my testing.

I just bumped into this issue, and while I don't have any insights I do have a question. In theory, I should be able to recover the lost dimensions by replacing the file where this data is written with a backup from before this issue occurred. Which file would this be? Thanks in advance if someone has the answer, and if not, I understand, this is not a tech support channel.

@Luis Busta
Try replacing the level.dat file with the old one and see if that fixes the issue. Some people had luck fixing the dimension entries in the level.dat directly to specify only the dimensions that should exist

That's what we initially tried but it didn't work for us. We ended up creating a new server and copied over everything but the following files:

  • level.dat

  • level.dat_old

  • uid.dat

  • session.lock

One of those should do the trick. Thanks anyway!

Your datapack is not working in 20w49a it needs the "min_y" and "height"

An update on this issue, the root cause of the issue been narrowed down to one of the methods in UnboundedMapCodec in Mojang's DataFixerUpper library being too aggresive with handling erroring data entries.

There has been a working Pull Request solution made on their Github, if anyone is interested. It's a 2-3 line change.

I've tested the pull request and can confirm it works.

However, it is only a solution for new world saves created after the solution is pulled. To allow older worlds already affected by this bug to retain the Nether and End dimension, a seperate solution will be needed to reinject the removed dimension entries back into the SaveFormat.

Linked PR: https://github.com/Mojang/DataFixerUpper/pull/55

Steps to get the dimensions back before this bug is fixed:

  1. Open level.dat using e.g. https://irath96.github.io/webNBT/

  2. Go to Data -> WorldGenSettings, and delete the dimensions tag

Can confirm in 1.19.3

Alan O'Cull

(Unassigned)

Confirmed

Platform

Important

Custom Worlds

1.16.2, 1.16.3, 1.16.4 Release Candidate 1, 1.16.4, 20w45a, 20w51a, 1.16.5, 1.17, 1.17.1, 1.19.3

Retrieved