package net.minecraft.world.level.levelgen.structure.placement; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import java.util.Optional; import net.minecraft.core.Vec3i; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.level.levelgen.WorldgenRandom; public class RandomSpreadStructurePlacement extends StructurePlacement { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> placementCodec(instance) .and( instance.group( Codec.intRange(0, 4096).fieldOf("spacing").forGetter(RandomSpreadStructurePlacement::spacing), Codec.intRange(0, 4096).fieldOf("separation").forGetter(RandomSpreadStructurePlacement::separation), RandomSpreadType.CODEC.optionalFieldOf("spread_type", RandomSpreadType.LINEAR).forGetter(RandomSpreadStructurePlacement::spreadType) ) ) .apply(instance, RandomSpreadStructurePlacement::new) ) .validate(RandomSpreadStructurePlacement::validate); private final int spacing; private final int separation; private final RandomSpreadType spreadType; private static DataResult validate(RandomSpreadStructurePlacement placement) { return placement.spacing <= placement.separation ? DataResult.error(() -> "Spacing has to be larger than separation") : DataResult.success(placement); } public RandomSpreadStructurePlacement( Vec3i locateOffset, StructurePlacement.FrequencyReductionMethod frequencyReductionMethod, float frequency, int salt, Optional exclusionZone, int spacing, int separation, RandomSpreadType spreadType ) { super(locateOffset, frequencyReductionMethod, frequency, salt, exclusionZone); this.spacing = spacing; this.separation = separation; this.spreadType = spreadType; } public RandomSpreadStructurePlacement(int spacing, int separation, RandomSpreadType spreadType, int salt) { this(Vec3i.ZERO, StructurePlacement.FrequencyReductionMethod.DEFAULT, 1.0F, salt, Optional.empty(), spacing, separation, spreadType); } public int spacing() { return this.spacing; } public int separation() { return this.separation; } public RandomSpreadType spreadType() { return this.spreadType; } public ChunkPos getPotentialStructureChunk(long seed, int regionX, int regionZ) { int i = Math.floorDiv(regionX, this.spacing); int j = Math.floorDiv(regionZ, this.spacing); WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L)); worldgenRandom.setLargeFeatureWithSalt(seed, i, j, this.salt()); int k = this.spacing - this.separation; int l = this.spreadType.evaluate(worldgenRandom, k); int m = this.spreadType.evaluate(worldgenRandom, k); return new ChunkPos(i * this.spacing + l, j * this.spacing + m); } @Override protected boolean isPlacementChunk(ChunkGeneratorStructureState structureState, int x, int z) { ChunkPos chunkPos = this.getPotentialStructureChunk(structureState.getLevelSeed(), x, z); return chunkPos.x == x && chunkPos.z == z; } @Override public StructurePlacementType type() { return StructurePlacementType.RANDOM_SPREAD; } }