2019-01-19 16:52:04 +01:00
|
|
|
package world.bentobox.greenhouses.greenhouse;
|
|
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.List;
|
2021-01-16 18:16:09 +01:00
|
|
|
import java.util.concurrent.CompletableFuture;
|
2019-01-19 16:52:04 +01:00
|
|
|
|
2021-01-16 23:27:29 +01:00
|
|
|
import org.bukkit.Bukkit;
|
2019-01-19 16:52:04 +01:00
|
|
|
import org.bukkit.Location;
|
|
|
|
import org.bukkit.Material;
|
|
|
|
|
2021-01-16 23:27:29 +01:00
|
|
|
import world.bentobox.bentobox.BentoBox;
|
2020-08-23 00:52:18 +02:00
|
|
|
import world.bentobox.greenhouses.Greenhouses;
|
2021-01-16 23:27:29 +01:00
|
|
|
import world.bentobox.greenhouses.world.AsyncWorldCache;
|
2020-08-23 00:52:18 +02:00
|
|
|
|
2021-09-25 20:34:36 +02:00
|
|
|
@SuppressWarnings("deprecation")
|
2019-11-01 05:51:24 +01:00
|
|
|
public class Walls extends MinMaxXZ {
|
2020-08-23 00:52:18 +02:00
|
|
|
private static final List<Material> WALL_BLOCKS;
|
2019-11-23 05:58:32 +01:00
|
|
|
static {
|
2021-08-01 08:10:07 +02:00
|
|
|
// Hoppers
|
|
|
|
WALL_BLOCKS = Arrays.stream(Material.values())
|
2019-11-01 05:36:05 +01:00
|
|
|
.filter(Material::isBlock) // Blocks only, no items
|
2021-09-25 20:34:36 +02:00
|
|
|
.filter(m -> !m.isLegacy())
|
2019-11-01 05:36:05 +01:00
|
|
|
.filter(m -> !m.name().contains("TRAPDOOR")) // No trap doors
|
|
|
|
.filter(m -> m.name().contains("DOOR") // All doors
|
2021-01-10 19:51:35 +01:00
|
|
|
|| (m.name().contains("GLASS") && !m.name().contains("GLASS_PANE")) // All glass blocks
|
2021-08-01 08:10:07 +02:00
|
|
|
|| m.equals(Material.HOPPER)).toList();
|
2019-11-01 05:36:05 +01:00
|
|
|
}
|
2019-01-26 17:38:13 +01:00
|
|
|
|
2019-11-23 05:58:32 +01:00
|
|
|
private int floor;
|
|
|
|
|
2021-01-16 23:27:29 +01:00
|
|
|
private final AsyncWorldCache cache;
|
2019-11-23 05:58:32 +01:00
|
|
|
|
2021-09-18 19:33:48 +02:00
|
|
|
static class WallFinder {
|
2020-10-11 18:03:13 +02:00
|
|
|
int radiusMinX;
|
|
|
|
int radiusMaxX;
|
|
|
|
int radiusMinZ;
|
|
|
|
int radiusMaxZ;
|
|
|
|
boolean stopMinX;
|
|
|
|
boolean stopMaxX;
|
|
|
|
boolean stopMinZ;
|
|
|
|
boolean stopMaxZ;
|
|
|
|
boolean isSearching() {
|
|
|
|
return !stopMinX || !stopMaxX || !stopMinZ || !stopMaxZ;
|
|
|
|
}
|
2021-01-16 23:27:29 +01:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "WallFinder [radiusMinX=" + radiusMinX + ", radiusMaxX=" + radiusMaxX + ", radiusMinZ=" + radiusMinZ
|
|
|
|
+ ", radiusMaxZ=" + radiusMaxZ + ", stopMinX=" + stopMinX + ", stopMaxX=" + stopMaxX + ", stopMinZ="
|
|
|
|
+ stopMinZ + ", stopMaxZ=" + stopMaxZ + "]";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Walls(AsyncWorldCache cache) {
|
|
|
|
this.cache = cache;
|
2020-10-11 18:03:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-16 18:16:09 +01:00
|
|
|
/**
|
|
|
|
* Find walls given a roof
|
|
|
|
* @param roof - the roof
|
|
|
|
* @return Future walls
|
|
|
|
*/
|
2021-01-16 23:27:29 +01:00
|
|
|
public CompletableFuture<Walls> findWalls(final Roof roof) {
|
|
|
|
CompletableFuture<Walls> r = new CompletableFuture<>();
|
|
|
|
Bukkit.getScheduler().runTaskAsynchronously(BentoBox.getInstance(), () -> findWalls(r, roof));
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
Walls findWalls(CompletableFuture<Walls> r, Roof roof) {
|
2019-01-19 16:52:04 +01:00
|
|
|
// The player is under the roof
|
|
|
|
// Assume the player is inside the greenhouse they are trying to create
|
2021-01-16 23:27:29 +01:00
|
|
|
final Location loc = roof.getLocation();
|
|
|
|
floor = getFloorY(roof.getHeight(), roof.getMinX(), roof.getMaxX(), roof.getMinZ(), roof.getMaxZ());
|
2019-01-19 16:52:04 +01:00
|
|
|
// Now start with the player's x and z location
|
2020-10-11 18:03:13 +02:00
|
|
|
WallFinder wf = new WallFinder();
|
2019-01-19 16:52:04 +01:00
|
|
|
minX = loc.getBlockX();
|
|
|
|
maxX = loc.getBlockX();
|
|
|
|
minZ = loc.getBlockZ();
|
|
|
|
maxZ = loc.getBlockZ();
|
|
|
|
do {
|
2020-10-11 18:03:13 +02:00
|
|
|
lookAround(loc, wf, roof);
|
|
|
|
} while (wf.isSearching());
|
2019-01-19 16:52:04 +01:00
|
|
|
// We should have the largest cube we can make now
|
|
|
|
minX--;
|
|
|
|
maxX++;
|
|
|
|
minZ--;
|
|
|
|
maxZ++;
|
|
|
|
// Find the floor again, only looking within the walls
|
2021-01-16 23:27:29 +01:00
|
|
|
floor = getFloorY(roof.getHeight(), minX, maxX, minZ,maxZ);
|
|
|
|
// Complete on main thread
|
|
|
|
Bukkit.getScheduler().runTask(BentoBox.getInstance(), () -> r.complete(this));
|
|
|
|
return this;
|
|
|
|
|
2020-10-11 18:03:13 +02:00
|
|
|
}
|
|
|
|
|
2021-01-16 23:27:29 +01:00
|
|
|
void lookAround(final Location loc, WallFinder wf, final Roof roof) {
|
2020-10-11 18:03:13 +02:00
|
|
|
// Look around player in an ever expanding cube
|
|
|
|
minX = loc.getBlockX() - wf.radiusMinX;
|
|
|
|
maxX = loc.getBlockX() + wf.radiusMaxX;
|
|
|
|
minZ = loc.getBlockZ() - wf.radiusMinZ;
|
|
|
|
maxZ = loc.getBlockZ() + wf.radiusMaxZ;
|
|
|
|
for (int 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
|
2021-01-16 23:27:29 +01:00
|
|
|
lookAtBlockFaces(wf, x, y, z);
|
2020-10-11 18:03:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
analyzeFindings(wf, roof);
|
|
|
|
}
|
|
|
|
|
|
|
|
void analyzeFindings(WallFinder wf, Roof roof) {
|
|
|
|
if (minX < roof.getMinX()) {
|
|
|
|
wf.stopMinX = true;
|
|
|
|
}
|
|
|
|
if (maxX > roof.getMaxX()) {
|
|
|
|
wf.stopMaxX = true;
|
|
|
|
}
|
|
|
|
if (minZ < roof.getMinZ()) {
|
|
|
|
wf.stopMinZ = true;
|
|
|
|
}
|
|
|
|
if (maxZ > roof.getMaxZ()) {
|
|
|
|
wf.stopMaxZ = true;
|
|
|
|
}
|
|
|
|
// Expand the edges
|
|
|
|
if (!wf.stopMinX) {
|
|
|
|
wf.radiusMinX++;
|
|
|
|
}
|
|
|
|
if (!wf.stopMaxX) {
|
|
|
|
wf.radiusMaxX++;
|
|
|
|
}
|
|
|
|
if (!wf.stopMinZ) {
|
|
|
|
wf.radiusMinZ++;
|
|
|
|
}
|
|
|
|
if (!wf.stopMaxZ) {
|
|
|
|
wf.radiusMaxZ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-16 23:27:29 +01:00
|
|
|
void lookAtBlockFaces(WallFinder wf, int x, int y, int z) {
|
|
|
|
// positive x
|
|
|
|
if (WALL_BLOCKS.contains(cache.getBlockType(x + 1, y, z))) {
|
|
|
|
wf.stopMaxX = true;
|
|
|
|
}
|
|
|
|
// negative x
|
|
|
|
if (WALL_BLOCKS.contains(cache.getBlockType(x - 1, y, z))) {
|
|
|
|
wf.stopMinX = true;
|
|
|
|
}
|
|
|
|
// negative Z
|
|
|
|
if (WALL_BLOCKS.contains(cache.getBlockType(x, y, z - 1))) {
|
|
|
|
wf.stopMinZ = true;
|
|
|
|
}
|
|
|
|
// positive Z
|
|
|
|
if (WALL_BLOCKS.contains(cache.getBlockType(x, y, z + 1))) {
|
|
|
|
wf.stopMaxZ = true;
|
2020-10-11 18:03:13 +02:00
|
|
|
}
|
2019-01-26 17:38:13 +01:00
|
|
|
}
|
|
|
|
|
2021-01-16 23:27:29 +01:00
|
|
|
int getFloorY(int y, int minX, int maxX, int minZ, int maxZ) {
|
2019-01-26 17:38:13 +01:00
|
|
|
// Find the floor - defined as the last y under the roof where there are no wall blocks
|
|
|
|
int wallBlockCount;
|
2019-01-19 16:52:04 +01:00
|
|
|
do {
|
|
|
|
wallBlockCount = 0;
|
|
|
|
for (int x = minX; x <= maxX; x++) {
|
|
|
|
for (int z = minZ; z <= maxZ; z++) {
|
2021-01-16 23:27:29 +01:00
|
|
|
if (WALL_BLOCKS.contains(cache.getBlockType(x, y, z))) {
|
2019-01-19 16:52:04 +01:00
|
|
|
wallBlockCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} while( y-- > 0 && wallBlockCount > 0);
|
2019-01-26 17:38:13 +01:00
|
|
|
return y + 1;
|
|
|
|
|
2019-01-19 16:52:04 +01:00
|
|
|
}
|
|
|
|
|
2020-08-23 00:52:18 +02:00
|
|
|
/**
|
|
|
|
* Check if material is a wall material
|
|
|
|
* @param m - material
|
|
|
|
* @return true if wall material
|
|
|
|
*/
|
|
|
|
public static boolean wallBlocks(Material m) {
|
2021-01-10 19:51:35 +01:00
|
|
|
return WALL_BLOCKS.contains(m)
|
|
|
|
|| (m.equals(Material.GLOWSTONE) && Greenhouses.getInstance().getSettings().isAllowGlowstone())
|
|
|
|
|| (m.name().endsWith("GLASS_PANE") && Greenhouses.getInstance().getSettings().isAllowPanes());
|
2020-08-23 00:52:18 +02:00
|
|
|
}
|
|
|
|
|
2019-01-19 16:52:04 +01:00
|
|
|
/**
|
|
|
|
* @return the floor
|
|
|
|
*/
|
|
|
|
public int getFloor() {
|
|
|
|
return floor;
|
|
|
|
}
|
|
|
|
|
2019-01-23 05:54:43 +01:00
|
|
|
/**
|
|
|
|
* @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);
|
|
|
|
}
|
|
|
|
|
2019-01-22 02:53:34 +01:00
|
|
|
/* (non-Javadoc)
|
|
|
|
* @see java.lang.Object#toString()
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "Walls [minX=" + minX + ", maxX=" + maxX + ", minZ=" + minZ + ", maxZ=" + maxZ + ", floor=" + floor
|
|
|
|
+ "]";
|
|
|
|
}
|
2019-01-23 05:54:43 +01:00
|
|
|
|
|
|
|
|
2019-01-19 16:52:04 +01:00
|
|
|
}
|