Greenhouses/src/main/java/world/bentobox/greenhouses/greenhouse/Walls.java

220 lines
7.0 KiB
Java

package world.bentobox.greenhouses.greenhouse;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
public class Walls {
private int minX;
private int maxX;
private int minZ;
private int maxZ;
private int floor;
public static final List<BlockFace> ORDINALS = Arrays.asList(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
/**
* @return list of valid wall blocks
*/
public static List<Material> getWallBlocks() {
return Arrays.stream(Material.values())
.filter(Material::isBlock) // Blocks only, no items
.filter(m -> !m.name().contains("TRAPDOOR")) // No trap doors
.filter(m -> m.name().contains("DOOR") // All doors
|| m.name().contains("GLASS") // All glass blocks
|| m.equals(Material.HOPPER) // Hoppers
|| m.equals(Material.GLOWSTONE)) // Glowstone
.collect(Collectors.toList());
}
public Walls(Roof roof) {
// The player is under the roof
// Assume the player is inside the greenhouse they are trying to create
Location loc = roof.getLocation();
World world = roof.getLocation().getWorld();
floor = getFloorY(world, roof.getHeight(), roof.getMinX(), roof.getMaxX(), roof.getMinZ(), roof.getMaxZ());
// Now start with the player's x and z location
int radiusMinX = 0;
int radiusMaxX = 0;
int radiusMinZ = 0;
int radiusMaxZ = 0;
boolean stopMinX = false;
boolean stopMaxX = false;
boolean stopMinZ = false;
boolean stopMaxZ = false;
minX = loc.getBlockX();
maxX = loc.getBlockX();
minZ = loc.getBlockZ();
maxZ = loc.getBlockZ();
do {
// Look around player in an ever expanding cube
minX = loc.getBlockX() - radiusMinX;
maxX = loc.getBlockX() + radiusMaxX;
minZ = loc.getBlockZ() - radiusMinZ;
maxZ = loc.getBlockZ() + radiusMaxZ;
int y;
for (y = roof.getHeight() - 1; y > floor; y--) {
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
// Only look around outside edge
if (!((x > minX && x < maxX) && (z > minZ && z < maxZ))) {
// Look at block faces
for (BlockFace bf: ORDINALS) {
switch (bf) {
case EAST:
// positive x
if (getWallBlocks().contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMaxX = true;
}
break;
case WEST:
// negative x
if (getWallBlocks().contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMinX = true;
}
break;
case NORTH:
// negative Z
if (getWallBlocks().contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMinZ = true;
}
break;
case SOUTH:
// positive Z
if (getWallBlocks().contains(world.getBlockAt(x, y, z).getRelative(bf).getType())) {
stopMaxZ = true;
}
break;
default:
break;
}
}
}
}
}
}
if (minX < roof.getMinX()) {
stopMinX = true;
}
if (maxX > roof.getMaxX()) {
stopMaxX = true;
}
if (minZ < roof.getMinZ()) {
stopMinZ = true;
}
if (maxZ > roof.getMaxZ()) {
stopMaxZ = true;
}
// Expand the edges
if (!stopMinX) {
radiusMinX++;
}
if (!stopMaxX) {
radiusMaxX++;
}
if (!stopMinZ) {
radiusMinZ++;
}
if (!stopMaxZ) {
radiusMaxZ++;
}
} while (!stopMinX || !stopMaxX || !stopMinZ || !stopMaxZ);
// We should have the largest cube we can make now
minX--;
maxX++;
minZ--;
maxZ++;
// Find the floor again, only looking within the walls
floor = getFloorY(world, roof.getHeight(), minX, maxX, minZ,maxZ);
}
private int getFloorY(World world, int y, int minX, int maxX, int minZ, int maxZ) {
// Find the floor - defined as the last y under the roof where there are no wall blocks
int wallBlockCount;
do {
wallBlockCount = 0;
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
if (getWallBlocks().contains(world.getBlockAt(x, y, z).getType())) {
wallBlockCount++;
}
}
}
} while( y-- > 0 && wallBlockCount > 0);
return y + 1;
}
/**
* @return the minXX
*/
public int getMinX() {
return minX;
}
/**
* @return the maxXX
*/
public int getMaxX() {
return maxX;
}
/**
* @return the minZZ
*/
public int getMinZ() {
return minZ;
}
/**
* @return the maxZZ
*/
public int getMaxZ() {
return maxZ;
}
public int getArea() {
// Get interior area
return (maxX - minX) * (maxZ - minZ);
}
/**
* @return the floor
*/
public int getFloor() {
return floor;
}
public static boolean isWallBlock(Material blockType) {
return getWallBlocks().contains(blockType);
}
/**
* @return width of the space
*/
public int getWidth() {
return Math.abs(maxX - minX);
}
/**
* @return length of the space
*/
public int getLength() {
return Math.abs(maxZ - minZ);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Walls [minX=" + minX + ", maxX=" + maxX + ", minZ=" + minZ + ", maxZ=" + maxZ + ", floor=" + floor
+ "]";
}
}