Tags, surface builders, biome API (WIP), processors, features
This commit is contained in:
parent
6b0bf593ad
commit
979e2ab92a
15 changed files with 1513 additions and 51 deletions
204
src/main/java/ru/bclib/world/biomes/BCLBiome.java
Normal file
204
src/main/java/ru/bclib/world/biomes/BCLBiome.java
Normal file
|
@ -0,0 +1,204 @@
|
|||
package ru.bclib.world.biomes;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import ru.bclib.config.IdConfig;
|
||||
import ru.bclib.util.JsonFactory;
|
||||
import ru.bclib.util.StructureHelper;
|
||||
import ru.bclib.world.features.BCLFeature;
|
||||
import ru.bclib.world.features.ListFeature;
|
||||
import ru.bclib.world.features.ListFeature.StructureInfo;
|
||||
import ru.bclib.world.features.NBTStructureFeature.TerrainMerge;
|
||||
|
||||
public class BCLBiome {
|
||||
protected List<BCLBiome> subbiomes = Lists.newArrayList();
|
||||
|
||||
protected final Biome biome;
|
||||
protected final ResourceLocation mcID;
|
||||
protected BCLBiome edge;
|
||||
protected int edgeSize;
|
||||
|
||||
protected BCLBiome biomeParent;
|
||||
protected float maxSubBiomeChance = 1;
|
||||
protected final float genChanceUnmutable;
|
||||
protected float genChance = 1;
|
||||
|
||||
private final float fogDensity;
|
||||
private BCLFeature structuresFeature;
|
||||
private Biome actualBiome;
|
||||
|
||||
public BCLBiome(BiomeDefinition definition, IdConfig config) {
|
||||
this.mcID = definition.getID();
|
||||
this.readStructureList();
|
||||
if (structuresFeature != null) {
|
||||
definition.addFeature(structuresFeature);
|
||||
}
|
||||
this.biome = definition.build();
|
||||
this.fogDensity = config.getFloat(mcID, "fog_density", definition.getFodDensity());
|
||||
this.genChanceUnmutable = config.getFloat(mcID, "generation_chance", definition.getGenChance());
|
||||
this.edgeSize = config.getInt(mcID, "edge_size", 32);
|
||||
}
|
||||
|
||||
public BCLBiome(ResourceLocation id, Biome biome, float fogDensity, float genChance, boolean hasCaves, IdConfig config) {
|
||||
this.mcID = id;
|
||||
this.readStructureList();
|
||||
this.biome = biome;
|
||||
this.fogDensity = config.getFloat(mcID, "fog_density", fogDensity);
|
||||
this.genChanceUnmutable = config.getFloat(mcID, "generation_chance", genChance);
|
||||
this.edgeSize = config.getInt(mcID, "edge_size", 32);
|
||||
}
|
||||
|
||||
public BCLBiome getEdge() {
|
||||
return edge == null ? this : edge;
|
||||
}
|
||||
|
||||
public void setEdge(BCLBiome edge) {
|
||||
this.edge = edge;
|
||||
edge.biomeParent = this;
|
||||
}
|
||||
|
||||
public int getEdgeSize() {
|
||||
return edgeSize;
|
||||
}
|
||||
|
||||
public void setEdgeSize(int size) {
|
||||
edgeSize = size;
|
||||
}
|
||||
|
||||
public void addSubBiome(BCLBiome biome) {
|
||||
maxSubBiomeChance += biome.mutateGenChance(maxSubBiomeChance);
|
||||
biome.biomeParent = this;
|
||||
subbiomes.add(biome);
|
||||
}
|
||||
|
||||
public boolean containsSubBiome(BCLBiome biome) {
|
||||
return subbiomes.contains(biome);
|
||||
}
|
||||
|
||||
public BCLBiome getSubBiome(Random random) {
|
||||
float chance = random.nextFloat() * maxSubBiomeChance;
|
||||
for (BCLBiome biome : subbiomes)
|
||||
if (biome.canGenerate(chance))
|
||||
return biome;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BCLBiome getParentBiome() {
|
||||
return this.biomeParent;
|
||||
}
|
||||
|
||||
public boolean hasEdge() {
|
||||
return edge != null;
|
||||
}
|
||||
|
||||
public boolean hasParentBiome() {
|
||||
return biomeParent != null;
|
||||
}
|
||||
|
||||
public boolean isSame(BCLBiome biome) {
|
||||
return biome == this || (biome.hasParentBiome() && biome.getParentBiome() == this);
|
||||
}
|
||||
|
||||
public boolean canGenerate(float chance) {
|
||||
return chance <= this.genChance;
|
||||
}
|
||||
|
||||
public float mutateGenChance(float chance) {
|
||||
genChance = genChanceUnmutable;
|
||||
genChance += chance;
|
||||
return genChance;
|
||||
}
|
||||
|
||||
public Biome getBiome() {
|
||||
return biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mcID.toString();
|
||||
}
|
||||
|
||||
public ResourceLocation getID() {
|
||||
return mcID;
|
||||
}
|
||||
|
||||
public float getFogDensity() {
|
||||
return fogDensity;
|
||||
}
|
||||
|
||||
protected void readStructureList() {
|
||||
String ns = mcID.getNamespace();
|
||||
String nm = mcID.getPath();
|
||||
|
||||
String path = "/data/" + ns + "/structures/biome/" + nm + "/";
|
||||
InputStream inputstream = StructureHelper.class.getResourceAsStream(path + "structures.json");
|
||||
if (inputstream != null) {
|
||||
JsonObject obj = JsonFactory.getJsonObject(inputstream);
|
||||
JsonArray enties = obj.getAsJsonArray("structures");
|
||||
if (enties != null) {
|
||||
List<StructureInfo> list = Lists.newArrayList();
|
||||
enties.forEach((entry) -> {
|
||||
JsonObject e = entry.getAsJsonObject();
|
||||
String structure = path + e.get("nbt").getAsString() + ".nbt";
|
||||
TerrainMerge terrainMerge = TerrainMerge.getFromString(e.get("terrainMerge").getAsString());
|
||||
int offsetY = e.get("offsetY").getAsInt();
|
||||
list.add(new StructureInfo(structure, offsetY, terrainMerge));
|
||||
});
|
||||
if (!list.isEmpty()) {
|
||||
structuresFeature = BCLFeature.makeChansedFeature(new ResourceLocation(ns, nm + "_structures"), new ListFeature(list), 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BCLFeature getStructuresFeature() {
|
||||
return structuresFeature;
|
||||
}
|
||||
|
||||
public Biome getActualBiome() {
|
||||
return this.actualBiome;
|
||||
}
|
||||
|
||||
public float getGenChance() {
|
||||
return this.genChance;
|
||||
}
|
||||
|
||||
public float getGenChanceImmutable() {
|
||||
return this.genChanceUnmutable;
|
||||
}
|
||||
|
||||
public void updateActualBiomes(Registry<Biome> biomeRegistry) {
|
||||
subbiomes.forEach((sub) -> {
|
||||
if (sub != this) {
|
||||
sub.updateActualBiomes(biomeRegistry);
|
||||
}
|
||||
});
|
||||
if (edge != null && edge != this) {
|
||||
edge.updateActualBiomes(biomeRegistry);
|
||||
}
|
||||
this.actualBiome = biomeRegistry.get(mcID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
BCLBiome biome = (BCLBiome) obj;
|
||||
return biome == null ? false : biome.mcID.equals(mcID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mcID.hashCode();
|
||||
}
|
||||
}
|
358
src/main/java/ru/bclib/world/biomes/BiomeDefinition.java
Normal file
358
src/main/java/ru/bclib/world/biomes/BiomeDefinition.java
Normal file
|
@ -0,0 +1,358 @@
|
|||
package ru.bclib.world.biomes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.data.worldgen.biome.Biomes;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.Music;
|
||||
import net.minecraft.sounds.Musics;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
|
||||
import net.minecraft.world.level.biome.AmbientMoodSettings;
|
||||
import net.minecraft.world.level.biome.AmbientParticleSettings;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.Biome.BiomeCategory;
|
||||
import net.minecraft.world.level.biome.Biome.Precipitation;
|
||||
import net.minecraft.world.level.biome.BiomeGenerationSettings;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects.Builder;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
|
||||
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.ProbabilityFeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder;
|
||||
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder;
|
||||
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration;
|
||||
import ru.bclib.util.ColorUtil;
|
||||
import ru.bclib.world.features.BCLFeature;
|
||||
import ru.bclib.world.structures.BCLStructureFeature;
|
||||
import ru.bclib.world.surface.DoubleBlockSurfaceBuilder;
|
||||
|
||||
public class BiomeDefinition {
|
||||
private static final int DEF_FOLIAGE_OVERWORLD = Biomes.PLAINS.getFoliageColor();
|
||||
private static final int DEF_FOLIAGE_NETHER =ColorUtil.color(117, 10, 10);
|
||||
private static final int DEF_FOLIAGE_END = ColorUtil.color(197, 210, 112);
|
||||
|
||||
private final List<ConfiguredStructureFeature<?, ?>> structures = Lists.newArrayList();
|
||||
private final List<FeatureInfo> features = Lists.newArrayList();
|
||||
private final List<CarverInfo> carvers = Lists.newArrayList();
|
||||
private final List<SpawnInfo> mobs = Lists.newArrayList();
|
||||
private final List<SpawnerData> spawns = Lists.newArrayList();
|
||||
|
||||
private final ResourceLocation id;
|
||||
|
||||
private AmbientParticleSettings particleConfig;
|
||||
private AmbientAdditionsSettings additions;
|
||||
private AmbientMoodSettings mood;
|
||||
private SoundEvent music;
|
||||
private SoundEvent loop;
|
||||
|
||||
private int foliageColor = DEF_FOLIAGE_OVERWORLD;
|
||||
private int grassColor = DEF_FOLIAGE_OVERWORLD;
|
||||
private int waterFogColor = 329011;
|
||||
private int waterColor = 4159204;
|
||||
private int fogColor = 10518688;
|
||||
private float fogDensity = 1F;
|
||||
private float depth = 0.1F;
|
||||
|
||||
private Precipitation precipitation = Precipitation.NONE;
|
||||
private BiomeCategory category = BiomeCategory.NONE;
|
||||
private float temperature = 1F;
|
||||
private float genChance = 1F;
|
||||
private float downfall = 0F;
|
||||
private int edgeSize = 32;
|
||||
|
||||
private ConfiguredSurfaceBuilder<?> surface;
|
||||
|
||||
/**
|
||||
* Custom biome definition. Can be extended with new parameters.
|
||||
* @param id - Biome {@link ResourceLocation} (identifier).
|
||||
*/
|
||||
public BiomeDefinition(ResourceLocation id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default definition for The Nether biome.
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static BiomeDefinition netherBiome(ResourceLocation id) {
|
||||
BiomeDefinition def = new BiomeDefinition(id);
|
||||
def.foliageColor = DEF_FOLIAGE_NETHER;
|
||||
def.grassColor = DEF_FOLIAGE_NETHER;
|
||||
def.setCategory(BiomeCategory.NETHER);
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default definition for The End biome.
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public static BiomeDefinition endBiome(ResourceLocation id) {
|
||||
BiomeDefinition def = new BiomeDefinition(id);
|
||||
def.foliageColor = DEF_FOLIAGE_END;
|
||||
def.grassColor = DEF_FOLIAGE_END;
|
||||
def.setCategory(BiomeCategory.THEEND);
|
||||
return def;
|
||||
}
|
||||
|
||||
public BiomeDefinition setCategory(BiomeCategory category) {
|
||||
this.category = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setPrecipitation(Precipitation precipitation) {
|
||||
this.precipitation = precipitation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setSurface(Block block) {
|
||||
setSurface(SurfaceBuilder.DEFAULT.configured(new SurfaceBuilderBaseConfiguration(
|
||||
block.defaultBlockState(),
|
||||
Blocks.END_STONE.defaultBlockState(),
|
||||
Blocks.END_STONE.defaultBlockState()
|
||||
)));
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setSurface(Block block1, Block block2) {
|
||||
setSurface(DoubleBlockSurfaceBuilder.register("bclib_" + id.getPath() + "_surface").setBlock1(block1).setBlock2(block2).configured());
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setSurface(ConfiguredSurfaceBuilder<?> builder) {
|
||||
this.surface = builder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setParticles(ParticleOptions particle, float probability) {
|
||||
this.particleConfig = new AmbientParticleSettings(particle, probability);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setGenChance(float genChance) {
|
||||
this.genChance = genChance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setDepth(float depth) {
|
||||
this.depth = depth;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setTemperature(float temperature) {
|
||||
this.temperature = temperature;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setDownfall(float downfall) {
|
||||
this.downfall = downfall;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setEdgeSize(int edgeSize) {
|
||||
this.edgeSize = edgeSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addMobSpawn(EntityType<?> type, int weight, int minGroupSize, int maxGroupSize) {
|
||||
ResourceLocation eID = Registry.ENTITY_TYPE.getKey(type);
|
||||
if (eID != Registry.ENTITY_TYPE.getDefaultKey()) {
|
||||
SpawnInfo info = new SpawnInfo();
|
||||
info.type = type;
|
||||
info.weight = weight;
|
||||
info.minGroupSize = minGroupSize;
|
||||
info.maxGroupSize = maxGroupSize;
|
||||
mobs.add(info);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addMobSpawn(SpawnerData entry) {
|
||||
spawns.add(entry);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addStructureFeature(ConfiguredStructureFeature<?, ?> feature) {
|
||||
structures.add(feature);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addStructureFeature(BCLStructureFeature feature) {
|
||||
structures.add(feature.getFeatureConfigured());
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addFeature(BCLFeature feature) {
|
||||
FeatureInfo info = new FeatureInfo();
|
||||
info.featureStep = feature.getFeatureStep();
|
||||
info.feature = feature.getFeatureConfigured();
|
||||
features.add(info);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition addFeature(Decoration featureStep, ConfiguredFeature<?, ?> feature) {
|
||||
FeatureInfo info = new FeatureInfo();
|
||||
info.featureStep = featureStep;
|
||||
info.feature = feature;
|
||||
features.add(info);
|
||||
return this;
|
||||
}
|
||||
|
||||
private int getColor(int r, int g, int b) {
|
||||
r = Mth.clamp(r, 0, 255);
|
||||
g = Mth.clamp(g, 0, 255);
|
||||
b = Mth.clamp(b, 0, 255);
|
||||
return ColorUtil.color(r, g, b);
|
||||
}
|
||||
|
||||
public BiomeDefinition setFogColor(int r, int g, int b) {
|
||||
this.fogColor = getColor(r, g, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setFogDensity(float density) {
|
||||
this.fogDensity = density;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setWaterColor(int r, int g, int b) {
|
||||
this.waterColor = getColor(r, g, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setWaterFogColor(int r, int g, int b) {
|
||||
this.waterFogColor = getColor(r, g, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setWaterAndFogColor(int r, int g, int b) {
|
||||
return setWaterColor(r, g, b).setWaterFogColor(r, g, b);
|
||||
}
|
||||
|
||||
public BiomeDefinition setFoliageColor(int r, int g, int b) {
|
||||
this.foliageColor = getColor(r, g, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setGrassColor(int r, int g, int b) {
|
||||
this.grassColor = getColor(r, g, b);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setPlantsColor(int r, int g, int b) {
|
||||
return this.setFoliageColor(r, g, b).setGrassColor(r, g, b);
|
||||
}
|
||||
|
||||
public BiomeDefinition setLoop(SoundEvent loop) {
|
||||
this.loop = loop;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setMood(SoundEvent mood) {
|
||||
this.mood = new AmbientMoodSettings(mood, 6000, 8, 2.0D);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setAdditions(SoundEvent additions) {
|
||||
this.additions = new AmbientAdditionsSettings(additions, 0.0111);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BiomeDefinition setMusic(SoundEvent music) {
|
||||
this.music = music;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Biome build() {
|
||||
MobSpawnSettings.Builder spawnSettings = new MobSpawnSettings.Builder();
|
||||
BiomeGenerationSettings.Builder generationSettings = new BiomeGenerationSettings.Builder();
|
||||
Builder effects = new Builder();
|
||||
|
||||
mobs.forEach((spawn) -> {
|
||||
spawnSettings.addSpawn(spawn.type.getCategory(), new MobSpawnSettings.SpawnerData(spawn.type, spawn.weight, spawn.minGroupSize, spawn.maxGroupSize));
|
||||
});
|
||||
|
||||
spawns.forEach((entry) -> {
|
||||
spawnSettings.addSpawn(entry.type.getCategory(), entry);
|
||||
});
|
||||
|
||||
generationSettings.surfaceBuilder(surface == null ? net.minecraft.data.worldgen.SurfaceBuilders.END : surface);
|
||||
structures.forEach((structure) -> generationSettings.addStructureStart(structure));
|
||||
features.forEach((info) -> generationSettings.addFeature(info.featureStep, info.feature));
|
||||
carvers.forEach((info) -> generationSettings.addCarver(info.carverStep, info.carver));
|
||||
|
||||
effects.skyColor(0).waterColor(waterColor).waterFogColor(waterFogColor).fogColor(fogColor).foliageColorOverride(foliageColor).grassColorOverride(grassColor);
|
||||
if (loop != null) effects.ambientLoopSound(loop);
|
||||
if (mood != null) effects.ambientMoodSound(mood);
|
||||
if (additions != null) effects.ambientAdditionsSound(additions);
|
||||
if (particleConfig != null) effects.ambientParticle(particleConfig);
|
||||
effects.backgroundMusic(music != null ? new Music(music, 600, 2400, true) : Musics.END);
|
||||
|
||||
return new Biome.BiomeBuilder()
|
||||
.precipitation(precipitation)
|
||||
.biomeCategory(category)
|
||||
.depth(depth)
|
||||
.scale(0.2F)
|
||||
.temperature(temperature)
|
||||
.downfall(downfall)
|
||||
.specialEffects(effects.build())
|
||||
.mobSpawnSettings(spawnSettings.build())
|
||||
.generationSettings(generationSettings.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static final class SpawnInfo {
|
||||
EntityType<?> type;
|
||||
int weight;
|
||||
int minGroupSize;
|
||||
int maxGroupSize;
|
||||
}
|
||||
|
||||
private static final class FeatureInfo {
|
||||
Decoration featureStep;
|
||||
ConfiguredFeature<?, ?> feature;
|
||||
}
|
||||
|
||||
private static final class CarverInfo {
|
||||
Carving carverStep;
|
||||
ConfiguredWorldCarver<ProbabilityFeatureConfiguration> carver;
|
||||
}
|
||||
|
||||
public ResourceLocation getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public float getFodDensity() {
|
||||
return fogDensity;
|
||||
}
|
||||
|
||||
public float getGenChance() {
|
||||
return genChance;
|
||||
}
|
||||
|
||||
public int getEdgeSize() {
|
||||
return edgeSize;
|
||||
}
|
||||
|
||||
public BiomeDefinition addCarver(Carving carverStep, ConfiguredWorldCarver<ProbabilityFeatureConfiguration> carver) {
|
||||
CarverInfo info = new CarverInfo();
|
||||
info.carverStep = carverStep;
|
||||
info.carver = carver;
|
||||
carvers.add(info);
|
||||
return this;
|
||||
}
|
||||
}
|
94
src/main/java/ru/bclib/world/features/BCLFeature.java
Normal file
94
src/main/java/ru/bclib/world/features/BCLFeature.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
package ru.bclib.world.features;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.data.worldgen.Features;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.CountConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.RangeDecoratorConfiguration;
|
||||
import net.minecraft.world.level.levelgen.placement.ChanceDecoratorConfiguration;
|
||||
import net.minecraft.world.level.levelgen.placement.FeatureDecorator;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockMatchTest;
|
||||
|
||||
public class BCLFeature {
|
||||
private Feature<?> feature;
|
||||
private ConfiguredFeature<?, ?> featureConfigured;
|
||||
private GenerationStep.Decoration featureStep;
|
||||
|
||||
public BCLFeature(Feature<?> feature, ConfiguredFeature<?, ?> configuredFeature, GenerationStep.Decoration featureStep) {
|
||||
this.featureConfigured = configuredFeature;
|
||||
this.featureStep = featureStep;
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
public BCLFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, GenerationStep.Decoration featureStep, ConfiguredFeature<?, ?> configuredFeature) {
|
||||
this.featureConfigured = Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, id, configuredFeature);
|
||||
this.feature = Registry.register(Registry.FEATURE, id, feature);
|
||||
this.featureStep = featureStep;
|
||||
}
|
||||
|
||||
public static BCLFeature makeVegetationFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int density) {
|
||||
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE).decorated(Features.Decorators.HEIGHTMAP_SQUARE).countRandom(density);
|
||||
return new BCLFeature(id, feature, GenerationStep.Decoration.VEGETAL_DECORATION, configured);
|
||||
}
|
||||
|
||||
public static BCLFeature makeRawGenFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int chance) {
|
||||
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE).decorated(FeatureDecorator.CHANCE.configured(new ChanceDecoratorConfiguration(chance)));
|
||||
return new BCLFeature(id, feature, GenerationStep.Decoration.RAW_GENERATION, configured);
|
||||
}
|
||||
|
||||
public static BCLFeature makeLakeFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int chance) {
|
||||
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE).decorated(FeatureDecorator.WATER_LAKE.configured(new ChanceDecoratorConfiguration(chance)));
|
||||
return new BCLFeature(id, feature, GenerationStep.Decoration.LAKES, configured);
|
||||
}
|
||||
|
||||
public static BCLFeature makeOreFeature(ResourceLocation id, Block blockOre, int veins, int veinSize, int offset, int minY, int maxY) {
|
||||
OreConfiguration featureConfig = new OreConfiguration(new BlockMatchTest(Blocks.END_STONE), blockOre.defaultBlockState(), veinSize);
|
||||
RangeDecoratorConfiguration rangeDecorator = new RangeDecoratorConfiguration(offset, minY, maxY);
|
||||
ConfiguredFeature<?, ?> oreFeature = Feature.ORE.configured(featureConfig)
|
||||
.decorated(FeatureDecorator.RANGE.configured(rangeDecorator))
|
||||
.squared()
|
||||
.count(veins);
|
||||
return new BCLFeature(Feature.ORE, Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, id, oreFeature), GenerationStep.Decoration.UNDERGROUND_ORES);
|
||||
}
|
||||
|
||||
public static BCLFeature makeChunkFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature) {
|
||||
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE).decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(1)));
|
||||
return new BCLFeature(id, feature, GenerationStep.Decoration.LOCAL_MODIFICATIONS, configured);
|
||||
}
|
||||
|
||||
public static BCLFeature makeChansedFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int chance) {
|
||||
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE).decorated(FeatureDecorator.CHANCE.configured(new ChanceDecoratorConfiguration(chance)));
|
||||
return new BCLFeature(id, feature, GenerationStep.Decoration.SURFACE_STRUCTURES, configured);
|
||||
}
|
||||
|
||||
public static BCLFeature makeCountRawFeature(ResourceLocation id, Feature<NoneFeatureConfiguration> feature, int chance) {
|
||||
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE).decorated(FeatureDecorator.COUNT.configured(new CountConfiguration(chance)));
|
||||
return new BCLFeature(id, feature, GenerationStep.Decoration.RAW_GENERATION, configured);
|
||||
}
|
||||
|
||||
public static BCLFeature makeFeatureConfigured(ResourceLocation id, Feature<NoneFeatureConfiguration> feature) {
|
||||
ConfiguredFeature<?, ?> configured = feature.configured(FeatureConfiguration.NONE);
|
||||
return new BCLFeature(id, feature, GenerationStep.Decoration.RAW_GENERATION, configured);
|
||||
}
|
||||
|
||||
public Feature<?> getFeature() {
|
||||
return feature;
|
||||
}
|
||||
|
||||
public ConfiguredFeature<?, ?> getFeatureConfigured() {
|
||||
return featureConfigured;
|
||||
}
|
||||
|
||||
public GenerationStep.Decoration getFeatureStep() {
|
||||
return featureStep;
|
||||
}
|
||||
}
|
44
src/main/java/ru/bclib/world/features/DefaultFeature.java
Normal file
44
src/main/java/ru/bclib/world/features/DefaultFeature.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
package ru.bclib.world.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
import ru.bclib.util.BlocksHelper;
|
||||
|
||||
public abstract class DefaultFeature extends Feature<NoneFeatureConfiguration> {
|
||||
protected static final BlockState AIR = Blocks.AIR.defaultBlockState();
|
||||
protected static final BlockState WATER = Blocks.WATER.defaultBlockState();
|
||||
|
||||
public DefaultFeature() {
|
||||
super(NoneFeatureConfiguration.CODEC);
|
||||
}
|
||||
|
||||
public static int getYOnSurface(WorldGenLevel world, int x, int z) {
|
||||
return world.getHeight(Types.WORLD_SURFACE, x, z);
|
||||
}
|
||||
|
||||
public static int getYOnSurfaceWG(WorldGenLevel world, int x, int z) {
|
||||
return world.getHeight(Types.WORLD_SURFACE_WG, x, z);
|
||||
}
|
||||
|
||||
public static BlockPos getPosOnSurface(WorldGenLevel world, BlockPos pos) {
|
||||
return world.getHeightmapPos(Types.WORLD_SURFACE, pos);
|
||||
}
|
||||
|
||||
public static BlockPos getPosOnSurfaceWG(WorldGenLevel world, BlockPos pos) {
|
||||
return world.getHeightmapPos(Types.WORLD_SURFACE_WG, pos);
|
||||
}
|
||||
|
||||
public static BlockPos getPosOnSurfaceRaycast(WorldGenLevel world, BlockPos pos) {
|
||||
return getPosOnSurfaceRaycast(world, pos, 256);
|
||||
}
|
||||
|
||||
public static BlockPos getPosOnSurfaceRaycast(WorldGenLevel world, BlockPos pos, int dist) {
|
||||
int h = BlocksHelper.downRay(world, pos, dist);
|
||||
return pos.below(h);
|
||||
}
|
||||
}
|
78
src/main/java/ru/bclib/world/features/ListFeature.java
Normal file
78
src/main/java/ru/bclib/world/features/ListFeature.java
Normal file
|
@ -0,0 +1,78 @@
|
|||
package ru.bclib.world.features;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
import ru.bclib.util.StructureHelper;
|
||||
|
||||
public class ListFeature extends NBTStructureFeature {
|
||||
private final List<StructureInfo> list;
|
||||
private StructureInfo selected;
|
||||
|
||||
public ListFeature(List<StructureInfo> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureTemplate getStructure(WorldGenLevel world, BlockPos pos, Random random) {
|
||||
selected = list.get(random.nextInt(list.size()));
|
||||
return selected.getStructure();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpawn(WorldGenLevel world, BlockPos pos, Random random) {
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
return ((cx + cz) & 1) == 0 && pos.getY() > 58;// && world.getBlockState(pos.below()).is(EndTags.GEN_TERRAIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rotation getRotation(WorldGenLevel world, BlockPos pos, Random random) {
|
||||
return Rotation.getRandom(random);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mirror getMirror(WorldGenLevel world, BlockPos pos, Random random) {
|
||||
return Mirror.values()[random.nextInt(3)];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getYOffset(StructureTemplate structure, WorldGenLevel world, BlockPos pos, Random random) {
|
||||
return selected.offsetY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TerrainMerge getTerrainMerge(WorldGenLevel world, BlockPos pos, Random random) {
|
||||
return selected.terrainMerge;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addStructureData(StructurePlaceSettings data) {}
|
||||
|
||||
public static final class StructureInfo {
|
||||
public final TerrainMerge terrainMerge;
|
||||
public final String structurePath;
|
||||
public final int offsetY;
|
||||
|
||||
private StructureTemplate structure;
|
||||
|
||||
public StructureInfo(String structurePath, int offsetY, TerrainMerge terrainMerge) {
|
||||
this.terrainMerge = terrainMerge;
|
||||
this.structurePath = structurePath;
|
||||
this.offsetY = offsetY;
|
||||
}
|
||||
|
||||
public StructureTemplate getStructure() {
|
||||
if (structure == null) {
|
||||
structure = StructureHelper.readStructure(structurePath);
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ru.bclib.world.processors;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
import ru.bclib.util.BlocksHelper;
|
||||
import ru.bclib.util.MHelper;
|
||||
|
||||
public class DestructionStructureProcessor extends StructureProcessor {
|
||||
private int chance = 4;
|
||||
|
||||
public void setChance(int chance) {
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureBlockInfo processBlock(LevelReader worldView, BlockPos pos, BlockPos blockPos, StructureBlockInfo structureBlockInfo, StructureBlockInfo structureBlockInfo2, StructurePlaceSettings structurePlacementData) {
|
||||
if (!BlocksHelper.isInvulnerable(structureBlockInfo2.state, worldView, structureBlockInfo2.pos) && MHelper.RANDOM.nextInt(chance) == 0) {
|
||||
return null;
|
||||
}
|
||||
return structureBlockInfo2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureProcessorType<?> getType() {
|
||||
return StructureProcessorType.RULE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package ru.bclib.world.processors;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
|
||||
public class TerrainStructureProcessor extends StructureProcessor {
|
||||
@Override
|
||||
public StructureBlockInfo processBlock(LevelReader worldView, BlockPos pos, BlockPos blockPos, StructureBlockInfo structureBlockInfo, StructureBlockInfo structureBlockInfo2, StructurePlaceSettings structurePlacementData) {
|
||||
BlockPos bpos = structureBlockInfo2.pos;
|
||||
if (structureBlockInfo2.state.is(Blocks.END_STONE) && worldView.isEmptyBlock(bpos.above())) {
|
||||
BlockState top = worldView.getBiome(structureBlockInfo2.pos).getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
|
||||
return new StructureBlockInfo(bpos, top, structureBlockInfo2.nbt);
|
||||
}
|
||||
return structureBlockInfo2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureProcessorType<?> getType() {
|
||||
return StructureProcessorType.RULE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package ru.bclib.world.surface;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder;
|
||||
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilder;
|
||||
import net.minecraft.world.level.levelgen.surfacebuilders.SurfaceBuilderBaseConfiguration;
|
||||
import ru.bclib.noise.OpenSimplexNoise;
|
||||
import ru.bclib.util.MHelper;
|
||||
|
||||
public class DoubleBlockSurfaceBuilder extends SurfaceBuilder<SurfaceBuilderBaseConfiguration> {
|
||||
private static final OpenSimplexNoise NOISE = new OpenSimplexNoise(4141);
|
||||
private SurfaceBuilderBaseConfiguration config1;
|
||||
private SurfaceBuilderBaseConfiguration config2;
|
||||
|
||||
private DoubleBlockSurfaceBuilder() {
|
||||
super(SurfaceBuilderBaseConfiguration.CODEC);
|
||||
}
|
||||
|
||||
public DoubleBlockSurfaceBuilder setBlock1(Block block) {
|
||||
BlockState stone = Blocks.END_STONE.defaultBlockState();
|
||||
config1 = new SurfaceBuilderBaseConfiguration(block.defaultBlockState(), stone, stone);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DoubleBlockSurfaceBuilder setBlock2(Block block) {
|
||||
BlockState stone = Blocks.END_STONE.defaultBlockState();
|
||||
config2 = new SurfaceBuilderBaseConfiguration(block.defaultBlockState(), stone, stone);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Random random, ChunkAccess chunk, Biome biome, int x, int z, int height, double noise, BlockState defaultBlock, BlockState defaultFluid, int seaLevel, long seed, SurfaceBuilderBaseConfiguration surfaceBlocks) {
|
||||
noise = NOISE.eval(x * 0.1, z * 0.1) + MHelper.randRange(-0.4, 0.4, random);
|
||||
SurfaceBuilder.DEFAULT.apply(random, chunk, biome, x, z, height, noise, defaultBlock, defaultFluid, seaLevel, seed, noise > 0 ? config1 : config2);
|
||||
}
|
||||
|
||||
public static DoubleBlockSurfaceBuilder register(String name) {
|
||||
return Registry.register(Registry.SURFACE_BUILDER, name, new DoubleBlockSurfaceBuilder());
|
||||
}
|
||||
|
||||
public ConfiguredSurfaceBuilder<SurfaceBuilderBaseConfiguration> configured() {
|
||||
BlockState stone = Blocks.END_STONE.defaultBlockState();
|
||||
return this.configured(new SurfaceBuilderBaseConfiguration(config1.getTopMaterial(), stone, stone));
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue