Example #1
0
    def __init__(self, ploader, settings):
        super(PathfindingPlugin, self).__init__(ploader, settings)

        self.bounding_box = BoundingBox(w=0.6, h=1.8)
        self.path_job = None
        self.col = MTVTest(
            self.world, BoundingBox(const.PLAYER_WIDTH, const.PLAYER_HEIGHT)
        )
        ploader.provides('Pathfinding', PathfindingCore(self.start_path))
Example #2
0
    def __init__(self, ploader, settings):
        super(PathfindingPlugin, self).__init__(ploader, settings)

        self.bounding_box = BoundingBox(w=0.6, h=1.8)
        self.path_job = None
        self.col = MTVTest(self.world, BoundingBox(const.PLAYER_WIDTH, const.PLAYER_HEIGHT))
        ploader.provides("Pathfinding", PathfindingCore(self.start_path))
Example #3
0
class PathfindingPlugin(PluginBase):
    requires = ('Event', 'World', 'Physics', 'ClientInfo', 'Timers')

    def __init__(self, ploader, settings):
        super(PathfindingPlugin, self).__init__(ploader, settings)

        self.bounding_box = BoundingBox(w=0.6, h=1.8)
        self.path_job = None
        self.col = MTVTest(
            self.world, BoundingBox(const.PLAYER_WIDTH, const.PLAYER_HEIGHT)
        )
        ploader.provides('Pathfinding', PathfindingCore(self.start_path))

    def build_list_from_node(self, node):
        ret = collections.deque()
        ret.append(node)
        while ret[0].parent is not None:
            ret.appendleft(ret[0].parent)
        return ret

    def start_path(self, pos, target, scb, fcb=None):
        pos = center_position(pos.floor(), BoundingBox(1, 1))
        target = center_position(target.floor(), BoundingBox(1, 1))
        new_job = Path(PathNode(pos), PathNode(target)), scb, fcb
        if self.path_job:
            self.path_job = new_job
            return
        self.path_job = new_job
        if not self.do_job():
            self.event.reg_event_handler('event_tick', self.do_job)

    def do_job(self, _=None, __=None):
        path, scb, fcb = self.path_job
        ret = self.pathfind(path)
        if ret == FOUND_VALID_PATH:
            self.path_job = None
            scb(self.build_list_from_node(path.result))
            return EVENT_UNREGISTER
        elif ret == NO_VALID_PATH and fcb:
            self.path_job = None
            fcb(None)

    def pathfind(self, path):
        while path.open_list and self.timers.get_timeout():
            cur_node = path.open_list.pop(0)
            p = cur_node.parent
            if p is not None and not (p.is_fall or p.is_jump):
                p = cur_node.parent.parent
                if p is not None and not (p.is_fall or p.is_jump) \
                        and self.raycast_bbox(p, cur_node):
                    cur_node.parent = p
                    cur_node.node_dist = p.node_dist + cur_node.dist(p)
            if cur_node == path.end_node:
                path.result = cur_node
                return FOUND_VALID_PATH
            for valid_node in self.find_valid_nodes(cur_node):
                if valid_node not in (path.open_list + path.closed_list):
                    path.open_list.append(valid_node)
            path.open_list.sort(key=path.calc_f_val)
            path.closed_list.append(cur_node)
        if not path.open_list and cur_node != path.end_node:
            return NO_VALID_PATH
        return TIMEOUT_REACHED

    def raycast_bbox(self, start, end):
        pos = PathNode(uncenter_position(start, self.col.bbox))
        path = end - start
        if not path:
            return True
        depth = Vector3(
            *map(lambda a: a[0] * a[1], zip(path.norm(), self.col.bbox))
        )
        i, r = divmod(path.dist(), depth.dist())
        for j in range(int(i)):
            pos += depth
            if not self.get_block(pos.floor() - Vector3(0, 1, 0)).bounding_box:
                return False
            if any(self.col.block_collision(pos)):
                return False
        return True

    def get_block(self, pos):
        return blocks.get_block(*self.world.get_block(*pos))

    def check_for_bbox(self, pos):
        pos = pos.floor()
        block = self.get_block(pos)
        if block.bounding_box:
            return True
        block = self.get_block(pos + Vector3(0, 1, 0))
        if block.bounding_box:
            return True
        return False

    def check_node(self, node, offset, node_list, walk_fall=True, jump=True):
        w_node = PathNode(node + offset).set(node)
        if walk_fall and not self.check_for_bbox(w_node):
            f_node = PathNode(w_node - Vector3(0, 1, 0)).set(node, True)
            if not self.check_for_bbox(f_node):
                node_list.append(f_node)
                walk_bool, fall_bool = False, True
            else:
                node_list.append(w_node)
                walk_bool, fall_bool = True, False
        else:
            walk_bool, fall_bool = False, False
        j_node = PathNode(w_node + Vector3(0, 1, 0)).set(node, is_jump=True)
        if jump and not walk_bool and not (node.is_fall or node.is_jump) \
                and not self.check_for_bbox(j_node):
                node_list.append(j_node)
                jump_bool = True
        else:
            jump_bool = False
        return walk_bool or fall_bool, jump_bool

    def find_valid_nodes(self, node):
        node_list = []
        pos_x, pos_jump_x = self.check_node(node, Vector3(1, 0, 0), node_list)
        pos_z, pos_jump_z = self.check_node(node, Vector3(0, 0, 1), node_list)
        neg_x, neg_jump_x = self.check_node(node, Vector3(-1, 0, 0), node_list)
        neg_z, neg_jump_z = self.check_node(node, Vector3(0, 0, -1), node_list)

        self.check_node(node, Vector3(1, 0, 1), node_list,
                        pos_x and pos_z, pos_jump_x and pos_jump_z)
        self.check_node(node, Vector3(-1, 0, -1), node_list,
                        neg_x and neg_z, neg_jump_x and neg_jump_z)
        self.check_node(node, Vector3(1, 0, -1), node_list,
                        pos_x and neg_z, pos_jump_x and neg_jump_z)
        self.check_node(node, Vector3(-1, 0, 1), node_list,
                        neg_x and pos_z, neg_jump_x and pos_jump_z)

        return node_list
Example #4
0
class PathfindingPlugin(PluginBase):
    requires = ('Event', 'World', 'Physics', 'ClientInfo', 'Timers')

    def __init__(self, ploader, settings):
        super(PathfindingPlugin, self).__init__(ploader, settings)

        self.bounding_box = BoundingBox(w=0.6, h=1.8)
        self.path_job = None
        self.col = MTVTest(
            self.world, BoundingBox(const.PLAYER_WIDTH, const.PLAYER_HEIGHT)
        )
        ploader.provides('Pathfinding', PathfindingCore(self.start_path))

    def build_list_from_node(self, node):
        ret = collections.deque()
        ret.append(node)
        while ret[0].parent is not None:
            ret.appendleft(ret[0].parent)
        return ret

    def start_path(self, pos, target, scb, fcb=None):
        pos = center_position(pos.floor(), BoundingBox(1, 1))
        target = center_position(target.floor(), BoundingBox(1, 1))
        new_job = Path(PathNode(pos), PathNode(target)), scb, fcb
        if self.path_job:
            self.path_job = new_job
            return
        self.path_job = new_job
        if not self.do_job():
            self.event.reg_event_handler('event_tick', self.do_job)

    def do_job(self, _=None, __=None):
        path, scb, fcb = self.path_job
        ret = self.pathfind(path)
        if ret == FOUND_VALID_PATH:
            self.path_job = None
            scb(self.build_list_from_node(path.result))
            return EVENT_UNREGISTER
        elif ret == NO_VALID_PATH and fcb:
            self.path_job = None
            fcb(None)

    def pathfind(self, path):
        while path.open_list and self.timers.get_timeout():
            cur_node = path.open_list.pop(0)
            p = cur_node.parent
            if p is not None and not (p.is_fall or p.is_jump):
                p = cur_node.parent.parent
                if p is not None and not (p.is_fall or p.is_jump) \
                        and self.raycast_bbox(p, cur_node):
                    cur_node.parent = p
                    cur_node.node_dist = p.node_dist + cur_node.dist(p)
            if cur_node == path.end_node:
                path.result = cur_node
                return FOUND_VALID_PATH
            for valid_node in self.find_valid_nodes(cur_node):
                if valid_node not in (path.open_list + path.closed_list):
                    path.open_list.append(valid_node)
            path.open_list.sort(key=path.calc_f_val)
            path.closed_list.append(cur_node)
        if not path.open_list and cur_node != path.end_node:
            return NO_VALID_PATH
        return TIMEOUT_REACHED

    def raycast_bbox(self, start, end):
        pos = PathNode(uncenter_position(start, self.col.bbox))
        path = end - start
        if not path:
            return True
        depth = Vector3(
            *map(lambda a: a[0] * a[1], zip(path.norm(), self.col.bbox))
        )
        i, r = divmod(path.dist(), depth.dist())
        for j in range(int(i)):
            pos += depth
            if not self.get_block(pos.floor() - Vector3(0, 1, 0)).bounding_box:
                return False
            if any(self.col.block_collision(pos)):
                return False
        return True

    def get_block(self, pos):
        block_id, meta = self.world.get_block(*pos.vector)
        return blocks.get_block(block_id, meta)

    def check_for_bbox(self, pos):
        pos = pos.floor()
        block = self.get_block(pos)
        if block.bounding_box:
            return True
        block = self.get_block(pos + Vector3(0, 1, 0))
        if block.bounding_box:
            return True
        return False

    def check_node(self, node, offset, node_list, walk_fall=True, jump=True):
        w_node = PathNode(node + offset).set(node)
        if walk_fall and not self.check_for_bbox(w_node):
            f_node = PathNode(w_node - Vector3(0, 1, 0)).set(node, True)
            if not self.check_for_bbox(f_node):
                node_list.append(f_node)
                walk_bool, fall_bool = False, True
            else:
                node_list.append(w_node)
                walk_bool, fall_bool = True, False
        else:
            walk_bool, fall_bool = False, False
        j_node = PathNode(w_node + Vector3(0, 1, 0)).set(node, is_jump=True)
        if jump and not walk_bool and not (node.is_fall or node.is_jump) \
                and not self.check_for_bbox(j_node):
                node_list.append(j_node)
                jump_bool = True
        else:
            jump_bool = False
        return walk_bool or fall_bool, jump_bool

    def find_valid_nodes(self, node):
        node_list = []
        pos_x, pos_jump_x = self.check_node(node, Vector3(1, 0, 0), node_list)
        pos_z, pos_jump_z = self.check_node(node, Vector3(0, 0, 1), node_list)
        neg_x, neg_jump_x = self.check_node(node, Vector3(-1, 0, 0), node_list)
        neg_z, neg_jump_z = self.check_node(node, Vector3(0, 0, -1), node_list)

        self.check_node(node, Vector3(1, 0, 1), node_list,
                        pos_x and pos_z, pos_jump_x and pos_jump_z)
        self.check_node(node, Vector3(-1, 0, -1), node_list,
                        neg_x and neg_z, neg_jump_x and neg_jump_z)
        self.check_node(node, Vector3(1, 0, -1), node_list,
                        pos_x and neg_z, pos_jump_x and neg_jump_z)
        self.check_node(node, Vector3(-1, 0, 1), node_list,
                        neg_x and pos_z, neg_jump_x and pos_jump_z)

        return node_list