package com.hypixel.hytale.server.worldgen.climate;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.procedurallib.logic.ResultBuffer;
import com.hypixel.hytale.procedurallib.logic.cell.CellDistanceFunction;
import com.hypixel.hytale.procedurallib.logic.cell.evaluator.PointEvaluator;
import com.hypixel.hytale.procedurallib.property.NoiseProperty;
import javax.annotation.Nonnull;
public class ClimateNoise {
@Nonnull
public final Grid grid;
@Nonnull
public final NoiseProperty continent;
@Nonnull
public final NoiseProperty temperature;
@Nonnull
public final NoiseProperty intensity;
@Nonnull
public final Thresholds thresholds;
public ClimateNoise(@Nonnull Grid grid, @Nonnull NoiseProperty continent, @Nonnull NoiseProperty temperature, @Nonnull NoiseProperty intensity, @Nonnull Thresholds thresholds) {
this.grid = grid;
this.temperature = temperature;
this.intensity = intensity;
this.continent = continent;
this.thresholds = thresholds;
}
public int generate(int seed, double x, double y, @Nonnull Buffer buffer, @Nonnull ClimateGraph climate) {
this.grid.eval(seed, x, y, buffer.pos);
double c = this.continent.get(seed, x, y);
double t = this.temperature.get(seed, buffer.pos.x, buffer.pos.y);
double i = this.intensity.get(seed, buffer.pos.x, buffer.pos.y);
int index = climate.indexOf(t, i);
buffer.continent = c;
buffer.temperature = t;
buffer.intensity = i;
buffer.fade = climate.getFade(index);
int id = climate.getId(index);
int flags = getContinentFlags(c, this.thresholds);
return id | flags;
}
private static int getContinentFlags(double value, @Nonnull Thresholds thresholds) {
boolean isLand = value <= thresholds.landShallowOceanOuter;
boolean isIsland = value >= thresholds.islandShallowOceanOuter;
boolean isOcean = value > thresholds.land && value < thresholds.island;
boolean isShore = isLand && value > thresholds.landShoreInner || isIsland && value < thresholds.islandShoreInner;
int flags = 0;
if (isOcean) {
flags |= -2147483648;
}
if (isShore) {
flags |= 1073741824;
}
if (isIsland) {
flags |= 536870912;
}
return flags;
}
public static class Buffer {
public double continent = 0.0;
public double temperature = 0.0;
public double intensity = 0.0;
public double fade = 0.0;
public final ResultBuffer.ResultBuffer2d pos = new ResultBuffer.ResultBuffer2d();
public Buffer() {
}
}
public static class Grid {
public final int seedOffset;
public final double scale;
@Nonnull
public final PointEvaluator evaluator;
@Nonnull
public final CellDistanceFunction grid;
public final transient double invScale;
public Grid(int seedOffset, double scale, @Nonnull CellDistanceFunction grid, @Nonnull PointEvaluator evaluator) {
this.seedOffset = seedOffset;
this.scale = scale;
this.evaluator = evaluator;
this.grid = grid;
this.invScale = 1.0 / scale;
}
public void eval(int seed, double x, double y, ResultBuffer.ResultBuffer2d buffer) {
x *= this.scale;
y *= this.scale;
buffer.distance = 1.7976931348623157E308;
buffer.distance2 = 1.7976931348623157E308;
this.grid.nearest2D(seed + this.seedOffset, x, y, MathUtil.floor(x), MathUtil.floor(y), buffer, this.evaluator);
buffer.x *= this.invScale;
buffer.y *= this.invScale;
}
}
public static class Thresholds {
public static final double LAND_DEFAULT = 0.5;
public static final double ISLAND_DEFAULT = 0.8;
public static final double BEACH_SIZE_DEFAULT = 0.05;
public static final double SHALLOW_OCEAN_SIZE_DEFAULT = 0.15;
public final double land;
public final double island;
public final double beachSize;
public final double shallowOceanSize;
public final transient double landShoreInner;
public final transient double islandShoreInner;
public final transient double landShallowOceanOuter;
public final transient double islandShallowOceanOuter;
public Thresholds(double land, double island, double beach, double shore) {
this.land = land;
this.island = island;
this.beachSize = beach;
this.shallowOceanSize = shore;
this.landShoreInner = land - beach;
this.islandShoreInner = island + beach;
this.landShallowOceanOuter = land + shore;
this.islandShallowOceanOuter = island - shore * 0.5;
}
}
}