Add 3D BFS iterator
This commit is contained in:
		
							
								
								
									
										12
									
								
								blocks.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								blocks.py
									
									
									
									
									
								
							@@ -59,6 +59,12 @@ AVOID = [
 | 
				
			|||||||
    'sandstone_wall',
 | 
					    'sandstone_wall',
 | 
				
			||||||
    'end_stone_brick_wall',
 | 
					    'end_stone_brick_wall',
 | 
				
			||||||
    'diorite_wall',
 | 
					    'diorite_wall',
 | 
				
			||||||
 | 
					    'oak_sapling',       # saplings can grow up and hurt
 | 
				
			||||||
 | 
					    'spruce_sapling',
 | 
				
			||||||
 | 
					    'birch_sapling',
 | 
				
			||||||
 | 
					    'jungle_sapling',
 | 
				
			||||||
 | 
					    'acacia_sapling',
 | 
				
			||||||
 | 
					    'dark_oak_sapling',
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NON_SOLID = [
 | 
					NON_SOLID = [
 | 
				
			||||||
@@ -194,12 +200,6 @@ NON_SOLID = [
 | 
				
			|||||||
    'cave_air',
 | 
					    'cave_air',
 | 
				
			||||||
    'lantern',
 | 
					    'lantern',
 | 
				
			||||||
    'soul_torch',
 | 
					    'soul_torch',
 | 
				
			||||||
    #'oak_sapling',       # saplings can grow up and hurt
 | 
					 | 
				
			||||||
    #'spruce_sapling',
 | 
					 | 
				
			||||||
    #'birch_sapling',
 | 
					 | 
				
			||||||
    #'jungle_sapling',
 | 
					 | 
				
			||||||
    #'acacia_sapling',
 | 
					 | 
				
			||||||
    #'dark_oak_sapling',
 | 
					 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LOGS = [
 | 
					LOGS = [
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										47
									
								
								game.py
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								game.py
									
									
									
									
									
								
							@@ -41,6 +41,12 @@ class MCWorld:
 | 
				
			|||||||
    def block_at(self, x, y, z):
 | 
					    def block_at(self, x, y, z):
 | 
				
			||||||
        return self.g.chunks.get_block_at(x, y, z)
 | 
					        return self.g.chunks.get_block_at(x, y, z)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def find_blocks_3d(self, center, block_ids, distance=0, y_limit=0):
 | 
				
			||||||
 | 
					        for offset in utils.search_3d(distance, y_limit):
 | 
				
			||||||
 | 
					            check = utils.padd(center, offset)
 | 
				
			||||||
 | 
					            if self.block_at(*check) in block_ids:
 | 
				
			||||||
 | 
					                yield check
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find_blocks(self, center, distance, block_ids, limit=0):
 | 
					    def find_blocks(self, center, distance, block_ids, limit=0):
 | 
				
			||||||
        # search in a spiral from center to all blocks with ID
 | 
					        # search in a spiral from center to all blocks with ID
 | 
				
			||||||
        result = []
 | 
					        result = []
 | 
				
			||||||
@@ -112,16 +118,10 @@ class MCWorld:
 | 
				
			|||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find_bed_areas(self, center, distance):
 | 
					    def find_bed_areas(self, center, distance):
 | 
				
			||||||
        air = []
 | 
					 | 
				
			||||||
        for i in range(5):
 | 
					 | 
				
			||||||
            check = utils.padd(center, utils.alternate(i, 1))
 | 
					 | 
				
			||||||
            air.extend(self.find_blocks(check, distance, [0], 0))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bed_clearance = 25  # 5x5 area
 | 
					        bed_clearance = 25  # 5x5 area
 | 
				
			||||||
        clear_distance = 3
 | 
					        clear_distance = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        areas = []
 | 
					        for a in self.find_blocks_3d(center, [0], distance, 10):
 | 
				
			||||||
        for a in air:
 | 
					 | 
				
			||||||
            # check for air around the area
 | 
					            # check for air around the area
 | 
				
			||||||
            if len(self.find_blocks(a, clear_distance, [0], bed_clearance)) < bed_clearance:
 | 
					            if len(self.find_blocks(a, clear_distance, [0], bed_clearance)) < bed_clearance:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
@@ -134,10 +134,7 @@ class MCWorld:
 | 
				
			|||||||
            if len(self.find_blocks(utils.padd(a, path.BLOCK_ABOVE), clear_distance, [0], bed_clearance)) < bed_clearance:
 | 
					            if len(self.find_blocks(utils.padd(a, path.BLOCK_ABOVE), clear_distance, [0], bed_clearance)) < bed_clearance:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            areas.append(a)
 | 
					            yield a
 | 
				
			||||||
 | 
					 | 
				
			||||||
        areas.sort(key=lambda x: utils.phyp(center, x))
 | 
					 | 
				
			||||||
        return areas
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find_cache_areas(self, center, distance):
 | 
					    def find_cache_areas(self, center, distance):
 | 
				
			||||||
        return self.find_bed_areas(center, distance)
 | 
					        return self.find_bed_areas(center, distance)
 | 
				
			||||||
@@ -264,15 +261,19 @@ class Game:
 | 
				
			|||||||
    def handle_chat(self, message):
 | 
					    def handle_chat(self, message):
 | 
				
			||||||
        source, text = message
 | 
					        source, text = message
 | 
				
			||||||
        reply = None
 | 
					        reply = None
 | 
				
			||||||
 | 
					        private = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if source == 'SYSTEM':
 | 
					        if source == 'SYSTEM':
 | 
				
			||||||
            print('unlocking command...')
 | 
					 | 
				
			||||||
            self.g.command_lock = False
 | 
					            self.g.command_lock = False
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match = re.match(r'<(\w+)> (.*)', text)
 | 
					        match1 = re.match(r'<(\w+)> (.*)', text)
 | 
				
			||||||
        if match:
 | 
					        match2 = re.match(r'\[(\w+) -> me] (.*)', text)
 | 
				
			||||||
            sender, text = match.groups()
 | 
					        if match1:
 | 
				
			||||||
 | 
					            sender, text = match1.groups()
 | 
				
			||||||
 | 
					        elif match2:
 | 
				
			||||||
 | 
					            sender, text = match2.groups()
 | 
				
			||||||
 | 
					            private = True
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -350,15 +351,12 @@ class Game:
 | 
				
			|||||||
            reply = 'ok'
 | 
					            reply = 'ok'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if command == 'inv':
 | 
					        if command == 'inv':
 | 
				
			||||||
            print(self.g.inv)
 | 
					 | 
				
			||||||
            inv_list = []
 | 
					            inv_list = []
 | 
				
			||||||
            for i in self.g.inv.values():
 | 
					            for i in self.g.inv.values():
 | 
				
			||||||
                if i.present:
 | 
					                if i.present:
 | 
				
			||||||
                    inv_list.append('{}:{} x {}'.format(items.ITEM_NAMES[i.item_id], str(i.item_id), i.item_count))
 | 
					                    inv_list.append('{}:{} x {}'.format(items.ITEM_NAMES[i.item_id], str(i.item_id), i.item_count))
 | 
				
			||||||
            reply = ', '.join(inv_list)
 | 
					            result = '\n'.join(inv_list)
 | 
				
			||||||
 | 
					            print(result or 'Empty')
 | 
				
			||||||
            if not reply:
 | 
					 | 
				
			||||||
                reply = 'empty'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if command == 'drop':
 | 
					        if command == 'drop':
 | 
				
			||||||
            self.drop_stack()
 | 
					            self.drop_stack()
 | 
				
			||||||
@@ -416,8 +414,15 @@ class Game:
 | 
				
			|||||||
                if data and v.item_id != int(data): continue
 | 
					                if data and v.item_id != int(data): continue
 | 
				
			||||||
                print(str(k) + ':', v)
 | 
					                print(str(k) + ':', v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if command == 'cache':
 | 
				
			||||||
 | 
					            self.g.job.state = self.g.job.cache_items
 | 
				
			||||||
 | 
					            reply = 'ok'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if reply:
 | 
					        if reply:
 | 
				
			||||||
            print(reply)
 | 
					            print(reply)
 | 
				
			||||||
 | 
					            if private and not reply.startswith('/'):
 | 
				
			||||||
 | 
					                self.g.chat.send('/m ' + sender + ' ' + reply)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
                self.g.chat.send(reply)
 | 
					                self.g.chat.send(reply)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle_time_update(self, packet):
 | 
					    def handle_time_update(self, packet):
 | 
				
			||||||
@@ -578,7 +583,7 @@ class Game:
 | 
				
			|||||||
    def handle_spawn_object(self, packet):
 | 
					    def handle_spawn_object(self, packet):
 | 
				
			||||||
        #return
 | 
					        #return
 | 
				
			||||||
        if packet.type_id != 37: return
 | 
					        if packet.type_id != 37: return
 | 
				
			||||||
        print(packet)
 | 
					        #print(packet)
 | 
				
			||||||
        self.g.objects[packet.entity_id] = Munch(
 | 
					        self.g.objects[packet.entity_id] = Munch(
 | 
				
			||||||
            entity_id=packet.entity_id,
 | 
					            entity_id=packet.entity_id,
 | 
				
			||||||
            x=packet.x,
 | 
					            x=packet.x,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								items.py
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								items.py
									
									
									
									
									
								
							@@ -47,4 +47,5 @@ CHEST_ID = set([ITEMS['minecraft:chest']['protocol_id']])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GAPPLE_ID = set([ITEMS['minecraft:enchanted_golden_apple']['protocol_id']])
 | 
					GAPPLE_ID = set([ITEMS['minecraft:enchanted_golden_apple']['protocol_id']])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USEFUL_ITEMS = BED_IDS | CHEST_ID
 | 
					NEEDED_ITEMS = BED_IDS | CHEST_ID
 | 
				
			||||||
 | 
					WANTED_ITEMS = SAPLING_IDS
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										101
									
								
								jobs.py
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								jobs.py
									
									
									
									
									
								
							@@ -385,20 +385,16 @@ class SleepWithBedStates:
 | 
				
			|||||||
        w = self.g.world
 | 
					        w = self.g.world
 | 
				
			||||||
        p = utils.pint(self.g.pos)
 | 
					        p = utils.pint(self.g.pos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        areas = w.find_bed_areas(p, 100)
 | 
					        for area in w.find_bed_areas(p, 100):
 | 
				
			||||||
        print('Found areas:', areas)
 | 
					            print('Found area:', area)
 | 
				
			||||||
 | 
					            if area not in self.bad_areas:
 | 
				
			||||||
        if len(areas):
 | 
					                break
 | 
				
			||||||
            while areas[0] in self.bad_areas:
 | 
					        else: # for
 | 
				
			||||||
                areas.pop(0)
 | 
					            print('Unable to find area')
 | 
				
			||||||
            self.area = areas[0]
 | 
					 | 
				
			||||||
        elif self.last_area:
 | 
					 | 
				
			||||||
            self.area = self.last_area
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            print('Unable to find area, and no last area')
 | 
					 | 
				
			||||||
            self.state = self.cleanup
 | 
					            self.state = self.cleanup
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.area = area
 | 
				
			||||||
        openings = w.find_bed_openings(self.area)
 | 
					        openings = w.find_bed_openings(self.area)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for o in openings:
 | 
					        for o in openings:
 | 
				
			||||||
@@ -413,7 +409,6 @@ class SleepWithBedStates:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.g.path = navpath
 | 
					        self.g.path = navpath
 | 
				
			||||||
        self.state = self.going_to_area
 | 
					        self.state = self.going_to_area
 | 
				
			||||||
        self.last_area = self.area
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def going_to_area(self):
 | 
					    def going_to_area(self):
 | 
				
			||||||
        if utils.pint(self.g.pos) == self.opening:
 | 
					        if utils.pint(self.g.pos) == self.opening:
 | 
				
			||||||
@@ -479,7 +474,6 @@ class SleepWithBedStates:
 | 
				
			|||||||
        self.area = None
 | 
					        self.area = None
 | 
				
			||||||
        self.opening = None
 | 
					        self.opening = None
 | 
				
			||||||
        self.bad_areas = []
 | 
					        self.bad_areas = []
 | 
				
			||||||
        self.last_area = None
 | 
					 | 
				
			||||||
        self.wait_time = 0
 | 
					        self.wait_time = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def run(self):
 | 
					    def run(self):
 | 
				
			||||||
@@ -491,8 +485,11 @@ class CacheItemsStates:
 | 
				
			|||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def init(self):
 | 
					    def init(self):
 | 
				
			||||||
 | 
					        self.skip_slots = []
 | 
				
			||||||
 | 
					        self.skip_items = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        num_stacks = len([x for x in self.g.inv.values() if x.present])
 | 
					        num_stacks = len([x for x in self.g.inv.values() if x.present])
 | 
				
			||||||
        print('inventory amount:', num_stacks)
 | 
					        print('Inventory amount:', num_stacks)
 | 
				
			||||||
        if num_stacks >= 27:
 | 
					        if num_stacks >= 27:
 | 
				
			||||||
            self.state = self.find_cache_spot
 | 
					            self.state = self.find_cache_spot
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
@@ -504,20 +501,16 @@ class CacheItemsStates:
 | 
				
			|||||||
        w = self.g.world
 | 
					        w = self.g.world
 | 
				
			||||||
        p = utils.pint(self.g.pos)
 | 
					        p = utils.pint(self.g.pos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        areas = w.find_cache_areas(p, 100)
 | 
					        for area in w.find_cache_areas(p, 100):
 | 
				
			||||||
        print('Found areas:', areas)
 | 
					            print('Found area:', area)
 | 
				
			||||||
 | 
					            if area not in self.bad_areas:
 | 
				
			||||||
        if len(areas):
 | 
					                break
 | 
				
			||||||
            while areas[0] in self.bad_areas:
 | 
					        else: # for
 | 
				
			||||||
                areas.pop(0)
 | 
					            print('Unable to find area')
 | 
				
			||||||
            self.area = areas[0]
 | 
					 | 
				
			||||||
        elif self.last_area:
 | 
					 | 
				
			||||||
            self.area = self.last_area
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            print('Unable to find area, and no last area')
 | 
					 | 
				
			||||||
            self.state = self.cleanup
 | 
					            self.state = self.cleanup
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.area = area
 | 
				
			||||||
        openings = w.find_cache_openings(self.area)
 | 
					        openings = w.find_cache_openings(self.area)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for o in openings:
 | 
					        for o in openings:
 | 
				
			||||||
@@ -532,7 +525,6 @@ class CacheItemsStates:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.g.path = navpath
 | 
					        self.g.path = navpath
 | 
				
			||||||
        self.state = self.going_to_area
 | 
					        self.state = self.going_to_area
 | 
				
			||||||
        self.last_area = self.area
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def going_to_area(self):
 | 
					    def going_to_area(self):
 | 
				
			||||||
        if utils.pint(self.g.pos) == self.opening:
 | 
					        if utils.pint(self.g.pos) == self.opening:
 | 
				
			||||||
@@ -571,6 +563,8 @@ class CacheItemsStates:
 | 
				
			|||||||
        w_info = data.WINDOWS[w.data.window_type]
 | 
					        w_info = data.WINDOWS[w.data.window_type]
 | 
				
			||||||
        w_inventory_slots = w_info.inventory
 | 
					        w_inventory_slots = w_info.inventory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        slot_list = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for slot_num in w_inventory_slots:
 | 
					        for slot_num in w_inventory_slots:
 | 
				
			||||||
            if slot_num not in w.contents:
 | 
					            if slot_num not in w.contents:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
@@ -580,14 +574,25 @@ class CacheItemsStates:
 | 
				
			|||||||
            if not slot.present:
 | 
					            if not slot.present:
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if slot.item_id in items.USEFUL_ITEMS:
 | 
					            if slot.item_id in self.needed_items:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if slot_num in self.skip_slots:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            slot_list.append((slot_num, slot))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        slot_list.sort(key=lambda x: x[1].item_count, reverse=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for slot_num, slot in slot_list:
 | 
				
			||||||
 | 
					            if slot.item_id in self.wanted_items and slot.item_id not in self.skip_items:
 | 
				
			||||||
 | 
					                print('skipping wanted item', slot)
 | 
				
			||||||
 | 
					                self.skip_slots.append(slot_num)
 | 
				
			||||||
 | 
					                self.skip_items.append(slot.item_id)
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            print('moving', slot)
 | 
					            print('moving', slot)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #inv_slot_num = slot_num - w_info.slot_diff
 | 
					 | 
				
			||||||
            #self.g.inv.pop(inv_slot_num, None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.g.item_lock = True
 | 
					            self.g.item_lock = True
 | 
				
			||||||
            self.g.game.click_window(slot_num, 0, 1, slot)
 | 
					            self.g.game.click_window(slot_num, 0, 1, slot)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
@@ -613,10 +618,17 @@ class CacheItemsStates:
 | 
				
			|||||||
        self.g = global_state
 | 
					        self.g = global_state
 | 
				
			||||||
        self.state = self.idle
 | 
					        self.state = self.idle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # keep all needed items
 | 
				
			||||||
 | 
					        self.needed_items = items.NEEDED_ITEMS
 | 
				
			||||||
 | 
					        # keep one stack of wanted items
 | 
				
			||||||
 | 
					        self.wanted_items = items.WANTED_ITEMS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.skip_slots = []
 | 
				
			||||||
 | 
					        self.skip_items = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.area = None
 | 
					        self.area = None
 | 
				
			||||||
        self.opening = None
 | 
					        self.opening = None
 | 
				
			||||||
        self.bad_areas = []
 | 
					        self.bad_areas = []
 | 
				
			||||||
        self.last_area = None
 | 
					 | 
				
			||||||
        self.wait_time = 0
 | 
					        self.wait_time = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def run(self):
 | 
					    def run(self):
 | 
				
			||||||
@@ -681,19 +693,16 @@ class PlantTreeStates:
 | 
				
			|||||||
        w = self.g.world
 | 
					        w = self.g.world
 | 
				
			||||||
        p = utils.pint(self.g.pos)
 | 
					        p = utils.pint(self.g.pos)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        areas = w.find_cache_areas(p, 20)
 | 
					        for area in w.find_cache_areas(p, 20):
 | 
				
			||||||
        print('Found areas:', areas)
 | 
					            print('Found area:', area)
 | 
				
			||||||
 | 
					            if area not in self.bad_areas:
 | 
				
			||||||
        try:
 | 
					                break
 | 
				
			||||||
            while areas[0] in self.bad_areas:
 | 
					        else: # for
 | 
				
			||||||
                areas.pop(0)
 | 
					            print('Unable to find area')
 | 
				
			||||||
            self.area = areas[0]
 | 
					 | 
				
			||||||
        except IndexError:
 | 
					 | 
				
			||||||
            print('No good areas left, aborting.')
 | 
					 | 
				
			||||||
            self.bad_areas = []
 | 
					 | 
				
			||||||
            self.state = self.cleanup
 | 
					            self.state = self.cleanup
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.area = area
 | 
				
			||||||
        navpath = w.path_to_place(p, self.area)
 | 
					        navpath = w.path_to_place(p, self.area)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not navpath:
 | 
					        if not navpath:
 | 
				
			||||||
@@ -803,6 +812,16 @@ class JobStates:
 | 
				
			|||||||
    def idle(self):
 | 
					    def idle(self):
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def cache_items(self):
 | 
				
			||||||
 | 
					        s1 = self.cache_items_states
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if s1.state == s1.idle:
 | 
				
			||||||
 | 
					            s1.state = s1.init
 | 
				
			||||||
 | 
					        elif s1.state == s1.done:
 | 
				
			||||||
 | 
					            self.state = self.idle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        s1.run()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find_gapple(self):
 | 
					    def find_gapple(self):
 | 
				
			||||||
        s1 = self.find_gapple_states
 | 
					        s1 = self.find_gapple_states
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										48
									
								
								utils.py
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								utils.py
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
				
			|||||||
import importlib
 | 
					import importlib
 | 
				
			||||||
 | 
					import collections
 | 
				
			||||||
from math import floor, ceil, sqrt, hypot
 | 
					from math import floor, ceil, sqrt, hypot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import blocks
 | 
					import blocks
 | 
				
			||||||
@@ -94,3 +95,50 @@ def break_time(block_id, held_item=0, in_water=False, on_ground=True, enchantmen
 | 
				
			|||||||
    if not on_ground: time *= 5.0
 | 
					    if not on_ground: time *= 5.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return time
 | 
					    return time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def search_3d(distance=0, y_limit=0):
 | 
				
			||||||
 | 
					    def get_neighbors(x,y,z):
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            (x+1, y+1, z+0),
 | 
				
			||||||
 | 
					            (x+1, y-1, z+0),
 | 
				
			||||||
 | 
					            (x+1, y+1, z+1),
 | 
				
			||||||
 | 
					            (x+1, y+0, z+1),
 | 
				
			||||||
 | 
					            (x+1, y-1, z+1),
 | 
				
			||||||
 | 
					            (x+1, y+1, z-1),
 | 
				
			||||||
 | 
					            (x+1, y+0, z-1),
 | 
				
			||||||
 | 
					            (x+1, y-1, z-1),
 | 
				
			||||||
 | 
					            (x+1, y+0, z+0),
 | 
				
			||||||
 | 
					            (x+0, y+1, z+0),
 | 
				
			||||||
 | 
					            (x+0, y-1, z+0),
 | 
				
			||||||
 | 
					            (x+0, y+1, z+1),
 | 
				
			||||||
 | 
					            (x+0, y+0, z+1),
 | 
				
			||||||
 | 
					            (x+0, y-1, z+1),
 | 
				
			||||||
 | 
					            (x+0, y+1, z-1),
 | 
				
			||||||
 | 
					            (x+0, y+0, z-1),
 | 
				
			||||||
 | 
					            (x+0, y-1, z-1),
 | 
				
			||||||
 | 
					            (x-1, y+1, z+0),
 | 
				
			||||||
 | 
					            (x-1, y-1, z+0),
 | 
				
			||||||
 | 
					            (x-1, y+1, z+1),
 | 
				
			||||||
 | 
					            (x-1, y+0, z+1),
 | 
				
			||||||
 | 
					            (x-1, y-1, z+1),
 | 
				
			||||||
 | 
					            (x-1, y+1, z-1),
 | 
				
			||||||
 | 
					            (x-1, y+0, z-1),
 | 
				
			||||||
 | 
					            (x-1, y-1, z-1),
 | 
				
			||||||
 | 
					            (x-1, y+0, z+0),
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    to_visit = collections.deque([(0, 0, 0)])
 | 
				
			||||||
 | 
					    visited = set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while to_visit:
 | 
				
			||||||
 | 
					        cur = to_visit.pop()
 | 
				
			||||||
 | 
					        if cur in visited:
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        if y_limit and abs(cur[1]) > y_limit:
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        if distance and hypot(*cur) > distance:
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					        for neighbor in get_neighbors(*cur):
 | 
				
			||||||
 | 
					            to_visit.appendleft(neighbor)
 | 
				
			||||||
 | 
					        visited.add(cur)
 | 
				
			||||||
 | 
					        yield cur
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user