mojira.dev
MC-131745

Shipwrecks sometimes generate split into different variants at chunk boundaries

Shipwrecks that generate on land/beaches can get split on the Y axis when on chunk boundaries. To reproduce, use the seed 551270389 and run the following command:

/execute in minecraft:overworld run tp @p 202 68 144

Code analysis

Code analysis by @unknown can be found in this comment.

Linked issues

MC-128152 Village House Generation Resolved MC-133367 Generation error in a village Resolved MC-134260 Funky village generation on chunk borders Resolved MC-134467 Weird Village Generation In 1.13 Resolved MC-134978 Village houses split in two Resolved

Attachments

Comments 22

[^1.20.1 large biomes x:-978 y:74 z:-1111 seed:-6466533622157603850.png]

[media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media][media]

I can't see this issue with your given seed and coordinates. Can you post the seed/coordinates of the other villages and shipwrecks in your screenshots?

It seems to work just fine for me. Check your seed and coordinates again and look at the shipwreck in game to see if it looks any different from the screenshots (including the ones I just added). It always worked for me regardless of render distance or performance so it should be easier than cake to teleport to the given coordinates and look at the glitched shipwreck in game. This also doesn't happen very often so I posted more screenshots to show the glitched shipwreck for now.

I see it now and can confirm this issue.

For some reason the game must have converted the seed I pasted as if it wasn't a numeric string, and it just happened to have a shipwreck at those coordinates specified.

That's good. I think you accidentally put a space before the seed I provided and teleported to a shipwreck that was like mine, but sideways and non-glitched (I used the same seed but with a space at the start). Just make sure the seed you paste doesn't have a space at the start because it actually changes the seed.

12 more comments

if the shipwreck is split into 3 or 4 chunks, it can have 3 variants in one.

Code Analysis (Yarn 22w15a)

net.minecraft.structure.ShipwreckGenerator.java

public void generate(StructureWorldAccess world, StructureAccessor structureAccessor, ChunkGenerator chunkGenerator, AbstractRandom abstractRandom, BlockBox chunkBox, ChunkPos chunkPos, BlockPos pos) {
	int minY = world.getTopY(), topY = 0;
	Vec3i size = this.structure.getSize();
	Heightmap.Type type = this.grounded ? Heightmap.Type.WORLD_SURFACE_WG : Heightmap.Type.OCEAN_FLOOR_WG;
	int k = size.getX() * size.getZ();
	if (k == 0) { // If size is 0, not relevant here
		topY = world.getTopY(type, this.pos.getX(), this.pos.getZ());
	} else {
		BlockPos blockPos = this.pos.add(size.getX() - 1, 0, size.getZ() - 1);
		for(BlockPos blockPos2 : BlockPos.iterate(this.pos, blockPos)) {
			int y = world.getTopY(type, blockPos2.getX(), blockPos2.getZ());
			topY += y;
			minY = Math.min(minY, y);
		}
		topY /= k;
	}
	int newY = this.grounded ? minY - size.getY() / 2 - abstractRandom.nextInt(3) : topY;
	this.pos = new BlockPos(this.pos.getX(), newY, this.pos.getZ());
	super.generate(world, structureAccessor, chunkGenerator, abstractRandom, chunkBox, chunkPos, pos);
}

If you look at the code above, the bug is only visible when this.grounded is true which matches all previous sightings of this bug, basically if it's beached.

There are actually 3 major issues at play here. I'm going to first talk about the use of abstractRandom.nextInt(3)
The same abstractRandom is used for all pieces, so by doing .nextInt(3) you guarantee that all individual pieces have a different value. This results in the different pieces of the shipwreck being at different heights. Instead, you should use positional random which you do later in the shipwreck code. Such as:
this.placementData.getRandom(this.pos).nextInt(3)
The next issue is that this.pos's Y value get's set by the results of the random. In turn, making the next result get a different random outcome due to getting a different position. We would fix this by adding something like:
this.pos.withY(0)
The last issue is that the ship palette changes between the chunk borders. Although the above fixes already fix this issue, let me explain:

net.minecraft.structure.Structure.java

public boolean place(ServerWorldAccess world, BlockPos pos, BlockPos pivot, StructurePlacementData placementData, AbstractRandom abstractRandom, int flags) {
	// ...
	// In the next code block I will show you `getRandomBlockInfos` we will be following the `pos`
	List<Structure.StructureBlockInfo> list = placementData.getRandomBlockInfos(blockInfoLists, pos).getAll();
	// ...

net.minecraft.structure.StructurePlacementData.java

public Structure.PalettedBlockInfoList getRandomBlockInfos(List list, BlockPos pos) {
	// ...
	// In the next code block ill show the code for `this.getRandom(pos)` the positional random being used
	return list.get(this.getRandom(pos).nextInt(i));
	// ...
}
public AbstractRandom getRandom(@Nullable BlockPos pos) {
	// ...	
	// This creates a random based on the blockPos hashCode, so it's positional
	return pos == null ? AbstractRandom.method_43049(Util.getMeasuringTimeMs()) : AbstractRandom.method_43049(MathHelper.hashCode(pos));
	// ...
}

All that is just to say that placementData.getRandomBlockInfos picks which palette to use based on the position of the structure. This means that by fixing the position issues in the 2 other problems, the palette gets chosen correctly.

Working Fix

This only affects shipwrecks, other border chunk issues are either related to there own structures or based on a larger issue

Can confirm in 1.19.1.

[media]

Version: 1.19.1

Seed: -1541328582584882083
Coordinates: /execute in minecraft:overworld run tp @s 55.84 70.91 392.37 -59.10 40.60

Seed: 2275652456192416646

-1707 57 -1713

Can confirm in 1.19.2.

Version: 1.19.2

Seed: -2055074493936140863
Coordinates: /execute in minecraft:overworld run tp @s 30511.06 75.43 -365.74 -244.87 60.40

gaspoweredpick

(Unassigned)

Confirmed

Platform

Low

Structures

shipwreck

Minecraft 1.13-pre2, Minecraft 1.13-pre5, Minecraft 1.13-pre6, Minecraft 1.13-pre7, Minecraft 1.13-pre8, ..., 24w44a, 1.21.3, 1.21.4, 1.21.5, 1.21.6

Retrieved