From c5a5d037c99f23d4d62909e533a8be422e2a9e1b Mon Sep 17 00:00:00 2001 From: CovertJaguar Date: Fri, 17 May 2013 00:12:35 -0700 Subject: [PATCH] More improvements Height is "fixed", but there is still an issue with lakes generate in an L shape consistently. --- common/buildcraft/energy/OilPopulate.java | 285 +++++++++++++--------- 1 file changed, 167 insertions(+), 118 deletions(-) diff --git a/common/buildcraft/energy/OilPopulate.java b/common/buildcraft/energy/OilPopulate.java index 03867c22..04da0611 100644 --- a/common/buildcraft/energy/OilPopulate.java +++ b/common/buildcraft/energy/OilPopulate.java @@ -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 surfaceDepositBiomes = new HashSet(); - public final Set excludedBiomes = new HashSet(); + 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 chunkData = new HashMap(); - 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 surfaceDepositBiomes = new HashSet(); + public final Set excludedBiomes = new HashSet(); + private final Map 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; }