diff --git a/src/main/java/appeng/debug/MeteoritePlacerItem.java b/src/main/java/appeng/debug/MeteoritePlacerItem.java index 1578d1ec2..c26eb3763 100644 --- a/src/main/java/appeng/debug/MeteoritePlacerItem.java +++ b/src/main/java/appeng/debug/MeteoritePlacerItem.java @@ -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 { diff --git a/src/main/java/appeng/worldgen/meteorite/Constants.java b/src/main/java/appeng/worldgen/meteorite/Constants.java index eef85af6b..60576a01d 100644 --- a/src/main/java/appeng/worldgen/meteorite/Constants.java +++ b/src/main/java/appeng/worldgen/meteorite/Constants.java @@ -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"; } diff --git a/src/main/java/appeng/worldgen/meteorite/MeteoritePlacer.java b/src/main/java/appeng/worldgen/meteorite/MeteoritePlacer.java index bdec5884b..78bd20d26 100644 --- a/src/main/java/appeng/worldgen/meteorite/MeteoritePlacer.java +++ b/src/main/java/appeng/worldgen/meteorite/MeteoritePlacer.java @@ -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: diff --git a/src/main/java/appeng/worldgen/meteorite/MeteoriteStructure.java b/src/main/java/appeng/worldgen/meteorite/MeteoriteStructure.java index 6dfc8834a..e092b851f 100644 --- a/src/main/java/appeng/worldgen/meteorite/MeteoriteStructure.java +++ b/src/main/java/appeng/worldgen/meteorite/MeteoriteStructure.java @@ -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 { @Override public Structure.IStartFactory getStartFactory() { - return MeteoriteStructure.Start::new; + return MeteoriteStructureStart::new; } @Override @@ -76,24 +71,4 @@ public class MeteoriteStructure extends ScatteredStructure { 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(); - } - } - } diff --git a/src/main/java/appeng/worldgen/meteorite/MeteoriteStructurePiece.java b/src/main/java/appeng/worldgen/meteorite/MeteoriteStructurePiece.java index 390ff6b9e..c29cd77dc 100644 --- a/src/main/java/appeng/worldgen/meteorite/MeteoriteStructurePiece.java +++ b/src/main/java/appeng/worldgen/meteorite/MeteoriteStructurePiece.java @@ -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; - } - } diff --git a/src/main/java/appeng/worldgen/meteorite/MeteoriteStructureStart.java b/src/main/java/appeng/worldgen/meteorite/MeteoriteStructureStart.java new file mode 100644 index 000000000..df9d8259d --- /dev/null +++ b/src/main/java/appeng/worldgen/meteorite/MeteoriteStructureStart.java @@ -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 sandTag = BlockTags.getCollection().getOrCreate(new ResourceLocation("minecraft:sand")); + private final Tag 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 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; + } + } + +} \ No newline at end of file diff --git a/src/main/java/appeng/worldgen/meteorite/PlacedMeteoriteSettings.java b/src/main/java/appeng/worldgen/meteorite/PlacedMeteoriteSettings.java index fc7e55363..73ecb830b 100644 --- a/src/main/java/appeng/worldgen/meteorite/PlacedMeteoriteSettings.java +++ b/src/main/java/appeng/worldgen/meteorite/PlacedMeteoriteSettings.java @@ -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 + + "]"; } } diff --git a/src/main/java/appeng/worldgen/meteorite/MeteoriteSpawner.java b/src/main/java/appeng/worldgen/meteorite/debug/MeteoriteSpawner.java similarity index 60% rename from src/main/java/appeng/worldgen/meteorite/MeteoriteSpawner.java rename to src/main/java/appeng/worldgen/meteorite/debug/MeteoriteSpawner.java index f2b96a6b6..6ca79e220 100644 --- a/src/main/java/appeng/worldgen/meteorite/MeteoriteSpawner.java +++ b/src/main/java/appeng/worldgen/meteorite/debug/MeteoriteSpawner.java @@ -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 . */ -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 validSpawnTag; - private final Tag invalidSpawnTag; - - private final Tag sandTag; - private final Tag 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; - } - } - } diff --git a/src/main/resources/data/appliedenergistics2/tags/blocks/meteorite/invalid_spawn.json b/src/main/resources/data/appliedenergistics2/tags/blocks/meteorite/invalid_spawn.json deleted file mode 100644 index 4c998c935..000000000 --- a/src/main/resources/data/appliedenergistics2/tags/blocks/meteorite/invalid_spawn.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "values": [ - "appliedenergistics2:sky_stone_block", - "#minecraft:doors", - "minecraft:iron_bars", - "minecraft:bricks", - "#minecraft:planks", - "end_portal_frame" - ] -} diff --git a/src/main/resources/data/appliedenergistics2/tags/blocks/meteorite/valid_spawn.json b/src/main/resources/data/appliedenergistics2/tags/blocks/meteorite/valid_spawn.json deleted file mode 100644 index 10e00db37..000000000 --- a/src/main/resources/data/appliedenergistics2/tags/blocks/meteorite/valid_spawn.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "values": [ - "#forge:stone", - "#forge:cobblestone", - "minecraft:grass_block", - "#forge:sand", - "#forge:sandstone", - "#forge:dirt", - "#forge:gravel", - "#forge:netherrack", - "#forge:ores", - "#minecraft:ice", - "minecraft:snow", - "minecraft:snow_block", - "minecraft:water" - ] -}