package cofh.lib.world; import static cofh.lib.world.WorldGenMinableCluster.*; import static java.lang.Math.abs; import cofh.lib.util.WeightedRandomBlock; import cofh.lib.util.WeightedRandomNBTTag; import java.util.Arrays; import java.util.List; import java.util.Random; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.tileentity.TileEntityMobSpawner; import net.minecraft.util.WeightedRandom; import net.minecraft.util.WeightedRandomChestContent; import net.minecraft.world.World; import net.minecraft.world.gen.feature.WorldGenerator; import net.minecraftforge.common.ChestGenHooks; import net.minecraftforge.common.DungeonHooks.DungeonMob; public class WorldGenDungeon extends WorldGenerator { private final List<WeightedRandomBlock> walls; private final WeightedRandomBlock[] genBlock; private final WeightedRandomNBTTag[] spawners; public int minWidthX = 2, maxWidthX = 3; public int minWidthZ = 2, maxWidthZ = 3; public int minHeight = 3, maxHeight = 3; public int minHoles = 1, maxHoles = 5; public int maxChests = 2; public List<DungeonMob> lootTables = Arrays.asList(new DungeonMob(100, ChestGenHooks.DUNGEON_CHEST)); public List<WeightedRandomBlock> floor; public WorldGenDungeon(List<WeightedRandomBlock> blocks, List<WeightedRandomBlock> material, List<WeightedRandomNBTTag> mobs) { walls = blocks; floor = walls; spawners = mobs.toArray(new WeightedRandomNBTTag[mobs.size()]); genBlock = material.toArray(new WeightedRandomBlock[material.size()]); } @Override public boolean generate(World world, Random rand, int xStart, int yStart, int zStart) { if (yStart <= 2) return false; int height = nextInt(rand, maxHeight - minHeight + 1) + minHeight; int xWidth = nextInt(rand, maxWidthX - minWidthX + 1) + minWidthX; int zWidth = nextInt(rand, maxWidthZ - minWidthZ + 1) + minWidthZ; int holes = 0; int x, y, z; int floor = yStart - 1, ceiling = yStart + height + 1; for (x = xStart - xWidth - 1; x <= xStart + xWidth + 1; ++x) { for (z = zStart - zWidth - 1; z <= zStart + zWidth + 1; ++z) { for (y = floor; y <= ceiling; ++y) { if (y == floor && !canGenerateInBlock(world, x, y, z, genBlock)) return false; if (y == ceiling && !canGenerateInBlock(world, x, y, z, genBlock)) return false; if ((abs(x - xStart) == xWidth + 1 || abs(z - zStart) == zWidth + 1) && y == yStart && world.isAirBlock(x, y, z) && world.isAirBlock(x, y + 1, z)) ++holes; } } } if (holes < minHoles || holes > maxHoles) return false; NBTTagCompound tag = (NBTTagCompound) ((WeightedRandomNBTTag)WeightedRandom.getRandomItem(rand, spawners)).tag; ChestGenHooks table = ChestGenHooks.getInfo(((DungeonMob)WeightedRandom.getRandomItem(rand, lootTables)).type); for (x = xStart - xWidth - 1; x <= xStart + xWidth + 1; ++x) { for (z = zStart - zWidth - 1; z <= zStart + zWidth + 1; ++z) { for (y = yStart + height; y >= floor; --y) { if ((abs(x - xStart) != xWidth + 1 || abs(z - zStart) != zWidth + 1) && y != ceiling) { world.setBlockToAir(x, y, z); } else if (y >= 0 && !canGenerateInBlock(world, x, y - 1, z, genBlock)) { world.setBlockToAir(x, y, z); } else if (canGenerateInBlock(world, x, y, z, genBlock)) { if (y == floor) generateBlock(world, x, y, z, this.floor); else generateBlock(world, x, y, z, walls); } } } } for (int i = maxChests; i --> 0; ) { for (int j = 0; j < 3; ++j) { x = xStart + nextInt(rand, xWidth * 2 + 1) - xWidth; z = zStart + nextInt(rand, zWidth * 2 + 1) - zWidth; if (world.isAirBlock(x, yStart, z)) { int walls = 0; if (isWall(world, x - 1, yStart, z)) ++walls; if (isWall(world, x + 1, yStart, z)) ++walls; if (isWall(world, x, yStart, z - 1)) ++walls; if (isWall(world, x, yStart, z + 1)) ++walls; if (walls >= 1 && walls <= 2) { world.setBlock(x, yStart, z, Blocks.chest, 0, 2); TileEntityChest chest = (TileEntityChest)world.getTileEntity(x, yStart, z); if (chest != null) { WeightedRandomChestContent.generateChestContents(rand, table.getItems(rand), chest, table.getCount(rand)); } break; } } } } world.setBlock(xStart, yStart, zStart, Blocks.mob_spawner, 0, 2); TileEntityMobSpawner spawner = (TileEntityMobSpawner)world.getTileEntity(xStart, yStart, zStart); if (spawner != null) { spawner.func_145881_a().readFromNBT(tag); } else { System.err.println("Failed to fetch mob spawner entity at (" + xStart + ", " + yStart + ", " + zStart + ")"); } return true; } private static int nextInt(Random rand, int v) { if (v <= 1) return 0; return rand.nextInt(v); } private boolean isWall(World world, int x, int y, int z) { int metadata = world.getBlockMetadata(x, y, z); return WeightedRandomBlock.isBlockContained(world.getBlock(x, y, z), metadata, walls); } }