Skip to content

Commit

Permalink
added experimental underground biome generation
Browse files Browse the repository at this point in the history
  • Loading branch information
supermassimo committed Jul 4, 2024
1 parent cf99d0e commit 67473ab
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.ferreusveritas.dynamictrees.api.worldgen;

import com.ferreusveritas.dynamictrees.worldgen.OverworldGroundFinder;
import com.ferreusveritas.dynamictrees.worldgen.SurfaceGroundFinder;
import com.ferreusveritas.dynamictrees.worldgen.SubterraneanGroundFinder;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
Expand All @@ -21,11 +22,12 @@
public interface GroundFinder {

GroundFinder OVERWORLD = new OverworldGroundFinder();
GroundFinder SURFACE = new SurfaceGroundFinder();
GroundFinder SUBTERRANEAN = new SubterraneanGroundFinder();

/**
* If this is not set manually, the ground finder returned will be {@link #SUBTERRANEAN} if {@link DimensionType#hasCeiling()}
* returns {@code true} or {@link #OVERWORLD} if {@code false}.
* returns {@code true} or {@link #SURFACE} if {@code false}.
*/
Map<ResourceKey<Level>, GroundFinder> GROUND_FINDERS = new HashMap<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ public static BlockPos findWorldSurface(LevelAccessor level, BlockPos startPos,
);
}

public static boolean inRange(final BlockPos pos, final int minY, final int maxY) {
return pos.getY() >= minY && pos.getY() <= maxY;
}

//Some ready made not terrible prime hash factors
private static final int[][] coordHashMap = {
{4111, 271, 3067},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
import com.ferreusveritas.dynamictrees.api.worldgen.GroundFinder;
import com.ferreusveritas.dynamictrees.util.CoordUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.tags.BiomeTags;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraftforge.common.Tags;
import net.minecraftforge.common.data.ForgeBiomeTagsProvider;

import javax.annotation.Nullable;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
Expand All @@ -17,11 +21,26 @@ public final class OverworldGroundFinder implements GroundFinder {

@Override
public List<BlockPos> findGround(LevelAccessor level, BlockPos start, @Nullable Heightmap.Types heightmap) {
if (heightmap == null) {
return Collections.singletonList(CoordUtils.findWorldSurface(level, start, true));
} else {
return Collections.singletonList(CoordUtils.findWorldSurface(level, start, heightmap));
}
//We start of by getting the surface ground
LinkedList<BlockPos> surfaceGround = new LinkedList<>(SURFACE.findGround(level, start, heightmap));
BlockPos surfaceBlock = surfaceGround.get(0);
//Then we do a very sparse check to find underground biomes
final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(start.getX(), 0, start.getZ());
boolean caveBiomeFound = false;
while (CoordUtils.inRange(pos, level.getMinBuildHeight(), surfaceBlock.getY())) {
if (level.getBiome(pos).is(Tags.Biomes.IS_UNDERGROUND)){
caveBiomeFound = true;
break;
}
pos.move(0,-10,0);
}
//If underground biomes are present, we want to include them
if (caveBiomeFound){
List<BlockPos> subterraneanGround = SUBTERRANEAN.findGround(level, start, heightmap);
surfaceGround.addAll(subterraneanGround);
return new LinkedList<>(surfaceGround);
}
return surfaceGround;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import com.ferreusveritas.dynamictrees.api.worldgen.GroundFinder;
import com.ferreusveritas.dynamictrees.block.DynamicSaplingBlock;
import com.ferreusveritas.dynamictrees.util.CoordUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraftforge.common.Tags;

import javax.annotation.Nullable;
import java.util.ArrayList;
Expand All @@ -21,11 +24,7 @@ public class SubterraneanGroundFinder implements GroundFinder {
private static final List<BlockPos> NO_LAYERS = Collections.singletonList(BlockPos.ZERO);

protected boolean isReplaceable(final LevelAccessor level, final BlockPos pos) {
return (level.isEmptyBlock(pos) || !level.getBlockState(pos).blocksMotion() || level.getBlockState(pos).getBlock() instanceof DynamicSaplingBlock) && !level.getBlockState(pos).liquid();
}

protected boolean inRange(final BlockPos pos, final int minY, final int maxY) {
return pos.getY() >= minY && pos.getY() <= maxY;
return (level.isEmptyBlock(pos) || level.getBlockState(pos).is(BlockTags.REPLACEABLE_BY_TREES)) && level.getBlockState(pos).getFluidState().isEmpty();
}

protected int getTopY(final LevelAccessor level, final BlockPos pos) {
Expand All @@ -34,22 +33,22 @@ protected int getTopY(final LevelAccessor level, final BlockPos pos) {

protected ArrayList<Integer> findSubterraneanLayerHeights(final LevelAccessor level, final BlockPos start) {
final int maxY = this.getTopY(level, start);

final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(start.getX(), 0, start.getZ());
final int minY = level.getMinBuildHeight();
final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(start.getX(), minY, start.getZ());
final ArrayList<Integer> layers = new ArrayList<>();

while (this.inRange(pos, 0, maxY)) {
while (!isReplaceable(level, pos) && this.inRange(pos, 0, maxY)) {
while (CoordUtils.inRange(pos, minY, maxY)) {
while (!isReplaceable(level, pos) && CoordUtils.inRange(pos, minY, maxY)) {
pos.move(Direction.UP, 4); // Zip up 4 blocks at a time until we hit air
}
while (isReplaceable(level, pos) && this.inRange(pos, 0, maxY)) {
while (isReplaceable(level, pos) && CoordUtils.inRange(pos, minY, maxY)) {
pos.move(Direction.DOWN); // Move down 1 block at a time until we hit not-air
}
if (isReplaceable(level, pos.above(6))) { // If there is air 6 blocks above it is likely that the layer is not too cramped
layers.add(pos.getY()); // Record this position
}
pos.move(Direction.UP, 8); // Move up 8 blocks
while (isReplaceable(level, pos) && this.inRange(pos, 0, maxY)) {
while (isReplaceable(level, pos) && CoordUtils.inRange(pos, minY, maxY)) {
pos.move(Direction.UP, 4); // Zip up 4 blocks at a time until we hit ground
}
}
Expand All @@ -70,7 +69,10 @@ public List<BlockPos> findGround(LevelAccessor level, BlockPos start, @Nullable
}
List<BlockPos> positions = new LinkedList<>();
for (int y : layers) {
positions.add(new BlockPos(start.getX(), y, start.getZ()));
BlockPos pos = new BlockPos(start.getX(), y, start.getZ());
//We only want positions for underground biomes and underground dimensions
if (level.dimensionType().hasCeiling() || level.getBiome(pos).is(Tags.Biomes.IS_UNDERGROUND))
positions.add(pos);
}

return positions;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.ferreusveritas.dynamictrees.worldgen;

import com.ferreusveritas.dynamictrees.api.worldgen.GroundFinder;
import com.ferreusveritas.dynamictrees.util.CoordUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.levelgen.Heightmap;

import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;

/**
* @author Harley O'Connor
*/
public final class SurfaceGroundFinder implements GroundFinder {

@Override
public List<BlockPos> findGround(LevelAccessor level, BlockPos start, @Nullable Heightmap.Types heightmap) {
if (heightmap == null) {
return Collections.singletonList(CoordUtils.findWorldSurface(level, start, true));
} else {
return Collections.singletonList(CoordUtils.findWorldSurface(level, start, heightmap));
}
}

}

0 comments on commit 67473ab

Please sign in to comment.