2025-11-24 22:52:51 +03:00

385 lines
17 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.google.common.collect.ImmutableList
* com.mojang.datafixers.kinds.App
* com.mojang.datafixers.kinds.Applicative
* com.mojang.serialization.Codec
* com.mojang.serialization.MapCodec
* com.mojang.serialization.codecs.RecordCodecBuilder
* it.unimi.dsi.fastutil.longs.Long2FloatLinkedOpenHashMap
* org.jspecify.annotations.Nullable
*/
package net.minecraft.world.level.biome;
import com.google.common.collect.ImmutableList;
import com.mojang.datafixers.kinds.App;
import com.mojang.datafixers.kinds.Applicative;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.longs.Long2FloatLinkedOpenHashMap;
import java.util.List;
import java.util.Optional;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.RegistryCodecs;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.RegistryFileCodec;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.attribute.EnvironmentAttribute;
import net.minecraft.world.attribute.EnvironmentAttributeMap;
import net.minecraft.world.attribute.modifier.AttributeModifier;
import net.minecraft.world.level.DryFoliageColor;
import net.minecraft.world.level.FoliageColor;
import net.minecraft.world.level.GrassColor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSpecialEffects;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import org.jspecify.annotations.Nullable;
public final class Biome {
public static final Codec<Biome> DIRECT_CODEC = RecordCodecBuilder.create(i -> i.group((App)ClimateSettings.CODEC.forGetter(b -> b.climateSettings), (App)EnvironmentAttributeMap.CODEC_ONLY_POSITIONAL.optionalFieldOf("attributes", (Object)EnvironmentAttributeMap.EMPTY).forGetter(b -> b.attributes), (App)BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter(b -> b.specialEffects), (App)BiomeGenerationSettings.CODEC.forGetter(b -> b.generationSettings), (App)MobSpawnSettings.CODEC.forGetter(b -> b.mobSettings)).apply((Applicative)i, Biome::new));
public static final Codec<Biome> NETWORK_CODEC = RecordCodecBuilder.create(i -> i.group((App)ClimateSettings.CODEC.forGetter(b -> b.climateSettings), (App)EnvironmentAttributeMap.NETWORK_CODEC.optionalFieldOf("attributes", (Object)EnvironmentAttributeMap.EMPTY).forGetter(b -> b.attributes), (App)BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter(b -> b.specialEffects)).apply((Applicative)i, (climateSettings, attributes, specialEffects) -> new Biome((ClimateSettings)climateSettings, (EnvironmentAttributeMap)attributes, (BiomeSpecialEffects)specialEffects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY)));
public static final Codec<Holder<Biome>> CODEC = RegistryFileCodec.create(Registries.BIOME, DIRECT_CODEC);
public static final Codec<HolderSet<Biome>> LIST_CODEC = RegistryCodecs.homogeneousList(Registries.BIOME, DIRECT_CODEC);
private static final PerlinSimplexNoise TEMPERATURE_NOISE = new PerlinSimplexNoise((RandomSource)new WorldgenRandom(new LegacyRandomSource(1234L)), (List<Integer>)ImmutableList.of((Object)0));
private static final PerlinSimplexNoise FROZEN_TEMPERATURE_NOISE = new PerlinSimplexNoise((RandomSource)new WorldgenRandom(new LegacyRandomSource(3456L)), (List<Integer>)ImmutableList.of((Object)-2, (Object)-1, (Object)0));
@Deprecated(forRemoval=true)
public static final PerlinSimplexNoise BIOME_INFO_NOISE = new PerlinSimplexNoise((RandomSource)new WorldgenRandom(new LegacyRandomSource(2345L)), (List<Integer>)ImmutableList.of((Object)0));
private static final int TEMPERATURE_CACHE_SIZE = 1024;
private final ClimateSettings climateSettings;
private final BiomeGenerationSettings generationSettings;
private final MobSpawnSettings mobSettings;
private final EnvironmentAttributeMap attributes;
private final BiomeSpecialEffects specialEffects;
private final ThreadLocal<Long2FloatLinkedOpenHashMap> temperatureCache = ThreadLocal.withInitial(() -> {
Long2FloatLinkedOpenHashMap map = new Long2FloatLinkedOpenHashMap(1024, 0.25f){
protected void rehash(int newN) {
}
};
map.defaultReturnValue(Float.NaN);
return map;
});
private Biome(ClimateSettings climateSettings, EnvironmentAttributeMap attributes, BiomeSpecialEffects specialEffects, BiomeGenerationSettings generationSettings, MobSpawnSettings mobSettings) {
this.climateSettings = climateSettings;
this.generationSettings = generationSettings;
this.mobSettings = mobSettings;
this.attributes = attributes;
this.specialEffects = specialEffects;
}
public MobSpawnSettings getMobSettings() {
return this.mobSettings;
}
public boolean hasPrecipitation() {
return this.climateSettings.hasPrecipitation();
}
public Precipitation getPrecipitationAt(BlockPos pos, int seaLevel) {
if (!this.hasPrecipitation()) {
return Precipitation.NONE;
}
return this.coldEnoughToSnow(pos, seaLevel) ? Precipitation.SNOW : Precipitation.RAIN;
}
private float getHeightAdjustedTemperature(BlockPos pos, int seaLevel) {
float adjustedTemperature = this.climateSettings.temperatureModifier.modifyTemperature(pos, this.getBaseTemperature());
int snowLevel = seaLevel + 17;
if (pos.getY() > snowLevel) {
float v = (float)(TEMPERATURE_NOISE.getValue((float)pos.getX() / 8.0f, (float)pos.getZ() / 8.0f, false) * 8.0);
return adjustedTemperature - (v + (float)pos.getY() - (float)snowLevel) * 0.05f / 40.0f;
}
return adjustedTemperature;
}
@Deprecated
private float getTemperature(BlockPos pos, int seaLevel) {
long key = pos.asLong();
Long2FloatLinkedOpenHashMap cache = this.temperatureCache.get();
float cached = cache.get(key);
if (!Float.isNaN(cached)) {
return cached;
}
float temp = this.getHeightAdjustedTemperature(pos, seaLevel);
if (cache.size() == 1024) {
cache.removeFirstFloat();
}
cache.put(key, temp);
return temp;
}
public boolean shouldFreeze(LevelReader level, BlockPos pos) {
return this.shouldFreeze(level, pos, true);
}
public boolean shouldFreeze(LevelReader level, BlockPos pos, boolean checkNeighbors) {
if (this.warmEnoughToRain(pos, level.getSeaLevel())) {
return false;
}
if (level.isInsideBuildHeight(pos.getY()) && level.getBrightness(LightLayer.BLOCK, pos) < 10) {
BlockState blockState = level.getBlockState(pos);
FluidState fluidState = level.getFluidState(pos);
if (fluidState.getType() == Fluids.WATER && blockState.getBlock() instanceof LiquidBlock) {
boolean surroundedByWater;
if (!checkNeighbors) {
return true;
}
boolean bl = surroundedByWater = level.isWaterAt(pos.west()) && level.isWaterAt(pos.east()) && level.isWaterAt(pos.north()) && level.isWaterAt(pos.south());
if (!surroundedByWater) {
return true;
}
}
}
return false;
}
public boolean coldEnoughToSnow(BlockPos pos, int seaLevel) {
return !this.warmEnoughToRain(pos, seaLevel);
}
public boolean warmEnoughToRain(BlockPos pos, int seaLevel) {
return this.getTemperature(pos, seaLevel) >= 0.15f;
}
public boolean shouldMeltFrozenOceanIcebergSlightly(BlockPos pos, int seaLevel) {
return this.getTemperature(pos, seaLevel) > 0.1f;
}
public boolean shouldSnow(LevelReader level, BlockPos pos) {
BlockState state;
if (this.getPrecipitationAt(pos, level.getSeaLevel()) != Precipitation.SNOW) {
return false;
}
return level.isInsideBuildHeight(pos.getY()) && level.getBrightness(LightLayer.BLOCK, pos) < 10 && ((state = level.getBlockState(pos)).isAir() || state.is(Blocks.SNOW)) && Blocks.SNOW.defaultBlockState().canSurvive(level, pos);
}
public BiomeGenerationSettings getGenerationSettings() {
return this.generationSettings;
}
public int getGrassColor(double x, double z) {
int baseGrassColor = this.getBaseGrassColor();
return this.specialEffects.grassColorModifier().modifyColor(x, z, baseGrassColor);
}
private int getBaseGrassColor() {
Optional<Integer> colorOverride = this.specialEffects.grassColorOverride();
if (colorOverride.isPresent()) {
return colorOverride.get();
}
return this.getGrassColorFromTexture();
}
private int getGrassColorFromTexture() {
double temp = Mth.clamp(this.climateSettings.temperature, 0.0f, 1.0f);
double rain = Mth.clamp(this.climateSettings.downfall, 0.0f, 1.0f);
return GrassColor.get(temp, rain);
}
public int getFoliageColor() {
return this.specialEffects.foliageColorOverride().orElseGet(this::getFoliageColorFromTexture);
}
private int getFoliageColorFromTexture() {
double temp = Mth.clamp(this.climateSettings.temperature, 0.0f, 1.0f);
double rain = Mth.clamp(this.climateSettings.downfall, 0.0f, 1.0f);
return FoliageColor.get(temp, rain);
}
public int getDryFoliageColor() {
return this.specialEffects.dryFoliageColorOverride().orElseGet(this::getDryFoliageColorFromTexture);
}
private int getDryFoliageColorFromTexture() {
double temp = Mth.clamp(this.climateSettings.temperature, 0.0f, 1.0f);
double rain = Mth.clamp(this.climateSettings.downfall, 0.0f, 1.0f);
return DryFoliageColor.get(temp, rain);
}
public float getBaseTemperature() {
return this.climateSettings.temperature;
}
public EnvironmentAttributeMap getAttributes() {
return this.attributes;
}
public BiomeSpecialEffects getSpecialEffects() {
return this.specialEffects;
}
public int getWaterColor() {
return this.specialEffects.waterColor();
}
private record ClimateSettings(boolean hasPrecipitation, float temperature, TemperatureModifier temperatureModifier, float downfall) {
public static final MapCodec<ClimateSettings> CODEC = RecordCodecBuilder.mapCodec(i -> i.group((App)Codec.BOOL.fieldOf("has_precipitation").forGetter(b -> b.hasPrecipitation), (App)Codec.FLOAT.fieldOf("temperature").forGetter(b -> Float.valueOf(b.temperature)), (App)TemperatureModifier.CODEC.optionalFieldOf("temperature_modifier", (Object)TemperatureModifier.NONE).forGetter(b -> b.temperatureModifier), (App)Codec.FLOAT.fieldOf("downfall").forGetter(b -> Float.valueOf(b.downfall))).apply((Applicative)i, ClimateSettings::new));
}
public static enum Precipitation implements StringRepresentable
{
NONE("none"),
RAIN("rain"),
SNOW("snow");
public static final Codec<Precipitation> CODEC;
private final String name;
private Precipitation(String name) {
this.name = name;
}
@Override
public String getSerializedName() {
return this.name;
}
static {
CODEC = StringRepresentable.fromEnum(Precipitation::values);
}
}
public static enum TemperatureModifier implements StringRepresentable
{
NONE("none"){
@Override
public float modifyTemperature(BlockPos pos, float baseTemperature) {
return baseTemperature;
}
}
,
FROZEN("frozen"){
@Override
public float modifyTemperature(BlockPos pos, float baseTemperature) {
double groundValueSmallVariation;
double groundValueEdgeVariation;
double groundValueLargeVariation = FROZEN_TEMPERATURE_NOISE.getValue((double)pos.getX() * 0.05, (double)pos.getZ() * 0.05, false) * 7.0;
double icePatches = groundValueLargeVariation + (groundValueEdgeVariation = BIOME_INFO_NOISE.getValue((double)pos.getX() * 0.2, (double)pos.getZ() * 0.2, false));
if (icePatches < 0.3 && (groundValueSmallVariation = BIOME_INFO_NOISE.getValue((double)pos.getX() * 0.09, (double)pos.getZ() * 0.09, false)) < 0.8) {
return 0.2f;
}
return baseTemperature;
}
};
private final String name;
public static final Codec<TemperatureModifier> CODEC;
public abstract float modifyTemperature(BlockPos var1, float var2);
private TemperatureModifier(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
@Override
public String getSerializedName() {
return this.name;
}
static {
CODEC = StringRepresentable.fromEnum(TemperatureModifier::values);
}
}
public static class BiomeBuilder {
private boolean hasPrecipitation = true;
private @Nullable Float temperature;
private TemperatureModifier temperatureModifier = TemperatureModifier.NONE;
private @Nullable Float downfall;
private final EnvironmentAttributeMap.Builder attributes = EnvironmentAttributeMap.builder();
private @Nullable BiomeSpecialEffects specialEffects;
private @Nullable MobSpawnSettings mobSpawnSettings;
private @Nullable BiomeGenerationSettings generationSettings;
public BiomeBuilder hasPrecipitation(boolean hasPrecipitation) {
this.hasPrecipitation = hasPrecipitation;
return this;
}
public BiomeBuilder temperature(float temperature) {
this.temperature = Float.valueOf(temperature);
return this;
}
public BiomeBuilder downfall(float downfall) {
this.downfall = Float.valueOf(downfall);
return this;
}
public BiomeBuilder putAttributes(EnvironmentAttributeMap attributes) {
this.attributes.putAll(attributes);
return this;
}
public BiomeBuilder putAttributes(EnvironmentAttributeMap.Builder attributes) {
return this.putAttributes(attributes.build());
}
public <Value> BiomeBuilder setAttribute(EnvironmentAttribute<Value> attribute, Value value) {
this.attributes.set(attribute, value);
return this;
}
public <Value, Parameter> BiomeBuilder modifyAttribute(EnvironmentAttribute<Value> attribute, AttributeModifier<Value, Parameter> modifier, Parameter value) {
this.attributes.modify(attribute, modifier, value);
return this;
}
public BiomeBuilder specialEffects(BiomeSpecialEffects specialEffects) {
this.specialEffects = specialEffects;
return this;
}
public BiomeBuilder mobSpawnSettings(MobSpawnSettings mobSpawnSettings) {
this.mobSpawnSettings = mobSpawnSettings;
return this;
}
public BiomeBuilder generationSettings(BiomeGenerationSettings generationSettings) {
this.generationSettings = generationSettings;
return this;
}
public BiomeBuilder temperatureAdjustment(TemperatureModifier temperatureModifier) {
this.temperatureModifier = temperatureModifier;
return this;
}
public Biome build() {
if (this.temperature == null || this.downfall == null || this.specialEffects == null || this.mobSpawnSettings == null || this.generationSettings == null) {
throw new IllegalStateException("You are missing parameters to build a proper biome\n" + String.valueOf(this));
}
return new Biome(new ClimateSettings(this.hasPrecipitation, this.temperature.floatValue(), this.temperatureModifier, this.downfall.floatValue()), this.attributes.build(), this.specialEffects, this.generationSettings, this.mobSpawnSettings);
}
public String toString() {
return "BiomeBuilder{\nhasPrecipitation=" + this.hasPrecipitation + ",\ntemperature=" + this.temperature + ",\ntemperatureModifier=" + String.valueOf(this.temperatureModifier) + ",\ndownfall=" + this.downfall + ",\nspecialEffects=" + String.valueOf(this.specialEffects) + ",\nmobSpawnSettings=" + String.valueOf(this.mobSpawnSettings) + ",\ngenerationSettings=" + String.valueOf(this.generationSettings) + ",\n}";
}
}
}