improve how world spawn is located

This commit is contained in:
dags- 2020-04-30 17:16:47 +01:00
parent d9a7afb225
commit 151fc67284
6 changed files with 109 additions and 5 deletions

View File

@ -163,9 +163,8 @@ public class River extends TerrainPopulator {
// lerp the position's height to the riverbank height // lerp the position's height to the riverbank height
if (cell.value > bankHeight) { if (cell.value > bankHeight) {
cell.value = NoiseUtil.lerp(cell.value, bankHeight, valleyAlpha); cell.value = NoiseUtil.lerp(cell.value, bankHeight, valleyAlpha);
return true;
} }
return false; return true;
} }
private boolean carveBanks(Cell<Terrain> cell, float banksAlpha, float bedHeight) { private boolean carveBanks(Cell<Terrain> cell, float banksAlpha, float bedHeight) {

View File

@ -63,10 +63,22 @@ public class BiomeProvider extends AbstractBiomeProvider {
this.modifierManager = SetupHooks.setup(new BiomeModifierManager(context, biomeMap), context.copy()); this.modifierManager = SetupHooks.setup(new BiomeModifierManager(context, biomeMap), context.copy());
} }
public TerraContext getContext() {
return context;
}
public void lookupPos(int x, int z, Cell<Terrain> cell) {
worldLookup.applyCell(cell, x, z);
}
public Cell<Terrain> lookupPos(int x, int z) { public Cell<Terrain> lookupPos(int x, int z) {
return worldLookup.getCell(x, z); return worldLookup.getCell(x, z);
} }
public boolean canSpawnAt(Cell<Terrain> cell) {
return cell.tag != context.terrain.ocean && cell.tag != context.terrain.deepOcean && cell.value > context.levels.ground;
}
@Override @Override
public Biome getNoiseBiome(int x, int y, int z) { public Biome getNoiseBiome(int x, int y, int z) {
x = (x << 2); x = (x << 2);

View File

@ -0,0 +1,43 @@
package com.terraforged.mod.biome.spawn;
import com.terraforged.mod.Log;
import com.terraforged.mod.biome.provider.BiomeProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
public class SpawnHandler {
@SubscribeEvent
public static void createSpawn(WorldEvent.CreateSpawnPosition event) {
if (event.getWorld() instanceof ServerWorld) {
ServerWorld world =(ServerWorld) event.getWorld();
if (world.getChunkProvider().getChunkGenerator().getBiomeProvider() instanceof BiomeProvider) {
Log.info("Searching for world spawn position");
BiomeProvider provider = (BiomeProvider) world.getChunkProvider().getChunkGenerator().getBiomeProvider();
SpawnSearch search = new SpawnSearch(BlockPos.ZERO, provider);
BlockPos spawn = search.get();
Log.info("Setting world spawn: {}", spawn);
event.setCanceled(true);
event.getWorld().getWorldInfo().setSpawn(spawn);
if (event.getSettings().isBonusChestEnabled()) {
Log.info("Generating bonus chest");
createBonusChest(world, spawn);
}
}
}
}
private static void createBonusChest(ServerWorld world, BlockPos pos) {
ConfiguredFeature<?, ?> chest = Feature.BONUS_CHEST.withConfiguration(IFeatureConfig.NO_FEATURE_CONFIG);
chest.place(world, world.getChunkProvider().getChunkGenerator(), world.rand, pos);
}
}

View File

@ -0,0 +1,43 @@
package com.terraforged.mod.biome.spawn;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.terrain.Terrain;
import com.terraforged.mod.Log;
import com.terraforged.mod.biome.provider.BiomeProvider;
import com.terraforged.mod.command.search.Search;
import net.minecraft.util.math.BlockPos;
public class SpawnSearch extends Search {
private final BiomeProvider biomeProvider;
private final Cell<Terrain> cell = new Cell<>();
public SpawnSearch(BlockPos center, BiomeProvider biomeProvider) {
super(center, 0, 2048);
this.biomeProvider = biomeProvider;
}
@Override
public int getSpacing() {
return 64;
}
@Override
public boolean test(BlockPos pos) {
biomeProvider.lookupPos(pos.getX(), pos.getZ(), cell);
return biomeProvider.canSpawnAt(cell);
}
@Override
protected BlockPos success(BlockPos.Mutable pos) {
pos.setY(biomeProvider.getContext().levels.scale(cell.value));
Log.info("Found valid spawn position: {}", pos);
return super.success(pos);
}
@Override
protected BlockPos fail(BlockPos pos) {
Log.info("Unable to find valid spawn position, defaulting x=0, z=0");
return new BlockPos(0, biomeProvider.getContext().levels.groundLevel, 0);
}
}

View File

@ -41,7 +41,6 @@ import net.minecraft.command.arguments.IArgumentSerializer;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.StringTextComponent;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;

View File

@ -38,6 +38,14 @@ public abstract class Search implements Supplier<BlockPos> {
return 16; return 16;
} }
protected BlockPos success(BlockPos.Mutable pos) {
return pos.toImmutable();
}
protected BlockPos fail(BlockPos pos) {
return pos;
}
@Override @Override
public BlockPos get() { public BlockPos get() {
int radius = maxRadius; int radius = maxRadius;
@ -60,7 +68,7 @@ public abstract class Search implements Supplier<BlockPos> {
pos.setPos(center.getX() + (x * getSpacing()), center.getY(), center.getZ() + (z * getSpacing())); pos.setPos(center.getX() + (x * getSpacing()), center.getY(), center.getZ() + (z * getSpacing()));
if (center.distanceSq(pos) >= minRadius2) { if (center.distanceSq(pos) >= minRadius2) {
if (test(pos)) { if (test(pos)) {
return pos.toImmutable(); return success(pos);
} }
} }
} }
@ -75,7 +83,7 @@ public abstract class Search implements Supplier<BlockPos> {
z += dz; z += dz;
} }
return BlockPos.ZERO; return fail(BlockPos.ZERO);
} }
public abstract boolean test(BlockPos pos); public abstract boolean test(BlockPos pos);