public static Set<List<BlockPos>> resolveRows(Set<BlockPos> posSet, int dir) {

        // 1. Project every position onto the plane perpendicular to the given direction
        HashMap<BlockPos, HashSet<BlockPos>> projected = new HashMap<>();
        for (BlockPos pos : posSet) {
            BlockPos proj = projectDir(pos, dir);
            projected.computeIfAbsent(proj, k -> new HashSet<>()).add(pos);
        }

        // 2. Sort each row towards given dir
        Set<List<BlockPos>> rows = new HashSet<>();
        for (HashSet<BlockPos> rowSet : projected.values()) {
            List<BlockPos> row = sortTowardsDir(rowSet, dir);
            rows.add(row);
        }

        // 3. Split each row into contiguous sub-rows
        Set<List<BlockPos>> resolvedRows = new HashSet<>();
        for (List<BlockPos> row : rows) {
            resolvedRows.addAll(splitContinuousRows(row, dir));
        }

        return resolvedRows;
    }
Given a set of positions, this will resolve all contiguous rows of blocks towards
the given direction.

@param posSet Set of positions
@param dir Direction of each row (i.e. last pos of each row will be towards this dir from the first)
@return A set of rows, each row being a list of positions
core/src/main/java/mrtjp/projectred/lib/VecLib.java