protected void randomizeMaterials() { switch (random.nextInt(5)) { case 0: // lava, sand/sandstone/stone, mushroom stalks byteLiquid = (byte) Material.STATIONARY_LAVA.getId(); byteStone = (byte) Material.STONE.getId(); byteDirt = (byte) Material.SANDSTONE.getId(); byteGrass = (byte) Material.SAND.getId(); intTreeTrunk = Material.HUGE_MUSHROOM_1.getId(); intTreeLeaves = intAir; byteTreeData = (byte) (random.nextInt(2) == 0 ? 10 : 1); break; case 1: // air, sand/sandstone/stone, cactus byteLiquid = (byte) Material.AIR.getId(); byteStone = (byte) Material.STONE.getId(); byteDirt = (byte) Material.SANDSTONE.getId(); byteGrass = (byte) Material.SAND.getId(); intTreeTrunk = Material.CACTUS.getId(); intTreeLeaves = intAir; minTreeHeight = 2; maxTreeHeight = 4; break; case 3: // water, glass/glowstone/endstone, crystals byteLiquid = (byte) Material.STATIONARY_WATER.getId(); byteStone = (byte) Material.ENDER_STONE.getId(); byteDirt = (byte) Material.SOUL_SAND.getId(); byteGrass = (byte) Material.MYCEL.getId(); intTreeTrunk = Material.GLOWSTONE.getId(); intTreeLeaves = Material.THIN_GLASS.getId(); break; default: // water, grass/dirt/stone, normal trees are the default byteTreeData = (byte) random.nextInt(3); break; } }
public abstract class PlatLot { // extremes private CachedYs blockYs; protected int averageHeight; protected int minHeight = Integer.MAX_VALUE; protected int minHeightX = 0; protected int minHeightZ = 0; protected int maxHeight = Integer.MIN_VALUE; protected int maxHeightX = 0; protected int maxHeightZ = 0; protected Random platmapRandom; protected Random chunkRandom; // styling! public enum LotStyle { NATURE, STRUCTURE, ROAD, ROUNDABOUT }; public LotStyle style; public PlatLot(PlatMap platmap, int chunkX, int chunkZ) { super(); initializeDice(platmap, chunkX, chunkZ); style = LotStyle.NATURE; } protected static final byte airId = (byte) Material.AIR.getId(); protected static final byte stoneId = (byte) Material.STONE.getId(); protected static final byte dirtId = (byte) Material.DIRT.getId(); protected static final byte grassId = (byte) Material.GRASS.getId(); protected static final byte snowId = (byte) Material.SNOW_BLOCK.getId(); protected static final byte sandId = (byte) Material.SAND.getId(); protected static final byte sandstoneId = (byte) Material.SANDSTONE.getId(); protected static final byte bedrockId = (byte) Material.BEDROCK.getId(); protected static final byte fenceId = (byte) Material.FENCE.getId(); protected static final byte cobbleId = (byte) Material.COBBLESTONE.getId(); protected static final byte stillWaterId = (byte) Material.STATIONARY_WATER.getId(); protected static final byte stillLavaId = (byte) Material.STATIONARY_LAVA.getId(); protected static final byte waterId = (byte) Material.WATER.getId(); protected static final byte lavaId = (byte) Material.LAVA.getId(); protected static final byte leavesId = (byte) Material.LEAVES.getId(); protected static final byte glassId = (byte) Material.GLASS.getId(); protected static final byte paneId = (byte) Material.THIN_GLASS.getId(); protected static final byte logId = (byte) Material.LOG.getId(); protected static final byte glowId = (byte) Material.GLOWSTONE.getId(); protected static final byte stepId = (byte) Material.STEP.getId(); protected static final byte clayId = (byte) Material.CLAY.getId(); protected static final byte ironFenceId = (byte) Material.IRON_FENCE.getId(); protected static final byte endId = (byte) Material.ENDER_STONE.getId(); protected static final byte netherrackId = (byte) Material.NETHERRACK.getId(); protected static final byte soulsandId = (byte) Material.SOUL_SAND.getId(); protected static final int snowMaterialId = Material.SNOW.getId(); protected static final Material snowMaterial = Material.SNOW; protected static final Material airMaterial = Material.AIR; protected static final Material stoneMaterial = Material.STONE; protected static final Material rootMaterial = Material.GRASS; public abstract long getConnectedKey(); public abstract boolean makeConnected(PlatLot relative); public abstract boolean isConnectable(PlatLot relative); public abstract boolean isConnected(PlatLot relative); protected abstract void generateActualChunk( WorldGenerator generator, PlatMap platmap, ByteChunk chunk, BiomeGrid biomes, DataContext context, int platX, int platZ); protected abstract void generateActualBlocks( WorldGenerator generator, PlatMap platmap, RealChunk chunk, DataContext context, int platX, int platZ); public Biome getChunkBiome() { return Biome.PLAINS; } public boolean isPlaceableAt(WorldGenerator generator, int chunkX, int chunkZ) { return generator.settings.inCityRange(chunkX, chunkZ); } private void initializeDice(PlatMap platmap, int chunkX, int chunkZ) { // reset and pick up the dice platmapRandom = platmap.getRandomGenerator(); chunkRandom = platmap.getChunkRandomGenerator(chunkX, chunkZ); } protected void initializeContext(WorldGenerator generator, SupportChunk chunk) { if (blockYs == null) { blockYs = new CachedYs(generator, chunk); // what was the average height minHeight = blockYs.minHeight; minHeightX = blockYs.minHeightX; minHeightZ = blockYs.minHeightZ; maxHeight = blockYs.maxHeight; maxHeightX = blockYs.maxHeightX; maxHeightZ = blockYs.maxHeightZ; averageHeight = blockYs.averageHeight; } } private void deinitializeContext() { blockYs = null; } protected int getBlockY(int x, int z) { return blockYs == null ? 0 : blockYs.getBlockY(x, z); } protected double getPerciseY(int x, int z) { return blockYs == null ? 0 : blockYs.getPerciseY(x, z); } public abstract int getBottomY(WorldGenerator generator); public void generateChunk( WorldGenerator generator, PlatMap platmap, ByteChunk chunk, BiomeGrid biomes, DataContext context, int platX, int platZ) { initializeDice(platmap, chunk.chunkX, chunk.chunkZ); initializeContext(generator, chunk); // what do we need to first? generator.shapeProvider.preGenerateChunk(generator, this, chunk, biomes, blockYs); // let the specialized platlot do it's thing generateActualChunk(generator, platmap, chunk, biomes, context, platX, platZ); // polish things off generator.shapeProvider.postGenerateChunk(generator, this, chunk, blockYs); } public void generateBlocks( WorldGenerator generator, PlatMap platmap, RealChunk chunk, DataContext context, int platX, int platZ) { initializeDice(platmap, chunk.chunkX, chunk.chunkZ); initializeContext(generator, chunk); // what do we need to first? generator.shapeProvider.preGenerateBlocks(generator, this, chunk, blockYs); // let the specialized platlot do it's thing generateActualBlocks(generator, platmap, chunk, context, platX, platZ); // polish things off generator.shapeProvider.postGenerateBlocks(generator, this, chunk, blockYs); // all done deinitializeContext(); } private static final int lowestMineSegment = 16; public void generateMines(WorldGenerator generator, ByteChunk chunk) { // get shafted! (this builds down to keep the support poles happy) if (generator.settings.includeMines) for (int y = (minHeight / 16 - 1) * 16; y >= lowestMineSegment; y -= 16) { if (isShaftableLevel(generator, y)) generateHorizontalMineLevel(generator, chunk, y); } } protected int findHighestShaftableLevel( WorldGenerator generator, DataContext context, SupportChunk chunk) { // keep going down until we find what we are looking for for (int y = (minHeight / 16 - 1) * 16; y >= lowestMineSegment; y -= 16) { if (isShaftableLevel(generator, y) && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ)) return y + 7; } // nothing found return 0; } protected boolean isShaftableLevel(WorldGenerator generator, int y) { return y >= lowestMineSegment && y < minHeight && minHeight > generator.seaLevel; } private void generateHorizontalMineLevel(WorldGenerator generator, ByteChunk chunk, int y) { int y1 = y + 6; int y2 = y1 + 1; // draw the shafts/walkways boolean pathFound = false; if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ)) { generateMineShaftSpace(chunk, 6, 10, y1, y1 + 4, 0, 6); generateMineNSSupport(chunk, 6, y2, 1); generateMineNSSupport(chunk, 6, y2, 4); generateMineShaftSpace(chunk, 6, 10, y1, y1 + 4, 10, 16); generateMineNSSupport(chunk, 6, y2, 11); generateMineNSSupport(chunk, 6, y2, 14); pathFound = true; } if (generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ)) { generateMineShaftSpace(chunk, 0, 6, y1, y1 + 4, 6, 10); generateMineWESupport(chunk, 1, y2, 6); generateMineWESupport(chunk, 4, y2, 6); generateMineShaftSpace(chunk, 10, 16, y1, y1 + 4, 6, 10); generateMineWESupport(chunk, 11, y2, 6); generateMineWESupport(chunk, 14, y2, 6); pathFound = true; } // draw the center bit if (pathFound) generateMineShaftSpace(chunk, 6, 10, y1, y1 + 4, 6, 10); } private static final byte shaftBridgeId = (byte) Material.WOOD.getId(); private static final byte shaftSupportId = (byte) Material.FENCE.getId(); private static final byte shaftBeamId = (byte) Material.WOOD.getId(); private void generateMineShaftSpace( ByteChunk chunk, int x1, int x2, int y1, int y2, int z1, int z2) { chunk.setEmptyBlocks(x1, x2, y1, z1, z2, shaftBridgeId); chunk.setBlocks(x1, x2, y1 + 1, y2, z1, z2, airId); } private void generateMineNSSupport(ByteChunk chunk, int x, int y, int z) { // on a bridge if (chunk.getBlock(x, y - 1, z) == shaftBridgeId && chunk.getBlock(x + 3, y - 1, z) == shaftBridgeId) { // place supports generateMineSupport(chunk, x, y - 1, z); generateMineSupport(chunk, x + 3, y - 1, z); // in a tunnel } else { chunk.setBlock(x, y, z, shaftSupportId); chunk.setBlock(x, y + 1, z, shaftSupportId); chunk.setBlock(x + 3, y, z, shaftSupportId); chunk.setBlock(x + 3, y + 1, z, shaftSupportId); chunk.setBlocks(x, x + 4, y + 2, z, z + 1, shaftBeamId); } } private void generateMineWESupport(ByteChunk chunk, int x, int y, int z) { // on a bridge if (chunk.getBlock(x, y - 1, z) == shaftBridgeId && chunk.getBlock(x, y - 1, z + 3) == shaftBridgeId) { // place supports generateMineSupport(chunk, x, y - 1, z); generateMineSupport(chunk, x, y - 1, z + 3); // in a tunnel } else { chunk.setBlock(x, y, z, shaftSupportId); chunk.setBlock(x, y + 1, z, shaftSupportId); chunk.setBlock(x, y, z + 3, shaftSupportId); chunk.setBlock(x, y + 1, z + 3, shaftSupportId); chunk.setBlocks(x, x + 1, y + 2, z, z + 4, shaftBeamId); } } private void generateMineSupport(ByteChunk chunk, int x, int y, int z) { int aboveSupport = chunk.findLastEmptyAbove(x, y, z); if (aboveSupport < maxHeight) chunk.setBlocks(x, y + 1, aboveSupport + 1, z, shaftSupportId); } public void generateMines(WorldGenerator generator, RealChunk chunk) { // get shafted! if (generator.settings.includeMines) for (int y = 0; y + 16 < minHeight; y += 16) { if (isShaftableLevel(generator, y)) generateVerticalMineLevel(generator, chunk, y); } } private void generateVerticalMineLevel(WorldGenerator generator, RealChunk chunk, int y) { int y1 = y + 6; boolean stairsFound = false; // going down? if (isShaftableLevel(generator, y - 16)) { if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ) && generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y - 16, chunk.chunkZ)) { // draw the going down bit placeMineStairBase(chunk, 10, y1, 15); placeMineStairStep(chunk, 10, y1, 14, Stair.SOUTH, Stair.NORTHFLIP); placeMineStairStep(chunk, 10, y1 - 1, 13, Stair.SOUTH, Stair.NORTHFLIP); placeMineStairStep(chunk, 10, y1 - 2, 12, Stair.SOUTH, Stair.NORTHFLIP); placeMineStairStep(chunk, 10, y1 - 3, 11, Stair.SOUTH, Stair.NORTHFLIP); placeMineStairStep(chunk, 10, y1 - 4, 10, Stair.SOUTH, Stair.NORTHFLIP); placeMineStairStep(chunk, 10, y1 - 5, 9, Stair.SOUTH, Stair.NORTHFLIP); placeMineStairStep(chunk, 10, y1 - 6, 8, Stair.SOUTH, Stair.NORTHFLIP); stairsFound = true; } if (!stairsFound && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ) && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y - 16, chunk.chunkZ)) { // draw the going down bit placeMineStairBase(chunk, 15, y1, 10); placeMineStairStep(chunk, 14, y1, 10, Stair.EAST, Stair.WESTFLIP); placeMineStairStep(chunk, 13, y1 - 1, 10, Stair.EAST, Stair.WESTFLIP); placeMineStairStep(chunk, 12, y1 - 2, 10, Stair.EAST, Stair.WESTFLIP); placeMineStairStep(chunk, 11, y1 - 3, 10, Stair.EAST, Stair.WESTFLIP); placeMineStairStep(chunk, 10, y1 - 4, 10, Stair.EAST, Stair.WESTFLIP); placeMineStairStep(chunk, 9, y1 - 5, 10, Stair.EAST, Stair.WESTFLIP); placeMineStairStep(chunk, 8, y1 - 6, 10, Stair.EAST, Stair.WESTFLIP); } } // reset the stairs flag stairsFound = false; // going up? if (isShaftableLevel(generator, y + 32)) { if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ) && generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y + 16, chunk.chunkZ)) { // draw the going up bit placeMineStairBase(chunk, 5, y1, 15); placeMineStairStep(chunk, 5, y1 + 1, 14, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairStep(chunk, 5, y1 + 2, 13, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairStep(chunk, 5, y1 + 3, 12, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairStep(chunk, 5, y1 + 4, 11, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairStep(chunk, 5, y1 + 5, 10, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairStep(chunk, 5, y1 + 6, 9, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairStep(chunk, 5, y1 + 7, 8, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairStep(chunk, 5, y1 + 8, 7, Stair.NORTH, Stair.SOUTHFLIP); placeMineStairBase(chunk, 5, y1 + 8, 6); placeMineStairBase(chunk, 6, y1 + 8, 6); placeMineStairBase(chunk, 7, y1 + 8, 6); placeMineStairBase(chunk, 8, y1 + 8, 6); placeMineStairBase(chunk, 9, y1 + 8, 6); placeMineStairBase(chunk, 10, y1 + 8, 6); placeMineStairStep(chunk, 10, y1 + 9, 7, Stair.SOUTH, Stair.NORTHFLIP); generateMineSupport(chunk, 6, y1 + 7, 7); generateMineSupport(chunk, 9, y1 + 7, 7); stairsFound = true; } if (!stairsFound && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ) && generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y + 16, chunk.chunkZ)) { // draw the going up bit placeMineStairBase(chunk, 15, y1, 5); placeMineStairStep(chunk, 14, y1 + 1, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairStep(chunk, 13, y1 + 2, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairStep(chunk, 12, y1 + 3, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairStep(chunk, 11, y1 + 4, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairStep(chunk, 10, y1 + 5, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairStep(chunk, 9, y1 + 6, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairStep(chunk, 8, y1 + 7, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairStep(chunk, 7, y1 + 8, 5, Stair.WEST, Stair.EASTFLIP); placeMineStairBase(chunk, 6, y1 + 8, 5); placeMineStairBase(chunk, 6, y1 + 8, 6); placeMineStairBase(chunk, 6, y1 + 8, 7); placeMineStairBase(chunk, 6, y1 + 8, 8); placeMineStairBase(chunk, 6, y1 + 8, 9); placeMineStairBase(chunk, 6, y1 + 8, 10); placeMineStairStep(chunk, 7, y1 + 9, 10, Stair.EAST, Stair.WESTFLIP); generateMineSupport(chunk, 7, y1 + 7, 6); generateMineSupport(chunk, 7, y1 + 7, 9); } } // make the ceiling pretty boolean pathFound = false; if (generator.shapeProvider.isHorizontalNSShaft(chunk.chunkX, y, chunk.chunkZ)) { generateMineCeiling(chunk, 6, 10, y1 + 3, 0, 6); generateMineCeiling(chunk, 6, 10, y1 + 3, 10, 16); generateMineAlcove(generator, chunk, 4, y1, 2, 4, 2); generateMineAlcove(generator, chunk, 10, y1, 2, 11, 3); pathFound = true; } if (generator.shapeProvider.isHorizontalWEShaft(chunk.chunkX, y, chunk.chunkZ)) { generateMineCeiling(chunk, 0, 6, y1 + 3, 6, 10); generateMineCeiling(chunk, 10, 16, y1 + 3, 6, 10); generateMineAlcove(generator, chunk, 2, y1, 4, 2, 4); generateMineAlcove(generator, chunk, 2, y1, 10, 3, 11); pathFound = true; } // draw the center bit if (pathFound) generateMineCeiling(chunk, 6, 10, y1 + 3, 6, 10); } private void generateMineAlcove( WorldGenerator generator, RealChunk chunk, int x, int y, int z, int prizeX, int prizeZ) { if (chunkRandom.nextDouble() < 0.66) { if (!chunk.isEmpty(x, y, z) && !chunk.isEmpty(x + 1, y, z) && !chunk.isEmpty(x, y, z + 1) && !chunk.isEmpty(x + 1, y, z + 1)) { chunk.setBlocks(x, x + 2, y + 1, y + 4, z, z + 2, Material.AIR); generateMineCeiling(chunk, x, x + 2, y + 3, z, z + 2); if (chunkRandom.nextDouble() < 0.66) { if (chunkRandom.nextDouble() < 0.33) generateMineTreat(generator, chunk, prizeX, y + 1, prizeZ); else generateMineTrick(generator, chunk, prizeX, y + 1, prizeZ); } } } } private void generateMineCeiling(RealChunk chunk, int x1, int x2, int y, int z1, int z2) { for (int x = x1; x < x2; x++) { for (int z = z1; z < z2; z++) { if (chunkRandom.nextBoolean()) if (!chunk.isEmpty(x, y + 1, z) && chunk.isEmpty(x, y, z)) chunk.setStoneSlab(x, y, z, Direction.StoneSlab.COBBLESTONEFLIP); } } } private void generateMineSupport(RealChunk chunk, int x, int y, int z) { int aboveSupport = chunk.findLastEmptyAbove(x, y, z); if (aboveSupport < maxHeight) chunk.setBlocks(x, y + 1, aboveSupport + 1, z, Material.FENCE); } private void placeMineStairBase(RealChunk chunk, int x, int y, int z) { chunk.setBlocks(x, y + 1, y + 4, z, Material.AIR); chunk.setEmptyBlock(x, y, z, Material.WOOD); } private void placeMineStairStep( RealChunk chunk, int x, int y, int z, Stair direction, Stair flipDirection) { chunk.setBlocks(x, y + 1, y + 4, z, Material.AIR); chunk.setStair(x, y, z, Material.WOOD_STAIRS, direction); if (chunk.isEmpty(x, y - 1, z)) chunk.setStair(x, y - 1, z, Material.WOOD_STAIRS, flipDirection); } private void generateMineTreat(WorldGenerator generator, RealChunk chunk, int x, int y, int z) { // cool stuff? if (generator.settings.treasuresInMines && chunkRandom.nextDouble() <= generator.settings.oddsOfTreasureInMines) { chunk.setChest( x, y, z, Direction.General.SOUTH, generator.lootProvider.getItems(generator, chunkRandom, LootLocation.MINE)); } } private void generateMineTrick(WorldGenerator generator, RealChunk chunk, int x, int y, int z) { // not so cool stuff? if (generator.settings.spawnersInMines && chunkRandom.nextDouble() <= generator.settings.oddsOfSpawnerInMines) { chunk.setSpawner( x, y, z, generator.spawnProvider.getEntity(generator, chunkRandom, SpawnerLocation.MINE)); } } public boolean isValidStrataY(WorldGenerator generator, int blockX, int blockY, int blockZ) { return true; } public void generateOres(WorldGenerator generator, RealChunk chunk) { // shape the world if (generator.settings.includeOres || generator.settings.includeUndergroundFluids) generator.oreProvider.sprinkleOres( generator, this, chunk, blockYs, chunkRandom, OreLocation.CRUST); } // TODO move this logic to SurroundingLots, add to it the ability to produce SurroundingHeights // and SurroundingDepths public PlatLot[][] getNeighborPlatLots( PlatMap platmap, int platX, int platZ, boolean onlyConnectedNeighbors) { PlatLot[][] miniPlatMap = new PlatLot[3][3]; // populate the results for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { // which platchunk are we looking at? int atX = platX + x - 1; int atZ = platZ + z - 1; // is it in bounds? if (!(atX < 0 || atX > PlatMap.Width - 1 || atZ < 0 || atZ > PlatMap.Width - 1)) { PlatLot relative = platmap.getLot(atX, atZ); if (!onlyConnectedNeighbors || isConnected(relative)) { miniPlatMap[x][z] = relative; } } } } return miniPlatMap; } public void generateSurface(WorldGenerator generator, RealChunk chunk, boolean includeTrees) { // plant grass or snow generator.surfaceProvider.generateSurface(generator, this, chunk, blockYs, includeTrees); } }