163 lines
7.4 KiB
Java
163 lines
7.4 KiB
Java
|
package net.minecraft.world.level.levelgen;
|
||
|
|
||
|
import com.google.common.annotations.VisibleForTesting;
|
||
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||
|
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||
|
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
||
|
import net.minecraft.Util;
|
||
|
import net.minecraft.util.Mth;
|
||
|
import net.minecraft.world.level.ChunkPos;
|
||
|
import net.minecraft.world.level.StructureManager;
|
||
|
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||
|
import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece;
|
||
|
import net.minecraft.world.level.levelgen.structure.Structure;
|
||
|
import net.minecraft.world.level.levelgen.structure.StructurePiece;
|
||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||
|
import net.minecraft.world.level.levelgen.structure.TerrainAdjustment;
|
||
|
import net.minecraft.world.level.levelgen.structure.pools.JigsawJunction;
|
||
|
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
|
||
|
|
||
|
public class Beardifier implements DensityFunctions.BeardifierOrMarker {
|
||
|
public static final int BEARD_KERNEL_RADIUS = 12;
|
||
|
private static final int BEARD_KERNEL_SIZE = 24;
|
||
|
private static final float[] BEARD_KERNEL = Util.make(new float[13824], p_158082_ -> {
|
||
|
for (int i = 0; i < 24; i++) {
|
||
|
for (int j = 0; j < 24; j++) {
|
||
|
for (int k = 0; k < 24; k++) {
|
||
|
p_158082_[i * 24 * 24 + j * 24 + k] = (float)computeBeardContribution(j - 12, k - 12, i - 12);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
private final ObjectListIterator<Beardifier.Rigid> pieceIterator;
|
||
|
private final ObjectListIterator<JigsawJunction> junctionIterator;
|
||
|
|
||
|
public static Beardifier forStructuresInChunk(StructureManager p_223938_, ChunkPos p_223939_) {
|
||
|
int i = p_223939_.getMinBlockX();
|
||
|
int j = p_223939_.getMinBlockZ();
|
||
|
ObjectList<Beardifier.Rigid> objectlist = new ObjectArrayList<>(10);
|
||
|
ObjectList<JigsawJunction> objectlist1 = new ObjectArrayList<>(32);
|
||
|
p_223938_.startsForStructure(p_223939_, p_223941_ -> p_223941_.terrainAdaptation() != TerrainAdjustment.NONE).forEach(p_223936_ -> {
|
||
|
TerrainAdjustment terrainadjustment = p_223936_.getStructure().terrainAdaptation();
|
||
|
|
||
|
for (StructurePiece structurepiece : p_223936_.getPieces()) {
|
||
|
if (structurepiece.isCloseToChunk(p_223939_, 12)) {
|
||
|
if (structurepiece instanceof PoolElementStructurePiece poolelementstructurepiece) {
|
||
|
StructureTemplatePool.Projection structuretemplatepool$projection = poolelementstructurepiece.getElement().getProjection();
|
||
|
if (structuretemplatepool$projection == StructureTemplatePool.Projection.RIGID) {
|
||
|
objectlist.add(new Beardifier.Rigid(poolelementstructurepiece.getBoundingBox(), terrainadjustment, poolelementstructurepiece.getGroundLevelDelta()));
|
||
|
}
|
||
|
|
||
|
for (JigsawJunction jigsawjunction : poolelementstructurepiece.getJunctions()) {
|
||
|
int k = jigsawjunction.getSourceX();
|
||
|
int l = jigsawjunction.getSourceZ();
|
||
|
if (k > i - 12 && l > j - 12 && k < i + 15 + 12 && l < j + 15 + 12) {
|
||
|
objectlist1.add(jigsawjunction);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
objectlist.add(new Beardifier.Rigid(structurepiece.getBoundingBox(), terrainadjustment, 0));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
return new Beardifier(objectlist.iterator(), objectlist1.iterator());
|
||
|
}
|
||
|
|
||
|
@VisibleForTesting
|
||
|
public Beardifier(ObjectListIterator<Beardifier.Rigid> p_223917_, ObjectListIterator<JigsawJunction> p_223918_) {
|
||
|
this.pieceIterator = p_223917_;
|
||
|
this.junctionIterator = p_223918_;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public double compute(DensityFunction.FunctionContext p_208200_) {
|
||
|
int i = p_208200_.blockX();
|
||
|
int j = p_208200_.blockY();
|
||
|
int k = p_208200_.blockZ();
|
||
|
double d0 = 0.0;
|
||
|
|
||
|
while (this.pieceIterator.hasNext()) {
|
||
|
Beardifier.Rigid beardifier$rigid = this.pieceIterator.next();
|
||
|
BoundingBox boundingbox = beardifier$rigid.box();
|
||
|
int l = beardifier$rigid.groundLevelDelta();
|
||
|
int i1 = Math.max(0, Math.max(boundingbox.minX() - i, i - boundingbox.maxX()));
|
||
|
int j1 = Math.max(0, Math.max(boundingbox.minZ() - k, k - boundingbox.maxZ()));
|
||
|
int k1 = boundingbox.minY() + l;
|
||
|
int l1 = j - k1;
|
||
|
|
||
|
int i2 = switch (beardifier$rigid.terrainAdjustment()) {
|
||
|
case NONE -> 0;
|
||
|
case BURY, BEARD_THIN -> l1;
|
||
|
case BEARD_BOX -> Math.max(0, Math.max(k1 - j, j - boundingbox.maxY()));
|
||
|
case ENCAPSULATE -> Math.max(0, Math.max(boundingbox.minY() - j, j - boundingbox.maxY()));
|
||
|
};
|
||
|
|
||
|
d0 += switch (beardifier$rigid.terrainAdjustment()) {
|
||
|
case NONE -> 0.0;
|
||
|
case BURY -> getBuryContribution(i1, i2 / 2.0, j1);
|
||
|
case BEARD_THIN, BEARD_BOX -> getBeardContribution(i1, i2, j1, l1) * 0.8;
|
||
|
case ENCAPSULATE -> getBuryContribution(i1 / 2.0, i2 / 2.0, j1 / 2.0) * 0.8;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
this.pieceIterator.back(Integer.MAX_VALUE);
|
||
|
|
||
|
while (this.junctionIterator.hasNext()) {
|
||
|
JigsawJunction jigsawjunction = this.junctionIterator.next();
|
||
|
int j2 = i - jigsawjunction.getSourceX();
|
||
|
int k2 = j - jigsawjunction.getSourceGroundY();
|
||
|
int l2 = k - jigsawjunction.getSourceZ();
|
||
|
d0 += getBeardContribution(j2, k2, l2, k2) * 0.4;
|
||
|
}
|
||
|
|
||
|
this.junctionIterator.back(Integer.MAX_VALUE);
|
||
|
return d0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public double minValue() {
|
||
|
return Double.NEGATIVE_INFINITY;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public double maxValue() {
|
||
|
return Double.POSITIVE_INFINITY;
|
||
|
}
|
||
|
|
||
|
private static double getBuryContribution(double p_328731_, double p_336073_, double p_329819_) {
|
||
|
double d0 = Mth.length(p_328731_, p_336073_, p_329819_);
|
||
|
return Mth.clampedMap(d0, 0.0, 6.0, 1.0, 0.0);
|
||
|
}
|
||
|
|
||
|
private static double getBeardContribution(int p_223926_, int p_223927_, int p_223928_, int p_223929_) {
|
||
|
int i = p_223926_ + 12;
|
||
|
int j = p_223927_ + 12;
|
||
|
int k = p_223928_ + 12;
|
||
|
if (isInKernelRange(i) && isInKernelRange(j) && isInKernelRange(k)) {
|
||
|
double d0 = p_223929_ + 0.5;
|
||
|
double d1 = Mth.lengthSquared(p_223926_, d0, p_223928_);
|
||
|
double d2 = -d0 * Mth.fastInvSqrt(d1 / 2.0) / 2.0;
|
||
|
return d2 * BEARD_KERNEL[k * 24 * 24 + i * 24 + j];
|
||
|
} else {
|
||
|
return 0.0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static boolean isInKernelRange(int p_223920_) {
|
||
|
return p_223920_ >= 0 && p_223920_ < 24;
|
||
|
}
|
||
|
|
||
|
private static double computeBeardContribution(int p_158092_, int p_158093_, int p_158094_) {
|
||
|
return computeBeardContribution(p_158092_, p_158093_ + 0.5, p_158094_);
|
||
|
}
|
||
|
|
||
|
private static double computeBeardContribution(int p_223922_, double p_223923_, int p_223924_) {
|
||
|
double d0 = Mth.lengthSquared(p_223922_, p_223923_, p_223924_);
|
||
|
return Math.pow(Math.E, -d0 / 16.0);
|
||
|
}
|
||
|
|
||
|
@VisibleForTesting
|
||
|
public record Rigid(BoundingBox box, TerrainAdjustment terrainAdjustment, int groundLevelDelta) {
|
||
|
}
|
||
|
}
|