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:
yueh
2020-06-25 20:52:25 +02:00
committed by GitHub
parent d7a09f70ef
commit fd1dd982c1
10 changed files with 311 additions and 265 deletions
@@ -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
+ "]";
}
}
@@ -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;
}
}
}