More improvements
Height is "fixed", but there is still an issue with lakes generate in an L shape consistently.
This commit is contained in:
parent
9e117c0b31
commit
c5a5d037c9
1 changed files with 167 additions and 118 deletions
|
@ -16,7 +16,7 @@ import net.minecraftforge.event.ForgeSubscribe;
|
|||
import net.minecraftforge.event.terraingen.TerrainGen;
|
||||
import buildcraft.BuildCraftCore;
|
||||
import buildcraft.BuildCraftEnergy;
|
||||
import java.util.HashMap;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -33,13 +33,20 @@ import net.minecraftforge.event.world.ChunkDataEvent;
|
|||
public class OilPopulate {
|
||||
|
||||
public static final OilPopulate INSTANCE = new OilPopulate();
|
||||
public final Set<Integer> surfaceDepositBiomes = new HashSet<Integer>();
|
||||
public final Set<Integer> excludedBiomes = new HashSet<Integer>();
|
||||
public static final EventType EVENT_TYPE = EnumHelper.addEnum(EventType.class, "BUILDCRAFT_OIL", new Class[0], new Object[0]);
|
||||
private static final String CHUNK_TAG = "buildcraft";
|
||||
private static final String GROUND_TAG = "oilGenGroundLevel";
|
||||
private static final byte GEN_AREA = 2;
|
||||
private static final Map<Chunk, NBTTagCompound> chunkData = new HashMap<Chunk, NBTTagCompound>();
|
||||
private static EventType eventType = EnumHelper.addEnum(EventType.class, "BUILDCRAFT_OIL");
|
||||
private static final byte LARGE_WELL_HEIGHT = 16;
|
||||
private static final byte MEDIUM_WELL_HEIGHT = 4;
|
||||
public final Set<Integer> surfaceDepositBiomes = new HashSet<Integer>();
|
||||
public final Set<Integer> excludedBiomes = new HashSet<Integer>();
|
||||
private final Map<Chunk, Integer> chunkData = new MapMaker().weakKeys().makeMap();
|
||||
|
||||
private enum GenType {
|
||||
|
||||
LARGE, MEDIUM, LAKE, NONE
|
||||
};
|
||||
|
||||
private OilPopulate() {
|
||||
BuildCraftCore.debugMode = true;
|
||||
|
@ -55,7 +62,7 @@ public class OilPopulate {
|
|||
if (event.type != EventType.LAKE) {
|
||||
return;
|
||||
}
|
||||
boolean doGen = TerrainGen.populate(event.chunkProvider, event.world, event.rand, event.chunkX, event.chunkX, event.hasVillageGenerated, eventType);
|
||||
boolean doGen = TerrainGen.populate(event.chunkProvider, event.world, event.rand, event.chunkX, event.chunkX, event.hasVillageGenerated, EVENT_TYPE);
|
||||
|
||||
if (!doGen) {
|
||||
return;
|
||||
|
@ -65,6 +72,11 @@ public class OilPopulate {
|
|||
}
|
||||
|
||||
public void generateOil(World world, Random rand, int chunkX, int chunkZ) {
|
||||
Chunk targetChunk = world.getChunkFromChunkCoords(chunkX, chunkZ);
|
||||
|
||||
// if (chunkX == 16 && chunkZ == 40) {
|
||||
// System.out.println("target");
|
||||
// }
|
||||
for (int i = -GEN_AREA; i <= GEN_AREA; i++) {
|
||||
for (int k = -GEN_AREA; k <= GEN_AREA; k++) {
|
||||
int cx = chunkX + i;
|
||||
|
@ -73,70 +85,87 @@ public class OilPopulate {
|
|||
continue;
|
||||
}
|
||||
if (world.getChunkProvider().chunkExists(cx, cz)) {
|
||||
Chunk currentChunk = world.getChunkFromChunkCoords(cx, cz);
|
||||
Random r = getRandom(world, cx, cz);
|
||||
doPopulate(world, r, cx, cz, false);
|
||||
doPopulate(world, r, targetChunk, currentChunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Random r = getRandom(world, chunkX, chunkZ);
|
||||
doPopulate(world, r, chunkX, chunkZ, true);
|
||||
doPopulate(world, r, null, targetChunk);
|
||||
}
|
||||
|
||||
private Random getRandom(World world, int chunkX, int chunkZ) {
|
||||
return new Random(world.getSeed() + chunkX + chunkZ * 90373);
|
||||
}
|
||||
|
||||
public void doPopulate(World world, Random rand, int chunkX, int chunkZ, boolean modifyNeighbors) {
|
||||
// shift to world coordinates
|
||||
int x = chunkX * 16 + 8;
|
||||
int z = chunkZ * 16 + 8;
|
||||
private void doPopulate(World world, Random rand, Chunk targetChunk, Chunk currentChunk) {
|
||||
|
||||
BiomeGenBase biome = world.getBiomeGenForCoords(x + 8, z + 8);
|
||||
// if (currentChunk.xPosition == 17 && currentChunk.zPosition == 41) {
|
||||
// System.out.println("source");
|
||||
// }
|
||||
|
||||
// shift to world coordinates
|
||||
int x = currentChunk.xPosition * 16 + rand.nextInt(16);
|
||||
int z = currentChunk.zPosition * 16 + rand.nextInt(16);
|
||||
|
||||
BiomeGenBase biome = world.getBiomeGenForCoords(x, z);
|
||||
|
||||
// Do not generate oil in the End or Nether
|
||||
if (excludedBiomes.contains(biome.biomeID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate a surface oil lake
|
||||
if (surfaceDepositBiomes.contains(biome.biomeID) && rand.nextDouble() <= 0.02) { // 2%
|
||||
int lakeX = rand.nextInt(10) + 2 + x;
|
||||
int lakeZ = rand.nextInt(10) + 2 + z;
|
||||
int lakeY = world.getTopSolidOrLiquidBlock(lakeX, lakeZ) - 1;
|
||||
|
||||
int blockId = world.getBlockId(lakeX, lakeY, lakeZ);
|
||||
if (blockId == biome.topBlock) {
|
||||
generateSurfaceDeposit(world, rand, lakeX, lakeY, lakeZ, 2 + rand.nextInt(5), modifyNeighbors);
|
||||
}
|
||||
}
|
||||
|
||||
double bonus = surfaceDepositBiomes.contains(biome.biomeID) ? 1.5 : 1;
|
||||
boolean mediumDeposit = rand.nextDouble() <= 0.0015 * bonus; // 0.15%
|
||||
boolean largeDeposit = rand.nextDouble() <= 0.0005 * bonus; // 0.05%
|
||||
boolean oilBiome = surfaceDepositBiomes.contains(biome.biomeID);
|
||||
|
||||
double bonus = oilBiome ? 1.5 : 1.0;
|
||||
if (BuildCraftCore.debugMode) {
|
||||
largeDeposit = rand.nextDouble() < 0.01;
|
||||
bonus *= 20;
|
||||
}
|
||||
GenType type = GenType.NONE;
|
||||
if (rand.nextDouble() <= 0.0005 * bonus) {// 0.05%
|
||||
type = GenType.LARGE;
|
||||
} else if (rand.nextDouble() <= 0.0015 * bonus) {// 0.15%
|
||||
type = GenType.MEDIUM;
|
||||
} else if (oilBiome && rand.nextDouble() <= 0.02) {// 2%
|
||||
type = GenType.LAKE;
|
||||
}
|
||||
// if (currentChunk.xPosition == 17 && currentChunk.zPosition == 41 && type != GenType.NONE) {
|
||||
// System.out.println("well!");
|
||||
// }
|
||||
if (type == GenType.NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate a large cave deposit
|
||||
if (mediumDeposit || largeDeposit) {
|
||||
// System.out.printf("Gen: %d, %d, %d\n", x, z, seed);
|
||||
// Find ground level
|
||||
int groundLevel = getGroundLevel(currentChunk);
|
||||
if (groundLevel <= 0) {
|
||||
groundLevel = getTopBlock(world, currentChunk, x, z, type);
|
||||
setGroundLevel(currentChunk, groundLevel);
|
||||
}
|
||||
|
||||
int wellX = x, wellZ = z;
|
||||
int wellY = 20 + rand.nextInt(10);
|
||||
int baseY;
|
||||
if (largeDeposit && BuildCraftEnergy.spawnOilSprings && (BuildCraftCore.debugMode || rand.nextDouble() <= 0.25)) {
|
||||
baseY = 0;
|
||||
} else {
|
||||
baseY = wellY;
|
||||
// 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.getActualHeight() - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int radius = 0;
|
||||
// Generate a spherical cave deposit
|
||||
int wellY = 20 + rand.nextInt(10);
|
||||
|
||||
if (largeDeposit) {
|
||||
int radius;
|
||||
if (type == GenType.LARGE) {
|
||||
radius = 8 + rand.nextInt(9);
|
||||
} else if (mediumDeposit) {
|
||||
} else {
|
||||
radius = 4 + rand.nextInt(4);
|
||||
}
|
||||
|
||||
|
@ -147,83 +176,91 @@ public class OilPopulate {
|
|||
for (int poolZ = -radius; poolZ <= radius; poolZ++) {
|
||||
int distance = poolX * poolX + poolY * poolY + poolZ * poolZ;
|
||||
|
||||
if (distance <= radiusSq && canReplaceInChunk(chunkX, chunkZ, poolX + wellX, poolZ + wellZ, modifyNeighbors)) {
|
||||
if (distance <= radiusSq && canReplaceInChunk(targetChunk, poolX + wellX, poolZ + wellZ)) {
|
||||
world.setBlock(poolX + wellX, poolY + wellY, poolZ + wellZ, BuildCraftEnergy.oilStill.blockID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Chunk chunk = world.getChunkFromChunkCoords(chunkX, chunkZ);
|
||||
int groundLevel = getGroundLevel(chunk);
|
||||
if (groundLevel <= 0) {
|
||||
groundLevel = getTopBlock(world, chunk, wellX, wellZ);
|
||||
setGroundLevel(chunk, groundLevel);
|
||||
}
|
||||
if (largeDeposit) {
|
||||
int lakeRadius = 20 + rand.nextInt(20);
|
||||
// Generate Lake around Spout
|
||||
int lakeRadius;
|
||||
if (type == GenType.LARGE) {
|
||||
lakeRadius = 20 + rand.nextInt(20);
|
||||
if (BuildCraftCore.debugMode) {
|
||||
lakeRadius += 40;
|
||||
}
|
||||
generateSurfaceDeposit(world, rand, wellX, groundLevel, wellZ, lakeRadius, modifyNeighbors);
|
||||
} else if (mediumDeposit) {
|
||||
generateSurfaceDeposit(world, rand, wellX, groundLevel, wellZ, 5 + rand.nextInt(5), modifyNeighbors);
|
||||
} else {
|
||||
lakeRadius = 5 + rand.nextInt(5);
|
||||
}
|
||||
generateSurfaceDeposit(world, rand, targetChunk, wellX, groundLevel, wellZ, lakeRadius);
|
||||
|
||||
// Generate Spout
|
||||
int baseY;
|
||||
if (type == GenType.LARGE && BuildCraftEnergy.spawnOilSprings && (BuildCraftCore.debugMode || rand.nextDouble() <= 0.25)) {
|
||||
baseY = 0;
|
||||
} else {
|
||||
baseY = wellY;
|
||||
}
|
||||
|
||||
int wellHeight = 4;
|
||||
if (largeDeposit) {
|
||||
wellHeight = 16;
|
||||
}
|
||||
int maxHeight = Math.min(groundLevel + wellHeight, world.getActualHeight() - 1);
|
||||
|
||||
if (world.getBlockId(wellX, baseY, wellZ) == Block.bedrock.blockID) {
|
||||
if (BuildCraftEnergy.spawnOilSprings) {
|
||||
world.setBlock(wellX, baseY, wellZ, BuildCraftCore.springBlock.blockID, 1, 3);
|
||||
if (canReplaceInChunk(targetChunk, wellX, wellZ)) {
|
||||
if (world.getBlockId(wellX, baseY, wellZ) == Block.bedrock.blockID) {
|
||||
if (BuildCraftEnergy.spawnOilSprings) {
|
||||
world.setBlock(wellX, baseY, wellZ, BuildCraftCore.springBlock.blockID, 1, 3);
|
||||
}
|
||||
}
|
||||
for (int y = baseY + 1; y <= maxHeight; ++y) {
|
||||
world.setBlock(wellX, y, wellZ, BuildCraftEnergy.oilStill.blockID);
|
||||
}
|
||||
}
|
||||
for (int y = baseY + 1; y <= maxHeight; ++y) {
|
||||
world.setBlock(wellX, y, wellZ, BuildCraftEnergy.oilStill.blockID);
|
||||
|
||||
} else if (type == GenType.LAKE) {
|
||||
// Generate a surface oil lake
|
||||
int lakeX = x;
|
||||
int lakeZ = z;
|
||||
int lakeY = groundLevel;
|
||||
|
||||
int blockId = world.getBlockId(lakeX, lakeY, lakeZ);
|
||||
if (blockId == biome.topBlock) {
|
||||
generateSurfaceDeposit(world, rand, targetChunk, lakeX, lakeY, lakeZ, 2 + rand.nextInt(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateSurfaceDeposit(World world, Random rand, int x, int y, int z, int radius, boolean modifyNeighbors) {
|
||||
public void generateSurfaceDeposit(World world, Random rand, int x, int y, int z, int radius) {
|
||||
generateSurfaceDeposit(world, rand, null, x, y, z, radius);
|
||||
}
|
||||
|
||||
private void generateSurfaceDeposit(World world, Random rand, Chunk targetChunk, int x, int y, int z, int radius) {
|
||||
int depth = rand.nextDouble() < 0.5 ? 1 : 2;
|
||||
|
||||
setOilForLake(world, x, y, z, depth);
|
||||
|
||||
int chunkX = x / 16;
|
||||
int chunkZ = z / 16;
|
||||
// Center
|
||||
setOilForLake(world, targetChunk, x, y, z, depth);
|
||||
|
||||
// Generate tendrils, from the center outward
|
||||
for (int w = 1; w <= radius; ++w) {
|
||||
float proba = (float) (radius - w + 4) / (float) (radius + 4);
|
||||
|
||||
for (int d = -w; d <= w; ++d) {
|
||||
if (canReplaceInChunk(chunkX, chunkZ, x + d, z + w, modifyNeighbors)) {
|
||||
setOilWithProba(world, rand, proba, x + d, y, z + w, depth);
|
||||
}
|
||||
if (canReplaceInChunk(chunkX, chunkZ, x + d, z - w, modifyNeighbors)) {
|
||||
setOilWithProba(world, rand, proba, x + d, y, z - w, depth);
|
||||
}
|
||||
if (canReplaceInChunk(chunkX, chunkZ, x + w, z + d, modifyNeighbors)) {
|
||||
setOilWithProba(world, rand, proba, x + w, y, z + d, depth);
|
||||
}
|
||||
if (canReplaceInChunk(chunkX, chunkZ, x - w, z + d, modifyNeighbors)) {
|
||||
setOilWithProba(world, rand, proba, x - w, y, z + d, depth);
|
||||
}
|
||||
setOilWithProba(world, targetChunk, rand, proba, x + d, y, z + w, depth);
|
||||
setOilWithProba(world, targetChunk, rand, proba, x + d, y, z - w, depth);
|
||||
setOilWithProba(world, targetChunk, rand, proba, x + w, y, z + d, depth);
|
||||
setOilWithProba(world, targetChunk, rand, proba, x - w, y, z + d, depth);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in holes
|
||||
for (int dx = x - radius; dx <= x + radius; ++dx) {
|
||||
for (int dz = z - radius; dz <= z + radius; ++dz) {
|
||||
if (!canReplaceInChunk(x / 16, z / 16, dx, dz, modifyNeighbors)) {
|
||||
if (!canReplaceInChunk(targetChunk, dx, dz)) {
|
||||
continue;
|
||||
}
|
||||
if (isOil(world, dx, y - 1, dz)) {
|
||||
continue;
|
||||
}
|
||||
if (isOilSurrounded(world, dx, y - 1, dz)) {
|
||||
setOilForLake(world, dx, y, dz, depth);
|
||||
setOilForLake(world, targetChunk, dx, y, dz, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -246,12 +283,10 @@ public class OilPopulate {
|
|||
}
|
||||
|
||||
private boolean isOilAdjacent(World world, int x, int y, int z) {
|
||||
for (int d = -1; d <= 1; ++d) {
|
||||
if (isOil(world, x + d, y, z) || isOil(world, x - d, y, z) || isOil(world, x, y, z + d) || isOil(world, x, y, z - d)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
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) {
|
||||
|
@ -261,18 +296,24 @@ public class OilPopulate {
|
|||
&& isOil(world, x, y, z - 1);
|
||||
}
|
||||
|
||||
private void setOilWithProba(World world, Random rand, float proba, int x, int y, int z, int depth) {
|
||||
private void setOilWithProba(World world, Chunk targetChunk, Random rand, float proba, int x, int y, int z, int depth) {
|
||||
// if (x / 16 == 16 && z / 16 == 40) {
|
||||
// System.out.println("spawn tendril");
|
||||
// }
|
||||
if (!world.blockExists(x, y, z)) {
|
||||
return;
|
||||
}
|
||||
if (rand.nextFloat() <= proba && world.getBlockId(x, y - 2, z) != 0) {
|
||||
if (isOilAdjacent(world, x, y - 1, z)) {
|
||||
setOilForLake(world, x, y, z, depth);
|
||||
setOilForLake(world, targetChunk, x, y, z, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setOilForLake(World world, int x, int y, int z, int depth) {
|
||||
private void setOilForLake(World world, Chunk targetChunk, int x, int y, int z, int depth) {
|
||||
if (!canReplaceInChunk(targetChunk, x, z)) {
|
||||
return;
|
||||
}
|
||||
if (!world.blockExists(x, y, z)) {
|
||||
return;
|
||||
}
|
||||
|
@ -294,48 +335,44 @@ public class OilPopulate {
|
|||
|
||||
@ForgeSubscribe
|
||||
public void saveChunk(ChunkDataEvent.Save event) {
|
||||
NBTTagCompound nbt = chunkData.remove(event.getChunk());
|
||||
if (nbt != null && nbt.hasKey(CHUNK_TAG)) {
|
||||
event.getData().setTag(CHUNK_TAG, nbt.getTag(CHUNK_TAG));
|
||||
Integer groundLevel = chunkData.remove(event.getChunk());
|
||||
if (groundLevel != null) {
|
||||
NBTTagCompound nbt = new NBTTagCompound();
|
||||
nbt.setInteger(GROUND_TAG, groundLevel);
|
||||
event.getData().setTag(CHUNK_TAG, nbt);
|
||||
}
|
||||
}
|
||||
|
||||
@ForgeSubscribe
|
||||
public void loadChunk(ChunkDataEvent.Load event) {
|
||||
chunkData.put(event.getChunk(), event.getData());
|
||||
if (!chunkData.containsKey(event.getChunk())) {
|
||||
Integer groundLevel = event.getData().getCompoundTag(CHUNK_TAG).getInteger(GROUND_TAG);
|
||||
if (groundLevel > 0) {
|
||||
chunkData.put(event.getChunk(), groundLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private NBTTagCompound getChunkBuildcraftData(Chunk chunk) {
|
||||
NBTTagCompound nbt = chunkData.get(chunk);
|
||||
if (nbt == null) {
|
||||
nbt = new NBTTagCompound();
|
||||
chunkData.put(chunk, nbt);
|
||||
}
|
||||
NBTTagCompound buildcraftData = nbt.getCompoundTag(CHUNK_TAG);
|
||||
if (!nbt.hasKey(CHUNK_TAG)) {
|
||||
nbt.setCompoundTag(CHUNK_TAG, buildcraftData);
|
||||
}
|
||||
return buildcraftData;
|
||||
}
|
||||
|
||||
private boolean canReplaceInChunk(int chunkX, int chunkZ, int x, int z, boolean modifyNeighbors) {
|
||||
if (modifyNeighbors) {
|
||||
private boolean canReplaceInChunk(Chunk targetChunk, int x, int z) {
|
||||
// if (x / 16 == 16 && z / 16 == 40) {
|
||||
// System.out.println("fill target");
|
||||
// }
|
||||
if (targetChunk == null) {
|
||||
return true;
|
||||
}
|
||||
return chunkX == x / 16 && chunkZ == z / 16;
|
||||
return targetChunk.xPosition == x / 16 && targetChunk.zPosition == z / 16;
|
||||
}
|
||||
|
||||
private void setGroundLevel(Chunk chunk, int height) {
|
||||
NBTTagCompound nbt = getChunkBuildcraftData(chunk);
|
||||
nbt.setInteger(GROUND_TAG, height);
|
||||
chunkData.put(chunk, height);
|
||||
}
|
||||
|
||||
private int getGroundLevel(Chunk chunk) {
|
||||
NBTTagCompound nbt = getChunkBuildcraftData(chunk);
|
||||
return nbt.getInteger(GROUND_TAG);
|
||||
Integer groundLevel = chunkData.get(chunk);
|
||||
return groundLevel != null ? groundLevel : -1;
|
||||
}
|
||||
|
||||
private int getTopBlock(World world, Chunk chunk, int x, int z) {
|
||||
private int getTopBlock(World world, Chunk chunk, int x, int z, GenType type) {
|
||||
int y = chunk.getTopFilledSegment() + 15;
|
||||
|
||||
int trimmedX = x & 15;
|
||||
|
@ -347,6 +384,18 @@ public class OilPopulate {
|
|||
if (blockId == 0 || block.blockMaterial == Material.leaves) {
|
||||
continue;
|
||||
}
|
||||
if (blockId == BuildCraftEnergy.oilStill.blockID && y > 70) {
|
||||
System.out.println("Fail!");
|
||||
if (type != GenType.LAKE) {
|
||||
int wellHeight = type == GenType.LARGE ? LARGE_WELL_HEIGHT : MEDIUM_WELL_HEIGHT;
|
||||
int groundLevel = y - wellHeight;
|
||||
blockId = chunk.getBlockID(trimmedX, groundLevel, trimmedZ);
|
||||
if (blockId == BuildCraftEnergy.oilStill.blockID) {
|
||||
return groundLevel;
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
if (block instanceof BlockFlower) {
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue