104 lines
3.5 KiB
Java
104 lines
3.5 KiB
Java
package net.minecraft.world.level.levelgen;
|
|
|
|
import com.mojang.datafixers.util.Either;
|
|
import com.mojang.serialization.Codec;
|
|
import java.util.function.Function;
|
|
import net.minecraft.world.level.dimension.DimensionType;
|
|
|
|
/**
|
|
* Represents a resolvable height value, or y coordinate, based on the world minimum and maximum height.
|
|
* Can take one of the following three forms:
|
|
* <ul>
|
|
* <li>An absolute y value ({@link Absolute}).</li>
|
|
* <li>A height above the lowest valid y value in the level ({@link AboveBottom}).</li>
|
|
* <li>A height below the highest valid y value in the level ({@link BelowTop}).</li>
|
|
* </ul>
|
|
*/
|
|
public interface VerticalAnchor {
|
|
Codec<VerticalAnchor> CODEC = Codec.xor(VerticalAnchor.Absolute.CODEC, Codec.xor(VerticalAnchor.AboveBottom.CODEC, VerticalAnchor.BelowTop.CODEC))
|
|
.xmap(VerticalAnchor::merge, VerticalAnchor::split);
|
|
VerticalAnchor BOTTOM = aboveBottom(0);
|
|
VerticalAnchor TOP = belowTop(0);
|
|
|
|
static VerticalAnchor absolute(int value) {
|
|
return new VerticalAnchor.Absolute(value);
|
|
}
|
|
|
|
static VerticalAnchor aboveBottom(int value) {
|
|
return new VerticalAnchor.AboveBottom(value);
|
|
}
|
|
|
|
static VerticalAnchor belowTop(int value) {
|
|
return new VerticalAnchor.BelowTop(value);
|
|
}
|
|
|
|
static VerticalAnchor bottom() {
|
|
return BOTTOM;
|
|
}
|
|
|
|
static VerticalAnchor top() {
|
|
return TOP;
|
|
}
|
|
|
|
private static VerticalAnchor merge(Either<VerticalAnchor.Absolute, Either<VerticalAnchor.AboveBottom, VerticalAnchor.BelowTop>> anchor) {
|
|
return anchor.map(Function.identity(), Either::unwrap);
|
|
}
|
|
|
|
private static Either<VerticalAnchor.Absolute, Either<VerticalAnchor.AboveBottom, VerticalAnchor.BelowTop>> split(VerticalAnchor anchor) {
|
|
return anchor instanceof VerticalAnchor.Absolute
|
|
? Either.left((VerticalAnchor.Absolute)anchor)
|
|
: Either.right(
|
|
anchor instanceof VerticalAnchor.AboveBottom ? Either.left((VerticalAnchor.AboveBottom)anchor) : Either.right((VerticalAnchor.BelowTop)anchor)
|
|
);
|
|
}
|
|
|
|
int resolveY(WorldGenerationContext context);
|
|
|
|
public record AboveBottom(int offset) implements VerticalAnchor {
|
|
public static final Codec<VerticalAnchor.AboveBottom> CODEC = Codec.intRange(DimensionType.MIN_Y, DimensionType.MAX_Y)
|
|
.fieldOf("above_bottom")
|
|
.<VerticalAnchor.AboveBottom>xmap(VerticalAnchor.AboveBottom::new, VerticalAnchor.AboveBottom::offset)
|
|
.codec();
|
|
|
|
@Override
|
|
public int resolveY(WorldGenerationContext context) {
|
|
return context.getMinGenY() + this.offset;
|
|
}
|
|
|
|
public String toString() {
|
|
return this.offset + " above bottom";
|
|
}
|
|
}
|
|
|
|
public record Absolute(int y) implements VerticalAnchor {
|
|
public static final Codec<VerticalAnchor.Absolute> CODEC = Codec.intRange(DimensionType.MIN_Y, DimensionType.MAX_Y)
|
|
.fieldOf("absolute")
|
|
.<VerticalAnchor.Absolute>xmap(VerticalAnchor.Absolute::new, VerticalAnchor.Absolute::y)
|
|
.codec();
|
|
|
|
@Override
|
|
public int resolveY(WorldGenerationContext context) {
|
|
return this.y;
|
|
}
|
|
|
|
public String toString() {
|
|
return this.y + " absolute";
|
|
}
|
|
}
|
|
|
|
public record BelowTop(int offset) implements VerticalAnchor {
|
|
public static final Codec<VerticalAnchor.BelowTop> CODEC = Codec.intRange(DimensionType.MIN_Y, DimensionType.MAX_Y)
|
|
.fieldOf("below_top")
|
|
.<VerticalAnchor.BelowTop>xmap(VerticalAnchor.BelowTop::new, VerticalAnchor.BelowTop::offset)
|
|
.codec();
|
|
|
|
@Override
|
|
public int resolveY(WorldGenerationContext context) {
|
|
return context.getGenDepth() - 1 + context.getMinGenY() - this.offset;
|
|
}
|
|
|
|
public String toString() {
|
|
return this.offset + " below top";
|
|
}
|
|
}
|
|
}
|