use of eelfloat.replcraft.StructureMaterial in project replcraft by LeeFlemingRepl.
the class StructureUtil method verifyStructure.
/**
* Verifies the structure attached to a sign
* @param starting_block A block on the frame of the structure
* @throws InvalidStructure if the structure is invalid
* @return a partially validated structure, missing its sign field
*/
public static Structure verifyStructure(Block starting_block) throws InvalidStructure {
// A list of all seen frame blocks, attached chests, and signs.
HashSet<Location> seen = new HashSet<>();
Stack<Location> to_explore = new Stack<>();
int min_x = starting_block.getX();
int min_y = starting_block.getY();
int min_z = starting_block.getZ();
int max_x = starting_block.getX();
int max_y = starting_block.getY();
int max_z = starting_block.getZ();
List<Block> chests = new ArrayList<>();
to_explore.push(starting_block.getLocation());
StructureMaterial material = null;
int explored = 0;
while (!to_explore.isEmpty()) {
explored += 1;
if (material == null && explored > 100) {
throw new InvalidStructure("Too many connected blocks before finding any valid structure material.");
}
if (material != null && explored > material.max_size) {
throw new InvalidStructure(String.format("Too many connected %s blocks. The limit is %d for this material type.", material.name, material.max_size));
}
Block block = to_explore.pop().getBlock();
for (BlockFace face : BlockFace.values()) {
if (!face.isCartesian())
continue;
Block relative = block.getRelative(face);
Location location = relative.getLocation();
if (relative.getType() == Material.CHEST) {
seen.add(location);
chests.add(relative);
}
boolean isValidStructureMaterial = material == null ? ReplCraft.plugin.frame_materials.stream().flatMap(mats -> mats.validMaterials.stream()).anyMatch(mat -> relative.getType() == mat) : material.validMaterials.contains(relative.getType());
if (isValidStructureMaterial && !seen.contains(location)) {
if (material == null) {
material = ReplCraft.plugin.frame_materials.stream().filter(mats -> mats.validMaterials.contains(relative.getType())).findFirst().orElseThrow(() -> new RuntimeException("unreachable"));
ReplCraft.plugin.logger.info("Structure type determined to be " + material.name);
}
seen.add(location);
to_explore.push(location);
min_x = Math.min(min_x, location.getBlockX());
min_y = Math.min(min_y, location.getBlockY());
min_z = Math.min(min_z, location.getBlockZ());
max_x = Math.max(max_x, location.getBlockX());
max_y = Math.max(max_y, location.getBlockY());
max_z = Math.max(max_z, location.getBlockZ());
}
}
}
ReplCraft.plugin.logger.info(String.format("Structure min [%s %s %s] max [%s %s %s]", min_x, min_y, min_z, max_x, max_y, max_z));
if (material == null) {
throw new InvalidStructure("Structure must contain at least one valid structure block from any structure type.");
}
// Top edges
// 1
check_axis(material, new Location(starting_block.getWorld(), min_x, max_y, max_z), 1, 0, 0, max_x - min_x);
// 2
check_axis(material, new Location(starting_block.getWorld(), max_x, max_y, max_z), 0, 0, -1, max_z - min_z);
// 3
check_axis(material, new Location(starting_block.getWorld(), max_x, max_y, min_z), -1, 0, 0, max_x - min_x);
// 4
check_axis(material, new Location(starting_block.getWorld(), min_x, max_y, min_z), 0, 0, 1, max_z - min_z);
// Side edges
// 5
check_axis(material, new Location(starting_block.getWorld(), max_x, min_y, max_z), 0, 1, 0, max_y - min_y);
// 6
check_axis(material, new Location(starting_block.getWorld(), max_x, min_y, min_z), 0, 1, 0, max_y - min_y);
// 7
check_axis(material, new Location(starting_block.getWorld(), min_x, min_y, min_z), 0, 1, 0, max_y - min_y);
// 8
check_axis(material, new Location(starting_block.getWorld(), min_x, min_y, max_z), 0, 1, 0, max_y - min_y);
// Bottom edges
// 9
check_axis(material, new Location(starting_block.getWorld(), min_x, min_y, max_z), 1, 0, 0, max_x - min_x);
// 10
check_axis(material, new Location(starting_block.getWorld(), max_x, min_y, max_z), 0, 0, -1, max_z - min_z);
// 11
check_axis(material, new Location(starting_block.getWorld(), max_x, min_y, min_z), -1, 0, 0, max_x - min_x);
// 12
check_axis(material, new Location(starting_block.getWorld(), min_x, min_y, min_z), 0, 0, 1, max_z - min_z);
Structure structure = new Structure(material, null, null, null, null, null, seen, chests, min_x, min_y, min_z, max_x, max_y, max_z);
if (structure.inner_size_x() < 1 || structure.inner_size_y() < 1 || structure.inner_size_z() < 1) {
throw new InvalidStructure("Structure must have a nonzero interior size.");
}
return structure;
}
Aggregations