Fill the crater with water in case there is some adjacent water (#4430)
* Fill the crater with water in case there is some adjacent water * Removed whitelist/blacklist tags
This commit is contained in:
@@ -39,8 +39,8 @@ import appeng.items.AEBaseItem;
|
||||
import appeng.util.Platform;
|
||||
import appeng.worldgen.meteorite.CraterType;
|
||||
import appeng.worldgen.meteorite.MeteoritePlacer;
|
||||
import appeng.worldgen.meteorite.MeteoriteSpawner;
|
||||
import appeng.worldgen.meteorite.PlacedMeteoriteSettings;
|
||||
import appeng.worldgen.meteorite.debug.MeteoriteSpawner;
|
||||
|
||||
public class MeteoritePlacerItem extends AEBaseItem {
|
||||
|
||||
|
||||
@@ -23,4 +23,5 @@ public class Constants {
|
||||
public static final String TAG_CRATER = "t";
|
||||
public static final String TAG_FALLOUT = "f";
|
||||
public static final String TAG_PURE = "p";
|
||||
public static final String TAG_LAKE = "l";
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public final class MeteoritePlacer {
|
||||
private final boolean placeCrater;
|
||||
private final CraterType craterType;
|
||||
private final boolean pureCrater;
|
||||
private final boolean craterLake;
|
||||
private final MutableBoundingBox boundingBox;
|
||||
|
||||
public MeteoritePlacer(IWorld world, PlacedMeteoriteSettings settings, MutableBoundingBox boundingBox) {
|
||||
@@ -84,6 +85,7 @@ public final class MeteoritePlacer {
|
||||
this.placeCrater = settings.shouldPlaceCrater();
|
||||
this.craterType = settings.getCraterType();
|
||||
this.pureCrater = settings.isPureCrater();
|
||||
this.craterLake = settings.isCraterLake();
|
||||
this.squaredMeteoriteSize = this.meteoriteSize * this.meteoriteSize;
|
||||
this.crater = this.realCrater * this.realCrater;
|
||||
|
||||
@@ -108,6 +110,9 @@ public final class MeteoritePlacer {
|
||||
if (placeCrater) {
|
||||
this.decay();
|
||||
}
|
||||
if (craterLake) {
|
||||
this.placeCraterLake();
|
||||
}
|
||||
}
|
||||
|
||||
private int minX(int x) {
|
||||
@@ -374,6 +379,40 @@ public final class MeteoritePlacer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If it finds a single water block at y62, it will replace any air blocks below
|
||||
* the sea level with water.
|
||||
*/
|
||||
private void placeCraterLake() {
|
||||
final int maxY = world.getSeaLevel() - 1;
|
||||
BlockPos.Mutable blockPos = new BlockPos.Mutable();
|
||||
|
||||
for (int j = y - 5; j <= maxY; j++) {
|
||||
blockPos.setY(j);
|
||||
|
||||
for (int i = boundingBox.minX; i <= boundingBox.maxX; i++) {
|
||||
blockPos.setX(i);
|
||||
|
||||
for (int k = boundingBox.minZ; k <= boundingBox.maxZ; k++) {
|
||||
blockPos.setZ(k);
|
||||
final double dx = i - x;
|
||||
final double dz = k - z;
|
||||
final double h = y - this.meteoriteSize + 1 + this.type.adjustCrater();
|
||||
|
||||
final double distanceFrom = dx * dx + dz * dz;
|
||||
|
||||
if (j > h + distanceFrom * 0.02) {
|
||||
BlockState currentBlock = world.getBlockState(blockPos);
|
||||
if (currentBlock.getBlock() == Blocks.AIR) {
|
||||
this.putter.put(world, blockPos, Blocks.WATER.getDefaultState());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Fallout getFallout(IWorld w, BlockPos pos, FalloutMode mode) {
|
||||
switch (mode) {
|
||||
case SAND:
|
||||
|
||||
@@ -5,8 +5,6 @@ import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.Dynamic;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MutableBoundingBox;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeManager;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
@@ -15,10 +13,7 @@ import net.minecraft.world.gen.NetherChunkGenerator;
|
||||
import net.minecraft.world.gen.feature.NoFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.structure.ScatteredStructure;
|
||||
import net.minecraft.world.gen.feature.structure.Structure;
|
||||
import net.minecraft.world.gen.feature.structure.StructureStart;
|
||||
import net.minecraft.world.gen.feature.template.TemplateManager;
|
||||
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.AppEng;
|
||||
|
||||
@@ -68,7 +63,7 @@ public class MeteoriteStructure extends ScatteredStructure<NoFeatureConfig> {
|
||||
|
||||
@Override
|
||||
public Structure.IStartFactory getStartFactory() {
|
||||
return MeteoriteStructure.Start::new;
|
||||
return MeteoriteStructureStart::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,24 +71,4 @@ public class MeteoriteStructure extends ScatteredStructure<NoFeatureConfig> {
|
||||
return 124895654;
|
||||
}
|
||||
|
||||
public static class Start extends StructureStart {
|
||||
public Start(Structure<?> p_i225815_1_, int p_i225815_2_, int p_i225815_3_, MutableBoundingBox p_i225815_4_,
|
||||
int p_i225815_5_, long p_i225815_6_) {
|
||||
super(p_i225815_1_, p_i225815_2_, p_i225815_3_, p_i225815_4_, p_i225815_5_, p_i225815_6_);
|
||||
}
|
||||
|
||||
public void init(ChunkGenerator<?> generator, TemplateManager templateManagerIn, int chunkX, int chunkZ,
|
||||
Biome biome) {
|
||||
float meteoriteSize = (this.rand.nextFloat() * 6.0f) + 2;
|
||||
|
||||
int centerX = chunkX * 16 + rand.nextInt(16);
|
||||
int centerZ = chunkZ * 16 + rand.nextInt(16);
|
||||
|
||||
BlockPos actualPos = new BlockPos(centerX, AEConfig.instance().getMeteoriteMaximumSpawnHeight(), centerZ);
|
||||
|
||||
components.add(new MeteoriteStructurePiece(actualPos, meteoriteSize));
|
||||
this.recalculateStructureSize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,9 +24,6 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.MutableBoundingBox;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.Biome.Category;
|
||||
import net.minecraft.world.biome.Biome.TempCategory;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
import net.minecraft.world.gen.feature.structure.IStructurePieceType;
|
||||
import net.minecraft.world.gen.feature.structure.StructurePiece;
|
||||
@@ -42,35 +39,31 @@ public class MeteoriteStructurePiece extends StructurePiece {
|
||||
|
||||
private PlacedMeteoriteSettings settings;
|
||||
|
||||
protected MeteoriteStructurePiece(BlockPos center, float coreRadius) {
|
||||
protected MeteoriteStructurePiece(BlockPos center, float coreRadius, CraterType craterType, FalloutMode fallout,
|
||||
boolean pureCrater, boolean craterLake) {
|
||||
super(TYPE, 0);
|
||||
this.settings = new PlacedMeteoriteSettings(center, coreRadius, null, null, false);
|
||||
this.settings = new PlacedMeteoriteSettings(center, coreRadius, craterType, fallout, pureCrater, craterLake);
|
||||
|
||||
// Since we don't know yet if the meteorite will be underground or not,
|
||||
// we have to assume maximum size
|
||||
int range = (int) Math.ceil((coreRadius * 2 + 5) * 1.25f);
|
||||
// Assume a normal max height of 128 blocks for most biomes,
|
||||
// meteors spawned at about y64 are 9x9 chunks large at most.
|
||||
int range = 4 * 16;
|
||||
|
||||
this.boundingBox = new MutableBoundingBox(center.getX() - range, center.getY(), center.getZ() - range,
|
||||
center.getX() + range, center.getY(), center.getZ() + range);
|
||||
ChunkPos chunkPos = new ChunkPos(center);
|
||||
this.boundingBox = new MutableBoundingBox(chunkPos.getXStart() - range, center.getY(),
|
||||
chunkPos.getZStart() - range, chunkPos.getXEnd() + range, center.getY(), chunkPos.getZEnd() + range);
|
||||
}
|
||||
|
||||
public MeteoriteStructurePiece(TemplateManager templateManager, CompoundNBT tag) {
|
||||
super(TYPE, tag);
|
||||
|
||||
// Mandatory fields
|
||||
BlockPos center = BlockPos.fromLong(tag.getLong(Constants.TAG_POS));
|
||||
float coreRadius = tag.getFloat(Constants.TAG_RADIUS);
|
||||
CraterType craterType = null;
|
||||
FalloutMode fallout = null;
|
||||
boolean pureCrater = false;
|
||||
CraterType craterType = CraterType.values()[tag.getByte(Constants.TAG_CRATER)];
|
||||
FalloutMode fallout = FalloutMode.values()[tag.getByte(Constants.TAG_FALLOUT)];
|
||||
boolean pureCrater = tag.getBoolean(Constants.TAG_PURE);
|
||||
boolean craterLake = tag.getBoolean(Constants.TAG_LAKE);
|
||||
|
||||
if (tag.contains(Constants.TAG_CRATER)) {
|
||||
craterType = CraterType.values()[tag.getByte(Constants.TAG_CRATER)];
|
||||
fallout = FalloutMode.values()[tag.getByte(Constants.TAG_FALLOUT)];
|
||||
pureCrater = tag.getBoolean(Constants.TAG_PURE);
|
||||
}
|
||||
|
||||
this.settings = new PlacedMeteoriteSettings(center, coreRadius, craterType, fallout, pureCrater);
|
||||
this.settings = new PlacedMeteoriteSettings(center, coreRadius, craterType, fallout, pureCrater, craterLake);
|
||||
}
|
||||
|
||||
public boolean isFinalized() {
|
||||
@@ -85,134 +78,19 @@ public class MeteoriteStructurePiece extends StructurePiece {
|
||||
protected void readAdditional(CompoundNBT tag) {
|
||||
tag.putFloat(Constants.TAG_RADIUS, settings.getMeteoriteRadius());
|
||||
tag.putLong(Constants.TAG_POS, settings.getPos().toLong());
|
||||
if (isFinalized()) {
|
||||
tag.putByte(Constants.TAG_CRATER, (byte) settings.getCraterType().ordinal());
|
||||
tag.putByte(Constants.TAG_FALLOUT, (byte) settings.getFallout().ordinal());
|
||||
}
|
||||
tag.putByte(Constants.TAG_CRATER, (byte) settings.getCraterType().ordinal());
|
||||
tag.putByte(Constants.TAG_FALLOUT, (byte) settings.getFallout().ordinal());
|
||||
tag.putBoolean(Constants.TAG_PURE, settings.isPureCrater());
|
||||
tag.putBoolean(Constants.TAG_LAKE, settings.isCraterLake());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create(IWorld world, ChunkGenerator<?> chunkGeneratorIn, Random rand, MutableBoundingBox bounds,
|
||||
ChunkPos chunkPos) {
|
||||
|
||||
// The parent structure synchronizes on the list of components, so this
|
||||
// placement should be
|
||||
// mutually exclusive with any other chunk the structure is placed in. This
|
||||
// allows us to
|
||||
// finalize some of the placement parameters now that we have access to an
|
||||
// actual world object
|
||||
if (!isFinalized()) {
|
||||
MeteoriteSpawner spawner = new MeteoriteSpawner();
|
||||
BlockPos center = settings.getPos();
|
||||
float coreRadius = settings.getMeteoriteRadius();
|
||||
CraterType craterType = determineCraterType(world, center, rand);
|
||||
boolean pureCrater = rand.nextFloat() > .5f;
|
||||
settings = spawner.trySpawnMeteoriteAtSuitableHeight(world, center, coreRadius, craterType, pureCrater,
|
||||
true);
|
||||
if (settings == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MeteoritePlacer placer = new MeteoritePlacer(world, settings, bounds);
|
||||
placer.place();
|
||||
|
||||
WorldData.instance().compassData().service().updateArea(world, chunkPos); // FIXME: We know the y-range here...
|
||||
return true;
|
||||
}
|
||||
|
||||
private CraterType determineCraterType(IWorld world, BlockPos center, Random rand) {
|
||||
final Biome biome = world.getBiome(center);
|
||||
final TempCategory temp = biome.getTempCategory();
|
||||
final Category category = biome.getCategory();
|
||||
|
||||
// No craters in oceans
|
||||
if (category == Category.OCEAN) {
|
||||
return CraterType.NONE;
|
||||
}
|
||||
|
||||
// 50% chance for a special meteor
|
||||
final boolean specialMeteor = rand.nextFloat() > .5f;
|
||||
|
||||
// Just a normal one
|
||||
if (!specialMeteor) {
|
||||
return CraterType.NORMAL;
|
||||
}
|
||||
|
||||
// Warm biomes, higher chance for lava
|
||||
if (temp == TempCategory.WARM) {
|
||||
|
||||
// 50% chance to actually spawn as lava
|
||||
final boolean lava = rand.nextFloat() > .5f;
|
||||
|
||||
switch (biome.getPrecipitation()) {
|
||||
// No rainfall, only lava
|
||||
case NONE:
|
||||
return lava ? CraterType.LAVA : CraterType.NORMAL;
|
||||
|
||||
// 25% chance to convert a lava to obsidian
|
||||
case RAIN:
|
||||
final boolean obsidian = rand.nextFloat() > .75f;
|
||||
final CraterType alternativObsidian = obsidian ? CraterType.OBSIDIAN : CraterType.LAVA;
|
||||
return lava ? alternativObsidian : CraterType.NORMAL;
|
||||
|
||||
// Nothing for now.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Temperate biomes. Water or maybe lava
|
||||
if (temp == TempCategory.MEDIUM) {
|
||||
// 75% chance to actually spawn with a crater lake
|
||||
final boolean lake = rand.nextFloat() > .25f;
|
||||
// 20% to spawn with lava
|
||||
final boolean lava = rand.nextFloat() > .8f;
|
||||
|
||||
switch (biome.getPrecipitation()) {
|
||||
// No rainfall, water how?
|
||||
case NONE:
|
||||
return lava ? CraterType.LAVA : CraterType.NORMAL;
|
||||
// Rainfall, can also turn lava to obsidian
|
||||
case RAIN:
|
||||
final boolean obsidian = rand.nextFloat() > .75f;
|
||||
final CraterType alternativObsidian = obsidian ? CraterType.OBSIDIAN : CraterType.LAVA;
|
||||
final CraterType craterLake = lake ? CraterType.WATER : CraterType.NORMAL;
|
||||
return lava ? alternativObsidian : craterLake;
|
||||
// No lava, but snow
|
||||
case SNOW:
|
||||
final boolean snow = rand.nextFloat() > .75f;
|
||||
final CraterType water = lake ? CraterType.WATER : CraterType.NORMAL;
|
||||
return snow ? CraterType.SNOW : water;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Cold biomes, Snow or Ice, maybe water and very rarely lava.
|
||||
if (temp == TempCategory.COLD) {
|
||||
// 75% chance to actually spawn with a crater lake
|
||||
final boolean lake = rand.nextFloat() > .25f;
|
||||
// 5% to spawn with lava
|
||||
final boolean lava = rand.nextFloat() > .95f;
|
||||
// 75% chance to freeze
|
||||
final boolean frozen = rand.nextFloat() > .25f;
|
||||
|
||||
switch (biome.getPrecipitation()) {
|
||||
// No rainfall, water how?
|
||||
case NONE:
|
||||
return lava ? CraterType.LAVA : CraterType.NORMAL;
|
||||
case RAIN:
|
||||
final CraterType frozenLake = frozen ? CraterType.ICE : CraterType.WATER;
|
||||
final CraterType craterLake = lake ? frozenLake : CraterType.NORMAL;
|
||||
return lava ? CraterType.LAVA : craterLake;
|
||||
case SNOW:
|
||||
final CraterType snowCovered = lake ? CraterType.SNOW : CraterType.NORMAL;
|
||||
return lava ? CraterType.LAVA : snowCovered;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return CraterType.NORMAL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
package appeng.worldgen.meteorite;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.math.StatsAccumulator;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MutableBoundingBox;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.Biome.Category;
|
||||
import net.minecraft.world.biome.Biome.TempCategory;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.Heightmap.Type;
|
||||
import net.minecraft.world.gen.feature.structure.Structure;
|
||||
import net.minecraft.world.gen.feature.structure.StructureStart;
|
||||
import net.minecraft.world.gen.feature.template.TemplateManager;
|
||||
|
||||
import appeng.worldgen.meteorite.fallout.FalloutMode;
|
||||
|
||||
public class MeteoriteStructureStart extends StructureStart {
|
||||
|
||||
private final Tag<Block> sandTag = BlockTags.getCollection().getOrCreate(new ResourceLocation("minecraft:sand"));
|
||||
private final Tag<Block> terracottaTag = BlockTags.getCollection()
|
||||
.getOrCreate(new ResourceLocation("forge:terracotta"));
|
||||
|
||||
public MeteoriteStructureStart(Structure<?> p_i225815_1_, int p_i225815_2_, int p_i225815_3_,
|
||||
MutableBoundingBox p_i225815_4_, int p_i225815_5_, long p_i225815_6_) {
|
||||
super(p_i225815_1_, p_i225815_2_, p_i225815_3_, p_i225815_4_, p_i225815_5_, p_i225815_6_);
|
||||
}
|
||||
|
||||
public void init(ChunkGenerator<?> generator, TemplateManager templateManagerIn, int chunkX, int chunkZ,
|
||||
Biome biome) {
|
||||
final int centerX = chunkX * 16 + this.rand.nextInt(16);
|
||||
final int centerZ = chunkZ * 16 + this.rand.nextInt(16);
|
||||
final float meteoriteRadius = (this.rand.nextFloat() * 6.0f) + 2;
|
||||
final int yOffset = (int) Math.ceil(meteoriteRadius) + 1;
|
||||
|
||||
final Set<Biome> t2 = generator.getBiomeProvider().getBiomes(centerX, 0, centerZ, 0);
|
||||
final Biome spawnBiome = t2.stream().findFirst().orElse(biome);
|
||||
|
||||
final boolean isOcean = spawnBiome.getCategory() == Category.OCEAN;
|
||||
final Type heightmapType = isOcean ? Heightmap.Type.OCEAN_FLOOR_WG : Heightmap.Type.WORLD_SURFACE_WG;
|
||||
|
||||
// Accumulate stats about the surrounding heightmap
|
||||
StatsAccumulator stats = new StatsAccumulator();
|
||||
int scanRadius = (int) Math.max(1, meteoriteRadius * 2);
|
||||
for (int x = -scanRadius; x <= scanRadius; x++) {
|
||||
for (int z = -scanRadius; z <= scanRadius; z++) {
|
||||
int h = generator.func_222529_a(centerX + x, centerZ + z, heightmapType);
|
||||
stats.add(h);
|
||||
}
|
||||
}
|
||||
|
||||
int centerY = (int) stats.mean();
|
||||
// Spawn it down a bit further with a high variance.
|
||||
if (stats.populationVariance() > 5) {
|
||||
centerY -= (stats.mean() - stats.min()) * .75;
|
||||
}
|
||||
|
||||
// Offset caused by the meteorsize
|
||||
centerY -= yOffset;
|
||||
// Limit to not spawn below y32
|
||||
centerY = Math.max(32, centerY);
|
||||
|
||||
BlockPos actualPos = new BlockPos(centerX, centerY, centerZ);
|
||||
|
||||
boolean craterLake = this.locateWaterAroundTheCrater(generator, actualPos, meteoriteRadius);
|
||||
CraterType craterType = this.determineCraterType(spawnBiome);
|
||||
boolean pureCrater = this.rand.nextFloat() > .9f;
|
||||
FalloutMode fallout = getFalloutFromBaseBlock(spawnBiome.getSurfaceBuilderConfig().getTop());
|
||||
|
||||
components.add(
|
||||
new MeteoriteStructurePiece(actualPos, meteoriteRadius, craterType, fallout, pureCrater, craterLake));
|
||||
|
||||
this.recalculateStructureSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan for water about 1 block further than the crater radius 333 1174
|
||||
*
|
||||
* @return true, if it found a single block of water
|
||||
*/
|
||||
private boolean locateWaterAroundTheCrater(ChunkGenerator<?> generator, BlockPos pos, float radius) {
|
||||
final int seaLevel = generator.getSeaLevel();
|
||||
final int maxY = seaLevel - 1;
|
||||
BlockPos.Mutable blockPos = new BlockPos.Mutable();
|
||||
|
||||
blockPos.setY(maxY);
|
||||
for (int i = pos.getX() - 32; i <= pos.getX() + 32; i++) {
|
||||
blockPos.setX(i);
|
||||
|
||||
for (int k = pos.getZ() - 32; k <= pos.getZ() + 32; k++) {
|
||||
blockPos.setZ(k);
|
||||
final double dx = i - pos.getX();
|
||||
final double dz = k - pos.getZ();
|
||||
final double h = pos.getY() - radius + 1;
|
||||
|
||||
final double distanceFrom = dx * dx + dz * dz;
|
||||
|
||||
if (maxY > h + distanceFrom * 0.0175 && maxY < h + distanceFrom * 0.02) {
|
||||
int heigth = generator.func_222529_a(blockPos.getX(), blockPos.getZ(), Heightmap.Type.OCEAN_FLOOR);
|
||||
if (heigth < seaLevel) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private CraterType determineCraterType(Biome biome) {
|
||||
final TempCategory temp = biome.getTempCategory();
|
||||
final Category category = biome.getCategory();
|
||||
|
||||
// No craters in oceans
|
||||
if (category == Category.OCEAN) {
|
||||
return CraterType.NONE;
|
||||
}
|
||||
|
||||
// 50% chance for a special meteor
|
||||
final boolean specialMeteor = rand.nextFloat() > .5f;
|
||||
|
||||
// Just a normal one
|
||||
if (!specialMeteor) {
|
||||
return CraterType.NORMAL;
|
||||
}
|
||||
|
||||
// Warm biomes, higher chance for lava
|
||||
if (temp == TempCategory.WARM) {
|
||||
|
||||
// 50% chance to actually spawn as lava
|
||||
final boolean lava = rand.nextFloat() > .5f;
|
||||
|
||||
switch (biome.getPrecipitation()) {
|
||||
// No rainfall, only lava
|
||||
case NONE:
|
||||
return lava ? CraterType.LAVA : CraterType.NORMAL;
|
||||
|
||||
// 25% chance to convert a lava to obsidian
|
||||
case RAIN:
|
||||
final boolean obsidian = rand.nextFloat() > .75f;
|
||||
final CraterType alternativObsidian = obsidian ? CraterType.OBSIDIAN : CraterType.LAVA;
|
||||
return lava ? alternativObsidian : CraterType.NORMAL;
|
||||
|
||||
// Nothing for now.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Temperate biomes. Water or maybe lava
|
||||
if (temp == TempCategory.MEDIUM) {
|
||||
// 75% chance to actually spawn with a crater lake
|
||||
final boolean lake = rand.nextFloat() > .25f;
|
||||
// 20% to spawn with lava
|
||||
final boolean lava = rand.nextFloat() > .8f;
|
||||
|
||||
switch (biome.getPrecipitation()) {
|
||||
// No rainfall, water how?
|
||||
case NONE:
|
||||
return lava ? CraterType.LAVA : CraterType.NORMAL;
|
||||
// Rainfall, can also turn lava to obsidian
|
||||
case RAIN:
|
||||
final boolean obsidian = rand.nextFloat() > .75f;
|
||||
final CraterType alternativObsidian = obsidian ? CraterType.OBSIDIAN : CraterType.LAVA;
|
||||
final CraterType craterLake = lake ? CraterType.WATER : CraterType.NORMAL;
|
||||
return lava ? alternativObsidian : craterLake;
|
||||
// No lava, but snow
|
||||
case SNOW:
|
||||
final boolean snow = rand.nextFloat() > .75f;
|
||||
final CraterType water = lake ? CraterType.WATER : CraterType.NORMAL;
|
||||
return snow ? CraterType.SNOW : water;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Cold biomes, Snow or Ice, maybe water and very rarely lava.
|
||||
if (temp == TempCategory.COLD) {
|
||||
// 75% chance to actually spawn with a crater lake
|
||||
final boolean lake = rand.nextFloat() > .25f;
|
||||
// 5% to spawn with lava
|
||||
final boolean lava = rand.nextFloat() > .95f;
|
||||
// 75% chance to freeze
|
||||
final boolean frozen = rand.nextFloat() > .25f;
|
||||
|
||||
switch (biome.getPrecipitation()) {
|
||||
// No rainfall, water how?
|
||||
case NONE:
|
||||
return lava ? CraterType.LAVA : CraterType.NORMAL;
|
||||
case RAIN:
|
||||
final CraterType frozenLake = frozen ? CraterType.ICE : CraterType.WATER;
|
||||
final CraterType craterLake = lake ? frozenLake : CraterType.NORMAL;
|
||||
return lava ? CraterType.LAVA : craterLake;
|
||||
case SNOW:
|
||||
final CraterType snowCovered = lake ? CraterType.SNOW : CraterType.NORMAL;
|
||||
return lava ? CraterType.LAVA : snowCovered;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return CraterType.NORMAL;
|
||||
}
|
||||
|
||||
private FalloutMode getFalloutFromBaseBlock(BlockState blockState) {
|
||||
final Block block = blockState.getBlock();
|
||||
|
||||
if (block.isIn(sandTag)) {
|
||||
return FalloutMode.SAND;
|
||||
} else if (block.isIn(terracottaTag)) {
|
||||
return FalloutMode.TERRACOTTA;
|
||||
} else if (block == Blocks.SNOW || block == Blocks.SNOW || block == Blocks.SNOW_BLOCK || block == Blocks.ICE
|
||||
|| block == Blocks.PACKED_ICE) {
|
||||
return FalloutMode.ICE_SNOW;
|
||||
} else {
|
||||
return FalloutMode.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,14 +30,16 @@ public final class PlacedMeteoriteSettings {
|
||||
private final CraterType craterType;
|
||||
private final FalloutMode fallout;
|
||||
private final boolean pureCrater;
|
||||
private final boolean craterLake;
|
||||
|
||||
public PlacedMeteoriteSettings(BlockPos pos, float meteoriteRadius, CraterType craterType, FalloutMode fallout,
|
||||
boolean pureCrater) {
|
||||
boolean pureCrater, boolean craterLake) {
|
||||
this.pos = pos;
|
||||
this.craterType = craterType;
|
||||
this.meteoriteRadius = meteoriteRadius;
|
||||
this.fallout = fallout;
|
||||
this.pureCrater = pureCrater;
|
||||
this.craterLake = craterLake;
|
||||
}
|
||||
|
||||
public BlockPos getPos() {
|
||||
@@ -64,6 +66,10 @@ public final class PlacedMeteoriteSettings {
|
||||
return this.pureCrater;
|
||||
}
|
||||
|
||||
public boolean isCraterLake() {
|
||||
return craterLake;
|
||||
}
|
||||
|
||||
public CompoundNBT write(CompoundNBT tag) {
|
||||
tag.putLong(Constants.TAG_POS, pos.toLong());
|
||||
|
||||
@@ -71,6 +77,7 @@ public final class PlacedMeteoriteSettings {
|
||||
tag.putByte(Constants.TAG_CRATER, (byte) craterType.ordinal());
|
||||
tag.putByte(Constants.TAG_FALLOUT, (byte) fallout.ordinal());
|
||||
tag.putBoolean(Constants.TAG_PURE, this.pureCrater);
|
||||
tag.putBoolean(Constants.TAG_LAKE, this.craterLake);
|
||||
return tag;
|
||||
}
|
||||
|
||||
@@ -80,14 +87,16 @@ public final class PlacedMeteoriteSettings {
|
||||
CraterType craterType = CraterType.values()[tag.getByte(Constants.TAG_CRATER)];
|
||||
FalloutMode fallout = FalloutMode.values()[tag.getByte(Constants.TAG_FALLOUT)];
|
||||
boolean pureCrater = tag.getBoolean(Constants.TAG_PURE);
|
||||
boolean craterLake = tag.getBoolean(Constants.TAG_LAKE);
|
||||
|
||||
return new PlacedMeteoriteSettings(pos, meteoriteRadius, craterType, fallout, pureCrater);
|
||||
return new PlacedMeteoriteSettings(pos, meteoriteRadius, craterType, fallout, pureCrater, craterLake);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlacedMeteoriteSettings [pos=" + pos + ", meteoriteRadius=" + meteoriteRadius + ", craterType="
|
||||
+ craterType + ", fallout=" + fallout + ", pureCrater=" + pureCrater + "]";
|
||||
+ craterType + ", fallout=" + fallout + ", pureCrater=" + pureCrater + ", craterLake=" + craterLake
|
||||
+ "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-68
@@ -15,47 +15,24 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||
*/
|
||||
package appeng.worldgen.meteorite;
|
||||
package appeng.worldgen.meteorite.debug;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.Tag;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IWorldReader;
|
||||
import net.minecraft.world.biome.Biome.Category;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.Heightmap.Type;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
import appeng.worldgen.meteorite.fallout.FalloutMode;
|
||||
import appeng.worldgen.meteorite.CraterType;
|
||||
import appeng.worldgen.meteorite.PlacedMeteoriteSettings;
|
||||
|
||||
/**
|
||||
* Makes decisions about spawning meteorites in the world.
|
||||
*/
|
||||
public class MeteoriteSpawner {
|
||||
|
||||
private static final ResourceLocation TAG_VALID_SPAWN = new ResourceLocation(AppEng.MOD_ID,
|
||||
"meteorite/valid_spawn");
|
||||
|
||||
private static final ResourceLocation TAG_INVALID_SPAWN = new ResourceLocation(AppEng.MOD_ID,
|
||||
"meteorite/invalid_spawn");
|
||||
|
||||
private final Tag<Block> validSpawnTag;
|
||||
private final Tag<Block> invalidSpawnTag;
|
||||
|
||||
private final Tag<Block> sandTag;
|
||||
private final Tag<Block> terracottaTag;
|
||||
|
||||
public MeteoriteSpawner() {
|
||||
this.validSpawnTag = BlockTags.getCollection().getOrCreate(TAG_VALID_SPAWN);
|
||||
this.invalidSpawnTag = BlockTags.getCollection().getOrCreate(TAG_INVALID_SPAWN);
|
||||
this.sandTag = BlockTags.getCollection().getOrCreate(new ResourceLocation("minecraft:sand"));
|
||||
this.terracottaTag = BlockTags.getCollection().getOrCreate(new ResourceLocation("forge:terracotta"));
|
||||
}
|
||||
|
||||
public PlacedMeteoriteSettings trySpawnMeteoriteAtSuitableHeight(IWorldReader world, BlockPos startPos,
|
||||
@@ -64,19 +41,7 @@ public class MeteoriteSpawner {
|
||||
int minY = 10 + stepSize;
|
||||
BlockPos.Mutable mutablePos = new BlockPos.Mutable(startPos);
|
||||
|
||||
// Place the center on the first solid ground block,
|
||||
// but move it down a little to embed the meteorite more in the ground
|
||||
final boolean isOcean = world.getBiome(startPos).getCategory() == Category.OCEAN;
|
||||
final Type heightmapType;
|
||||
|
||||
if (isOcean) {
|
||||
heightmapType = worldGen ? Heightmap.Type.OCEAN_FLOOR_WG : Heightmap.Type.OCEAN_FLOOR;
|
||||
} else {
|
||||
heightmapType = worldGen ? Heightmap.Type.WORLD_SURFACE_WG : Heightmap.Type.WORLD_SURFACE;
|
||||
}
|
||||
|
||||
int startY = world.getHeight(heightmapType, startPos).getY() - stepSize / 2;
|
||||
mutablePos.setY(startY);
|
||||
mutablePos.move(Direction.DOWN, stepSize);
|
||||
|
||||
while (mutablePos.getY() > minY) {
|
||||
PlacedMeteoriteSettings spawned = trySpawnMeteorite(world, mutablePos, coreRadius, craterType, pureCrater);
|
||||
@@ -104,13 +69,14 @@ public class MeteoriteSpawner {
|
||||
boolean solid = !isAirBelowSpawnPoint(world, pos);
|
||||
|
||||
if (!solid || placeCrater) {
|
||||
// craterType = CraterType.NONE;
|
||||
// TODO: WHAT
|
||||
// return null;
|
||||
}
|
||||
|
||||
FalloutMode fallout = getFalloutFromBaseBlock(world.getBlockState(pos));
|
||||
// FalloutMode fallout = getFalloutFromBaseBlock(world.getBlockState(pos));
|
||||
|
||||
return new PlacedMeteoriteSettings(pos, coreRadius, craterType, fallout, pureCrater);
|
||||
boolean craterLake = false;
|
||||
|
||||
return new PlacedMeteoriteSettings(pos, coreRadius, craterType, null, pureCrater, craterLake);
|
||||
}
|
||||
|
||||
private static boolean isAirBelowSpawnPoint(IWorldReader w, BlockPos pos) {
|
||||
@@ -154,9 +120,7 @@ public class MeteoriteSpawner {
|
||||
for (int k = pos.getZ() - 6; k < pos.getZ() + 6; k++) {
|
||||
testPos.setZ(k);
|
||||
Block block = w.getBlockState(testPos).getBlock();
|
||||
if (block.isIn(validSpawnTag)) {
|
||||
realValidBlocks++;
|
||||
}
|
||||
realValidBlocks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,12 +133,7 @@ public class MeteoriteSpawner {
|
||||
for (int k = pos.getZ() - 15; k < pos.getZ() + 15; k++) {
|
||||
testPos.setZ(k);
|
||||
Block testBlk = w.getBlockState(testPos).getBlock();
|
||||
if (testBlk.isIn(invalidSpawnTag)) {
|
||||
return false;
|
||||
}
|
||||
if (testBlk.isIn(validSpawnTag)) {
|
||||
validBlocks++;
|
||||
}
|
||||
validBlocks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,19 +142,4 @@ public class MeteoriteSpawner {
|
||||
return validBlocks > minBlocks && realValidBlocks > 80;
|
||||
}
|
||||
|
||||
private FalloutMode getFalloutFromBaseBlock(BlockState blockState) {
|
||||
final Block block = blockState.getBlock();
|
||||
|
||||
if (block.isIn(sandTag)) {
|
||||
return FalloutMode.SAND;
|
||||
} else if (block.isIn(terracottaTag)) {
|
||||
return FalloutMode.TERRACOTTA;
|
||||
} else if (block == Blocks.SNOW || block == Blocks.SNOW || block == Blocks.SNOW_BLOCK || block == Blocks.ICE
|
||||
|| block == Blocks.PACKED_ICE) {
|
||||
return FalloutMode.ICE_SNOW;
|
||||
} else {
|
||||
return FalloutMode.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user