Register world features properlyTM
- Refactored Create's config-driven worldgen to better work with the feature infrastructure of 1.16. Adresses #539
This commit is contained in:
parent
01a83722cf
commit
dc13ea6485
10 changed files with 370 additions and 260 deletions
|
@ -84,6 +84,7 @@ public class Create {
|
|||
AllEntityTypes.register();
|
||||
AllTileEntities.register();
|
||||
AllMovementBehaviours.register();
|
||||
AllWorldFeatures.register();
|
||||
|
||||
modEventBus.addListener(Create::init);
|
||||
MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGH, Create::onBiomeLoad);
|
||||
|
@ -118,6 +119,7 @@ public class Create {
|
|||
|
||||
event.enqueueWork(() -> {
|
||||
SchematicProcessor.register();
|
||||
AllWorldFeatures.registerFeatures();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,90 +1,93 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import static net.minecraft.world.biome.Biome.Category.DESERT;
|
||||
import static net.minecraft.world.biome.Biome.Category.OCEAN;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.Create;
|
||||
import com.simibubi.create.content.palettes.AllPaletteBlocks;
|
||||
import com.simibubi.create.foundation.utility.Lang;
|
||||
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.WorldGenRegistries;
|
||||
import net.minecraft.world.biome.Biome.Category;
|
||||
import net.minecraft.world.biome.Biomes;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.GenerationStage;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.event.world.BiomeLoadingEvent;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
public enum AllWorldFeatures {
|
||||
public class AllWorldFeatures {
|
||||
|
||||
COPPER_ORE(new CountedOreFeature(AllBlocks.COPPER_ORE, 18, 2).between(40, 86)),
|
||||
COPPER_ORE_OCEAN(new CountedOreFeature(AllBlocks.COPPER_ORE, 15, 4).between(20, 55).inBiomes(OCEAN)),
|
||||
static Map<String, ConfigDrivenFeatureEntry> entries = new HashMap<>();
|
||||
|
||||
ZINC_ORE(new CountedOreFeature(AllBlocks.ZINC_ORE, 14, 4).between(15, 70)),
|
||||
ZINC_ORE_DESERT(new CountedOreFeature(AllBlocks.ZINC_ORE, 17, 5).between(10, 85).inBiomes(DESERT)),
|
||||
static final ConfigDrivenFeatureEntry
|
||||
|
||||
LIMESTONE(new ChanceOreFeature(AllPaletteBlocks.LIMESTONE, 128, 1 / 32f).between(30, 70)),
|
||||
WEATHERED_LIMESTONE(new ChanceOreFeature(AllPaletteBlocks.WEATHERED_LIMESTONE, 128, 1 / 32f).between(10, 30)),
|
||||
DOLOMITE(new ChanceOreFeature(AllPaletteBlocks.DOLOMITE, 128, 1 / 64f).between(20, 70)),
|
||||
GABBRO(new ChanceOreFeature(AllPaletteBlocks.GABBRO, 128, 1 / 64f).between(20, 70)),
|
||||
SCORIA(new ChanceOreFeature(AllPaletteBlocks.NATURAL_SCORIA, 128, 1 / 32f).between(0, 10)),
|
||||
COPPER = register("copper_ore", AllBlocks.COPPER_ORE, 18, 2).between(40, 85),
|
||||
|
||||
ZINC = register("zinc_ore", AllBlocks.ZINC_ORE, 14, 4).between(15, 70),
|
||||
|
||||
LIMESTONE = register("limestone", AllPaletteBlocks.LIMESTONE, 128, 1 / 64f).between(30, 70),
|
||||
|
||||
WEATHERED_LIMESTONE =
|
||||
register("weathered_limestone", AllPaletteBlocks.WEATHERED_LIMESTONE, 128, 1 / 64f).between(10, 30),
|
||||
|
||||
DOLOMITE = register("dolomite", AllPaletteBlocks.DOLOMITE, 128, 1 / 64f).between(20, 70),
|
||||
|
||||
GABBRO = register("gabbro", AllPaletteBlocks.GABBRO, 128, 1 / 64f).between(20, 70),
|
||||
|
||||
SCORIA = register("scoria", AllPaletteBlocks.NATURAL_SCORIA, 128, 1 / 32f).between(0, 10)
|
||||
|
||||
;
|
||||
|
||||
private static ConfigDrivenFeatureEntry register(String id, NonNullSupplier<? extends Block> block, int clusterSize,
|
||||
float frequency) {
|
||||
ConfigDrivenFeatureEntry configDrivenFeatureEntry =
|
||||
new ConfigDrivenFeatureEntry(id, block, clusterSize, frequency);
|
||||
entries.put(id, configDrivenFeatureEntry);
|
||||
return configDrivenFeatureEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment this number if all worldgen entries should be overwritten in this
|
||||
* update. Worlds from the previous version will overwrite potentially changed
|
||||
* values with the new defaults.
|
||||
*/
|
||||
public static final int forcedUpdateVersion = 1;
|
||||
public static final int forcedUpdateVersion = 2;
|
||||
|
||||
public IFeature feature;
|
||||
|
||||
AllWorldFeatures(IFeature feature) {
|
||||
this.feature = feature;
|
||||
this.feature.setId(Lang.asId(name()));
|
||||
public static void registerFeatures() {
|
||||
ForgeRegistries.FEATURES.register(ConfigDrivenOreFeature.INSTANCE);
|
||||
ForgeRegistries.DECORATORS.register(ConfigDrivenDecorator.INSTANCE);
|
||||
entries.entrySet()
|
||||
.forEach((entry) -> {
|
||||
Registry.register(WorldGenRegistries.CONFIGURED_FEATURE, Create.ID + "_" + entry.getKey(),
|
||||
entry.getValue()
|
||||
.getFeature());
|
||||
});
|
||||
}
|
||||
|
||||
public static void reload(BiomeLoadingEvent event) {
|
||||
for (AllWorldFeatures entry : AllWorldFeatures.values()) {
|
||||
entries.values()
|
||||
.forEach(entry -> {
|
||||
if (event.getName() == Biomes.THE_VOID.getRegistryName())
|
||||
continue;
|
||||
return;
|
||||
if (event.getCategory() == Category.NETHER)
|
||||
continue;
|
||||
|
||||
Optional<ConfiguredFeature<?, ?>> createFeature = entry.feature.createFeature(event);
|
||||
if (!createFeature.isPresent())
|
||||
continue;
|
||||
|
||||
event.getGeneration().feature(entry.feature.getGenerationStage(), createFeature.get());
|
||||
}
|
||||
|
||||
// // Debug contained ore features
|
||||
// for (Biome biome : ForgeRegistries.BIOMES) {
|
||||
// Debug.markTemporary();
|
||||
// System.out.println(biome.getRegistryName().getPath() + " has the following features:");
|
||||
// for (ConfiguredFeature<?> configuredFeature : biome.getFeatures(Decoration.UNDERGROUND_ORES)) {
|
||||
// IFeatureConfig config = configuredFeature.config;
|
||||
// if (!(config instanceof DecoratedFeatureConfig))
|
||||
// continue;
|
||||
// DecoratedFeatureConfig decoConf = (DecoratedFeatureConfig) config;
|
||||
// if (!(decoConf.feature.config instanceof OreFeatureConfig))
|
||||
// continue;
|
||||
// OreFeatureConfig oreConf = (OreFeatureConfig) decoConf.feature.config;
|
||||
// System.out.println(configuredFeature.feature.getRegistryName().getPath());
|
||||
// System.out.println(oreConf.state.getBlock().getRegistryName().getPath());
|
||||
// System.out.println("--");
|
||||
// }
|
||||
// }
|
||||
return;
|
||||
event.getGeneration()
|
||||
.feature(GenerationStage.Decoration.UNDERGROUND_ORES, entry.getFeature());
|
||||
});
|
||||
}
|
||||
|
||||
public static void fillConfig(ForgeConfigSpec.Builder builder) {
|
||||
Arrays.stream(values()).forEach(entry -> {
|
||||
builder.push(Lang.asId(entry.name()));
|
||||
entry.feature.addToConfig(builder);
|
||||
entries.values()
|
||||
.forEach(entry -> {
|
||||
builder.push(entry.id);
|
||||
entry.addToConfig(builder);
|
||||
builder.pop();
|
||||
});
|
||||
}
|
||||
|
||||
public static void register() {}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.gen.placement.ChanceConfig;
|
||||
import net.minecraft.world.gen.placement.Placement;
|
||||
|
||||
public class ChanceOreFeature extends OreFeature<ChanceConfig> {
|
||||
|
||||
private ConfigFloat clusterChance;
|
||||
|
||||
public ChanceOreFeature(NonNullSupplier<? extends Block> block, int clusterSize, float clusterChance) {
|
||||
super(block, clusterSize);
|
||||
this.clusterChance = f(clusterChance, 0, 1, "clusterChance");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canGenerate() {
|
||||
return super.canGenerate() && clusterChance.get() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<Placement<ChanceConfig>, ChanceConfig> getPlacement() {
|
||||
return Pair.of(Placement.CHANCE,
|
||||
// TODO 1.16 worldgen verify this
|
||||
new ChanceConfig((int) (1 / clusterChance.getF())));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.gen.placement.SimplePlacement;
|
||||
|
||||
public class ConfigDrivenDecorator extends SimplePlacement<ConfigDrivenOreFeatureConfig> {
|
||||
|
||||
public static final ConfigDrivenDecorator INSTANCE = new ConfigDrivenDecorator();
|
||||
|
||||
public ConfigDrivenDecorator() {
|
||||
super(ConfigDrivenOreFeatureConfig.CODEC);
|
||||
setRegistryName("create_config_driven_decorator");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<BlockPos> getPositions(Random r, ConfigDrivenOreFeatureConfig config, BlockPos pos) {
|
||||
float frequency = config.getFrequency();
|
||||
|
||||
int floored = MathHelper.floor(frequency);
|
||||
int count = floored + (r.nextFloat() < frequency - floored ? 1 : 0);
|
||||
if (count == 0)
|
||||
return Stream.empty();
|
||||
|
||||
int maxY = config.getMaxY();
|
||||
int minY = config.getMinY();
|
||||
|
||||
return IntStream.range(0, count)
|
||||
.mapToObj($ -> pos)
|
||||
.map(p -> {
|
||||
int i = p.getX();
|
||||
int j = p.getZ();
|
||||
int k = r.nextInt(maxY - minY) + minY;
|
||||
return new BlockPos(i, k, j);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.feature.OreFeatureConfig.FillerBlockType;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
public class ConfigDrivenFeatureEntry extends ConfigBase {
|
||||
|
||||
public final String id;
|
||||
public final NonNullSupplier<? extends Block> block;
|
||||
|
||||
protected ConfigInt clusterSize;
|
||||
protected ConfigInt minHeight;
|
||||
protected ConfigInt maxHeight;
|
||||
protected ConfigFloat frequency;
|
||||
|
||||
Optional<ConfiguredFeature<?, ?>> feature = Optional.empty();
|
||||
|
||||
public ConfigDrivenFeatureEntry(String id, NonNullSupplier<? extends Block> block, int clusterSize,
|
||||
float frequency) {
|
||||
this.id = id;
|
||||
this.block = block;
|
||||
this.clusterSize = i(clusterSize, 0, "clusterSize");
|
||||
this.minHeight = i(0, 0, "minHeight");
|
||||
this.maxHeight = i(256, 0, "maxHeight");
|
||||
this.frequency = f(frequency, 0, 512, "frequency", "Amount of clusters generated per Chunk.",
|
||||
" >1 to spawn multiple.", " <1 to make it a chance.", " 0 to disable.");
|
||||
}
|
||||
|
||||
public ConfigDrivenFeatureEntry between(int minHeight, int maxHeight) {
|
||||
allValues.remove(this.minHeight);
|
||||
allValues.remove(this.maxHeight);
|
||||
this.minHeight = i(minHeight, 0, "minHeight");
|
||||
this.maxHeight = i(maxHeight, 0, "maxHeight");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ConfiguredFeature<?, ?> getFeature() {
|
||||
if (!feature.isPresent())
|
||||
feature = Optional.of(createFeature());
|
||||
return feature.get();
|
||||
}
|
||||
|
||||
private ConfiguredFeature<?, ?> createFeature() {
|
||||
ConfigDrivenOreFeatureConfig config =
|
||||
new ConfigDrivenOreFeatureConfig(FillerBlockType.BASE_STONE_OVERWORLD, block.get()
|
||||
.getDefaultState(), id);
|
||||
|
||||
return ConfigDrivenOreFeature.INSTANCE.configure(config)
|
||||
.decorate(ConfigDrivenDecorator.INSTANCE.configure(config));
|
||||
}
|
||||
|
||||
public void addToConfig(ForgeConfigSpec.Builder builder) {
|
||||
registerAll(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.ISeedReader;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.feature.Feature;
|
||||
|
||||
public class ConfigDrivenOreFeature extends Feature<ConfigDrivenOreFeatureConfig> {
|
||||
|
||||
public static final ConfigDrivenOreFeature INSTANCE = new ConfigDrivenOreFeature();
|
||||
|
||||
public ConfigDrivenOreFeature() {
|
||||
super(ConfigDrivenOreFeatureConfig.CODEC);
|
||||
setRegistryName("create_config_driven_ore");
|
||||
}
|
||||
|
||||
// From OreFeature, slight adjustments
|
||||
|
||||
public boolean generate(ISeedReader p_241855_1_, ChunkGenerator p_241855_2_, Random p_241855_3_,
|
||||
BlockPos p_241855_4_, ConfigDrivenOreFeatureConfig p_241855_5_) {
|
||||
float f = p_241855_3_.nextFloat() * (float) Math.PI;
|
||||
float size = p_241855_5_.getSize();
|
||||
float f1 = size / 8.0F;
|
||||
int i = MathHelper.ceil((size / 16.0F * 2.0F + 1.0F) / 2.0F);
|
||||
double d0 = (double) p_241855_4_.getX() + Math.sin((double) f) * (double) f1;
|
||||
double d1 = (double) p_241855_4_.getX() - Math.sin((double) f) * (double) f1;
|
||||
double d2 = (double) p_241855_4_.getZ() + Math.cos((double) f) * (double) f1;
|
||||
double d3 = (double) p_241855_4_.getZ() - Math.cos((double) f) * (double) f1;
|
||||
double d4 = (double) (p_241855_4_.getY() + p_241855_3_.nextInt(3) - 2);
|
||||
double d5 = (double) (p_241855_4_.getY() + p_241855_3_.nextInt(3) - 2);
|
||||
int k = p_241855_4_.getX() - MathHelper.ceil(f1) - i;
|
||||
int l = p_241855_4_.getY() - 2 - i;
|
||||
int i1 = p_241855_4_.getZ() - MathHelper.ceil(f1) - i;
|
||||
int j1 = 2 * (MathHelper.ceil(f1) + i);
|
||||
int k1 = 2 * (2 + i);
|
||||
|
||||
for (int l1 = k; l1 <= k + j1; ++l1) {
|
||||
for (int i2 = i1; i2 <= i1 + j1; ++i2) {
|
||||
if (l <= p_241855_1_.getHeight(Heightmap.Type.OCEAN_FLOOR_WG, l1, i2)) {
|
||||
return this.func_207803_a(p_241855_1_, p_241855_3_, p_241855_5_, d0, d1, d2, d3, d4, d5, k, l, i1,
|
||||
j1, k1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean func_207803_a(IWorld p_207803_1_, Random p_207803_2_, ConfigDrivenOreFeatureConfig p_207803_3_,
|
||||
double p_207803_4_, double p_207803_6_, double p_207803_8_, double p_207803_10_, double p_207803_12_,
|
||||
double p_207803_14_, int p_207803_16_, int p_207803_17_, int p_207803_18_, int p_207803_19_, int p_207803_20_) {
|
||||
int i = 0;
|
||||
BitSet bitset = new BitSet(p_207803_19_ * p_207803_20_ * p_207803_19_);
|
||||
BlockPos.Mutable blockpos$mutable = new BlockPos.Mutable();
|
||||
int j = p_207803_3_.getSize();
|
||||
double[] adouble = new double[j * 4];
|
||||
|
||||
for (int k = 0; k < j; ++k) {
|
||||
float f = (float) k / (float) j;
|
||||
double d0 = MathHelper.lerp((double) f, p_207803_4_, p_207803_6_);
|
||||
double d2 = MathHelper.lerp((double) f, p_207803_12_, p_207803_14_);
|
||||
double d4 = MathHelper.lerp((double) f, p_207803_8_, p_207803_10_);
|
||||
double d6 = p_207803_2_.nextDouble() * (double) j / 16.0D;
|
||||
double d7 = ((double) (MathHelper.sin((float) Math.PI * f) + 1.0F) * d6 + 1.0D) / 2.0D;
|
||||
adouble[k * 4 + 0] = d0;
|
||||
adouble[k * 4 + 1] = d2;
|
||||
adouble[k * 4 + 2] = d4;
|
||||
adouble[k * 4 + 3] = d7;
|
||||
}
|
||||
|
||||
for (int i3 = 0; i3 < j - 1; ++i3) {
|
||||
if (!(adouble[i3 * 4 + 3] <= 0.0D)) {
|
||||
for (int k3 = i3 + 1; k3 < j; ++k3) {
|
||||
if (!(adouble[k3 * 4 + 3] <= 0.0D)) {
|
||||
double d12 = adouble[i3 * 4 + 0] - adouble[k3 * 4 + 0];
|
||||
double d13 = adouble[i3 * 4 + 1] - adouble[k3 * 4 + 1];
|
||||
double d14 = adouble[i3 * 4 + 2] - adouble[k3 * 4 + 2];
|
||||
double d15 = adouble[i3 * 4 + 3] - adouble[k3 * 4 + 3];
|
||||
if (d15 * d15 > d12 * d12 + d13 * d13 + d14 * d14) {
|
||||
if (d15 > 0.0D) {
|
||||
adouble[k3 * 4 + 3] = -1.0D;
|
||||
} else {
|
||||
adouble[i3 * 4 + 3] = -1.0D;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j3 = 0; j3 < j; ++j3) {
|
||||
double d11 = adouble[j3 * 4 + 3];
|
||||
if (!(d11 < 0.0D)) {
|
||||
double d1 = adouble[j3 * 4 + 0];
|
||||
double d3 = adouble[j3 * 4 + 1];
|
||||
double d5 = adouble[j3 * 4 + 2];
|
||||
int l = Math.max(MathHelper.floor(d1 - d11), p_207803_16_);
|
||||
int l3 = Math.max(MathHelper.floor(d3 - d11), p_207803_17_);
|
||||
int i1 = Math.max(MathHelper.floor(d5 - d11), p_207803_18_);
|
||||
int j1 = Math.max(MathHelper.floor(d1 + d11), l);
|
||||
int k1 = Math.max(MathHelper.floor(d3 + d11), l3);
|
||||
int l1 = Math.max(MathHelper.floor(d5 + d11), i1);
|
||||
|
||||
for (int i2 = l; i2 <= j1; ++i2) {
|
||||
double d8 = ((double) i2 + 0.5D - d1) / d11;
|
||||
if (d8 * d8 < 1.0D) {
|
||||
for (int j2 = l3; j2 <= k1; ++j2) {
|
||||
double d9 = ((double) j2 + 0.5D - d3) / d11;
|
||||
if (d8 * d8 + d9 * d9 < 1.0D) {
|
||||
for (int k2 = i1; k2 <= l1; ++k2) {
|
||||
double d10 = ((double) k2 + 0.5D - d5) / d11;
|
||||
if (d8 * d8 + d9 * d9 + d10 * d10 < 1.0D) {
|
||||
int l2 = i2 - p_207803_16_ + (j2 - p_207803_17_) * p_207803_19_
|
||||
+ (k2 - p_207803_18_) * p_207803_19_ * p_207803_20_;
|
||||
if (!bitset.get(l2)) {
|
||||
bitset.set(l2);
|
||||
blockpos$mutable.setPos(i2, j2, k2);
|
||||
if (p_207803_3_.target.test(p_207803_1_.getBlockState(blockpos$mutable),
|
||||
p_207803_2_)) {
|
||||
p_207803_1_.setBlockState(blockpos$mutable, p_207803_3_.state, 2);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i > 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.world.gen.feature.IFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.template.RuleTest;
|
||||
import net.minecraft.world.gen.placement.IPlacementConfig;
|
||||
|
||||
public class ConfigDrivenOreFeatureConfig implements IFeatureConfig, IPlacementConfig {
|
||||
|
||||
public static final Codec<ConfigDrivenOreFeatureConfig> CODEC = RecordCodecBuilder.create((p_236568_0_) -> {
|
||||
return p_236568_0_.group(RuleTest.field_25012.fieldOf("target")
|
||||
.forGetter((p_236570_0_) -> {
|
||||
return p_236570_0_.target;
|
||||
}), BlockState.CODEC.fieldOf("state")
|
||||
.forGetter((p_236569_0_) -> {
|
||||
return p_236569_0_.state;
|
||||
}),
|
||||
Codec.STRING.fieldOf("key")
|
||||
.forGetter(t -> t.key))
|
||||
.apply(p_236568_0_, ConfigDrivenOreFeatureConfig::new);
|
||||
});
|
||||
|
||||
public final RuleTest target;
|
||||
public final BlockState state;
|
||||
public final String key;
|
||||
|
||||
public ConfigDrivenOreFeatureConfig(RuleTest target, BlockState state, String key) {
|
||||
this.target = target;
|
||||
this.state = state;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return entry().clusterSize.get();
|
||||
}
|
||||
|
||||
public int getMinY() {
|
||||
return entry().minHeight.get();
|
||||
}
|
||||
|
||||
public int getMaxY() {
|
||||
return entry().maxHeight.get();
|
||||
}
|
||||
|
||||
public float getFrequency() {
|
||||
return entry().frequency.getF();
|
||||
}
|
||||
|
||||
protected ConfigDrivenFeatureEntry entry() {
|
||||
return AllWorldFeatures.entries.get(key);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.placement.IPlacementConfig;
|
||||
import net.minecraft.world.gen.placement.NoPlacementConfig;
|
||||
import net.minecraft.world.gen.placement.Placement;
|
||||
import net.minecraftforge.event.world.BiomeLoadingEvent;
|
||||
|
||||
public class CountedOreFeature extends OreFeature<NoPlacementConfig> {
|
||||
|
||||
private ConfigInt clusterCount;
|
||||
|
||||
public CountedOreFeature(NonNullSupplier<? extends Block> block, int clusterSize, int clusterCount) {
|
||||
super(block, clusterSize);
|
||||
this.clusterCount = i(clusterCount, 0, "clusterCount");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canGenerate() {
|
||||
return super.canGenerate() && clusterCount.get() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<Placement<NoPlacementConfig>, NoPlacementConfig> getPlacement() {
|
||||
return Pair.of(Placement.NOPE, IPlacementConfig.NO_PLACEMENT_CONFIG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ConfiguredFeature<?, ?>> createFeature(BiomeLoadingEvent biome) {
|
||||
return super.createFeature(biome)
|
||||
// TODO 1.16 worldgen verify this
|
||||
.map(cf -> cf.repeat(clusterCount.get()));
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.world.gen.GenerationStage.Decoration;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.event.world.BiomeLoadingEvent;
|
||||
|
||||
public interface IFeature {
|
||||
|
||||
public void setId(String id);
|
||||
|
||||
public void addToConfig(ForgeConfigSpec.Builder builder);
|
||||
|
||||
public Optional<ConfiguredFeature<?, ?>> createFeature(BiomeLoadingEvent biome);
|
||||
|
||||
public Decoration getGenerationStage();
|
||||
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package com.simibubi.create.foundation.worldgen;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
import com.simibubi.create.foundation.config.ConfigBase;
|
||||
import com.tterrag.registrate.util.nullness.NonNullSupplier;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.GenerationStage;
|
||||
import net.minecraft.world.gen.GenerationStage.Decoration;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.feature.Feature;
|
||||
import net.minecraft.world.gen.feature.OreFeatureConfig;
|
||||
import net.minecraft.world.gen.placement.IPlacementConfig;
|
||||
import net.minecraft.world.gen.placement.Placement;
|
||||
import net.minecraft.world.gen.placement.TopSolidRangeConfig;
|
||||
import net.minecraftforge.common.ForgeConfigSpec.Builder;
|
||||
import net.minecraftforge.event.world.BiomeLoadingEvent;
|
||||
|
||||
public abstract class OreFeature<T extends IPlacementConfig> extends ConfigBase implements IFeature {
|
||||
|
||||
public String id;
|
||||
|
||||
protected ConfigBool enable;
|
||||
protected ConfigInt clusterSize;
|
||||
protected ConfigInt minHeight;
|
||||
protected ConfigInt maxHeight;
|
||||
|
||||
private NonNullSupplier<? extends Block> block;
|
||||
private Biome.Category specificCategory;
|
||||
|
||||
public OreFeature(NonNullSupplier<? extends Block> block, int clusterSize) {
|
||||
this.block = block;
|
||||
this.enable = b(true, "enable", "Whether to spawn this in your World");
|
||||
this.clusterSize = i(clusterSize, 0, "clusterSize");
|
||||
this.minHeight = i(0, 0, "minHeight");
|
||||
this.maxHeight = i(256, 0, "maxHeight");
|
||||
}
|
||||
|
||||
public OreFeature<T> between(int minHeight, int maxHeight) {
|
||||
allValues.remove(this.minHeight);
|
||||
allValues.remove(this.maxHeight);
|
||||
this.minHeight = i(minHeight, 0, "minHeight");
|
||||
this.maxHeight = i(maxHeight, 0, "maxHeight");
|
||||
return this;
|
||||
}
|
||||
|
||||
public OreFeature<T> inBiomes(Biome.Category category) {
|
||||
specificCategory = category;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ConfiguredFeature<?, ?>> createFeature(BiomeLoadingEvent biome) {
|
||||
if (specificCategory != null && biome.getCategory() != specificCategory)
|
||||
return Optional.empty();
|
||||
if (!canGenerate())
|
||||
return Optional.empty();
|
||||
|
||||
Pair<Placement<T>, T> placement = getPlacement();
|
||||
ConfiguredFeature<?, ?> createdFeature = Feature.ORE
|
||||
.configure(new OreFeatureConfig(OreFeatureConfig.FillerBlockType.BASE_STONE_OVERWORLD, block.get()
|
||||
.getDefaultState(), clusterSize.get()))
|
||||
.decorate(placement.getKey()
|
||||
.configure(placement.getValue()))
|
||||
.decorate(Placement.RANGE
|
||||
// TODO 1.16 worldgen verify this
|
||||
.configure(new TopSolidRangeConfig(minHeight.get(), 0, maxHeight.get() - minHeight.get())))
|
||||
.spreadHorizontally();
|
||||
|
||||
return Optional.of(createdFeature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decoration getGenerationStage() {
|
||||
return GenerationStage.Decoration.UNDERGROUND_ORES;
|
||||
}
|
||||
|
||||
protected boolean canGenerate() {
|
||||
return minHeight.get() < maxHeight.get() && clusterSize.get() > 0 && enable.get()
|
||||
&& !AllConfigs.COMMON.worldGen.disable.get();
|
||||
}
|
||||
|
||||
protected abstract Pair<Placement<T>, T> getPlacement();
|
||||
|
||||
@Override
|
||||
public void addToConfig(Builder builder) {
|
||||
registerAll(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue