package net.glowstone.generator.structures;
import net.glowstone.GlowServer;
import net.glowstone.generator.objects.RandomItemsContent;
import net.glowstone.generator.objects.RandomItemsContent.RandomAmountItem;
import net.glowstone.generator.structures.util.StructureBoundingBox;
import net.glowstone.generator.structures.util.StructureBuilder;
import net.glowstone.generator.structures.util.StructureBuilder.StructureMaterial;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.entity.EntityType;
import org.bukkit.material.Chest;
import org.bukkit.util.Vector;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class GlowDungeon extends GlowStructurePiece {
private static final int HEIGHT = 6;
private static final int MIN_RADIUS = 3;
private final int radiusX;
private final int radiusZ;
private final int sizeX;
private final int sizeZ;
private final EntityType[] mobTypes = new EntityType[] {
EntityType.SKELETON, EntityType.ZOMBIE,
EntityType.ZOMBIE, EntityType.SPIDER
};
private final Location loc;
public GlowDungeon(Random random, Location location) {
super(location, new Vector(9, HEIGHT, 9));
// inner dungeon shape is 5x5, 5x7 or 7x7
radiusX = random.nextInt(2) + MIN_RADIUS;
radiusZ = random.nextInt(2) + MIN_RADIUS;
sizeX = radiusX * 2 + 1;
sizeZ = radiusZ * 2 + 1;
loc = location;
}
public boolean canPlace(StructureBuilder builder) {
if (boundingBox.getMin().getBlockY() < 1) {
return false;
}
int i = 0;
for (int x = 0; x < sizeX; x++) {
for (int z = 0; z < sizeZ; z++) {
for (int y = 0; y < HEIGHT; y++) {
final Material type = builder.getBlockState(new Vector(x, y, z)).getType();
// checks we are between 2 solid material layers
if ((y == 0 || y == HEIGHT - 1) && !type.isSolid()) {
return false;
}
// checks a few blocks at bottom of walls are opened to air
// in order to have a natural door like access
if ((x == 0 || x == sizeX - 1 || z == 0 || z == sizeZ - 1)
&& y == 1 && type == Material.AIR
&& builder.getBlockState(new Vector(x, y + 1, z)).getType() == Material.AIR) {
i++;
// TODO change min to 1 when caves will be generated ! this will be required so that dungeons are minimally exposed to air
if (i < 0 || i > 5) {
return false;
}
}
}
}
}
return true;
}
@Override
public boolean generate(World world, Random random, StructureBoundingBox genBoundingBox, BlockStateDelegate delegate) {
if (!super.generate(world, random, boundingBox, delegate)) {
return false;
}
boundingBox.offset(new Vector(-radiusX, -1, -radiusZ));
final StructureBuilder builder = new StructureBuilder(world, this, genBoundingBox, delegate);
if (!canPlace(builder)) {
return false;
}
final Map<StructureMaterial, Integer> stones = new HashMap<StructureMaterial, Integer>();
builder.addRandomMaterial(stones, 1, Material.COBBLESTONE, 0);
builder.addRandomMaterial(stones, 3, Material.MOSSY_COBBLESTONE, 0);
for (int x = 0; x < sizeX; x++) {
for (int z = 0; z < sizeZ; z++) {
for (int y = HEIGHT - 2; y >= 0; y--) {
final BlockState state = builder.getBlockState(new Vector(x, y, z));
if (y > 0 && x > 0 && z > 0 && x < sizeX - 1 && z < sizeZ - 1) {
// empty space inside
builder.setBlock(new Vector(x, y, z), Material.AIR);
} else if (!builder.getBlockState(new Vector(x, y - 1, z)).getType().isSolid()) {
// cleaning walls from non solid materials (because of air gaps below)
builder.setBlock(new Vector(x, y, z), Material.AIR);
} else if (state.getType().isSolid()) {
// for walls we only replace solid material in order to
// preserve the air gaps
if (y == 0) {
builder.setBlockWithRandomMaterial(new Vector(x, y, z), random, stones);
} else {
builder.setBlock(new Vector(x, y, z), Material.COBBLESTONE);
}
}
}
}
}
final RandomItemsContent chestContent = new RandomItemsContent();
chestContent.addItem(new RandomAmountItem(Material.SADDLE, 1, 1), 10);
chestContent.addItem(new RandomAmountItem(Material.IRON_INGOT, 1, 4), 10);
chestContent.addItem(new RandomAmountItem(Material.BREAD, 1, 1), 10);
chestContent.addItem(new RandomAmountItem(Material.WHEAT, 1, 4), 10);
chestContent.addItem(new RandomAmountItem(Material.SULPHUR, 1, 4), 10);
chestContent.addItem(new RandomAmountItem(Material.STRING, 1, 4), 10);
chestContent.addItem(new RandomAmountItem(Material.BUCKET, 1, 1), 10);
chestContent.addItem(new RandomAmountItem(Material.GOLDEN_APPLE, 1, 1), 1);
chestContent.addItem(new RandomAmountItem(Material.REDSTONE, 1, 4), 10);
chestContent.addItem(new RandomAmountItem(Material.GOLD_RECORD, 1, 1), 4);
chestContent.addItem(new RandomAmountItem(Material.GREEN_RECORD, 1, 1), 4);
chestContent.addItem(new RandomAmountItem(Material.NAME_TAG, 1, 1), 10);
chestContent.addItem(new RandomAmountItem(Material.GOLD_BARDING, 1, 1), 2);
chestContent.addItem(new RandomAmountItem(Material.IRON_BARDING, 1, 1), 5);
chestContent.addItem(new RandomAmountItem(Material.DIAMOND_BARDING, 1, 1), 1);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
int x = random.nextInt(radiusX * 2 - 1) + 1;
int z = random.nextInt(radiusZ * 2 - 1) + 1;
if (builder.getBlockState(new Vector(x, 1, z)).getType() == Material.AIR) {
BlockFace face = null;
int solidBlocksCount = 0;
if (builder.getBlockState(new Vector(x - 1, 1, z)).getType().isSolid()) {
solidBlocksCount++;
face = BlockFace.EAST;
}
if (builder.getBlockState(new Vector(x + 1, 1, z)).getType().isSolid()) {
solidBlocksCount++;
face = BlockFace.WEST;
}
if (builder.getBlockState(new Vector(x, 1, z - 1)).getType().isSolid()) {
solidBlocksCount++;
face = BlockFace.SOUTH;
}
if (builder.getBlockState(new Vector(x, 1, z + 1)).getType().isSolid()) {
solidBlocksCount++;
face = BlockFace.NORTH;
}
if (solidBlocksCount == 1) {
builder.createRandomItemsContainer(new Vector(x, 1, z), random, chestContent, new Chest(face), 8);
break;
}
}
}
}
builder.createMobSpawner(new Vector(radiusX, 1, radiusZ), mobTypes[random.nextInt(mobTypes.length)]);
GlowServer.logger.info("dungeon generated: " + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ());
return true;
}
}