diff --git a/src/generated/resources/data/ageofthegods/neoforge/biome_modifier/add_twisty_tree.json b/src/generated/resources/data/ageofthegods/neoforge/biome_modifier/add_twisty_tree.json new file mode 100644 index 0000000..4da86ed --- /dev/null +++ b/src/generated/resources/data/ageofthegods/neoforge/biome_modifier/add_twisty_tree.json @@ -0,0 +1,6 @@ +{ + "type": "neoforge:add_features", + "biomes": "ageofthegods:maquis_shrubland", + "features": "ageofthegods:twisty_tree_placed", + "step": "vegetal_decoration" +} \ No newline at end of file diff --git a/src/generated/resources/data/ageofthegods/worldgen/configured_feature/twisty_tree.json b/src/generated/resources/data/ageofthegods/worldgen/configured_feature/twisty_tree.json new file mode 100644 index 0000000..7ea6464 --- /dev/null +++ b/src/generated/resources/data/ageofthegods/worldgen/configured_feature/twisty_tree.json @@ -0,0 +1,64 @@ +{ + "type": "minecraft:tree", + "config": { + "below_trunk_provider": { + "type": "minecraft:rule_based_state_provider", + "rules": [ + { + "if_true": { + "type": "minecraft:not", + "predicate": { + "type": "minecraft:matching_block_tag", + "tag": "minecraft:cannot_replace_below_tree_trunk" + } + }, + "then": { + "type": "minecraft:simple_state_provider", + "state": { + "Name": "minecraft:dirt" + } + } + } + ] + }, + "decorators": [], + "foliage_placer": { + "type": "ageofthegods:spherical_foliage_placer", + "offset": 0, + "radius": 1 + }, + "foliage_provider": { + "type": "minecraft:simple_state_provider", + "state": { + "Name": "minecraft:oak_leaves", + "Properties": { + "distance": "7", + "persistent": "false", + "waterlogged": "false" + } + } + }, + "ignore_vines": false, + "minimum_size": { + "type": "minecraft:two_layers_feature_size", + "limit": 5, + "lower_size": 3, + "upper_size": 5 + }, + "trunk_placer": { + "type": "ageofthegods:twisty_trunk_placer", + "base_height": 10, + "height_rand_a": 6, + "height_rand_b": 4 + }, + "trunk_provider": { + "type": "minecraft:simple_state_provider", + "state": { + "Name": "minecraft:oak_log", + "Properties": { + "axis": "y" + } + } + } + } +} \ No newline at end of file diff --git a/src/generated/resources/data/ageofthegods/worldgen/placed_feature/twisty_tree_placed.json b/src/generated/resources/data/ageofthegods/worldgen/placed_feature/twisty_tree_placed.json new file mode 100644 index 0000000..13e6afa --- /dev/null +++ b/src/generated/resources/data/ageofthegods/worldgen/placed_feature/twisty_tree_placed.json @@ -0,0 +1,44 @@ +{ + "feature": "ageofthegods:twisty_tree", + "placement": [ + { + "type": "minecraft:count", + "count": 10 + }, + { + "type": "minecraft:rarity_filter", + "chance": 10 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:heightmap", + "heightmap": "OCEAN_FLOOR" + }, + { + "type": "minecraft:block_predicate_filter", + "predicate": { + "type": "minecraft:matching_blocks", + "blocks": [ + "ageofthegods:shale_grass_block", + "minecraft:sandstone", + "ageofthegods:shale_block", + "ageofthegods:limestone_grass_block" + ], + "offset": [ + 0, + -1, + 0 + ] + } + }, + { + "type": "minecraft:surface_water_depth_filter", + "max_water_depth": 0 + }, + { + "type": "minecraft:biome" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/worldgen/noise_settings/overworld.json b/src/generated/resources/data/minecraft/worldgen/noise_settings/overworld.json index b5e89ff..04b6bc6 100644 --- a/src/generated/resources/data/minecraft/worldgen/noise_settings/overworld.json +++ b/src/generated/resources/data/minecraft/worldgen/noise_settings/overworld.json @@ -489,9 +489,18 @@ "surface_type": "floor" }, "then_run": { - "type": "minecraft:block", - "result_state": { - "Name": "ageofthegods:limestone_block" + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157E308, + "min_threshold": 0.0, + "noise": "ageofthegods:tiny_patchy_noise" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "ageofthegods:limestone_grass_block" + } } } }, @@ -500,7 +509,23 @@ "if_true": { "type": "minecraft:stone_depth", "add_surface_depth": false, - "offset": 4, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:sandstone" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 10, "secondary_depth_range": 0, "surface_type": "floor" }, @@ -550,6 +575,31 @@ } } }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157E308, + "min_threshold": 0.1, + "noise": "ageofthegods:tiny_patchy_noise" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:granite" + } + } + } + }, { "type": "minecraft:condition", "if_true": { @@ -571,7 +621,32 @@ "if_true": { "type": "minecraft:stone_depth", "add_surface_depth": false, - "offset": 4, + "offset": 10, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 1.7976931348623157E308, + "min_threshold": 0.1, + "noise": "ageofthegods:tiny_patchy_noise" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:granite" + } + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 10, "secondary_depth_range": 0, "surface_type": "floor" }, diff --git a/src/main/java/net/halbear/aotg/AgeoftheGods.java b/src/main/java/net/halbear/aotg/AgeoftheGods.java index 9b8a7ae..0db150b 100644 --- a/src/main/java/net/halbear/aotg/AgeoftheGods.java +++ b/src/main/java/net/halbear/aotg/AgeoftheGods.java @@ -39,7 +39,9 @@ import net.neoforged.neoforge.registries.DeferredItem; import net.neoforged.neoforge.registries.DeferredRegister; import static net.halbear.aotg.registries.ModBlocks.*; +import static net.halbear.aotg.registries.ModFoliagePlacers.FOLIAGE_PLACERS; import static net.halbear.aotg.registries.ModItems.*; +import static net.halbear.aotg.registries.ModTreeGen.TRUNK_PLACERS; // The value here should match an entry in the META-INF/neoforge.mods.toml file @Mod(AgeoftheGods.MODID) @@ -74,6 +76,10 @@ public class AgeoftheGods { ITEMS.register(modEventBus); // Register the Deferred Register to the mod event bus so tabs get registered CREATIVE_MODE_TABS.register(modEventBus); + + TRUNK_PLACERS.register(modEventBus); + + FOLIAGE_PLACERS.register(modEventBus); // Register ourselves for server and other game events we are interested in. // Note that this is necessary if and only if we want *this* class (AgeoftheGods) to respond directly to events. // Do not add this line if there are no @SubscribeEvent-annotated functions in this class, like onServerStarting() below. diff --git a/src/main/java/net/halbear/aotg/custom/WorldGen/GenerationFeatures/LeafBunchFoliagePlacer.java b/src/main/java/net/halbear/aotg/custom/WorldGen/GenerationFeatures/LeafBunchFoliagePlacer.java new file mode 100644 index 0000000..c7d586f --- /dev/null +++ b/src/main/java/net/halbear/aotg/custom/WorldGen/GenerationFeatures/LeafBunchFoliagePlacer.java @@ -0,0 +1,57 @@ +package net.halbear.aotg.custom.WorldGen.GenerationFeatures; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.halbear.aotg.registries.ModFoliagePlacers; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.world.level.LevelSimulatedReader; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; +import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacer; +import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacerType; + +public class LeafBunchFoliagePlacer extends FoliagePlacer { + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> + foliagePlacerParts(instance).apply(instance, LeafBunchFoliagePlacer::new) + ); + + public LeafBunchFoliagePlacer(IntProvider radius, IntProvider offset) { + super(radius, offset); + } + + @Override + protected FoliagePlacerType type() { + return ModFoliagePlacers.LEAF_BUNCH_FOLIAGE_PLACER.get(); + } + + @Override + protected void createFoliage(WorldGenLevel worldGenLevel, FoliageSetter foliageSetter, RandomSource randomSource, TreeConfiguration treeConfiguration, int i, FoliageAttachment foliageAttachment, int foliageHeight, int radius, int offset) { + BlockPos center = foliageAttachment.pos().above(offset); + radius += foliageAttachment.radiusOffset(); + double radiusSq = radius * radius; + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { + for (int z = -radius; z <= radius; z++) { + double distanceSq = (x * x) + (y * y) + (z * z); + + if (distanceSq <= radiusSq + 0.5 && randomSource.nextDouble() < 0.6) { + tryPlaceLeaf(worldGenLevel, foliageSetter, randomSource, treeConfiguration, center.offset(x, y, z)); + } + } + } + } + } + + @Override + public int foliageHeight(RandomSource random, int height, TreeConfiguration config) { + return 0; + } + + @Override + protected boolean shouldSkipLocation(RandomSource random, int localX, int localY, int localZ, int range, boolean large) { + return false; + } +} diff --git a/src/main/java/net/halbear/aotg/custom/WorldGen/GenerationFeatures/TwistyBranchingTrunkPlacer.java b/src/main/java/net/halbear/aotg/custom/WorldGen/GenerationFeatures/TwistyBranchingTrunkPlacer.java new file mode 100644 index 0000000..218047f --- /dev/null +++ b/src/main/java/net/halbear/aotg/custom/WorldGen/GenerationFeatures/TwistyBranchingTrunkPlacer.java @@ -0,0 +1,143 @@ +package net.halbear.aotg.custom.WorldGen.GenerationFeatures; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.halbear.aotg.registries.ModTreeGen; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.LevelSimulatedReader; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; +import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacer; +import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacer; +import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerType; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; + +public class TwistyBranchingTrunkPlacer extends TrunkPlacer { + private static final int BEGINNING_TRUNK_WIDTH = 5; + public TwistyBranchingTrunkPlacer(int baseHeight, int heightRandA, int heightRandB) { + super(baseHeight, heightRandA, heightRandB); + } + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> + trunkPlacerParts(instance).apply(instance, TwistyBranchingTrunkPlacer::new) + ); + + @Override + protected TrunkPlacerType type() { + return ModTreeGen.TWISTY_TRUNK_PLACER.get(); + } + + @Override + public List placeTrunk(WorldGenLevel worldGenLevel, BiConsumer biConsumer, RandomSource randomSource, int freeSpace, BlockPos blockPos, TreeConfiguration treeConfiguration) { + int TRUNK_WIDTH = BEGINNING_TRUNK_WIDTH; + List leafNodes = new ArrayList<>(); + int mainHeight = this.getTreeHeight(randomSource); + BlockPos currentPos = blockPos; + + for (int i = 0; i < mainHeight; i++) { + TRUNK_WIDTH = (int)Math.max(BEGINNING_TRUNK_WIDTH * (1.0-((i*0.75)/(double)mainHeight)),2); + for (int xOffset = 0; xOffset < TRUNK_WIDTH; xOffset++) { + for (int zOffset = 0; zOffset < TRUNK_WIDTH; zOffset++) { + BlockPos thickLogPos = currentPos.offset(xOffset, 0, zOffset); + if(i == 0 ) { + if (checkPointPosition(xOffset, zOffset, TRUNK_WIDTH / 2.0, TRUNK_WIDTH / 2.0, TRUNK_WIDTH / 2.0) != 1 && (randomSource.nextInt(10) < 9) || TRUNK_WIDTH < 3) + this.placeLog(worldGenLevel, biConsumer, randomSource, thickLogPos.below(), treeConfiguration); + } + if(i < 2 && randomSource.nextFloat() < 0.40f){ + generateRoots(worldGenLevel, biConsumer, randomSource, thickLogPos, treeConfiguration); + } + if (checkPointPosition(xOffset, zOffset, TRUNK_WIDTH / 2.0, TRUNK_WIDTH / 2.0, TRUNK_WIDTH / 2.0) != 1 && (randomSource.nextInt(10) < 9) || TRUNK_WIDTH < 3) + this.placeLog(worldGenLevel, biConsumer, randomSource, thickLogPos, treeConfiguration); + else if (randomSource.nextDouble() < 0.1) + leafNodes.add(new FoliagePlacer.FoliageAttachment(thickLogPos, randomSource.nextInt(2), false)); + } + } + if (randomSource.nextFloat() < 0.6f && i > 1) { + currentPos = currentPos.offset(randomSource.nextInt(3) - 1, 0, randomSource.nextInt(3) - 1); + } + + if (i > 2 && randomSource.nextFloat() < 0.40f) { + BlockPos branchStart = currentPos.offset(randomSource.nextInt(TRUNK_WIDTH), 0, randomSource.nextInt(TRUNK_WIDTH)); + BlockPos branchEnd = generateBranch(worldGenLevel, biConsumer, randomSource, branchStart, treeConfiguration,i, leafNodes); + + leafNodes.add(new FoliagePlacer.FoliageAttachment(branchEnd, randomSource.nextInt(2) + (Math.max((int)(i/(double)(mainHeight/1.25))*3,1)), false)); + } else if(i > 2 && i == mainHeight - 1){ + for(int l = 0; l < 1 + randomSource.nextInt(2); l++){ + BlockPos branchStart = currentPos.offset(randomSource.nextInt(TRUNK_WIDTH), 0, randomSource.nextInt(TRUNK_WIDTH)); + BlockPos branchEnd = generateBranch(worldGenLevel, biConsumer, randomSource, branchStart, treeConfiguration,i, leafNodes); + + leafNodes.add(new FoliagePlacer.FoliageAttachment(branchEnd, randomSource.nextInt(2) + (Math.max((int)(i/(double)(mainHeight/1.25))*3,1)), false)); + } + } + + currentPos = currentPos.above(); + } + + for (int xOffset = 0; xOffset < TRUNK_WIDTH; xOffset++) { + for (int zOffset = 0; zOffset < TRUNK_WIDTH; zOffset++) { + leafNodes.add(new FoliagePlacer.FoliageAttachment(currentPos.offset(xOffset, 0, zOffset), 0, false)); + } + } + return leafNodes; + } + + private BlockPos generateRoots(WorldGenLevel level, BiConsumer blockSetter, + RandomSource random, BlockPos branchStart, TreeConfiguration config) { + int dirX = random.nextBoolean() ? 1 : -1; + int dirZ = random.nextBoolean() ? 1 : -1; + int branchLength = 2 + random.nextInt(6); + + BlockPos bPos = branchStart; + for (int b = 0; b < branchLength; b++) { + int stepX = random.nextFloat() < 0.7f ? dirX : 0; + int stepZ = random.nextFloat() < 0.7f ? dirZ : 0; + int stepY = random.nextFloat() < 0.4f ? -1 : 0; + bPos = bPos.offset(stepX, stepY, stepZ); + this.placeLog(level, blockSetter, random, bPos, config); + } + return bPos; + } + + private BlockPos generateBranch(WorldGenLevel level, BiConsumer blockSetter, + RandomSource random, BlockPos branchStart, TreeConfiguration config, int CurrentTreeHeight,List leafNodes) { + int dirX = random.nextBoolean() ? 1 : -1; + int dirZ = random.nextBoolean() ? 1 : -1; + int branchLength = 3 + random.nextInt(Math.min(CurrentTreeHeight,12)); + + BlockPos bPos = branchStart; + for (int b = 0; b < branchLength; b++) { + int stepX = random.nextFloat() < 0.7f ? dirX : 0; + int stepZ = random.nextFloat() < 0.7f ? dirZ : 0; + int stepY = random.nextFloat() < 0.4f ? 1 : 0; + bPos = bPos.offset(stepX, stepY, stepZ); + this.placeLog(level, blockSetter, random, bPos, config); + if (random.nextDouble() < 0.25) { + leafNodes.add(new FoliagePlacer.FoliageAttachment(bPos, random.nextInt(2), false)); + } + } + return bPos; + } + + public static int checkPointPosition(double xp, double yp, double xc, double yc, double r) { + double dx = xp - xc; + double dy = yp - yc; + double squaredDistance = (dx * dx) + (dy * dy); + + double squaredRadius = r * r * 1.25; + + if (squaredDistance < squaredRadius) { + return -1; + } else if (squaredDistance == squaredRadius) { + return 0; + } else { + return 1; + } + } +} diff --git a/src/main/java/net/halbear/aotg/custom/WorldGen/ModNoiseSettings.java b/src/main/java/net/halbear/aotg/custom/WorldGen/ModNoiseSettings.java index 9eb212e..5b6e152 100644 --- a/src/main/java/net/halbear/aotg/custom/WorldGen/ModNoiseSettings.java +++ b/src/main/java/net/halbear/aotg/custom/WorldGen/ModNoiseSettings.java @@ -25,11 +25,20 @@ public class ModNoiseSettings { ResourceKey maquisKey = ResourceKey.create(Registries.BIOME, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "maquis_shrubland")); - SurfaceRules.ConditionSource isGarrigueGrassPatch = SurfaceRules.noiseCondition(Noises.POWDER_SNOW, 0.0); + SurfaceRules.ConditionSource isGarrigueGrassSection = SurfaceRules.noiseCondition(Noises.POWDER_SNOW, 0); + SurfaceRules.ConditionSource isGarrigueGrassPatch = SurfaceRules.noiseCondition(AgeOfTheGodsDataGeneration.TINY_PATCHY_NOISE, 0.0); SurfaceRules.ConditionSource isMaquisGrassPatch = SurfaceRules.noiseCondition(AgeOfTheGodsDataGeneration.TINY_PATCHY_NOISE, 0.0); + SurfaceRules.ConditionSource isGranite = SurfaceRules.noiseCondition(AgeOfTheGodsDataGeneration.TINY_PATCHY_NOISE, 0.1); SurfaceRules.RuleSource garrigueSurface = SurfaceRules.sequence( + SurfaceRules.ifTrue( + SurfaceRules.stoneDepthCheck(0, false, 0, CaveSurface.FLOOR), + SurfaceRules.ifTrue( + isGarrigueGrassSection, + SurfaceRules.state(ModBlocks.LIMESTONE_GRASS_BLOCK.get().defaultBlockState()) + ) + ), SurfaceRules.ifTrue( SurfaceRules.stoneDepthCheck(0, false, 0, CaveSurface.FLOOR), SurfaceRules.ifTrue( @@ -39,9 +48,9 @@ public class ModNoiseSettings { ), SurfaceRules.ifTrue( SurfaceRules.stoneDepthCheck(0, false, 0, CaveSurface.FLOOR), - SurfaceRules.state(ModBlocks.LIMESTONE_BLOCK.get().defaultBlockState()) + SurfaceRules.state(Blocks.SANDSTONE.defaultBlockState()) ), - SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(4, false, 0, CaveSurface.FLOOR), + SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(10, false, 0, CaveSurface.FLOOR), SurfaceRules.state(ModBlocks.LIMESTONE_BLOCK.get().defaultBlockState())) ); @@ -53,11 +62,25 @@ public class ModNoiseSettings { SurfaceRules.state(ModBlocks.SHALE_GRASS_BLOCK.get().defaultBlockState()) ) ), + SurfaceRules.ifTrue( + SurfaceRules.stoneDepthCheck(0, false, 0, CaveSurface.FLOOR), + SurfaceRules.ifTrue( + isGranite, + SurfaceRules.state(Blocks.GRANITE.defaultBlockState()) + ) + ), SurfaceRules.ifTrue( SurfaceRules.stoneDepthCheck(0, false, 0, CaveSurface.FLOOR), SurfaceRules.state(ModBlocks.SHALE_BLOCK.get().defaultBlockState()) ), - SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(4, false, 0, CaveSurface.FLOOR), + SurfaceRules.ifTrue( + SurfaceRules.stoneDepthCheck(10, false, 0, CaveSurface.FLOOR), + SurfaceRules.ifTrue( + isGranite, + SurfaceRules.state(Blocks.GRANITE.defaultBlockState()) + ) + ), + SurfaceRules.ifTrue(SurfaceRules.stoneDepthCheck(10, false, 0, CaveSurface.FLOOR), SurfaceRules.state(ModBlocks.SHALE_BLOCK.get().defaultBlockState())) ); diff --git a/src/main/java/net/halbear/aotg/registries/ModBiomeModifiers.java b/src/main/java/net/halbear/aotg/registries/ModBiomeModifiers.java new file mode 100644 index 0000000..9bd21da --- /dev/null +++ b/src/main/java/net/halbear/aotg/registries/ModBiomeModifiers.java @@ -0,0 +1,36 @@ +package net.halbear.aotg.registries; + +import net.halbear.aotg.AgeoftheGods; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.Biomes; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.neoforged.neoforge.common.world.BiomeModifier; +import net.neoforged.neoforge.common.world.BiomeModifiers; +import net.neoforged.neoforge.registries.NeoForgeRegistries; + +public class ModBiomeModifiers { + public static final ResourceKey ADD_TWISTY_TREE = + ResourceKey.create(NeoForgeRegistries.Keys.BIOME_MODIFIERS, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "add_twisty_tree")); + + public static void bootstrap(BootstrapContext context) { + HolderGetter placedFeatures = context.lookup(Registries.PLACED_FEATURE); + HolderGetter biomes = context.lookup(Registries.BIOME); + + var placedTreeHolder = placedFeatures.getOrThrow(ModPlacedFeatures.TWISTY_TREE_PLACED_KEY); + + var targetBiomes = HolderSet.direct(biomes.getOrThrow(ModBiomes.MAQUIS_SHRUBLAND)); + + context.register(ADD_TWISTY_TREE, new BiomeModifiers.AddFeaturesBiomeModifier( + targetBiomes, + HolderSet.direct(placedTreeHolder), + GenerationStep.Decoration.VEGETAL_DECORATION + )); + } +} diff --git a/src/main/java/net/halbear/aotg/registries/ModConfiguredFeatures.java b/src/main/java/net/halbear/aotg/registries/ModConfiguredFeatures.java new file mode 100644 index 0000000..5d5d05b --- /dev/null +++ b/src/main/java/net/halbear/aotg/registries/ModConfiguredFeatures.java @@ -0,0 +1,36 @@ +package net.halbear.aotg.registries; + +import net.halbear.aotg.AgeoftheGods; +import net.halbear.aotg.custom.WorldGen.GenerationFeatures.LeafBunchFoliagePlacer; +import net.halbear.aotg.custom.WorldGen.GenerationFeatures.TwistyBranchingTrunkPlacer; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.valueproviders.ConstantInt; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration; +import net.minecraft.world.level.levelgen.feature.featuresize.TwoLayersFeatureSize; +import net.minecraft.world.level.levelgen.feature.foliageplacers.BlobFoliagePlacer; +import net.minecraft.world.level.levelgen.feature.foliageplacers.CherryFoliagePlacer; +import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider; + +public class ModConfiguredFeatures { + public static final ResourceKey> TWISTY_TREE_KEY = + ResourceKey.create(Registries.CONFIGURED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "twisty_tree")); + + public static void bootstrap(BootstrapContext> context) { + context.register(TWISTY_TREE_KEY, new ConfiguredFeature<>( + Feature.TREE, + new TreeConfiguration.TreeConfigurationBuilder( + BlockStateProvider.simple(Blocks.OAK_LOG.defaultBlockState()), + new TwistyBranchingTrunkPlacer(10, 6, 4), + BlockStateProvider.simple(Blocks.OAK_LEAVES.defaultBlockState()), + new LeafBunchFoliagePlacer(ConstantInt.of(1),ConstantInt.of(0)), + new TwoLayersFeatureSize(5, 3, 5) + ).build() + )); + } +} diff --git a/src/main/java/net/halbear/aotg/registries/ModFoliagePlacers.java b/src/main/java/net/halbear/aotg/registries/ModFoliagePlacers.java new file mode 100644 index 0000000..c23dc85 --- /dev/null +++ b/src/main/java/net/halbear/aotg/registries/ModFoliagePlacers.java @@ -0,0 +1,22 @@ +package net.halbear.aotg.registries; + +import net.halbear.aotg.AgeoftheGods; +import net.halbear.aotg.custom.WorldGen.GenerationFeatures.LeafBunchFoliagePlacer; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacerType; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +public class ModFoliagePlacers { + + public static final DeferredRegister> FOLIAGE_PLACERS = + DeferredRegister.create(Registries.FOLIAGE_PLACER_TYPE, AgeoftheGods.MODID); + + public static final DeferredHolder, FoliagePlacerType> LEAF_BUNCH_FOLIAGE_PLACER = + FOLIAGE_PLACERS.register("spherical_foliage_placer", () -> new FoliagePlacerType<>(LeafBunchFoliagePlacer.CODEC)); + + public static void register(IEventBus eventBus) { + FOLIAGE_PLACERS.register(eventBus); + } +} diff --git a/src/main/java/net/halbear/aotg/registries/ModPlacedFeatures.java b/src/main/java/net/halbear/aotg/registries/ModPlacedFeatures.java new file mode 100644 index 0000000..7c1a03d --- /dev/null +++ b/src/main/java/net/halbear/aotg/registries/ModPlacedFeatures.java @@ -0,0 +1,48 @@ +package net.halbear.aotg.registries; + +import net.halbear.aotg.AgeoftheGods; +import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.data.worldgen.placement.PlacementUtils; +import net.minecraft.resources.Identifier; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicate; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.placement.*; + +import java.util.List; + +public class ModPlacedFeatures { + public static final ResourceKey TWISTY_TREE_PLACED_KEY = + ResourceKey.create(Registries.PLACED_FEATURE, Identifier.fromNamespaceAndPath(AgeoftheGods.MODID, "twisty_tree_placed")); + + public static void bootstrap(BootstrapContext context) { + HolderGetter> configuredFeatures = context.lookup(Registries.CONFIGURED_FEATURE); + var configuredTreeHolder = configuredFeatures.getOrThrow(ModConfiguredFeatures.TWISTY_TREE_KEY); + + context.register(TWISTY_TREE_PLACED_KEY, new PlacedFeature( + configuredTreeHolder, + List.of( + CountPlacement.of(10), + RarityFilter.onAverageOnceEvery(10), + InSquarePlacement.spread(), + PlacementUtils.HEIGHTMAP_OCEAN_FLOOR, + BlockPredicateFilter.forPredicate( + BlockPredicate.matchesBlocks( + new BlockPos(0, -1, 0), + ModBlocks.SHALE_GRASS_BLOCK.get(), + Blocks.SANDSTONE, + ModBlocks.SHALE_BLOCK.get(), + ModBlocks.LIMESTONE_GRASS_BLOCK.get() + ) + ), + SurfaceWaterDepthFilter.forMaxDepth(0), + + BiomeFilter.biome() + ) + )); + } +} diff --git a/src/main/java/net/halbear/aotg/registries/ModTreeGen.java b/src/main/java/net/halbear/aotg/registries/ModTreeGen.java new file mode 100644 index 0000000..318bc33 --- /dev/null +++ b/src/main/java/net/halbear/aotg/registries/ModTreeGen.java @@ -0,0 +1,21 @@ +package net.halbear.aotg.registries; + +import net.halbear.aotg.AgeoftheGods; +import net.halbear.aotg.custom.WorldGen.GenerationFeatures.TwistyBranchingTrunkPlacer; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerType; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +public class ModTreeGen { + public static final DeferredRegister> TRUNK_PLACERS = + DeferredRegister.create(Registries.TRUNK_PLACER_TYPE, AgeoftheGods.MODID); + + public static final DeferredHolder, TrunkPlacerType> TWISTY_TRUNK_PLACER = + TRUNK_PLACERS.register("twisty_trunk_placer", () -> new TrunkPlacerType<>(TwistyBranchingTrunkPlacer.CODEC)); + + public static void register(IEventBus eventBus) { + TRUNK_PLACERS.register(eventBus); + } +} diff --git a/src/main/java/net/halbear/aotg/rendering/skybox/SkyBoxRendering.java b/src/main/java/net/halbear/aotg/rendering/skybox/SkyBoxRendering.java index f897276..f13e3b0 100644 --- a/src/main/java/net/halbear/aotg/rendering/skybox/SkyBoxRendering.java +++ b/src/main/java/net/halbear/aotg/rendering/skybox/SkyBoxRendering.java @@ -152,13 +152,13 @@ public class SkyBoxRendering { public static void renderCustomSun(RenderLevelStageEvent.AfterSky event, Identifier textureId) { initBuffers(); SkyRenderState state = event.getLevelRenderState().skyRenderState; - render2DObjectInSkybox(event, textureId, "Sun",(float)Math.toRadians(-90F),state.sunAngle,new Vector3f(0,100.0f,0),new Vector3f(30.0F,-1.0F,30.0F),new Vector4f(1f,1f,1f,state.rainBrightness), sunBuffer,RenderPipelines.CELESTIAL); + render2DObjectInSkybox(event, textureId, "Sun",(float)Math.toRadians(-90F),state.sunAngle,new Vector3f(0,100.0f,0),new Vector3f(30.0F,-1.0F,30.0F),new Vector4f(1f,1f,1f,state.rainBrightness), sunBuffer,CUSTOM_SKYBOX_PIPELINE);//RenderPipelines.CELESTIAL); } public static void renderCustomMoon(RenderLevelStageEvent.AfterSky event, Identifier textureId) { initBuffers(); SkyRenderState state = event.getLevelRenderState().skyRenderState; - render2DObjectInSkybox(event, textureId, "Moon",(float)Math.toRadians(-90F),state.moonAngle,new Vector3f(0,100.0f,0),new Vector3f(30.0F,-1.0F,30.0F),new Vector4f(1f,1f,1f,1f), moonBuffer,RenderPipelines.CELESTIAL); + render2DObjectInSkybox(event, textureId, "Moon",(float)Math.toRadians(-90F),state.moonAngle,new Vector3f(0,100.0f,0),new Vector3f(30.0F,-1.0F,30.0F),new Vector4f(1f,1f,1f,1f), moonBuffer,CUSTOM_SKYBOX_PIPELINE);//RenderPipelines.CELESTIAL); } public static float getNightAlpha(long dayTime) { diff --git a/src/main/java/net/halbear/aotg/utility/DataGenerators/AgeOfTheGodsDataGeneration.java b/src/main/java/net/halbear/aotg/utility/DataGenerators/AgeOfTheGodsDataGeneration.java index 08309e1..5ab77de 100644 --- a/src/main/java/net/halbear/aotg/utility/DataGenerators/AgeOfTheGodsDataGeneration.java +++ b/src/main/java/net/halbear/aotg/utility/DataGenerators/AgeOfTheGodsDataGeneration.java @@ -2,6 +2,9 @@ package net.halbear.aotg.utility.DataGenerators; import net.halbear.aotg.AgeoftheGods; import net.halbear.aotg.custom.WorldGen.ModNoiseSettings; +import net.halbear.aotg.registries.ModBiomeModifiers; +import net.halbear.aotg.registries.ModConfiguredFeatures; +import net.halbear.aotg.registries.ModPlacedFeatures; import net.minecraft.core.HolderGetter; import net.minecraft.core.RegistrySetBuilder; import net.minecraft.core.registries.Registries; @@ -17,6 +20,7 @@ import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider; import net.neoforged.neoforge.data.event.GatherDataEvent; +import net.neoforged.neoforge.registries.NeoForgeRegistries; import java.util.Set; @@ -31,7 +35,6 @@ public class AgeOfTheGodsDataGeneration { @SubscribeEvent public static void gatherData(GatherDataEvent.Client event) { LOGGER.info("gatherData event"); - RegistrySetBuilder builder = new RegistrySetBuilder(). add(Registries.NOISE, context -> { context.register(TINY_PATCHY_NOISE, new net.minecraft.world.level.levelgen.synth.NormalNoise.NoiseParameters( @@ -60,7 +63,10 @@ public class AgeOfTheGodsDataGeneration { false ) ); - }); + }) + .add(Registries.CONFIGURED_FEATURE, ModConfiguredFeatures::bootstrap) + .add(Registries.PLACED_FEATURE, ModPlacedFeatures::bootstrap) // Add this + .add(NeoForgeRegistries.Keys.BIOME_MODIFIERS, ModBiomeModifiers::bootstrap);; LOGGER.info("World Gen something or other"); event.createProvider(output -> new DatapackBuiltinEntriesProvider( output, @@ -71,11 +77,7 @@ public class AgeOfTheGodsDataGeneration { } @SubscribeEvent - public static void GatherClientData(GatherDataEvent.Client event){ - LOGGER.info("GatherClientData event"); - DataGenerator generator = event.getGenerator(); - PackOutput output = generator.getPackOutput(); + public static void GatherClientData(GatherDataEvent.Server event){ - // generator.addProvider(true, new AOTGModelProvider(output)); } } diff --git a/src/main/java/net/halbear/aotg/utility/DataGenerators/ModWorldGenProvider.java b/src/main/java/net/halbear/aotg/utility/DataGenerators/ModWorldGenProvider.java new file mode 100644 index 0000000..5631fa2 --- /dev/null +++ b/src/main/java/net/halbear/aotg/utility/DataGenerators/ModWorldGenProvider.java @@ -0,0 +1,26 @@ +package net.halbear.aotg.utility.DataGenerators; + +import net.halbear.aotg.AgeoftheGods; +import net.halbear.aotg.registries.ModBiomeModifiers; +import net.halbear.aotg.registries.ModConfiguredFeatures; +import net.halbear.aotg.registries.ModPlacedFeatures; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.RegistrySetBuilder; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.PackOutput; +import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider; +import net.neoforged.neoforge.registries.NeoForgeRegistries; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +public class ModWorldGenProvider extends DatapackBuiltinEntriesProvider { + public static final RegistrySetBuilder BUILDER = new RegistrySetBuilder() + .add(Registries.CONFIGURED_FEATURE, ModConfiguredFeatures::bootstrap) + .add(Registries.PLACED_FEATURE, ModPlacedFeatures::bootstrap) // Add this + .add(NeoForgeRegistries.Keys.BIOME_MODIFIERS, ModBiomeModifiers::bootstrap); + + public ModWorldGenProvider(PackOutput output, CompletableFuture registries) { + super(output, registries, BUILDER, Set.of(AgeoftheGods.MODID)); + } +}