Migrated Feature Code to new BCLib API
This commit is contained in:
parent
031a14f278
commit
5c3a9986bc
45 changed files with 1363 additions and 629 deletions
|
@ -5,66 +5,89 @@ import org.betterx.bclib.api.v3.levelgen.features.BCLFeatureBuilder;
|
|||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.integration.Integrations;
|
||||
import org.betterx.betterend.integration.byg.BYGBlocks;
|
||||
import org.betterx.betterend.world.features.SinglePlantFeature;
|
||||
import org.betterx.betterend.world.features.VineFeature;
|
||||
import org.betterx.betterend.world.features.WallPlantFeature;
|
||||
import org.betterx.betterend.world.features.WallPlantOnLogFeature;
|
||||
import org.betterx.betterend.registry.EndFeatures;
|
||||
import org.betterx.betterend.world.features.*;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
||||
public class BYGFeatures {
|
||||
public static final BCLFeature OLD_BULBIS_TREE = redisterVegetation(
|
||||
public static final BCLFeature<OldBulbisTreeFeature, NoneFeatureConfiguration> OLD_BULBIS_TREE = redisterVegetation(
|
||||
"old_bulbis_tree",
|
||||
new OldBulbisTreeFeature(),
|
||||
EndFeatures.inlineBuild("old_bulbis_tree_feature", new OldBulbisTreeFeature()),
|
||||
1
|
||||
);
|
||||
public static final BCLFeature IVIS_SPROUT = redisterVegetation(
|
||||
public static final BCLFeature<SinglePlantFeature, SinglePlantFeatureConfig> IVIS_SPROUT = redisterVegetation(
|
||||
"ivis_sprout",
|
||||
new SinglePlantFeature(Integrations.BYG.getBlock("ivis_sprout"), 6, 2),
|
||||
EndFeatures.SINGLE_PLANT_FEATURE,
|
||||
new SinglePlantFeatureConfig(Integrations.BYG.getBlock("ivis_sprout"), 6, 2),
|
||||
6
|
||||
);
|
||||
public static final BCLFeature IVIS_VINE = redisterVegetation(
|
||||
public static final BCLFeature<VineFeature, VineFeatureConfig> IVIS_VINE = redisterVegetation(
|
||||
"ivis_vine",
|
||||
new VineFeature(BYGBlocks.IVIS_VINE, 24),
|
||||
EndFeatures.VINE_FEATURE,
|
||||
new VineFeatureConfig(BYGBlocks.IVIS_VINE, 24),
|
||||
5
|
||||
);
|
||||
public static final BCLFeature IVIS_MOSS = redisterVegetation(
|
||||
public static final BCLFeature<WallPlantFeature, WallPlantFeatureConfig> IVIS_MOSS = redisterVegetation(
|
||||
"ivis_moss",
|
||||
new WallPlantFeature(BYGBlocks.IVIS_MOSS, 6),
|
||||
EndFeatures.WALL_PLANT_FEATURE,
|
||||
new WallPlantFeatureConfig(BYGBlocks.IVIS_MOSS, 6),
|
||||
1
|
||||
);
|
||||
public static final BCLFeature IVIS_MOSS_WOOD = redisterVegetation(
|
||||
public static final BCLFeature<WallPlantOnLogFeature, WallPlantFeatureConfig> IVIS_MOSS_WOOD = redisterVegetation(
|
||||
"ivis_moss_wood",
|
||||
new WallPlantOnLogFeature(BYGBlocks.IVIS_MOSS, 6),
|
||||
EndFeatures.WALL_PLANT_ON_LOG_FEATURE,
|
||||
new WallPlantFeatureConfig(BYGBlocks.IVIS_MOSS, 6),
|
||||
15
|
||||
);
|
||||
public static final BCLFeature NIGHTSHADE_MOSS = redisterVegetation(
|
||||
public static final BCLFeature<WallPlantFeature, WallPlantFeatureConfig> NIGHTSHADE_MOSS = redisterVegetation(
|
||||
"nightshade_moss",
|
||||
new WallPlantFeature(BYGBlocks.NIGHTSHADE_MOSS, 5),
|
||||
EndFeatures.WALL_PLANT_FEATURE,
|
||||
new WallPlantFeatureConfig(BYGBlocks.NIGHTSHADE_MOSS, 5),
|
||||
2
|
||||
);
|
||||
public static final BCLFeature NIGHTSHADE_MOSS_WOOD = redisterVegetation(
|
||||
public static final BCLFeature<WallPlantOnLogFeature, WallPlantFeatureConfig> NIGHTSHADE_MOSS_WOOD = redisterVegetation(
|
||||
"nightshade_moss_wood",
|
||||
new WallPlantOnLogFeature(BYGBlocks.NIGHTSHADE_MOSS, 5),
|
||||
EndFeatures.WALL_PLANT_ON_LOG_FEATURE,
|
||||
new WallPlantFeatureConfig(BYGBlocks.NIGHTSHADE_MOSS, 5),
|
||||
8
|
||||
);
|
||||
|
||||
public static final BCLFeature NIGHTSHADE_REDWOOD_TREE = redisterVegetation(
|
||||
public static final BCLFeature<NightshadeRedwoodTreeFeature, NoneFeatureConfiguration> NIGHTSHADE_REDWOOD_TREE = redisterVegetation(
|
||||
"nightshade_redwood_tree",
|
||||
new NightshadeRedwoodTreeFeature(),
|
||||
1
|
||||
);
|
||||
public static final BCLFeature BIG_ETHER_TREE = redisterVegetation("big_ether_tree", new BigEtherTreeFeature(), 1);
|
||||
public static final BCLFeature<BigEtherTreeFeature, NoneFeatureConfiguration> BIG_ETHER_TREE = redisterVegetation(
|
||||
"big_ether_tree",
|
||||
new BigEtherTreeFeature(),
|
||||
1
|
||||
);
|
||||
|
||||
public static void register() {
|
||||
}
|
||||
|
||||
private static BCLFeature redisterVegetation(String name, Feature<NoneFeatureConfiguration> feature, int density) {
|
||||
private static <F extends Feature<NoneFeatureConfiguration>> BCLFeature<F, NoneFeatureConfiguration> redisterVegetation(
|
||||
String name,
|
||||
F feature,
|
||||
int density
|
||||
) {
|
||||
return redisterVegetation(name, feature, NoneFeatureConfiguration.NONE, density);
|
||||
}
|
||||
|
||||
private static <F extends Feature<FC>, FC extends FeatureConfiguration> BCLFeature<F, FC> redisterVegetation(
|
||||
String name,
|
||||
F feature,
|
||||
FC config,
|
||||
int density
|
||||
) {
|
||||
ResourceLocation id = BetterEnd.makeID(name);
|
||||
return BCLFeatureBuilder
|
||||
.start(id, feature)
|
||||
.configuration(config)
|
||||
.buildAndRegister()
|
||||
.place()
|
||||
.countMax(density)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,14 +3,15 @@ package org.betterx.betterend.world.biome.cave;
|
|||
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeBuilder;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeBuilder.BiomeSupplier;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeSettings;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.v3.levelgen.features.BCLFeature;
|
||||
import org.betterx.bclib.api.v3.levelgen.features.BCLFeatureBuilder;
|
||||
import org.betterx.bclib.util.WeightedList;
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.registry.EndFeatures;
|
||||
import org.betterx.betterend.registry.EndSounds;
|
||||
import org.betterx.betterend.world.biome.EndBiome;
|
||||
import org.betterx.betterend.world.features.terrain.caves.CaveChunkPopulatorFeature;
|
||||
import org.betterx.betterend.world.features.terrain.caves.CaveChunkPopulatorFeatureConfig;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -28,11 +29,13 @@ public class EndCaveBiome extends EndBiome {
|
|||
|
||||
@Override
|
||||
protected void addCustomBuildData(BCLBiomeBuilder builder) {
|
||||
BCLFeature feature = BCLFeatureBuilder
|
||||
|
||||
BCLFeature<CaveChunkPopulatorFeature, CaveChunkPopulatorFeatureConfig> feature = BCLFeatureBuilder
|
||||
.start(
|
||||
BetterEnd.makeID(ID.getPath() + "_cave_populator"),
|
||||
new CaveChunkPopulatorFeature(() -> (EndCaveBiome) BiomeAPI.getBiome(ID))
|
||||
EndFeatures.CAVE_CHUNK_POPULATOR
|
||||
)
|
||||
.configuration(new CaveChunkPopulatorFeatureConfig(ID))
|
||||
.buildAndRegister()
|
||||
.place()
|
||||
.decoration(GenerationStep.Decoration.RAW_GENERATION)
|
||||
|
|
|
@ -26,8 +26,8 @@ public class LushAuroraCaveBiome extends EndCaveBiome.Config {
|
|||
|
||||
this.addCeilFeature(EndFeatures.CAVE_BUSH, 1);
|
||||
this.addCeilFeature(EndFeatures.CAVE_PUMPKIN, 1);
|
||||
this.addCeilFeature(EndFeatures.RUBINEA, 3);
|
||||
this.addCeilFeature(EndFeatures.MAGNULA, 1);
|
||||
this.addCeilFeature(EndFeatures.RUBINEA.getFeature(), 3);
|
||||
this.addCeilFeature(EndFeatures.MAGNULA.getFeature(), 1);
|
||||
this.addCeilFeature(EndFeatures.END_STONE_STALACTITE_CAVEMOSS, 10);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
|
||||
|
@ -9,16 +10,17 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
|
||||
public class BlueVineFeature extends ScatterFeature {
|
||||
public class BlueVineFeature extends ScatterFeature<ScatterFeatureConfig> {
|
||||
private boolean small;
|
||||
|
||||
public BlueVineFeature() {
|
||||
super(5);
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public boolean canGenerate(
|
||||
ScatterFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -30,11 +32,11 @@ public class BlueVineFeature extends ScatterFeature {
|
|||
center.getZ() - blockPos.getZ()
|
||||
) / radius * 0.6F + random.nextFloat() * 0.4F;
|
||||
small = d > 0.5F;
|
||||
return EndBlocks.BLUE_VINE_SEED.canSurvive(AIR, world, blockPos);
|
||||
return EndBlocks.BLUE_VINE_SEED.canSurvive(DefaultFeature.AIR, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
if (small) {
|
||||
BlocksHelper.setWithoutUpdate(
|
||||
world,
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.util.StructureHelper;
|
||||
import org.betterx.betterend.util.LootTableUtil;
|
||||
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.ChestBlock;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
@ -17,20 +24,89 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProc
|
|||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BuildingListFeature extends ListFeature {
|
||||
public BuildingListFeature(List<StructureInfo> list, BlockState defaultBlock) {
|
||||
super(list, defaultBlock);
|
||||
public class BuildingListFeature extends NBTFeature<BuildingListFeatureConfig> {
|
||||
private StructureInfo selected;
|
||||
|
||||
public BuildingListFeature() {
|
||||
super(BuildingListFeatureConfig.CODEC);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addStructureData(StructurePlaceSettings data) {
|
||||
super.addStructureData(data);
|
||||
data.addProcessor(new ChestProcessor());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureTemplate getStructure(
|
||||
BuildingListFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
BlockPos pos,
|
||||
RandomSource random
|
||||
) {
|
||||
selected = cfg.getRandom(random);
|
||||
return selected.getStructure();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpawn(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
return ((cx + cz) & 1) == 0 && pos.getY() > 58
|
||||
&& world.getBlockState(pos).isAir()
|
||||
&& world.getBlockState(pos.below()).is(CommonBlockTags.TERRAIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rotation getRotation(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
return Rotation.getRandom(random);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mirror getMirror(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
return Mirror.values()[random.nextInt(3)];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getYOffset(StructureTemplate structure, WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
return selected.offsetY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TerrainMerge getTerrainMerge(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
return selected.terrainMerge;
|
||||
}
|
||||
|
||||
public static final class StructureInfo {
|
||||
public static final Codec<StructureInfo> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
Codec.STRING.fieldOf("path").forGetter(o -> o.structurePath),
|
||||
Codec.INT.fieldOf("offset_y").forGetter(o -> o.offsetY),
|
||||
TerrainMerge.CODEC.fieldOf("terrain_merger").forGetter(o -> o.terrainMerge)
|
||||
)
|
||||
.apply(instance, StructureInfo::new));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
class ChestProcessor extends StructureProcessor {
|
||||
@Nullable
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BuildingListFeatureConfig extends NBTFeatureConfig {
|
||||
public static final Codec<BuildingListFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
ExtraCodecs.nonEmptyList(BuildingListFeature.StructureInfo.CODEC.listOf())
|
||||
.fieldOf("structures")
|
||||
.forGetter(a -> a.list),
|
||||
BlockState.CODEC.fieldOf("default").forGetter(o -> o.defaultBlock)
|
||||
)
|
||||
.apply(instance, BuildingListFeatureConfig::new)
|
||||
);
|
||||
protected final List<BuildingListFeature.StructureInfo> list;
|
||||
|
||||
public BuildingListFeatureConfig(List<BuildingListFeature.StructureInfo> list, BlockState defaultBlock) {
|
||||
super(defaultBlock);
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public BuildingListFeature.StructureInfo getRandom(RandomSource random) {
|
||||
return this.list.get(random.nextInt(this.list.size()));
|
||||
}
|
||||
}
|
|
@ -1,12 +1,6 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
public class CharniaFeature extends UnderwaterPlantFeature {
|
||||
public CharniaFeature(Block plant) {
|
||||
super(plant, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChance() {
|
||||
return 3;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.bclib.util.StructureErode;
|
||||
import org.betterx.bclib.util.StructureHelper;
|
||||
import org.betterx.betterend.util.BlockFixer;
|
||||
import org.betterx.betterend.world.biome.EndBiome;
|
||||
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -17,23 +17,27 @@ import net.minecraft.world.level.block.Mirror;
|
|||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.*;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
|
||||
public class CrashedShipFeature extends NBTFeature {
|
||||
public class CrashedShipFeature extends NBTFeature<NBTFeatureConfig> {
|
||||
private static final StructureProcessor REPLACER;
|
||||
private static final String STRUCTURE_PATH = "/data/minecraft/structures/end_city/ship.nbt";
|
||||
private StructureTemplate structure;
|
||||
|
||||
public CrashedShipFeature() {
|
||||
super(EndBiome.Config.DEFAULT_MATERIAL.getTopMaterial());
|
||||
super(NBTFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureTemplate getStructure(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
protected StructureTemplate getStructure(
|
||||
NBTFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
BlockPos pos,
|
||||
RandomSource random
|
||||
) {
|
||||
if (structure == null) {
|
||||
structure = world.getLevel().getStructureManager().getOrCreate(new ResourceLocation("end_city/ship"));
|
||||
if (structure == null) {
|
||||
|
@ -76,7 +80,7 @@ public class CrashedShipFeature extends NBTFeature {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featureConfig) {
|
||||
public boolean place(FeaturePlaceContext<NBTFeatureConfig> featureConfig) {
|
||||
final RandomSource random = featureConfig.random();
|
||||
BlockPos center = featureConfig.origin();
|
||||
final WorldGenLevel world = featureConfig.level();
|
||||
|
@ -88,7 +92,7 @@ public class CrashedShipFeature extends NBTFeature {
|
|||
return false;
|
||||
}
|
||||
|
||||
StructureTemplate structure = getStructure(world, center, random);
|
||||
StructureTemplate structure = getStructure(featureConfig.config(), world, center, random);
|
||||
Rotation rotation = getRotation(world, center, random);
|
||||
Mirror mirror = getMirror(world, center, random);
|
||||
BlockPos offset = StructureTemplate.transform(
|
||||
|
@ -135,7 +139,7 @@ public class CrashedShipFeature extends NBTFeature {
|
|||
) {
|
||||
BlockState state = structureBlockInfo2.state;
|
||||
if (state.is(Blocks.SPAWNER) || state.getMaterial().equals(Material.WOOL)) {
|
||||
return new StructureBlockInfo(structureBlockInfo2.pos, AIR, null);
|
||||
return new StructureBlockInfo(structureBlockInfo2.pos, DefaultFeature.AIR, null);
|
||||
}
|
||||
return structureBlockInfo2;
|
||||
}
|
||||
|
|
|
@ -7,22 +7,19 @@ import org.betterx.bclib.util.MHelper;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class DoublePlantFeature extends ScatterFeature {
|
||||
private final Block smallPlant;
|
||||
private final Block largePlant;
|
||||
private Block plant;
|
||||
public class DoublePlantFeature extends ScatterFeature<DoublePlantFeatureConfig> {
|
||||
private BlockState plant;
|
||||
|
||||
public DoublePlantFeature() {
|
||||
super(DoublePlantFeatureConfig.CODEC);
|
||||
|
||||
public DoublePlantFeature(Block smallPlant, Block largePlant, int radius) {
|
||||
super(radius);
|
||||
this.smallPlant = smallPlant;
|
||||
this.largePlant = largePlant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
DoublePlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -33,16 +30,21 @@ public class DoublePlantFeature extends ScatterFeature {
|
|||
center.getX() - blockPos.getX(),
|
||||
center.getZ() - blockPos.getZ()
|
||||
) / radius * 0.6F + random.nextFloat() * 0.4F;
|
||||
plant = d < 0.5F ? largePlant : smallPlant;
|
||||
plant = d < 0.5F ? cfg.getLargePlantState(random, blockPos) : cfg.getSmallPlantState(random, blockPos);
|
||||
//noinspection deprecation
|
||||
return plant.canSurvive(plant.defaultBlockState(), world, blockPos);
|
||||
return plant.getBlock().canSurvive(plant, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
if (plant instanceof BaseDoublePlantBlock) {
|
||||
public void generate(
|
||||
DoublePlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos blockPos
|
||||
) {
|
||||
if (plant.getBlock() instanceof BaseDoublePlantBlock) {
|
||||
int rot = random.nextInt(4);
|
||||
BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot);
|
||||
BlockState state = plant.setValue(BaseDoublePlantBlock.ROTATION, rot);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, state);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true));
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.SimpleStateProvider;
|
||||
|
||||
public class DoublePlantFeatureConfig extends ScatterFeatureConfig {
|
||||
public static final Codec<DoublePlantFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockStateProvider.CODEC.fieldOf("small_state").forGetter(o -> o.smallPlant),
|
||||
BlockStateProvider.CODEC.fieldOf("large_state").forGetter(o -> o.largePlant),
|
||||
Codec.INT.fieldOf("radius").forGetter(o -> o.radius)
|
||||
)
|
||||
.apply(
|
||||
instance,
|
||||
DoublePlantFeatureConfig::new
|
||||
));
|
||||
|
||||
public final BlockStateProvider smallPlant;
|
||||
public final BlockStateProvider largePlant;
|
||||
|
||||
public DoublePlantFeatureConfig(Block smallPlant, Block largePlant, int radius) {
|
||||
this(SimpleStateProvider.simple(smallPlant), SimpleStateProvider.simple(largePlant), radius);
|
||||
}
|
||||
|
||||
public DoublePlantFeatureConfig(BlockStateProvider smallPlant, BlockStateProvider largePlant, int radius) {
|
||||
super(radius);
|
||||
this.smallPlant = smallPlant;
|
||||
this.largePlant = largePlant;
|
||||
}
|
||||
|
||||
BlockState getLargePlantState(RandomSource rnd, BlockPos pos) {
|
||||
return largePlant.getState(rnd, pos);
|
||||
}
|
||||
|
||||
BlockState getSmallPlantState(RandomSource rnd, BlockPos pos) {
|
||||
return smallPlant.getState(rnd, pos);
|
||||
}
|
||||
}
|
|
@ -7,13 +7,13 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
|
||||
public class EndLilyFeature extends UnderwaterPlantScatter {
|
||||
public EndLilyFeature(int radius) {
|
||||
super(radius);
|
||||
public class EndLilyFeature extends UnderwaterPlantScatter<ScatterFeatureConfig> {
|
||||
public EndLilyFeature() {
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
EndLilySeedBlock seed = (EndLilySeedBlock) EndBlocks.END_LILY_SEED;
|
||||
seed.grow(world, random, blockPos);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
|
||||
public class EndLotusFeature extends UnderwaterPlantScatter {
|
||||
public EndLotusFeature(int radius) {
|
||||
super(radius);
|
||||
public class EndLotusFeature extends UnderwaterPlantScatter<ScatterFeatureConfig> {
|
||||
public EndLotusFeature() {
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
EndLotusSeedBlock seed = (EndLotusSeedBlock) EndBlocks.END_LOTUS_SEED;
|
||||
seed.grow(world, random, blockPos);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.blocks.BlockProperties.TripleShape;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.betterend.blocks.EndLotusLeafBlock;
|
||||
|
@ -13,13 +14,13 @@ import net.minecraft.world.level.WorldGenLevel;
|
|||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class EndLotusLeafFeature extends ScatterFeature {
|
||||
public EndLotusLeafFeature(int radius) {
|
||||
super(radius);
|
||||
public class EndLotusLeafFeature extends ScatterFeature<ScatterFeatureConfig> {
|
||||
public EndLotusLeafFeature() {
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
if (canGenerate(world, blockPos)) {
|
||||
generateLeaf(world, blockPos);
|
||||
}
|
||||
|
@ -31,8 +32,8 @@ public class EndLotusLeafFeature extends ScatterFeature {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) {
|
||||
return getPosOnSurface(world, pos);
|
||||
protected BlockPos getCenterGround(ScatterFeatureConfig cfg, WorldGenLevel world, BlockPos pos) {
|
||||
return DefaultFeature.getPosOnSurface(world, pos);
|
||||
}
|
||||
|
||||
private void generateLeaf(WorldGenLevel world, BlockPos pos) {
|
||||
|
@ -75,6 +76,7 @@ public class EndLotusLeafFeature extends ScatterFeature {
|
|||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
ScatterFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
|
|
@ -14,12 +14,8 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
||||
public class FilaluxFeature extends SkyScatterFeature {
|
||||
public FilaluxFeature() {
|
||||
super(10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
BlockState vine = EndBlocks.FILALUX.defaultBlockState();
|
||||
BlockState wings = EndBlocks.FILALUX_WINGS.defaultBlockState();
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, EndBlocks.FILALUX_LANTERN);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
|
||||
import org.betterx.betterend.registry.EndBlocks;
|
||||
|
||||
|
@ -7,13 +8,14 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
|
||||
public class GlowPillarFeature extends ScatterFeature {
|
||||
public class GlowPillarFeature extends ScatterFeature<ScatterFeatureConfig> {
|
||||
public GlowPillarFeature() {
|
||||
super(9);
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
ScatterFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -21,11 +23,13 @@ public class GlowPillarFeature extends ScatterFeature {
|
|||
float radius
|
||||
) {
|
||||
//noinspection deprecation
|
||||
return EndBlocks.GLOWING_PILLAR_SEED.canSurvive(AIR, world, blockPos);
|
||||
return EndBlocks.GLOWING_PILLAR_SEED.canSurvive(DefaultFeature.AIR, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(
|
||||
ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos
|
||||
) {
|
||||
EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.GLOWING_PILLAR_SEED);
|
||||
seed.growAdult(world, random, blockPos);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
|
||||
public class HydraluxFeature extends UnderwaterPlantScatter {
|
||||
public HydraluxFeature(int radius) {
|
||||
super(radius);
|
||||
public class HydraluxFeature extends UnderwaterPlantScatter<ScatterFeatureConfig> {
|
||||
public HydraluxFeature() {
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
HydraluxSaplingBlock seed = (HydraluxSaplingBlock) EndBlocks.HYDRALUX_SAPLING;
|
||||
seed.grow(world, random, blockPos);
|
||||
}
|
||||
|
|
|
@ -1,26 +1,27 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.betterend.util.GlobalState;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
||||
public abstract class InvertedScatterFeature extends DefaultFeature {
|
||||
private final int radius;
|
||||
public abstract class InvertedScatterFeature<FC extends ScatterFeatureConfig> extends Feature<FC> {
|
||||
|
||||
public InvertedScatterFeature(int radius) {
|
||||
this.radius = radius;
|
||||
|
||||
public InvertedScatterFeature(Codec<FC> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
public abstract boolean canGenerate(
|
||||
FC cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -28,10 +29,11 @@ public abstract class InvertedScatterFeature extends DefaultFeature {
|
|||
float radius
|
||||
);
|
||||
|
||||
public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos);
|
||||
public abstract void generate(FC cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos);
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featureConfig) {
|
||||
public boolean place(FeaturePlaceContext<FC> featureConfig) {
|
||||
FC cfg = featureConfig.config();
|
||||
final MutableBlockPos POS = GlobalState.stateForThread().POS;
|
||||
final RandomSource random = featureConfig.random();
|
||||
final BlockPos center = featureConfig.origin();
|
||||
|
@ -41,7 +43,7 @@ public abstract class InvertedScatterFeature extends DefaultFeature {
|
|||
for (int y = maxY; y > minY; y--) {
|
||||
POS.set(center.getX(), y, center.getZ());
|
||||
if (world.getBlockState(POS).isAir() && !world.getBlockState(POS.above()).isAir()) {
|
||||
float r = MHelper.randRange(radius * 0.5F, radius, random);
|
||||
float r = MHelper.randRange(cfg.radius * 0.5F, cfg.radius, random);
|
||||
int count = MHelper.floor(r * r * MHelper.randRange(0.5F, 1.5F, random));
|
||||
for (int i = 0; i < count; i++) {
|
||||
float pr = r * (float) Math.sqrt(random.nextFloat());
|
||||
|
@ -54,8 +56,8 @@ public abstract class InvertedScatterFeature extends DefaultFeature {
|
|||
if (up > 14) continue;
|
||||
POS.setY(POS.getY() + up);
|
||||
|
||||
if (canGenerate(world, random, center, POS, r)) {
|
||||
generate(world, random, POS);
|
||||
if (canGenerate(cfg, world, random, center, POS, r)) {
|
||||
generate(cfg, world, random, POS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
|
||||
import org.betterx.betterend.registry.EndBlocks;
|
||||
|
||||
|
@ -7,13 +8,14 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
|
||||
public class LanceleafFeature extends ScatterFeature {
|
||||
public class LanceleafFeature extends ScatterFeature<ScatterFeatureConfig> {
|
||||
public LanceleafFeature() {
|
||||
super(7);
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
ScatterFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -21,11 +23,11 @@ public class LanceleafFeature extends ScatterFeature {
|
|||
float radius
|
||||
) {
|
||||
//noinspection deprecation
|
||||
return EndBlocks.LANCELEAF_SEED.canSurvive(AIR, world, blockPos);
|
||||
return EndBlocks.LANCELEAF_SEED.canSurvive(DefaultFeature.AIR, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
EndPlantWithAgeBlock seed = ((EndPlantWithAgeBlock) EndBlocks.LANCELEAF_SEED);
|
||||
seed.growAdult(world, random, blockPos);
|
||||
}
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
|
||||
import org.betterx.bclib.util.StructureHelper;
|
||||
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
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.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ListFeature extends NBTFeature {
|
||||
private final List<StructureInfo> list;
|
||||
private StructureInfo selected;
|
||||
|
||||
public ListFeature(List<StructureInfo> list, BlockState defaultBlock) {
|
||||
super(defaultBlock);
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureTemplate getStructure(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
selected = list.get(random.nextInt(list.size()));
|
||||
return selected.getStructure();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpawn(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
return ((cx + cz) & 1) == 0 && pos.getY() > 58
|
||||
&& world.getBlockState(pos).isAir()
|
||||
&& world.getBlockState(pos.below()).is(CommonBlockTags.TERRAIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rotation getRotation(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
return Rotation.getRandom(random);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mirror getMirror(WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
return Mirror.values()[random.nextInt(3)];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getYOffset(StructureTemplate structure, WorldGenLevel world, BlockPos pos, RandomSource random) {
|
||||
return selected.offsetY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TerrainMerge getTerrainMerge(WorldGenLevel world, BlockPos pos, RandomSource 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,15 +11,15 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class MengerSpongeFeature extends UnderwaterPlantScatter {
|
||||
public class MengerSpongeFeature extends UnderwaterPlantScatter<ScatterFeatureConfig> {
|
||||
private static final Function<BlockState, Boolean> REPLACE;
|
||||
|
||||
public MengerSpongeFeature(int radius) {
|
||||
super(radius);
|
||||
public MengerSpongeFeature() {
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
public void generate(ScatterFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, EndBlocks.MENGER_SPONGE_WET);
|
||||
if (random.nextBoolean()) {
|
||||
for (Direction dir : BlocksHelper.DIRECTIONS) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.betterx.bclib.api.v2.levelgen.structures.templatesystem.DestructionSt
|
|||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -16,13 +17,14 @@ import net.minecraft.nbt.NbtIo;
|
|||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
|
@ -30,17 +32,14 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemp
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
//TODO: 1.19 Check if we can merge this with the new TemplateFeature!
|
||||
public abstract class NBTFeature extends DefaultFeature {
|
||||
private final BlockState defaultBlock;
|
||||
|
||||
public NBTFeature(BlockState defaultBlock) {
|
||||
this.defaultBlock = defaultBlock;
|
||||
public abstract class NBTFeature<FC extends NBTFeatureConfig> extends Feature<FC> {
|
||||
public NBTFeature(Codec<FC> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
protected static final DestructionStructureProcessor DESTRUCTION = new DestructionStructureProcessor();
|
||||
|
||||
protected abstract StructureTemplate getStructure(WorldGenLevel world, BlockPos pos, RandomSource random);
|
||||
protected abstract StructureTemplate getStructure(FC cfg, WorldGenLevel world, BlockPos pos, RandomSource random);
|
||||
|
||||
protected abstract boolean canSpawn(WorldGenLevel world, BlockPos pos, RandomSource random);
|
||||
|
||||
|
@ -72,25 +71,26 @@ public abstract class NBTFeature extends DefaultFeature {
|
|||
}
|
||||
|
||||
protected int getAverageY(WorldGenLevel world, BlockPos center) {
|
||||
int y = getYOnSurface(world, center.getX(), center.getZ());
|
||||
y += getYOnSurface(world, center.getX() - 2, center.getZ() - 2);
|
||||
y += getYOnSurface(world, center.getX() + 2, center.getZ() - 2);
|
||||
y += getYOnSurface(world, center.getX() - 2, center.getZ() + 2);
|
||||
y += getYOnSurface(world, center.getX() + 2, center.getZ() + 2);
|
||||
int y = DefaultFeature.getYOnSurface(world, center.getX(), center.getZ());
|
||||
y += DefaultFeature.getYOnSurface(world, center.getX() - 2, center.getZ() - 2);
|
||||
y += DefaultFeature.getYOnSurface(world, center.getX() + 2, center.getZ() - 2);
|
||||
y += DefaultFeature.getYOnSurface(world, center.getX() - 2, center.getZ() + 2);
|
||||
y += DefaultFeature.getYOnSurface(world, center.getX() + 2, center.getZ() + 2);
|
||||
return y / 5;
|
||||
}
|
||||
|
||||
protected int getAverageYWG(WorldGenLevel world, BlockPos center) {
|
||||
int y = getYOnSurfaceWG(world, center.getX(), center.getZ());
|
||||
y += getYOnSurfaceWG(world, center.getX() - 2, center.getZ() - 2);
|
||||
y += getYOnSurfaceWG(world, center.getX() + 2, center.getZ() - 2);
|
||||
y += getYOnSurfaceWG(world, center.getX() - 2, center.getZ() + 2);
|
||||
y += getYOnSurfaceWG(world, center.getX() + 2, center.getZ() + 2);
|
||||
int y = DefaultFeature.getYOnSurfaceWG(world, center.getX(), center.getZ());
|
||||
y += DefaultFeature.getYOnSurfaceWG(world, center.getX() - 2, center.getZ() - 2);
|
||||
y += DefaultFeature.getYOnSurfaceWG(world, center.getX() + 2, center.getZ() - 2);
|
||||
y += DefaultFeature.getYOnSurfaceWG(world, center.getX() - 2, center.getZ() + 2);
|
||||
y += DefaultFeature.getYOnSurfaceWG(world, center.getX() + 2, center.getZ() + 2);
|
||||
return y / 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> context) {
|
||||
public boolean place(FeaturePlaceContext<FC> context) {
|
||||
FC cfg = context.config();
|
||||
WorldGenLevel world = context.level();
|
||||
RandomSource random = context.random();
|
||||
BlockPos center = context.origin();
|
||||
|
@ -103,7 +103,7 @@ public abstract class NBTFeature extends DefaultFeature {
|
|||
}
|
||||
|
||||
int posY = center.getY() + 1;
|
||||
StructureTemplate structure = getStructure(world, center, random);
|
||||
StructureTemplate structure = getStructure(cfg, world, center, random);
|
||||
Rotation rotation = getRotation(world, center, random);
|
||||
Mirror mirror = getMirror(world, center, random);
|
||||
BlockPos offset = StructureTemplate.transform(
|
||||
|
@ -160,7 +160,7 @@ public abstract class NBTFeature extends DefaultFeature {
|
|||
Holder<Biome> b = world.getBiome(mut);
|
||||
BlockState top = (isTop
|
||||
? BiomeAPI.findTopMaterial(b)
|
||||
: BiomeAPI.findUnderMaterial(b)).orElse(defaultBlock);
|
||||
: BiomeAPI.findUnderMaterial(b)).orElse(cfg.defaultBlock);
|
||||
BlocksHelper.setWithoutUpdate(world, mut, top);
|
||||
} else {
|
||||
BlocksHelper.setWithoutUpdate(world, mut, state);
|
||||
|
@ -169,7 +169,7 @@ public abstract class NBTFeature extends DefaultFeature {
|
|||
if (isTerrain(state) && state.getMaterial().isSolidBlocking()) {
|
||||
if (merge == TerrainMerge.SURFACE) {
|
||||
Holder<Biome> b = world.getBiome(mut);
|
||||
BlockState bottom = BiomeAPI.findUnderMaterial(b).orElse(defaultBlock);
|
||||
BlockState bottom = BiomeAPI.findUnderMaterial(b).orElse(cfg.defaultBlock);
|
||||
BlocksHelper.setWithoutUpdate(world, mut, bottom);
|
||||
} else {
|
||||
BlocksHelper.setWithoutUpdate(world, mut, state);
|
||||
|
@ -222,9 +222,11 @@ public abstract class NBTFeature extends DefaultFeature {
|
|||
return template;
|
||||
}
|
||||
|
||||
public enum TerrainMerge {
|
||||
public enum TerrainMerge implements StringRepresentable {
|
||||
NONE, SURFACE, OBJECT;
|
||||
|
||||
public static final Codec<TerrainMerge> CODEC = StringRepresentable.fromEnum(TerrainMerge::values);
|
||||
|
||||
public static TerrainMerge getFromString(String type) {
|
||||
if (type.equals("surface")) {
|
||||
return SURFACE;
|
||||
|
@ -234,5 +236,10 @@ public abstract class NBTFeature extends DefaultFeature {
|
|||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
||||
public class NBTFeatureConfig implements FeatureConfiguration {
|
||||
public static final Codec<NBTFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockState.CODEC.fieldOf("default").forGetter(o -> o.defaultBlock)
|
||||
)
|
||||
.apply(instance, NBTFeatureConfig::new)
|
||||
);
|
||||
public final BlockState defaultBlock;
|
||||
|
||||
public NBTFeatureConfig(BlockState defaultBlock) {
|
||||
this.defaultBlock = defaultBlock;
|
||||
}
|
||||
}
|
|
@ -6,21 +6,21 @@ import org.betterx.bclib.util.MHelper;
|
|||
import org.betterx.betterend.util.GlobalState;
|
||||
import org.betterx.worlds.together.tag.v3.CommonBlockTags;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
||||
public abstract class ScatterFeature extends DefaultFeature {
|
||||
private final int radius;
|
||||
|
||||
public ScatterFeature(int radius) {
|
||||
this.radius = radius;
|
||||
public abstract class ScatterFeature<FC extends ScatterFeatureConfig> extends Feature<FC> {
|
||||
public ScatterFeature(Codec<FC> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
public abstract boolean canGenerate(
|
||||
FC cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -28,19 +28,19 @@ public abstract class ScatterFeature extends DefaultFeature {
|
|||
float radius
|
||||
);
|
||||
|
||||
public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos);
|
||||
public abstract void generate(FC cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos);
|
||||
|
||||
protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) {
|
||||
return getPosOnSurfaceWG(world, pos);
|
||||
protected BlockPos getCenterGround(FC cfg, WorldGenLevel world, BlockPos pos) {
|
||||
return DefaultFeature.getPosOnSurfaceWG(world, pos);
|
||||
}
|
||||
|
||||
protected boolean canSpawn(WorldGenLevel world, BlockPos pos) {
|
||||
protected boolean canSpawn(FC cfg, WorldGenLevel world, BlockPos pos) {
|
||||
if (pos.getY() < 5) {
|
||||
return false;
|
||||
} else return world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES);
|
||||
}
|
||||
|
||||
protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) {
|
||||
protected boolean getGroundPlant(FC cfg, WorldGenLevel world, MutableBlockPos pos) {
|
||||
int down = BlocksHelper.downRay(world, pos, 16);
|
||||
if (down > Math.abs(getYOffset() * 2)) {
|
||||
return false;
|
||||
|
@ -58,18 +58,19 @@ public abstract class ScatterFeature extends DefaultFeature {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featureConfig) {
|
||||
public boolean place(FeaturePlaceContext<FC> featureConfig) {
|
||||
FC cfg = featureConfig.config();
|
||||
final MutableBlockPos POS = GlobalState.stateForThread().POS;
|
||||
final RandomSource random = featureConfig.random();
|
||||
BlockPos center = featureConfig.origin();
|
||||
final WorldGenLevel world = featureConfig.level();
|
||||
center = getCenterGround(world, center);
|
||||
center = getCenterGround(cfg, world, center);
|
||||
|
||||
if (!canSpawn(world, center)) {
|
||||
if (!canSpawn(cfg, world, center)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float r = MHelper.randRange(radius * 0.5F, radius, random);
|
||||
float r = MHelper.randRange(cfg.radius * 0.5F, cfg.radius, random);
|
||||
int count = MHelper.floor(r * r * MHelper.randRange(1.5F, 3F, random));
|
||||
for (int i = 0; i < count; i++) {
|
||||
float pr = r * (float) Math.sqrt(random.nextFloat());
|
||||
|
@ -78,14 +79,15 @@ public abstract class ScatterFeature extends DefaultFeature {
|
|||
float z = pr * (float) Math.sin(theta);
|
||||
|
||||
POS.set(center.getX() + x, center.getY() + getYOffset(), center.getZ() + z);
|
||||
if (getGroundPlant(world, POS) && canGenerate(
|
||||
if (getGroundPlant(cfg, world, POS) && canGenerate(
|
||||
cfg,
|
||||
world,
|
||||
random,
|
||||
center,
|
||||
POS,
|
||||
r
|
||||
) && (getChance() < 2 || random.nextInt(getChance()) == 0)) {
|
||||
generate(world, random, POS);
|
||||
generate(cfg, world, random, POS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
||||
public class ScatterFeatureConfig implements FeatureConfiguration {
|
||||
public static final Codec<ScatterFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
Codec.INT.fieldOf("radius").forGetter(o -> o.radius)
|
||||
)
|
||||
.apply(instance, ScatterFeatureConfig::new));
|
||||
|
||||
public final int radius;
|
||||
|
||||
public ScatterFeatureConfig(int radius) {
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public static ScatterFeatureConfig blueVine() {
|
||||
return new ScatterFeatureConfig(5);
|
||||
}
|
||||
|
||||
public static ScatterFeatureConfig filalux() {
|
||||
return new ScatterFeatureConfig(10);
|
||||
}
|
||||
|
||||
public static ScatterFeatureConfig glowPillar() {
|
||||
return new ScatterFeatureConfig(9);
|
||||
}
|
||||
|
||||
public static ScatterFeatureConfig lanceleaf() {
|
||||
return new ScatterFeatureConfig(7);
|
||||
}
|
||||
}
|
|
@ -7,20 +7,19 @@ import net.minecraft.core.BlockPos;
|
|||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
||||
public class SingleInvertedScatterFeature extends InvertedScatterFeature {
|
||||
private final Block block;
|
||||
public class SingleInvertedScatterFeature extends InvertedScatterFeature<SinglePlantFeatureConfig> {
|
||||
private BlockState block;
|
||||
|
||||
public SingleInvertedScatterFeature(Block block, int radius) {
|
||||
super(radius);
|
||||
this.block = block;
|
||||
public SingleInvertedScatterFeature() {
|
||||
super(SinglePlantFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
SinglePlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -30,17 +29,18 @@ public class SingleInvertedScatterFeature extends InvertedScatterFeature {
|
|||
if (!world.isEmptyBlock(blockPos)) {
|
||||
return false;
|
||||
}
|
||||
BlockState state = block.defaultBlockState();
|
||||
if (block instanceof BaseAttachedBlock) {
|
||||
block = cfg.getPlantState(random, blockPos);
|
||||
BlockState state = block;
|
||||
if (block.getBlock() instanceof BaseAttachedBlock) {
|
||||
state = state.setValue(BlockStateProperties.FACING, Direction.DOWN);
|
||||
}
|
||||
return state.canSurvive(world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
BlockState state = block.defaultBlockState();
|
||||
if (block instanceof BaseAttachedBlock) {
|
||||
public void generate(SinglePlantFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
BlockState state = block;
|
||||
if (block.getBlock() instanceof BaseAttachedBlock) {
|
||||
state = state.setValue(BlockStateProperties.FACING, Direction.DOWN);
|
||||
}
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, state);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.blocks.BaseCropBlock;
|
||||
import org.betterx.bclib.blocks.BaseDoublePlantBlock;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
@ -8,70 +9,53 @@ import org.betterx.betterend.blocks.basis.EndPlantWithAgeBlock;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class SinglePlantFeature extends ScatterFeature {
|
||||
private final Block plant;
|
||||
private final boolean rawHeightmap;
|
||||
private final int chance;
|
||||
public class SinglePlantFeature extends ScatterFeature<SinglePlantFeatureConfig> {
|
||||
|
||||
public SinglePlantFeature(Block plant, int radius) {
|
||||
this(plant, radius, true, 1);
|
||||
}
|
||||
BlockState plant;
|
||||
|
||||
public SinglePlantFeature(Block plant, int radius, int chance) {
|
||||
this(plant, radius, true, chance);
|
||||
}
|
||||
|
||||
public SinglePlantFeature(Block plant, int radius, boolean rawHeightmap) {
|
||||
this(plant, radius, rawHeightmap, 1);
|
||||
}
|
||||
|
||||
public SinglePlantFeature(Block plant, int radius, boolean rawHeightmap, int chance) {
|
||||
super(radius);
|
||||
this.plant = plant;
|
||||
this.rawHeightmap = rawHeightmap;
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
protected int getChance() {
|
||||
return chance;
|
||||
public SinglePlantFeature() {
|
||||
super(SinglePlantFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) {
|
||||
return rawHeightmap ? getPosOnSurfaceWG(world, pos) : getPosOnSurface(world, pos);
|
||||
protected BlockPos getCenterGround(SinglePlantFeatureConfig cfg, WorldGenLevel world, BlockPos pos) {
|
||||
return cfg.rawHeightmap
|
||||
? DefaultFeature.getPosOnSurfaceWG(world, pos)
|
||||
: DefaultFeature.getPosOnSurface(world, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
SinglePlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
BlockPos blockPos,
|
||||
float radius
|
||||
) {
|
||||
this.plant = cfg.getPlantState(random, blockPos);
|
||||
//noinspection deprecation
|
||||
return plant.canSurvive(plant.defaultBlockState(), world, blockPos);
|
||||
return plant.getBlock().canSurvive(plant, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
if (plant instanceof BaseDoublePlantBlock) {
|
||||
public void generate(SinglePlantFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
if (this.plant.getBlock() instanceof BaseDoublePlantBlock) {
|
||||
int rot = random.nextInt(4);
|
||||
BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot);
|
||||
BlockState state = this.plant.setValue(BaseDoublePlantBlock.ROTATION, rot);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, state);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true));
|
||||
} else if (plant instanceof BaseCropBlock) {
|
||||
BlockState state = plant.defaultBlockState().setValue(BaseCropBlock.AGE, 3);
|
||||
} else if (this.plant.getBlock() instanceof BaseCropBlock) {
|
||||
BlockState state = this.plant.setValue(BaseCropBlock.AGE, 3);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, state);
|
||||
} else if (plant instanceof EndPlantWithAgeBlock) {
|
||||
} else if (this.plant.getBlock() instanceof EndPlantWithAgeBlock) {
|
||||
int age = random.nextInt(4);
|
||||
BlockState state = plant.defaultBlockState().setValue(EndPlantWithAgeBlock.AGE, age);
|
||||
BlockState state = this.plant.setValue(EndPlantWithAgeBlock.AGE, age);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, state);
|
||||
} else {
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, plant);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, this.plant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.SimpleStateProvider;
|
||||
|
||||
public class SinglePlantFeatureConfig extends ScatterFeatureConfig {
|
||||
public static final Codec<SinglePlantFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockStateProvider.CODEC.fieldOf("state").forGetter(o -> o.plant),
|
||||
Codec.INT.fieldOf("radius").forGetter(o -> o.radius),
|
||||
Codec.BOOL.fieldOf("raw_heightmap").forGetter(o -> o.rawHeightmap),
|
||||
Codec.INT.fieldOf("chance").forGetter(o -> o.chance)
|
||||
)
|
||||
.apply(
|
||||
instance,
|
||||
SinglePlantFeatureConfig::new
|
||||
));
|
||||
|
||||
public final BlockStateProvider plant;
|
||||
public final boolean rawHeightmap;
|
||||
public final int chance;
|
||||
|
||||
public SinglePlantFeatureConfig(Block plant, int radius) {
|
||||
this(SimpleStateProvider.simple(plant), radius, true, 1);
|
||||
}
|
||||
|
||||
public SinglePlantFeatureConfig(Block plant, int radius, int chance) {
|
||||
this(SimpleStateProvider.simple(plant), radius, true, chance);
|
||||
}
|
||||
|
||||
public SinglePlantFeatureConfig(Block plant, int radius, boolean rawHeightmap) {
|
||||
this(SimpleStateProvider.simple(plant), radius, rawHeightmap, 1);
|
||||
}
|
||||
|
||||
public SinglePlantFeatureConfig(Block plant, int radius, boolean rawHeightmap, int chance) {
|
||||
this(SimpleStateProvider.simple(plant), radius, rawHeightmap, chance);
|
||||
}
|
||||
|
||||
public SinglePlantFeatureConfig(BlockStateProvider plant, int radius, boolean rawHeightmap, int chance) {
|
||||
super(radius);
|
||||
this.plant = plant;
|
||||
this.rawHeightmap = rawHeightmap;
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
public BlockState getPlantState(RandomSource rnd, BlockPos pos) {
|
||||
return plant.getState(rnd, pos);
|
||||
}
|
||||
|
||||
public static SinglePlantFeatureConfig charnia(Block plant) {
|
||||
return new SinglePlantFeatureConfig(plant, 6);
|
||||
}
|
||||
}
|
|
@ -9,9 +9,9 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
|
||||
public abstract class SkyScatterFeature extends ScatterFeature {
|
||||
public SkyScatterFeature(int radius) {
|
||||
super(radius);
|
||||
public abstract class SkyScatterFeature extends ScatterFeature<ScatterFeatureConfig> {
|
||||
public SkyScatterFeature() {
|
||||
super(ScatterFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,6 +21,7 @@ public abstract class SkyScatterFeature extends ScatterFeature {
|
|||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
ScatterFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -44,12 +45,12 @@ public abstract class SkyScatterFeature extends ScatterFeature {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpawn(WorldGenLevel world, BlockPos pos) {
|
||||
protected boolean canSpawn(ScatterFeatureConfig cfg, WorldGenLevel world, BlockPos pos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) {
|
||||
protected BlockPos getCenterGround(ScatterFeatureConfig cfg, WorldGenLevel world, BlockPos pos) {
|
||||
return new BlockPos(pos.getX(), MHelper.randRange(32, 192, world.getRandom()), pos.getZ());
|
||||
}
|
||||
|
||||
|
|
|
@ -6,34 +6,35 @@ import org.betterx.bclib.util.BlocksHelper;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class UnderwaterPlantFeature extends UnderwaterPlantScatter {
|
||||
private final Block plant;
|
||||
public class UnderwaterPlantFeature extends UnderwaterPlantScatter<SinglePlantFeatureConfig> {
|
||||
private BlockState plant;
|
||||
|
||||
public UnderwaterPlantFeature() {
|
||||
super(SinglePlantFeatureConfig.CODEC);
|
||||
|
||||
public UnderwaterPlantFeature(Block plant, int radius) {
|
||||
super(radius);
|
||||
this.plant = plant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
SinglePlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
BlockPos blockPos,
|
||||
float radius
|
||||
) {
|
||||
plant = cfg.getPlantState(random, blockPos);
|
||||
//noinspection deprecation
|
||||
return super.canSpawn(world, blockPos) && plant.canSurvive(plant.defaultBlockState(), world, blockPos);
|
||||
return super.canSpawn(cfg, world, blockPos) && plant.getBlock().canSurvive(plant, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
if (plant instanceof BaseDoublePlantBlock) {
|
||||
public void generate(SinglePlantFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
if (plant.getBlock() instanceof BaseDoublePlantBlock) {
|
||||
int rot = random.nextInt(4);
|
||||
BlockState state = plant.defaultBlockState().setValue(BaseDoublePlantBlock.ROTATION, rot);
|
||||
BlockState state = plant.setValue(BaseDoublePlantBlock.ROTATION, rot);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, state);
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos.above(), state.setValue(BaseDoublePlantBlock.TOP, true));
|
||||
} else {
|
||||
|
|
|
@ -2,19 +2,20 @@ package org.betterx.betterend.world.features;
|
|||
|
||||
import org.betterx.betterend.util.GlobalState;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
public abstract class UnderwaterPlantScatter extends ScatterFeature {
|
||||
public UnderwaterPlantScatter(int radius) {
|
||||
super(radius);
|
||||
public abstract class UnderwaterPlantScatter<FC extends ScatterFeatureConfig> extends ScatterFeature<FC> {
|
||||
public UnderwaterPlantScatter(Codec<FC> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockPos getCenterGround(WorldGenLevel world, BlockPos pos) {
|
||||
protected BlockPos getCenterGround(FC cfg, WorldGenLevel world, BlockPos pos) {
|
||||
final MutableBlockPos POS = GlobalState.stateForThread().POS;
|
||||
POS.setX(pos.getX());
|
||||
POS.setZ(pos.getZ());
|
||||
|
@ -24,6 +25,7 @@ public abstract class UnderwaterPlantScatter extends ScatterFeature {
|
|||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
FC cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
|
@ -34,12 +36,12 @@ public abstract class UnderwaterPlantScatter extends ScatterFeature {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSpawn(WorldGenLevel world, BlockPos pos) {
|
||||
protected boolean canSpawn(FC cfg, WorldGenLevel world, BlockPos pos) {
|
||||
return world.getBlockState(pos).is(Blocks.WATER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getGroundPlant(WorldGenLevel world, MutableBlockPos pos) {
|
||||
protected boolean getGroundPlant(FC cfg, WorldGenLevel world, MutableBlockPos pos) {
|
||||
return getGround(world, pos).getY() < 128;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,39 +8,37 @@ import org.betterx.bclib.util.BlocksHelper;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class VineFeature extends InvertedScatterFeature {
|
||||
private final Block vineBlock;
|
||||
private final int maxLength;
|
||||
private final boolean vine;
|
||||
public class VineFeature extends InvertedScatterFeature<VineFeatureConfig> {
|
||||
private BlockState plant;
|
||||
boolean vine;
|
||||
|
||||
public VineFeature(Block vineBlock, int maxLength) {
|
||||
super(6);
|
||||
this.vineBlock = vineBlock;
|
||||
this.maxLength = maxLength;
|
||||
this.vine = vineBlock instanceof BaseVineBlock;
|
||||
public VineFeature() {
|
||||
super(VineFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(
|
||||
VineFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos center,
|
||||
BlockPos blockPos,
|
||||
float radius
|
||||
) {
|
||||
plant = cfg.getPlantState(random, blockPos);
|
||||
|
||||
BlockState state = world.getBlockState(blockPos);
|
||||
return state.getMaterial().isReplaceable() && canPlaceBlock(state, world, blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
int h = BlocksHelper.downRay(world, blockPos, random.nextInt(maxLength)) - 1;
|
||||
public void generate(VineFeatureConfig cfg, WorldGenLevel world, RandomSource random, BlockPos blockPos) {
|
||||
int h = BlocksHelper.downRay(world, blockPos, random.nextInt(cfg.maxLength)) - 1;
|
||||
if (h > 2) {
|
||||
BlockState top = getTopState();
|
||||
BlockState middle = getMiggleState();
|
||||
BlockState middle = getMiddleState();
|
||||
BlockState bottom = getBottomState();
|
||||
BlocksHelper.setWithoutUpdate(world, blockPos, top);
|
||||
for (int i = 1; i < h; i++) {
|
||||
|
@ -51,25 +49,28 @@ public class VineFeature extends InvertedScatterFeature {
|
|||
}
|
||||
|
||||
private boolean canPlaceBlock(BlockState state, WorldGenLevel world, BlockPos blockPos) {
|
||||
if (vine) {
|
||||
return ((BaseVineBlock) vineBlock).canGenerate(state, world, blockPos);
|
||||
if (plant == null) return false;
|
||||
if (plant.getBlock() instanceof BaseVineBlock vineBlock) {
|
||||
vine = true;
|
||||
return vineBlock.canGenerate(state, world, blockPos);
|
||||
} else {
|
||||
return vineBlock.canSurvive(state, world, blockPos);
|
||||
vine = false;
|
||||
return plant.getBlock().canSurvive(state, world, blockPos);
|
||||
}
|
||||
}
|
||||
|
||||
private BlockState getTopState() {
|
||||
BlockState state = vineBlock.defaultBlockState();
|
||||
BlockState state = plant;
|
||||
return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.TOP) : state;
|
||||
}
|
||||
|
||||
private BlockState getMiggleState() {
|
||||
BlockState state = vineBlock.defaultBlockState();
|
||||
private BlockState getMiddleState() {
|
||||
BlockState state = plant;
|
||||
return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.MIDDLE) : state;
|
||||
}
|
||||
|
||||
private BlockState getBottomState() {
|
||||
BlockState state = vineBlock.defaultBlockState();
|
||||
BlockState state = plant;
|
||||
return vine ? state.setValue(BlockProperties.TRIPLE_SHAPE, TripleShape.BOTTOM) : state;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.SimpleStateProvider;
|
||||
|
||||
public class VineFeatureConfig extends ScatterFeatureConfig {
|
||||
public static final Codec<VineFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockStateProvider.CODEC.fieldOf("state").forGetter(o -> o.plant),
|
||||
Codec.INT.fieldOf("radius").forGetter(o -> o.radius),
|
||||
Codec.INT.fieldOf("max_length").forGetter(o -> o.maxLength)
|
||||
)
|
||||
.apply(
|
||||
instance,
|
||||
VineFeatureConfig::new
|
||||
));
|
||||
|
||||
|
||||
public final BlockStateProvider plant;
|
||||
public final int maxLength;
|
||||
|
||||
public VineFeatureConfig(Block vineBlock, int maxLength) {
|
||||
this(SimpleStateProvider.simple(vineBlock), 6, maxLength);
|
||||
}
|
||||
|
||||
public VineFeatureConfig(BlockStateProvider plant, int radius, int maxLength) {
|
||||
super(radius);
|
||||
this.plant = plant;
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
public BlockState getPlantState(RandomSource rnd, BlockPos pos) {
|
||||
return plant.getState(rnd, pos);
|
||||
}
|
||||
|
||||
}
|
|
@ -12,34 +12,47 @@ import net.minecraft.world.level.block.Block;
|
|||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
|
||||
public class WallPlantFeature extends WallScatterFeature {
|
||||
private final Block block;
|
||||
public class WallPlantFeature extends WallScatterFeature<WallPlantFeatureConfig> {
|
||||
protected BlockState plant;
|
||||
|
||||
public WallPlantFeature(Block block, int radius) {
|
||||
super(radius);
|
||||
this.block = block;
|
||||
public WallPlantFeature() {
|
||||
super(WallPlantFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) {
|
||||
public boolean canGenerate(
|
||||
WallPlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos pos,
|
||||
Direction dir
|
||||
) {
|
||||
plant = cfg.getPlantState(random, pos);
|
||||
Block block = plant.getBlock();
|
||||
if (block instanceof BaseWallPlantBlock) {
|
||||
BlockState state = block.defaultBlockState().setValue(BaseWallPlantBlock.FACING, dir);
|
||||
BlockState state = plant.setValue(BaseWallPlantBlock.FACING, dir);
|
||||
return block.canSurvive(state, world, pos);
|
||||
} else if (block instanceof BaseAttachedBlock) {
|
||||
BlockState state = block.defaultBlockState().setValue(BlockStateProperties.FACING, dir);
|
||||
BlockState state = plant.setValue(BlockStateProperties.FACING, dir);
|
||||
return block.canSurvive(state, world, pos);
|
||||
}
|
||||
return block.canSurvive(block.defaultBlockState(), world, pos);
|
||||
return block.canSurvive(plant, world, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) {
|
||||
BlockState state = block.defaultBlockState();
|
||||
public void generate(
|
||||
WallPlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos pos,
|
||||
Direction dir
|
||||
) {
|
||||
Block block = plant.getBlock();
|
||||
if (block instanceof BaseWallPlantBlock) {
|
||||
state = state.setValue(BaseWallPlantBlock.FACING, dir);
|
||||
plant = plant.setValue(BaseWallPlantBlock.FACING, dir);
|
||||
} else if (block instanceof BaseAttachedBlock) {
|
||||
state = state.setValue(BlockStateProperties.FACING, dir);
|
||||
plant = plant.setValue(BlockStateProperties.FACING, dir);
|
||||
}
|
||||
BlocksHelper.setWithoutUpdate(world, pos, state);
|
||||
BlocksHelper.setWithoutUpdate(world, pos, plant);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.SimpleStateProvider;
|
||||
|
||||
public class WallPlantFeatureConfig extends ScatterFeatureConfig {
|
||||
public static final Codec<WallPlantFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockStateProvider.CODEC.fieldOf("state").forGetter(o -> o.plant),
|
||||
Codec.INT.fieldOf("radius").forGetter(o -> o.radius)
|
||||
)
|
||||
.apply(
|
||||
instance,
|
||||
WallPlantFeatureConfig::new
|
||||
));
|
||||
|
||||
|
||||
public final BlockStateProvider plant;
|
||||
|
||||
public WallPlantFeatureConfig(Block plant, int radius) {
|
||||
this(SimpleStateProvider.simple(plant), radius);
|
||||
}
|
||||
|
||||
public WallPlantFeatureConfig(BlockStateProvider plant, int radius) {
|
||||
super(radius);
|
||||
this.plant = plant;
|
||||
}
|
||||
|
||||
public BlockState getPlantState(RandomSource rnd, BlockPos pos) {
|
||||
return plant.getState(rnd, pos);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,16 +5,18 @@ import net.minecraft.core.Direction;
|
|||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class WallPlantOnLogFeature extends WallPlantFeature {
|
||||
public WallPlantOnLogFeature(Block block, int radius) {
|
||||
super(block, radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir) {
|
||||
public boolean canGenerate(
|
||||
WallPlantFeatureConfig cfg,
|
||||
WorldGenLevel world,
|
||||
RandomSource random,
|
||||
BlockPos pos,
|
||||
Direction dir
|
||||
) {
|
||||
plant = cfg.getPlantState(random, pos);
|
||||
BlockPos blockPos = pos.relative(dir.getOpposite());
|
||||
BlockState blockState = world.getBlockState(blockPos);
|
||||
return blockState.is(BlockTags.LOGS);
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
package org.betterx.betterend.world.features;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
||||
public abstract class WallScatterFeature extends DefaultFeature {
|
||||
public abstract class WallScatterFeature<FC extends ScatterFeatureConfig> extends Feature<FC> {
|
||||
private static final Direction[] DIR = BlocksHelper.makeHorizontal();
|
||||
private final int radius;
|
||||
|
||||
public WallScatterFeature(int radius) {
|
||||
this.radius = radius;
|
||||
public WallScatterFeature(Codec<FC> codec) {
|
||||
super(codec);
|
||||
}
|
||||
|
||||
public abstract boolean canGenerate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir);
|
||||
public abstract boolean canGenerate(FC cfg, WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir);
|
||||
|
||||
public abstract void generate(WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir);
|
||||
public abstract void generate(FC cfg, WorldGenLevel world, RandomSource random, BlockPos pos, Direction dir);
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featureConfig) {
|
||||
public boolean place(FeaturePlaceContext<FC> featureConfig) {
|
||||
FC cfg = featureConfig.config();
|
||||
final RandomSource random = featureConfig.random();
|
||||
final BlockPos center = featureConfig.origin();
|
||||
final WorldGenLevel world = featureConfig.level();
|
||||
|
@ -38,17 +38,17 @@ public abstract class WallScatterFeature extends DefaultFeature {
|
|||
int py = MHelper.randRange(minY, maxY, random);
|
||||
|
||||
MutableBlockPos mut = new MutableBlockPos();
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
for (int x = -cfg.radius; x <= cfg.radius; x++) {
|
||||
mut.setX(center.getX() + x);
|
||||
for (int y = -radius; y <= radius; y++) {
|
||||
for (int y = -cfg.radius; y <= cfg.radius; y++) {
|
||||
mut.setY(py + y);
|
||||
for (int z = -radius; z <= radius; z++) {
|
||||
for (int z = -cfg.radius; z <= cfg.radius; z++) {
|
||||
mut.setZ(center.getZ() + z);
|
||||
if (random.nextInt(4) == 0 && world.isEmptyBlock(mut)) {
|
||||
shuffle(random);
|
||||
for (Direction dir : DIR) {
|
||||
if (canGenerate(world, random, mut, dir)) {
|
||||
generate(world, random, mut, dir);
|
||||
if (canGenerate(cfg, world, random, mut, dir)) {
|
||||
generate(cfg, world, random, mut, dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,32 +14,25 @@ import net.minecraft.util.RandomSource;
|
|||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ArchFeature extends DefaultFeature {
|
||||
private final Function<BlockPos, BlockState> surfaceFunction;
|
||||
private final Block block;
|
||||
|
||||
public ArchFeature(Block block, Function<BlockPos, BlockState> surfaceFunction) {
|
||||
this.surfaceFunction = surfaceFunction;
|
||||
this.block = block;
|
||||
public class ArchFeature extends Feature<ArchFeatureConfig> {
|
||||
public ArchFeature() {
|
||||
super(ArchFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featurePlaceContext) {
|
||||
public boolean place(FeaturePlaceContext<ArchFeatureConfig> featurePlaceContext) {
|
||||
ArchFeatureConfig cfg = featurePlaceContext.config();
|
||||
final WorldGenLevel world = featurePlaceContext.level();
|
||||
BlockPos origin = featurePlaceContext.origin();
|
||||
RandomSource random = featurePlaceContext.random();
|
||||
|
||||
BlockPos pos = getPosOnSurfaceWG(
|
||||
BlockState cfgBlockState = cfg.block.getState(random, origin);
|
||||
Block cfgBlock = cfgBlockState.getBlock();
|
||||
BlockPos pos = DefaultFeature.getPosOnSurfaceWG(
|
||||
world,
|
||||
new BlockPos((origin.getX() & 0xFFFFFFF0) | 7, 0, (origin.getZ() & 0xFFFFFFF0) | 7)
|
||||
);
|
||||
|
@ -52,27 +45,24 @@ public class ArchFeature extends DefaultFeature {
|
|||
if (smallRadius + bigRadius > 23) {
|
||||
smallRadius = 23 - bigRadius;
|
||||
}
|
||||
SDF arch = new SDFTorus().setBigRadius(bigRadius).setSmallRadius(smallRadius).setBlock(block);
|
||||
SDF arch = new SDFTorus().setBigRadius(bigRadius).setSmallRadius(smallRadius).setBlock(cfgBlock);
|
||||
arch = new SDFRotation().setRotation(MHelper.randomHorizontal(random), (float) Math.PI * 0.5F).setSource(arch);
|
||||
|
||||
final float smallRadiusF = smallRadius;
|
||||
OpenSimplexNoise noise = new OpenSimplexNoise(random.nextLong());
|
||||
arch = new SDFDisplacement().setFunction((vec) -> {
|
||||
return (float) (Math.abs(noise.eval(
|
||||
vec.x() * 0.1,
|
||||
vec.y() * 0.1,
|
||||
vec.z() * 0.1
|
||||
)) * 3F + Math.abs(noise.eval(
|
||||
vec.x() * 0.3,
|
||||
vec.y() * 0.3 + 100,
|
||||
vec.z() * 0.3
|
||||
)) * 1.3F) - smallRadiusF * Math.abs(1 - vec.y() / bigRadius);
|
||||
}).setSource(arch);
|
||||
arch = new SDFDisplacement().setFunction((vec) -> (float) (Math.abs(noise.eval(
|
||||
vec.x() * 0.1,
|
||||
vec.y() * 0.1,
|
||||
vec.z() * 0.1
|
||||
)) * 3F + Math.abs(noise.eval(
|
||||
vec.x() * 0.3,
|
||||
vec.y() * 0.3 + 100,
|
||||
vec.z() * 0.3
|
||||
)) * 1.3F) - smallRadiusF * Math.abs(1 - vec.y() / bigRadius)).setSource(arch);
|
||||
|
||||
List<BlockPos> surface = Lists.newArrayList();
|
||||
arch.addPostProcess((info) -> {
|
||||
if (info.getStateUp().isAir()) {
|
||||
return surfaceFunction.apply(info.getPos());
|
||||
return cfg.surfaceFunction.apply(info.getPos());
|
||||
}
|
||||
return info.getState();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package org.betterx.betterend.world.features.terrain;
|
||||
|
||||
import org.betterx.betterend.world.biome.land.UmbraValleyBiome;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.SimpleStateProvider;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ArchFeatureConfig implements FeatureConfiguration {
|
||||
public static final Codec<ArchFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockStateProvider.CODEC.fieldOf("states").forGetter(o -> o.block),
|
||||
SurfaceFunction.CODEC.fieldOf("surface_function").forGetter(o -> o.surfaceFunction)
|
||||
)
|
||||
.apply(instance, ArchFeatureConfig::new));
|
||||
|
||||
|
||||
public final BlockStateProvider block;
|
||||
public final SurfaceFunction surfaceFunction;
|
||||
|
||||
public ArchFeatureConfig(Block block, SurfaceFunction surfaceFunction) {
|
||||
this(SimpleStateProvider.simple(block), surfaceFunction);
|
||||
}
|
||||
|
||||
public ArchFeatureConfig(BlockStateProvider block, SurfaceFunction surfaceFunction) {
|
||||
this.block = block;
|
||||
this.surfaceFunction = surfaceFunction;
|
||||
}
|
||||
|
||||
public enum SurfaceFunction implements StringRepresentable {
|
||||
UMBRA_VALLEY("umbra_valley", pos -> UmbraValleyBiome.getSurface(pos.getX(), pos.getZ()).defaultBlockState());
|
||||
public static final Codec<SurfaceFunction> CODEC = StringRepresentable.fromEnum(SurfaceFunction::values);
|
||||
private final Function<BlockPos, BlockState> surfaceFunction;
|
||||
private final String name;
|
||||
|
||||
SurfaceFunction(String name, Function<BlockPos, BlockState> surfaceFunction) {
|
||||
this.name = name;
|
||||
this.surfaceFunction = surfaceFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public BlockState apply(BlockPos pos) {
|
||||
return this.surfaceFunction.apply(pos);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,59 +1,46 @@
|
|||
package org.betterx.betterend.world.features.terrain;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.sdf.SDF;
|
||||
import org.betterx.bclib.sdf.operator.SDFCoordModify;
|
||||
import org.betterx.bclib.sdf.operator.SDFScale3D;
|
||||
import org.betterx.bclib.sdf.primitive.SDFSphere;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.betterend.noise.OpenSimplexNoise;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
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.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
||||
public class OreLayerFeature extends DefaultFeature {
|
||||
public class OreLayerFeature extends Feature<OreLayerFeatureConfig> {
|
||||
private static final SDFSphere SPHERE;
|
||||
private static final SDFCoordModify NOISE;
|
||||
private static final SDF FUNCTION;
|
||||
|
||||
private final BlockState state;
|
||||
private final float radius;
|
||||
private final int minY;
|
||||
private final int maxY;
|
||||
private OpenSimplexNoise noise;
|
||||
|
||||
public OreLayerFeature(BlockState state, float radius, int minY, int maxY) {
|
||||
this.state = state;
|
||||
this.radius = radius;
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
public OreLayerFeature() {
|
||||
super(OreLayerFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featureConfig) {
|
||||
public boolean place(FeaturePlaceContext<OreLayerFeatureConfig> featureConfig) {
|
||||
final OreLayerFeatureConfig cfg = featureConfig.config();
|
||||
final RandomSource random = featureConfig.random();
|
||||
final BlockPos pos = featureConfig.origin();
|
||||
final WorldGenLevel world = featureConfig.level();
|
||||
float radius = this.radius * 0.5F;
|
||||
float radius = cfg.radius * 0.5F;
|
||||
int r = MHelper.floor(radius + 1);
|
||||
int posX = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getX();
|
||||
int posZ = MHelper.randRange(Math.max(r - 16, 0), Math.min(31 - r, 15), random) + pos.getZ();
|
||||
int posY = MHelper.randRange(minY, maxY, random);
|
||||
int posY = MHelper.randRange(cfg.minY, cfg.maxY, random);
|
||||
|
||||
if (noise == null) {
|
||||
noise = new OpenSimplexNoise(world.getSeed());
|
||||
}
|
||||
|
||||
SPHERE.setRadius(radius).setBlock(state);
|
||||
SPHERE.setRadius(radius).setBlock(cfg.state);
|
||||
NOISE.setFunction((vec) -> {
|
||||
double x = (vec.x() + pos.getX()) * 0.1;
|
||||
double z = (vec.z() + pos.getZ()) * 0.1;
|
||||
double offset = noise.eval(x, z);
|
||||
double offset = cfg.getNoise(world.getSeed()).eval(x, z);
|
||||
vec.set(vec.x(), vec.y() + (float) offset * 8, vec.z());
|
||||
});
|
||||
FUNCTION.fillRecursive(world, new BlockPos(posX, posY, posZ));
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package org.betterx.betterend.world.features.terrain;
|
||||
|
||||
import org.betterx.betterend.noise.OpenSimplexNoise;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
||||
public class OreLayerFeatureConfig implements FeatureConfiguration {
|
||||
public static final Codec<OreLayerFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockState.CODEC.fieldOf("state").forGetter(o -> o.state),
|
||||
Codec.FLOAT.fieldOf("radius").forGetter(o -> o.radius),
|
||||
Codec.INT.fieldOf("min_y").forGetter(o -> o.minY),
|
||||
Codec.INT.fieldOf("max_y").forGetter(o -> o.maxY)
|
||||
)
|
||||
.apply(instance, OreLayerFeatureConfig::new));
|
||||
|
||||
public final BlockState state;
|
||||
public final float radius;
|
||||
public final int minY;
|
||||
public final int maxY;
|
||||
private OpenSimplexNoise noise;
|
||||
|
||||
public OreLayerFeatureConfig(BlockState state, float radius, int minY, int maxY) {
|
||||
this.state = state;
|
||||
this.radius = radius;
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
}
|
||||
|
||||
public OpenSimplexNoise getNoise(long seed) {
|
||||
if (noise == null) {
|
||||
noise = new OpenSimplexNoise(seed);
|
||||
}
|
||||
return noise;
|
||||
}
|
||||
}
|
|
@ -17,25 +17,28 @@ import net.minecraft.util.Mth;
|
|||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class ThinArchFeature extends DefaultFeature {
|
||||
private final Block block;
|
||||
public class ThinArchFeature extends Feature<ThinArchFeatureConfig> {
|
||||
|
||||
public ThinArchFeature(Block block) {
|
||||
this.block = block;
|
||||
public ThinArchFeature() {
|
||||
super(ThinArchFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featurePlaceContext) {
|
||||
public boolean place(FeaturePlaceContext<ThinArchFeatureConfig> featurePlaceContext) {
|
||||
final ThinArchFeatureConfig cfg = featurePlaceContext.config();
|
||||
final WorldGenLevel world = featurePlaceContext.level();
|
||||
BlockPos origin = featurePlaceContext.origin();
|
||||
RandomSource random = featurePlaceContext.random();
|
||||
BlockState state = cfg.block.getState(random, origin);
|
||||
Block block = state.getBlock();
|
||||
|
||||
BlockPos pos = getPosOnSurfaceWG(
|
||||
BlockPos pos = DefaultFeature.getPosOnSurfaceWG(
|
||||
world,
|
||||
new BlockPos(
|
||||
(origin.getX() & 0xFFFFFFF0) | 7,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package org.betterx.betterend.world.features.terrain;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.SimpleStateProvider;
|
||||
|
||||
public class ThinArchFeatureConfig implements FeatureConfiguration {
|
||||
public static final Codec<ThinArchFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(
|
||||
BlockStateProvider.CODEC.fieldOf("states").forGetter(o -> o.block)
|
||||
)
|
||||
.apply(instance, ThinArchFeatureConfig::new));
|
||||
|
||||
|
||||
public final BlockStateProvider block;
|
||||
|
||||
public ThinArchFeatureConfig(Block block) {
|
||||
this(SimpleStateProvider.simple(block));
|
||||
}
|
||||
|
||||
public ThinArchFeatureConfig(BlockStateProvider block) {
|
||||
this.block = block;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package org.betterx.betterend.world.features.terrain.caves;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.betterend.util.BlockFixer;
|
||||
import org.betterx.betterend.world.biome.cave.EndCaveBiome;
|
||||
|
@ -15,23 +14,21 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class CaveChunkPopulatorFeature extends DefaultFeature {
|
||||
private final Supplier<EndCaveBiome> supplier;
|
||||
public class CaveChunkPopulatorFeature extends Feature<CaveChunkPopulatorFeatureConfig> {
|
||||
|
||||
public CaveChunkPopulatorFeature(Supplier<EndCaveBiome> biome) {
|
||||
this.supplier = biome;
|
||||
public CaveChunkPopulatorFeature() {
|
||||
super(CaveChunkPopulatorFeatureConfig.CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean place(FeaturePlaceContext<NoneFeatureConfiguration> featureConfig) {
|
||||
public boolean place(FeaturePlaceContext<CaveChunkPopulatorFeatureConfig> featureConfig) {
|
||||
CaveChunkPopulatorFeatureConfig cfg = featureConfig.config();
|
||||
final RandomSource random = featureConfig.random();
|
||||
final BlockPos pos = featureConfig.origin();
|
||||
final WorldGenLevel world = featureConfig.level();
|
||||
|
@ -42,7 +39,7 @@ public class CaveChunkPopulatorFeature extends DefaultFeature {
|
|||
MutableBlockPos min = new MutableBlockPos().set(pos);
|
||||
MutableBlockPos max = new MutableBlockPos().set(pos);
|
||||
fillSets(sx, sz, world.getChunk(pos), floorPositions, ceilPositions, min, max);
|
||||
EndCaveBiome biome = supplier.get();
|
||||
EndCaveBiome biome = cfg.getCaveBiome();
|
||||
BlockState surfaceBlock = Blocks.END_STONE.defaultBlockState(); //biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
|
||||
placeFloor(world, biome, floorPositions, random, surfaceBlock);
|
||||
placeCeil(world, biome, ceilPositions, random);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package org.betterx.betterend.world.features.terrain.caves;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
import org.betterx.betterend.world.biome.cave.EndCaveBiome;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
||||
public record CaveChunkPopulatorFeatureConfig(ResourceLocation biomeID) implements FeatureConfiguration {
|
||||
public static final Codec<CaveChunkPopulatorFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
|
||||
.group(ResourceLocation.CODEC.fieldOf("biome").forGetter(o -> o.biomeID))
|
||||
.apply(instance, CaveChunkPopulatorFeatureConfig::new));
|
||||
|
||||
public EndCaveBiome getCaveBiome() {
|
||||
return (EndCaveBiome) BiomeAPI.getBiome(biomeID);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue