3668dc883a
Just a few fixes for 7.1.18, whenever it comes out.
389 lines
11 KiB
Java
389 lines
11 KiB
Java
/**
|
|
* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
|
|
* http://www.mod-buildcraft.com
|
|
* <p/>
|
|
* BuildCraft is distributed under the terms of the Minecraft Mod Public
|
|
* License 1.0, or MMPL. Please check the contents of the license located in
|
|
* http://www.mod-buildcraft.com/MMPL-1.0.txt
|
|
*/
|
|
package buildcraft.energy.worldgen;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
|
|
import net.minecraft.block.Block;
|
|
import net.minecraft.block.BlockFlower;
|
|
import net.minecraft.block.BlockStaticLiquid;
|
|
import net.minecraft.block.material.Material;
|
|
import net.minecraft.init.Blocks;
|
|
import net.minecraft.world.World;
|
|
import net.minecraft.world.biome.BiomeGenBase;
|
|
import net.minecraft.world.chunk.Chunk;
|
|
|
|
import cpw.mods.fml.common.eventhandler.Event.Result;
|
|
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
|
import net.minecraftforge.common.util.EnumHelper;
|
|
import net.minecraftforge.common.util.ForgeDirection;
|
|
import net.minecraftforge.event.terraingen.PopulateChunkEvent;
|
|
import net.minecraftforge.event.terraingen.PopulateChunkEvent.Populate.EventType;
|
|
import net.minecraftforge.event.terraingen.TerrainGen;
|
|
import net.minecraftforge.fluids.BlockFluidBase;
|
|
import net.minecraftforge.fluids.IFluidBlock;
|
|
|
|
import buildcraft.BuildCraftCore;
|
|
import buildcraft.BuildCraftEnergy;
|
|
|
|
public final class OilPopulate {
|
|
|
|
public static final OilPopulate INSTANCE = new OilPopulate();
|
|
public static final EventType EVENT_TYPE = EnumHelper.addEnum(EventType.class, "BUILDCRAFT_OIL", new Class[0], new Object[0]);
|
|
private static final byte LARGE_WELL_HEIGHT = 16;
|
|
private static final byte MEDIUM_WELL_HEIGHT = 6;
|
|
public final Set<Integer> excessiveBiomes = new HashSet<Integer>();
|
|
public final Set<Integer> surfaceDepositBiomes = new HashSet<Integer>();
|
|
public final Set<Integer> excludedBiomes = new HashSet<Integer>();
|
|
|
|
private enum GenType {
|
|
LARGE, MEDIUM, LAKE, NONE
|
|
}
|
|
|
|
private OilPopulate() {
|
|
// BuildCraftCore.debugWorldgen = true;
|
|
}
|
|
|
|
@SubscribeEvent
|
|
public void populate(PopulateChunkEvent.Pre event) {
|
|
boolean doGen = TerrainGen.populate(event.chunkProvider, event.world, event.rand, event.chunkX, event.chunkZ, event.hasVillageGenerated, EVENT_TYPE);
|
|
|
|
if (!doGen) {
|
|
event.setResult(Result.ALLOW);
|
|
return;
|
|
}
|
|
|
|
generateOil(event.world, event.rand, event.chunkX, event.chunkZ);
|
|
}
|
|
|
|
public void generateOil(World world, Random rand, int chunkX, int chunkZ) {
|
|
|
|
// shift to world coordinates
|
|
int x = chunkX * 16 + 8 + rand.nextInt(16);
|
|
int z = chunkZ * 16 + 8 + rand.nextInt(16);
|
|
|
|
BiomeGenBase biome = world.getBiomeGenForCoords(x, z);
|
|
|
|
// Do not generate oil in the End or Nether
|
|
if (excludedBiomes.contains(biome.biomeID)) {
|
|
return;
|
|
}
|
|
|
|
boolean oilBiome = surfaceDepositBiomes.contains(biome.biomeID);
|
|
|
|
double bonus = oilBiome ? 3.0 : 1.0;
|
|
bonus *= BuildCraftEnergy.oilWellScalar;
|
|
if (excessiveBiomes.contains(biome.biomeID)) {
|
|
bonus *= 30.0;
|
|
} else if (BuildCraftCore.debugWorldgen) {
|
|
bonus *= 20.0;
|
|
}
|
|
GenType type = GenType.NONE;
|
|
if (rand.nextDouble() <= 0.0004 * bonus) {
|
|
// 0.04%
|
|
type = GenType.LARGE;
|
|
} else if (rand.nextDouble() <= 0.001 * bonus) {
|
|
// 0.1%
|
|
type = GenType.MEDIUM;
|
|
} else if (oilBiome && rand.nextDouble() <= 0.02 * bonus) {
|
|
// 2%
|
|
type = GenType.LAKE;
|
|
}
|
|
|
|
if (type == GenType.NONE) {
|
|
return;
|
|
}
|
|
|
|
|
|
// Find ground level
|
|
int groundLevel = getTopBlock(world, x, z);
|
|
if (groundLevel < 5) {
|
|
return;
|
|
}
|
|
|
|
double deviation = surfaceDeviation(world, x, groundLevel, z, 8);
|
|
if (deviation > 0.45) {
|
|
return;
|
|
}
|
|
|
|
// Generate a Well
|
|
if (type == GenType.LARGE || type == GenType.MEDIUM) {
|
|
int wellX = x;
|
|
int wellZ = z;
|
|
|
|
int wellHeight = MEDIUM_WELL_HEIGHT;
|
|
if (type == GenType.LARGE) {
|
|
wellHeight = LARGE_WELL_HEIGHT;
|
|
}
|
|
int maxHeight = groundLevel + wellHeight;
|
|
if (maxHeight >= world.getHeight() - 1) {
|
|
return;
|
|
}
|
|
|
|
// Generate a spherical cave deposit
|
|
int wellY = 20 + rand.nextInt(10);
|
|
|
|
int radius;
|
|
if (type == GenType.LARGE) {
|
|
radius = 8 + rand.nextInt(9);
|
|
} else {
|
|
radius = 4 + rand.nextInt(4);
|
|
}
|
|
|
|
int radiusSq = radius * radius;
|
|
|
|
for (int poolX = -radius; poolX <= radius; poolX++) {
|
|
for (int poolY = -radius; poolY <= radius; poolY++) {
|
|
for (int poolZ = -radius; poolZ <= radius; poolZ++) {
|
|
int distance = poolX * poolX + poolY * poolY + poolZ * poolZ;
|
|
|
|
if (distance <= radiusSq) {
|
|
world.setBlock(poolX + wellX, poolY + wellY, poolZ + wellZ, BuildCraftEnergy.blockOil, 0, distance == radiusSq ? 3 : 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generate Lake around Spout
|
|
int lakeRadius;
|
|
if (type == GenType.LARGE) {
|
|
lakeRadius = 25 + rand.nextInt(20);
|
|
// if (BuildCraftCore.debugMode) {
|
|
// lakeRadius += 40;
|
|
// }
|
|
} else {
|
|
lakeRadius = 5 + rand.nextInt(10);
|
|
}
|
|
generateSurfaceDeposit(world, rand, biome, wellX, groundLevel, wellZ, lakeRadius);
|
|
|
|
boolean makeSpring = type == GenType.LARGE && BuildCraftEnergy.spawnOilSprings && BuildCraftCore.springBlock != null && (BuildCraftCore.debugWorldgen || rand.nextDouble() <= 0.25);
|
|
|
|
// Generate Spout
|
|
int baseY;
|
|
if (makeSpring) {
|
|
baseY = 0;
|
|
} else {
|
|
baseY = wellY;
|
|
}
|
|
|
|
if (makeSpring && world.getBlock(wellX, baseY, wellZ) == Blocks.bedrock) {
|
|
world.setBlock(wellX, baseY, wellZ, BuildCraftCore.springBlock, 1, 3);
|
|
}
|
|
for (int y = baseY + 1; y <= maxHeight; ++y) {
|
|
world.setBlock(wellX, y, wellZ, BuildCraftEnergy.blockOil, 0, 3);
|
|
}
|
|
|
|
if (type == GenType.LARGE) {
|
|
for (int y = wellY; y <= maxHeight - wellHeight / 2; ++y) {
|
|
world.setBlock(wellX + 1, y, wellZ, BuildCraftEnergy.blockOil, 0, 3);
|
|
world.setBlock(wellX - 1, y, wellZ, BuildCraftEnergy.blockOil, 0, 3);
|
|
world.setBlock(wellX, y, wellZ + 1, BuildCraftEnergy.blockOil, 0, 3);
|
|
world.setBlock(wellX, y, wellZ - 1, BuildCraftEnergy.blockOil, 0, 3);
|
|
}
|
|
}
|
|
|
|
} else if (type == GenType.LAKE) {
|
|
// Generate a surface oil lake
|
|
int lakeX = x;
|
|
int lakeZ = z;
|
|
int lakeY = groundLevel;
|
|
|
|
Block block = world.getBlock(lakeX, lakeY, lakeZ);
|
|
if (block == biome.topBlock) {
|
|
generateSurfaceDeposit(world, rand, biome, lakeX, lakeY, lakeZ, 5 + rand.nextInt(10));
|
|
}
|
|
}
|
|
}
|
|
|
|
public void generateSurfaceDeposit(World world, Random rand, int x, int y, int z, int radius) {
|
|
BiomeGenBase biome = world.getBiomeGenForCoords(x, z);
|
|
generateSurfaceDeposit(world, rand, biome, x, y, z, radius);
|
|
}
|
|
|
|
private void generateSurfaceDeposit(World world, Random rand, BiomeGenBase biome, int x, int y, int z, int radius) {
|
|
int depth = rand.nextDouble() < 0.5 ? 1 : 2;
|
|
|
|
// Center
|
|
setOilColumnForLake(world, biome, x, y, z, depth, 2);
|
|
|
|
// Generate tendrils, from the center outward
|
|
for (int w = 1; w <= radius; ++w) {
|
|
float proba = (float) (radius - w + 4) / (float) (radius + 4);
|
|
|
|
setOilWithProba(world, biome, rand, proba, x, y, z + w, depth);
|
|
setOilWithProba(world, biome, rand, proba, x, y, z - w, depth);
|
|
setOilWithProba(world, biome, rand, proba, x + w, y, z, depth);
|
|
setOilWithProba(world, biome, rand, proba, x - w, y, z, depth);
|
|
|
|
for (int i = 1; i <= w; ++i) {
|
|
setOilWithProba(world, biome, rand, proba, x + i, y, z + w, depth);
|
|
setOilWithProba(world, biome, rand, proba, x + i, y, z - w, depth);
|
|
setOilWithProba(world, biome, rand, proba, x + w, y, z + i, depth);
|
|
setOilWithProba(world, biome, rand, proba, x - w, y, z + i, depth);
|
|
|
|
setOilWithProba(world, biome, rand, proba, x - i, y, z + w, depth);
|
|
setOilWithProba(world, biome, rand, proba, x - i, y, z - w, depth);
|
|
setOilWithProba(world, biome, rand, proba, x + w, y, z - i, depth);
|
|
setOilWithProba(world, biome, rand, proba, x - w, y, z - i, depth);
|
|
}
|
|
}
|
|
|
|
// Fill in holes
|
|
for (int dx = x - radius; dx <= x + radius; ++dx) {
|
|
for (int dz = z - radius; dz <= z + radius; ++dz) {
|
|
if (isOil(world, dx, y, dz)) {
|
|
continue;
|
|
}
|
|
if (isOilSurrounded(world, dx, y, dz)) {
|
|
setOilColumnForLake(world, biome, dx, y, dz, depth, 2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean isReplaceableFluid(World world, int x, int y, int z) {
|
|
Block block = world.getBlock(x, y, z);
|
|
return (block instanceof BlockStaticLiquid || block instanceof BlockFluidBase || block instanceof IFluidBlock) && block.getMaterial() != Material.lava;
|
|
}
|
|
|
|
private boolean isOil(World world, int x, int y, int z) {
|
|
Block block = world.getBlock(x, y, z);
|
|
return block == BuildCraftEnergy.blockOil;
|
|
}
|
|
|
|
private boolean isReplaceableForLake(World world, BiomeGenBase biome, int x, int y, int z) {
|
|
if (world.isAirBlock(x, y, z)) {
|
|
return true;
|
|
}
|
|
|
|
Block block = world.getBlock(x, y, z);
|
|
|
|
if (block == biome.fillerBlock || block == biome.topBlock) {
|
|
return true;
|
|
}
|
|
|
|
if (!block.getMaterial().blocksMovement()) {
|
|
return true;
|
|
}
|
|
|
|
if (block.isReplaceableOreGen(world, x, y, z, Blocks.stone)) {
|
|
return true;
|
|
}
|
|
|
|
if (block instanceof BlockFlower) {
|
|
return true;
|
|
}
|
|
|
|
if (!block.isOpaqueCube()) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private boolean isOilAdjacent(World world, int x, int y, int z) {
|
|
return isOil(world, x + 1, y, z)
|
|
|| isOil(world, x - 1, y, z)
|
|
|| isOil(world, x, y, z + 1)
|
|
|| isOil(world, x, y, z - 1);
|
|
}
|
|
|
|
private boolean isOilSurrounded(World world, int x, int y, int z) {
|
|
return isOil(world, x + 1, y, z)
|
|
&& isOil(world, x - 1, y, z)
|
|
&& isOil(world, x, y, z + 1)
|
|
&& isOil(world, x, y, z - 1);
|
|
}
|
|
|
|
private void setOilWithProba(World world, BiomeGenBase biome, Random rand, float proba, int x, int y, int z, int depth) {
|
|
if (rand.nextFloat() <= proba && !world.isAirBlock(x, y - depth - 1, z)) {
|
|
if (isOilAdjacent(world, x, y, z)) {
|
|
setOilColumnForLake(world, biome, x, y, z, depth, 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void setOilColumnForLake(World world, BiomeGenBase biome, int x, int y, int z, int depth, int update) {
|
|
if (isReplaceableForLake(world, biome, x, y + 1, z)) {
|
|
if (!world.isAirBlock(x, y + 2, z)) {
|
|
return;
|
|
}
|
|
if (isReplaceableFluid(world, x, y, z) || world.isSideSolid(x, y - 1, z, ForgeDirection.UP)) {
|
|
world.setBlock(x, y, z, BuildCraftEnergy.blockOil, 0, update);
|
|
} else {
|
|
return;
|
|
}
|
|
if (!world.isAirBlock(x, y + 1, z)) {
|
|
world.setBlock(x, y + 1, z, Blocks.air, 0, update);
|
|
}
|
|
|
|
for (int d = 1; d <= depth - 1; d++) {
|
|
if (isReplaceableFluid(world, x, y - d, z) || !world.isSideSolid(x, y - d - 1, z, ForgeDirection.UP)) {
|
|
return;
|
|
}
|
|
world.setBlock(x, y - d, z, BuildCraftEnergy.blockOil, 0, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
private int getTopBlock(World world, int x, int z) {
|
|
Chunk chunk = world.getChunkFromBlockCoords(x, z);
|
|
int y = chunk.getTopFilledSegment() + 15;
|
|
|
|
int trimmedX = x & 15;
|
|
int trimmedZ = z & 15;
|
|
|
|
for (; y > 0; --y) {
|
|
Block block = chunk.getBlock(trimmedX, y, trimmedZ);
|
|
|
|
if (block.isAir(world, x, y, z)) {
|
|
continue;
|
|
}
|
|
|
|
if (block instanceof BlockStaticLiquid) {
|
|
return y;
|
|
}
|
|
|
|
if (block instanceof BlockFluidBase) {
|
|
return y;
|
|
}
|
|
|
|
if (block instanceof IFluidBlock) {
|
|
return y;
|
|
}
|
|
|
|
if (!block.getMaterial().blocksMovement()) {
|
|
continue;
|
|
}
|
|
|
|
if (block instanceof BlockFlower) {
|
|
continue;
|
|
}
|
|
|
|
return y - 1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
private double surfaceDeviation(World world, int x, int y, int z, int radius) {
|
|
int diameter = radius * 2;
|
|
double centralTendancy = y;
|
|
double deviation = 0;
|
|
for (int i = 0; i < diameter; i++) {
|
|
for (int k = 0; k < diameter; k++) {
|
|
deviation += getTopBlock(world, x - radius + i, z - radius + k) - centralTendancy;
|
|
}
|
|
}
|
|
return Math.abs(deviation / centralTendancy);
|
|
}
|
|
}
|