Mangrove Swamps

This commit is contained in:
ItsBlackGear 2022-07-17 03:33:52 -04:00
parent b698b03a9a
commit 2a07f32d75
26 changed files with 525 additions and 26 deletions

View file

@ -4,11 +4,10 @@ import com.cursedcauldron.wildbackport.common.entities.Allay;
import com.cursedcauldron.wildbackport.common.entities.Frog;
import com.cursedcauldron.wildbackport.common.entities.Tadpole;
import com.cursedcauldron.wildbackport.common.entities.Warden;
import com.cursedcauldron.wildbackport.common.events.StructureEvent;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntities;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBWorldGeneration;
import com.cursedcauldron.wildbackport.core.api.Environment;
import com.cursedcauldron.wildbackport.core.api.MobRegistry;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeModifier;
public class CommonSetup {
/**
@ -20,15 +19,13 @@ public class CommonSetup {
MobRegistry.registerAttributes(WBEntities.FROG, Frog::createAttributes);
MobRegistry.registerAttributes(WBEntities.TADPOLE, Tadpole::createAttributes);
MobRegistry.registerAttributes(WBEntities.WARDEN, Warden::createAttributes);
// StructureEvent.bootstrap();
if (Environment.isFabric()) WBWorldGeneration.bootstrap();
}
/**
* Runs features post bootstrap
*/
public static void onPostCommon() {
// StructureEvent.bootstrap();
if (Environment.isForge()) WBWorldGeneration.bootstrap();
WBWorldGeneration.bootstrap();
BiomeModifier.setup();
}
}

View file

@ -5,7 +5,7 @@ import com.cursedcauldron.wildbackport.common.entities.Frog;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.BiasedLongJumpTask;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.Croak;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.FrogEat;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.LayFrogSpawnTask;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.LayFrogSpawn;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.WalkTowardsLand;
import com.cursedcauldron.wildbackport.common.entities.brain.frog.WalkTowardsWater;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
@ -80,7 +80,7 @@ public class FrogBrain {
}
private static void addLaySpawnActivities(Brain<Frog> brain) {
brain.addActivityWithConditions(WBActivities.LAY_SPAWN.get(), ImmutableList.of(Pair.of(0, new RunSometimes<LivingEntity>(new SetEntityLookTarget(EntityType.PLAYER, 6.0F), UniformInt.of(30, 60))), Pair.of(1, new StartAttacking<>(FrogBrain::isNotBreeding, frog -> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE))), Pair.of(2, new WalkTowardsWater(8, 1.0F)), Pair.of(3, new LayFrogSpawnTask(WBBlocks.FROGSPAWN.get(), WBMemoryModules.IS_PREGNANT.get())), Pair.of(4, new RunOne<>(ImmutableList.of(Pair.of(new RandomStroll(1.0F), 2), Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1), Pair.of(new Croak(), 2), Pair.of(new RunIf<>(Entity::isOnGround, new DoNothing(5, 20)), 1))))), ImmutableSet.of(Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.IS_PREGNANT.get(), MemoryStatus.VALUE_PRESENT)));
brain.addActivityWithConditions(WBActivities.LAY_SPAWN.get(), ImmutableList.of(Pair.of(0, new RunSometimes<LivingEntity>(new SetEntityLookTarget(EntityType.PLAYER, 6.0F), UniformInt.of(30, 60))), Pair.of(1, new StartAttacking<>(FrogBrain::isNotBreeding, frog -> frog.getBrain().getMemory(MemoryModuleType.NEAREST_ATTACKABLE))), Pair.of(2, new WalkTowardsWater(8, 1.0F)), Pair.of(3, new LayFrogSpawn(WBBlocks.FROGSPAWN.get(), WBMemoryModules.IS_PREGNANT.get())), Pair.of(4, new RunOne<>(ImmutableList.of(Pair.of(new RandomStroll(1.0F), 2), Pair.of(new SetWalkTargetFromLookTarget(1.0F, 3), 1), Pair.of(new Croak(), 2), Pair.of(new RunIf<>(Entity::isOnGround, new DoNothing(5, 20)), 1))))), ImmutableSet.of(Pair.of(MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT), Pair.of(WBMemoryModules.IS_PREGNANT.get(), MemoryStatus.VALUE_PRESENT)));
}
private static void addLongJumpActivities(Brain<Frog> brain) {

View file

@ -14,32 +14,33 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
public class LayFrogSpawnTask extends Behavior<Frog> {
public class LayFrogSpawn extends Behavior<Frog> {
private final Block frogSpawn;
private final MemoryModuleType<?> triggerMemory;
public LayFrogSpawnTask(Block block, MemoryModuleType<?> memoryModuleType) {
public LayFrogSpawn(Block block, MemoryModuleType<?> triggerMemory) {
super(ImmutableMap.of(MemoryModuleType.ATTACK_TARGET, MemoryStatus.VALUE_ABSENT, MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_PRESENT, WBMemoryModules.IS_PREGNANT.get(), MemoryStatus.VALUE_PRESENT));
this.frogSpawn = block;
this.triggerMemory = memoryModuleType;
this.triggerMemory = triggerMemory;
}
@Override
protected boolean checkExtraStartConditions(ServerLevel serverWorld, Frog arg) {
return !arg.isInWaterOrBubble() && arg.isOnGround();
protected boolean checkExtraStartConditions(ServerLevel level, Frog frog) {
return !frog.isInWaterOrBubble() && frog.isOnGround();
}
@Override
protected void start(ServerLevel serverWorld, Frog arg, long l) {
BlockPos blockPos = arg.blockPosition().below();
protected void start(ServerLevel level, Frog frog, long time) {
BlockPos blockPos = frog.blockPosition().below();
for (Direction direction : Direction.Plane.HORIZONTAL) {
BlockPos blockPos3;
BlockPos blockPos2 = blockPos.relative(direction);
if (!serverWorld.getBlockState(blockPos2).is(Blocks.WATER) || !serverWorld.getBlockState(blockPos3 = blockPos2.above()).isAir()) continue;
serverWorld.setBlock(blockPos3, this.frogSpawn.defaultBlockState(), 3);
serverWorld.playSound(null, arg, WBSoundEvents.FROG_LAY_SPAWN, SoundSource.BLOCKS, 1.0f, 1.0f);
arg.getBrain().eraseMemory(this.triggerMemory);
return;
BlockPos offset = blockPos.relative(direction);
BlockPos above = offset.above();
if (level.getBlockState(offset).is(Blocks.WATER) && level.getBlockState(above).isAir()) {
level.setBlock(above, this.frogSpawn.defaultBlockState(), 3);
level.playSound(null, frog, WBSoundEvents.FROG_LAY_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);
frog.getBrain().eraseMemory(this.triggerMemory);
return;
}
}
}
}

View file

@ -2,23 +2,77 @@ package com.cursedcauldron.wildbackport.common.registry;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.core.api.CoreRegistry;
import com.cursedcauldron.wildbackport.core.mixin.access.OverworldBiomesAccessor;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.biome.OverworldBiomes;
import net.minecraft.data.worldgen.BiomeDefaultFeatures;
import net.minecraft.data.worldgen.Carvers;
import net.minecraft.data.worldgen.placement.AquaticPlacements;
import net.minecraft.data.worldgen.placement.VegetationPlacements;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.level.biome.AmbientMoodSettings;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSpecialEffects;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.levelgen.GenerationStep;
import java.util.function.Supplier;
public class WBBiomes {
public static final CoreRegistry<Biome> BIOMES = CoreRegistry.create(BuiltinRegistries.BIOME, WildBackport.MOD_ID);
public static final ResourceKey<Biome> MANGROVE_SWAMP = create("mangrove_swamp", OverworldBiomes::theVoid);
public static final ResourceKey<Biome> DEEP_DARK = create("deep_dark", OverworldBiomes::theVoid);
public static final ResourceKey<Biome> MANGROVE_SWAMP = create("mangrove_swamp", WBBiomes::mangroveSwamp);
public static final ResourceKey<Biome> DEEP_DARK = create("deep_dark", WBBiomes::deepDark);
// Mangrove Swamp
public static Biome mangroveSwamp() {
MobSpawnSettings.Builder spawn = new MobSpawnSettings.Builder();
BiomeDefaultFeatures.commonSpawns(spawn);
BiomeGenerationSettings.Builder generation = new BiomeGenerationSettings.Builder();
BiomeDefaultFeatures.addFossilDecoration(generation);
OverworldBiomesAccessor.callGlobalOverworldGeneration(generation);
BiomeDefaultFeatures.addDefaultOres(generation);
BiomeDefaultFeatures.addSwampClayDisk(generation);
generation.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, VegetationPlacements.PATCH_GRASS_NORMAL);
generation.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, VegetationPlacements.PATCH_DEAD_BUSH);
generation.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, VegetationPlacements.PATCH_WATERLILY);
generation.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, AquaticPlacements.SEAGRASS_SWAMP);
return new Biome.BiomeBuilder().biomeCategory(Biome.BiomeCategory.SWAMP).precipitation(Biome.Precipitation.RAIN).temperature(0.8F).downfall(0.9f).specialEffects(new BiomeSpecialEffects.Builder().waterColor(3832426).waterFogColor(5077600).fogColor(12638463).skyColor(calculateSkyColor(0.8f)).foliageColorOverride(9285927).grassColorModifier(BiomeSpecialEffects.GrassColorModifier.SWAMP).ambientMoodSound(AmbientMoodSettings.LEGACY_CAVE_SETTINGS).build()).mobSpawnSettings(spawn.build()).generationSettings(generation.build()).build();
}
// Deep Dark
public static Biome deepDark() {
MobSpawnSettings.Builder spawn = new MobSpawnSettings.Builder();
BiomeGenerationSettings.Builder generation = new BiomeGenerationSettings.Builder();
generation.addCarver(GenerationStep.Carving.AIR, Carvers.CAVE);
generation.addCarver(GenerationStep.Carving.AIR, Carvers.CAVE_EXTRA_UNDERGROUND);
generation.addCarver(GenerationStep.Carving.AIR, Carvers.CANYON);
BiomeDefaultFeatures.addDefaultCrystalFormations(generation);
BiomeDefaultFeatures.addDefaultMonsterRoom(generation);
BiomeDefaultFeatures.addDefaultUndergroundVariety(generation);
BiomeDefaultFeatures.addSurfaceFreezing(generation);
BiomeDefaultFeatures.addPlainGrass(generation);
BiomeDefaultFeatures.addDefaultOres(generation, true);
BiomeDefaultFeatures.addDefaultSoftDisks(generation);
BiomeDefaultFeatures.addPlainVegetation(generation);
BiomeDefaultFeatures.addDefaultMushrooms(generation);
BiomeDefaultFeatures.addDefaultExtraVegetation(generation);
return new Biome.BiomeBuilder().biomeCategory(Biome.BiomeCategory.UNDERGROUND).precipitation(Biome.Precipitation.RAIN).temperature(0.8F).downfall(0.4F).specialEffects(new BiomeSpecialEffects.Builder().waterColor(4159204).waterFogColor(329011).fogColor(12638463).skyColor(calculateSkyColor(0.8F)).ambientMoodSound(AmbientMoodSettings.LEGACY_CAVE_SETTINGS).build()).mobSpawnSettings(spawn.build()).generationSettings(generation.build()).build();
}
// Registry
private static ResourceKey<Biome> create(String key, Supplier<Biome> biome) {
BIOMES.register(key, biome);
return ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation(WildBackport.MOD_ID, key));
}
protected static int calculateSkyColor(float temperature) {
float modifier = temperature / 3.0F;
modifier = Mth.clamp(modifier, -1.0F, 1.0F);
return Mth.hsvToRgb(0.62222224F - modifier * 0.05F, 0.5F + modifier * 0.1F, 1.0F);
}
}

View file

@ -1,6 +1,8 @@
package com.cursedcauldron.wildbackport.common.registry.worldgen;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.common.worldgen.features.GrassDiskConfiguration;
import com.cursedcauldron.wildbackport.common.worldgen.features.GrassDiskFeature;
import com.cursedcauldron.wildbackport.common.worldgen.features.RootedTreeConfig;
import com.cursedcauldron.wildbackport.common.worldgen.features.RootedTreeFeature;
import com.cursedcauldron.wildbackport.core.api.CoreRegistry;
@ -15,4 +17,5 @@ public class WBFeatures {
public static final CoreRegistry<Feature<?>> FEATURES = CoreRegistry.create(Registry.FEATURE, WildBackport.MOD_ID);
public static final Supplier<Feature<RootedTreeConfig>> TREE = FEATURES.register("tree", () -> new RootedTreeFeature(RootedTreeConfig.CODEC));
public static final Supplier<Feature<GrassDiskConfiguration>> DISK = FEATURES.register("disk", () -> new GrassDiskFeature(GrassDiskConfiguration.CODEC));
}

View file

@ -4,10 +4,13 @@ import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.common.blocks.MangrovePropaguleBlock;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import com.cursedcauldron.wildbackport.common.tag.WBBlockTags;
import com.cursedcauldron.wildbackport.common.worldgen.PredicatedStateProvider;
import com.cursedcauldron.wildbackport.common.worldgen.WorldGenerator;
import com.cursedcauldron.wildbackport.common.worldgen.decorator.AttachedToLeavesDecorator;
import com.cursedcauldron.wildbackport.common.worldgen.decorator.LayerRootDecorator;
import com.cursedcauldron.wildbackport.common.worldgen.decorator.MangroveRootPlacement;
import com.cursedcauldron.wildbackport.common.worldgen.decorator.WeightedLeaveVineDecorator;
import com.cursedcauldron.wildbackport.common.worldgen.features.GrassDiskConfiguration;
import com.cursedcauldron.wildbackport.common.worldgen.features.RootedTreeConfig;
import com.cursedcauldron.wildbackport.common.worldgen.placers.MangroveRootPlacer;
import com.cursedcauldron.wildbackport.common.worldgen.placers.UpwardBranchingTrunk;
@ -16,6 +19,7 @@ import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry;
import net.minecraft.core.Vec3i;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.data.worldgen.placement.PlacementUtils;
import net.minecraft.util.valueproviders.ConstantInt;
@ -39,7 +43,9 @@ import net.minecraft.world.level.levelgen.placement.CountPlacement;
import net.minecraft.world.level.levelgen.placement.InSquarePlacement;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
import net.minecraft.world.level.levelgen.placement.RandomOffsetPlacement;
import net.minecraft.world.level.levelgen.placement.SurfaceWaterDepthFilter;
import net.minecraft.world.level.material.Fluids;
import java.util.List;
import java.util.Optional;
@ -47,9 +53,12 @@ import java.util.Optional;
//<>
public class WBWorldGeneration {
public static void bootstrap() {}
public static void bootstrap() {
WorldGenerator.setup();
}
// Mangrove Swamp
//TODO: fix mangroves not generating moss
public static final Holder<ConfiguredFeature<RootedTreeConfig, ?>> MANGROVE = config("mangrove", WBFeatures.TREE.get(), new RootedTreeConfig.Builder(
BlockStateProvider.simple(WBBlocks.MANGROVE_LOG.get()),
@ -83,6 +92,8 @@ public class WBWorldGeneration {
public static final Holder<ConfiguredFeature<RandomFeatureConfiguration, ?>> MANGROVE_VEGETATION = config("mangrove_vegetation", Feature.RANDOM_SELECTOR, new RandomFeatureConfiguration(List.of(new WeightedPlacedFeature(TALL_MANGROVE_CHECKED, 0.85F)), MANGROVE_CHECKED));
public static final Holder<PlacedFeature> TREES_MANGROVE = place("trees_mangrove", MANGROVE_VEGETATION, CountPlacement.of(25), InSquarePlacement.spread(), SurfaceWaterDepthFilter.forMaxDepth(5), PlacementUtils.HEIGHTMAP_OCEAN_FLOOR, BiomeFilter.biome(), BlockPredicateFilter.forPredicate(BlockPredicate.wouldSurvive(WBBlocks.MANGROVE_PROPAGULE.get().defaultBlockState(), BlockPos.ZERO)));
public static final Holder<ConfiguredFeature<GrassDiskConfiguration, ?>> DISK_GRASS_CONFIG = config("disk_grass", WBFeatures.DISK.get(), new GrassDiskConfiguration(new PredicatedStateProvider(BlockStateProvider.simple(Blocks.DIRT), List.of(new PredicatedStateProvider.Rule(BlockPredicate.not(BlockPredicate.allOf(BlockPredicate.solid(Direction.UP.getNormal()), BlockPredicate.matchesFluid(Fluids.WATER, Direction.UP.getNormal()))), BlockStateProvider.simple(Blocks.GRASS_BLOCK)))), BlockPredicate.matchesBlocks(List.of(Blocks.DIRT, WBBlocks.MUD.get())), UniformInt.of(2, 6), 2));
public static final Holder<PlacedFeature> DISK_GRASS = place("disk_grass", DISK_GRASS_CONFIG, CountPlacement.of(1), InSquarePlacement.spread(), PlacementUtils.HEIGHTMAP_TOP_SOLID, RandomOffsetPlacement.vertical(ConstantInt.of(-1)), BlockPredicateFilter.forPredicate(BlockPredicate.matchesBlock(WBBlocks.MUD.get(), Vec3i.ZERO)), BiomeFilter.biome());
// Deep Dark

View file

@ -0,0 +1,24 @@
package com.cursedcauldron.wildbackport.common.worldgen;
import com.cursedcauldron.wildbackport.common.registry.WBBiomes;
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.Noises;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.VerticalAnchor;
public class MangroveSwampSurface {
public static final SurfaceRules.ConditionSource ABOVE_60 = SurfaceRules.yBlockCheck(VerticalAnchor.absolute(60), 0);
public static final SurfaceRules.ConditionSource ABOVE_63 = SurfaceRules.yBlockCheck(VerticalAnchor.absolute(63), 0);
public static SurfaceRules.RuleSource makeRules() {
SurfaceRules.RuleSource terrain = SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(WBBiomes.MANGROVE_SWAMP), makeStateRule(WBBlocks.MUD.get())));
SurfaceRules.RuleSource generation = SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.isBiome(WBBiomes.MANGROVE_SWAMP), SurfaceRules.ifTrue(ABOVE_60, SurfaceRules.ifTrue(SurfaceRules.not(ABOVE_63), SurfaceRules.ifTrue(SurfaceRules.noiseCondition(Noises.SWAMP, 0.0F), makeStateRule(Blocks.WATER))))))), SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SurfaceRules.ifTrue(SurfaceRules.waterBlockCheck(-1, 0), SurfaceRules.sequence(terrain))), SurfaceRules.ifTrue(SurfaceRules.waterStartCheck(-6, -1), SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, terrain))));
return SurfaceRules.sequence(SurfaceRules.ifTrue(SurfaceRules.abovePreliminarySurface(), generation));
}
private static SurfaceRules.RuleSource makeStateRule(Block block) {
return SurfaceRules.state(block.defaultBlockState());
}
}

View file

@ -0,0 +1,34 @@
package com.cursedcauldron.wildbackport.common.worldgen;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
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.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
import java.util.List;
import java.util.Random;
public record PredicatedStateProvider(BlockStateProvider fallback, List<Rule> rules) {
public static final Codec<PredicatedStateProvider> CODEC = RecordCodecBuilder.create(instance -> instance.group(BlockStateProvider.CODEC.fieldOf("fallback").forGetter(PredicatedStateProvider::fallback), Rule.CODEC.listOf().fieldOf("rules").forGetter(PredicatedStateProvider::rules)).apply(instance, PredicatedStateProvider::new));
public static PredicatedStateProvider of(BlockStateProvider provider) {
return new PredicatedStateProvider(provider, List.of());
}
public static PredicatedStateProvider of(Block block) {
return of(BlockStateProvider.simple(block));
}
public BlockState getBlockState(WorldGenLevel level, Random random, BlockPos pos) {
for (Rule rule : this.rules) if (rule.ifTrue.test(level, pos)) return rule.then.getState(random, pos);
return this.fallback.getState(random, pos);
}
public record Rule(BlockPredicate ifTrue, BlockStateProvider then) {
public static final Codec<Rule> CODEC = RecordCodecBuilder.create(instance -> instance.group(BlockPredicate.CODEC.fieldOf("if_true").forGetter(Rule::ifTrue), BlockStateProvider.CODEC.fieldOf("then").forGetter(Rule::then)).apply(instance, Rule::new));
}
}

View file

@ -0,0 +1,33 @@
package com.cursedcauldron.wildbackport.common.worldgen;
import com.cursedcauldron.wildbackport.common.registry.WBBiomes;
import com.cursedcauldron.wildbackport.common.registry.entity.WBEntities;
import com.cursedcauldron.wildbackport.common.registry.worldgen.WBWorldGeneration;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeModifier;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeWriter;
import net.minecraft.data.worldgen.placement.MiscOverworldPlacements;
import net.minecraft.data.worldgen.placement.VegetationPlacements;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.levelgen.GenerationStep;
//<>
public class WorldGenerator {
public static void setup() {
BiomeModifier.add(WorldGenerator::mangroveSwamp, WBBiomes.MANGROVE_SWAMP);
}
public static void mangroveSwamp(BiomeWriter writer) {
writer.addFeature(GenerationStep.Decoration.UNDERGROUND_ORES, WBWorldGeneration.DISK_GRASS);
writer.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, WBWorldGeneration.TREES_MANGROVE);
// writer.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, VegetationPlacements.PATCH_GRASS_NORMAL);
// writer.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, VegetationPlacements.PATCH_DEAD_BUSH);
// writer.addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, VegetationPlacements.PATCH_WATERLILY);
writer.addSpawn(MobCategory.MONSTER, EntityType.SLIME, 1, 1, 1);
writer.addSpawn(MobCategory.CREATURE, WBEntities.FROG.get(), 10, 2, 5);
writer.addSpawn(MobCategory.WATER_AMBIENT, EntityType.TROPICAL_FISH, 25, 8, 8);
}
}

View file

@ -0,0 +1,12 @@
package com.cursedcauldron.wildbackport.common.worldgen.features;
import com.cursedcauldron.wildbackport.common.worldgen.PredicatedStateProvider;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.valueproviders.IntProvider;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
public record GrassDiskConfiguration(PredicatedStateProvider stateProvider, BlockPredicate target, IntProvider radius, int halfHeight) implements FeatureConfiguration {
public static final Codec<GrassDiskConfiguration> CODEC = RecordCodecBuilder.create(instance -> instance.group(PredicatedStateProvider.CODEC.fieldOf("state_provider").forGetter(GrassDiskConfiguration::stateProvider), BlockPredicate.CODEC.fieldOf("target").forGetter(GrassDiskConfiguration::target), IntProvider.codec(0, 8).fieldOf("radius").forGetter(GrassDiskConfiguration::radius), Codec.intRange(0, 4).fieldOf("half_height").forGetter(GrassDiskConfiguration::halfHeight)).apply(instance, GrassDiskConfiguration::new));
}

View file

@ -0,0 +1,55 @@
package com.cursedcauldron.wildbackport.common.worldgen.features;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.WorldGenLevel;
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 java.util.Random;
public class GrassDiskFeature extends Feature<GrassDiskConfiguration> {
public GrassDiskFeature(Codec<GrassDiskConfiguration> codec) {
super(codec);
}
@Override
public boolean place(FeaturePlaceContext<GrassDiskConfiguration> context) {
GrassDiskConfiguration config = context.config();
BlockPos pos = context.origin();
WorldGenLevel level = context.level();
Random random = context.random();
boolean place = false;
int y = pos.getY();
int topY = y + config.halfHeight();
int bottomY = y - config.halfHeight() - 1;
int radius = config.radius().sample(random);
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
for (BlockPos position : BlockPos.betweenClosed(pos.offset(-radius, 0, -radius), pos.offset(radius, 0, radius))) {
int x = position.getX() - position.getX();
int z = position.getZ() - position.getZ();
if (x * x + z * z <= radius * radius) {
place |= this.placeBlock(config, level, random, topY, bottomY, mutable.set(position));
}
}
return place;
}
protected boolean placeBlock(GrassDiskConfiguration config, WorldGenLevel level, Random random, int topY, int bottomY, BlockPos.MutableBlockPos pos) {
boolean place = false;
for (int y = topY; y > bottomY; y--) {
pos.setY(y);
if (config.target().test(level, pos)) {
BlockState state = config.stateProvider().getBlockState(level, random, pos);
level.setBlock(pos, state, 2);
this.markAboveForPostProcessing(level, pos);
place = true;
}
}
return place;
}
}

View file

@ -0,0 +1,28 @@
package com.cursedcauldron.wildbackport.core.api.worldgen;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
public class BiomeModifier {
private static final Map<Consumer<BiomeWriter>, ResourceKey<Biome>[]> FEATURES = new ConcurrentHashMap<>();
public static final BiomeModifier INSTANCE = new BiomeModifier();
@ExpectPlatform
public static void setup() {
throw new AssertionError();
}
public void register(BiomeWriter writer) {
FEATURES.forEach(writer::add);
}
@SafeVarargs
public static void add(Consumer<BiomeWriter> writer, ResourceKey<Biome>... biomes) {
FEATURES.put(writer, biomes);
}
}

View file

@ -0,0 +1,32 @@
package com.cursedcauldron.wildbackport.core.api.worldgen;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import java.util.function.Consumer;
//<>
public abstract class BiomeWriter {
@SafeVarargs
public final void add(Consumer<BiomeWriter> writer, ResourceKey<Biome>... biomes) {
for (ResourceKey<Biome> biome : biomes) if (this.is(biome)) writer.accept(this);
}
public boolean is(ResourceKey<Biome> biome) {
return biome == ResourceKey.create(Registry.BIOME_REGISTRY, this.name());
}
public abstract ResourceLocation name();
public abstract void addFeature(GenerationStep.Decoration step, Holder<PlacedFeature> feature);
public abstract void addSpawn(MobCategory category, EntityType<?> entityType, int weight, int minGroupSize, int maxGroupSize);
}

View file

@ -0,0 +1,14 @@
package com.cursedcauldron.wildbackport.core.mixin.access;
import net.minecraft.data.worldgen.biome.OverworldBiomes;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(OverworldBiomes.class)
public interface OverworldBiomesAccessor {
@Invoker
static void callGlobalOverworldGeneration(BiomeGenerationSettings.Builder builder) {
throw new UnsupportedOperationException();
}
}

View file

@ -10,6 +10,7 @@
"access.DoorBlockAccessor",
"access.MemoryModuleTypeAccessor",
"access.ModelPartAccessor",
"access.OverworldBiomesAccessor",
"access.PressurePlateBlockAccessor",
"access.RecordItemAccessor",
"access.RegistryAccessor",

View file

@ -15,10 +15,18 @@ configurations {
developmentFabric.extendsFrom common
}
repositories {
maven {
url = 'https://maven.minecraftforge.net/'
}
}
dependencies {
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
modImplementation("com.github.glitchfiend:TerraBlender-fabric:${minecraft_version}-${terrablender_version}")
common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
}

View file

@ -0,0 +1,15 @@
package com.cursedcauldron.wildbackport.core.api.worldgen.fabric;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeModifier;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
import net.fabricmc.fabric.api.biome.v1.ModificationPhase;
import net.minecraft.resources.ResourceLocation;
public class BiomeModifierImpl {
public static void setup() {
BiomeModifications.create(new ResourceLocation(WildBackport.MOD_ID, "biome_modifier")).add(ModificationPhase.ADDITIONS, ctx -> true, (selector, modifier) -> {
BiomeModifier.INSTANCE.register(new FabricBiomeWriter().build(selector, modifier));
});
}
}

View file

@ -0,0 +1,38 @@
package com.cursedcauldron.wildbackport.core.api.worldgen.fabric;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeWriter;
import net.fabricmc.fabric.api.biome.v1.BiomeModificationContext;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
public class FabricBiomeWriter extends BiomeWriter {
private BiomeSelectionContext selection;
private BiomeModificationContext modification;
public BiomeWriter build(BiomeSelectionContext selectionCtx, BiomeModificationContext modificationCtx) {
this.selection = selectionCtx;
this.modification = modificationCtx;
return this;
}
@Override
public ResourceLocation name() {
return this.selection.getBiomeKey().location();
}
@Override
public void addFeature(GenerationStep.Decoration step, Holder<PlacedFeature> feature) {
this.modification.getGenerationSettings().addBuiltInFeature(step, feature.value());
}
@Override
public void addSpawn(MobCategory category, EntityType<?> entityType, int weight, int minGroupSize, int maxGroupSize) {
this.modification.getSpawnSettings().addSpawn(category, new MobSpawnSettings.SpawnerData(entityType, weight, minGroupSize, maxGroupSize));
}
}

View file

@ -0,0 +1,37 @@
package com.cursedcauldron.wildbackport.fabric;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.common.registry.WBBiomes;
import com.cursedcauldron.wildbackport.common.worldgen.MangroveSwampSurface;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import terrablender.api.ParameterUtils;
import terrablender.api.Region;
import terrablender.api.RegionType;
import terrablender.api.Regions;
import terrablender.api.SurfaceRuleManager;
import terrablender.api.TerraBlenderApi;
import java.util.List;
import java.util.function.Consumer;
public class TerrablenderSetup implements TerraBlenderApi {
@Override
public void onTerraBlenderInitialized() {
Regions.register(new Region(new ResourceLocation(WildBackport.MOD_ID, "overworld"), RegionType.OVERWORLD, 2) {
@Override public void addBiomes(Registry<Biome> registry, Consumer<Pair<Climate.ParameterPoint, ResourceKey<Biome>>> mapper) {
this.addModifiedVanillaOverworldBiomes(mapper, builder -> {
builder.replaceBiome(Biomes.SWAMP, WBBiomes.MANGROVE_SWAMP);
List<Climate.ParameterPoint> points = new ParameterUtils.ParameterPointListBuilder().erosion(ParameterUtils.Erosion.span(ParameterUtils.Erosion.EROSION_0, ParameterUtils.Erosion.EROSION_1)).depth(Climate.Parameter.point(1.1F)).build();
points.forEach(point -> mapper.accept(Pair.of(point, WBBiomes.DEEP_DARK)));
});
}
});
SurfaceRuleManager.addSurfaceRules(SurfaceRuleManager.RuleCategory.OVERWORLD, WildBackport.MOD_ID, MangroveSwampSurface.makeRules());
}
}

View file

@ -9,5 +9,6 @@ public class WildBackportFabric implements ModInitializer {
public void onInitialize() {
WildBackport.bootstrap();
CommonSetup.onCommon();
CommonSetup.onPostCommon();
}
}

View file

@ -19,6 +19,9 @@
],
"client": [
"com.cursedcauldron.wildbackport.fabric.WildBackportFabricClient"
],
"terrablender": [
"com.cursedcauldron.wildbackport.fabric.TerrablenderSetup"
]
},
"mixins": [

View file

@ -1,3 +1,11 @@
buildscript {
repositories {
maven {
url = 'https://maven.minecraftforge.net/'
}
}
}
plugins {
id "com.github.johnrengelman.shadow" version "7.1.2"
}
@ -26,6 +34,11 @@ configurations {
dependencies {
forge "net.minecraftforge:forge:${rootProject.forge_version}"
// forge "net.minecraftforge:forge:${rootProject.forge_version}"
modApi ("com.github.glitchfiend:TerraBlender-forge:${minecraft_version}-${terrablender_version}")
// implementation fg.deobf('com.github.glitchfiend:TerraBlender-forge:x.x.x-y.y.y.y')
common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }

View file

@ -0,0 +1,17 @@
package com.cursedcauldron.wildbackport.core.api.worldgen.forge;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeModifier;
import net.minecraftforge.event.world.BiomeLoadingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = WildBackport.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class BiomeModifierImpl {
public static void setup() {}
@SubscribeEvent
public static void event(BiomeLoadingEvent event) {
BiomeModifier.INSTANCE.register(new ForgeBiomeWriter().build(event));
}
}

View file

@ -0,0 +1,34 @@
package com.cursedcauldron.wildbackport.core.api.worldgen.forge;
import com.cursedcauldron.wildbackport.core.api.worldgen.BiomeWriter;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraftforge.event.world.BiomeLoadingEvent;
public class ForgeBiomeWriter extends BiomeWriter {
private BiomeLoadingEvent event;
public BiomeWriter build(BiomeLoadingEvent event) {
this.event = event;
return this;
}
@Override
public ResourceLocation name() {
return this.event.getName();
}
@Override
public void addFeature(GenerationStep.Decoration step, Holder<PlacedFeature> feature) {
this.event.getGeneration().addFeature(step, feature);
}
@Override
public void addSpawn(MobCategory category, EntityType<?> entityType, int weight, int minGroupSize, int maxGroupSize) {
}
}

View file

@ -3,7 +3,16 @@ package com.cursedcauldron.wildbackport.forge;
import com.cursedcauldron.wildbackport.WildBackport;
import com.cursedcauldron.wildbackport.client.ClientSetup;
import com.cursedcauldron.wildbackport.common.CommonSetup;
import com.cursedcauldron.wildbackport.common.registry.WBBiomes;
import com.cursedcauldron.wildbackport.common.worldgen.MangroveSwampSurface;
import com.cursedcauldron.wildbackport.core.api.forge.EventBuses;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.DistExecutor;
@ -11,6 +20,14 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import terrablender.api.ParameterUtils;
import terrablender.api.Region;
import terrablender.api.RegionType;
import terrablender.api.Regions;
import terrablender.api.SurfaceRuleManager;
import java.util.List;
import java.util.function.Consumer;
@Mod(WildBackport.MOD_ID)
public class WildBackportForge {
@ -20,8 +37,23 @@ public class WildBackportForge {
bus.<FMLCommonSetupEvent>addListener(event -> CommonSetup.onPostCommon());
bus.<FMLClientSetupEvent>addListener(event -> ClientSetup.onPostClient());
bus.addListener(this::terrablenderSetup);
WildBackport.bootstrap();
CommonSetup.onCommon();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClientSetup::onClient);
}
private void terrablenderSetup(final FMLCommonSetupEvent event) {
Regions.register(new Region(new ResourceLocation(WildBackport.MOD_ID, "overworld"), RegionType.OVERWORLD, 2) {
@Override public void addBiomes(Registry<Biome> registry, Consumer<Pair<Climate.ParameterPoint, ResourceKey<Biome>>> mapper) {
this.addModifiedVanillaOverworldBiomes(mapper, builder -> {
builder.replaceBiome(Biomes.SWAMP, WBBiomes.MANGROVE_SWAMP);
List<Climate.ParameterPoint> points = new ParameterUtils.ParameterPointListBuilder().erosion(ParameterUtils.Erosion.span(ParameterUtils.Erosion.EROSION_0, ParameterUtils.Erosion.EROSION_1)).depth(Climate.Parameter.point(1.1F)).build();
points.forEach(point -> mapper.accept(Pair.of(point, WBBiomes.DEEP_DARK)));
});
}
});
SurfaceRuleManager.addSurfaceRules(SurfaceRuleManager.RuleCategory.OVERWORLD, WildBackport.MOD_ID, MangroveSwampSurface.makeRules());
}
}

View file

@ -7,3 +7,5 @@ architectury_version=4.5.74
fabric_loader_version=0.14.8
fabric_api_version=0.56.1+1.18.2
forge_version=1.18.2-40.1.54
terrablender_version=1.1.0.95