import time from minecraft.networking.types import BlockFace from mosfet import path from mosfet import utils from mosfet.info import blocks from mosfet.info import items class GatherWartStates: BREAK_TIMEOUT = 5.0 ITEM_TIMEOUT = 8.0 PLACE_TIMEOUT = 3.0 def idle(self): return None def init(self): self.state = self.find_new_wart def _blacklist_wart(self): if self.wart is not None and self.wart not in self.bad_warts: self.bad_warts.append(self.wart) def find_new_wart(self): print('Finding new wart...') world = self.g.world center = utils.pint(self.g.pos) mature_wart = max(blocks.NETHERWART_IDS) candidates = world.find_blocks_indexed( center, {mature_wart}, 50) candidates = world.filter_work_positions(candidates) wart = next((position for position in candidates if position not in self.bad_warts), None) if wart is None: print('No good warts left, aborting.') self.state = self.cleanup return print('Found wart:', wart) self.wart = wart self.type_id = mature_wart self.state = self.nav_to_wart def nav_to_wart(self): world = self.g.world position = utils.pint(self.g.pos) navpath = world.path_to_place(position, self.wart) if navpath: print('Going to wart', self.wart) self.g.path = navpath self.g.look_at = utils.padd(self.wart, path.BLOCK_BELOW) self.state = self.going_to_wart else: print('Cant get to it, blacklisting') self._blacklist_wart() self.state = self.find_new_wart def going_to_wart(self): if utils.pint(self.g.pos) == self.wart: print('At the wart') self.state = self.break_wart def break_wart(self): current = self.g.world.block_at(*self.wart) if current != self.type_id: print('Wart changed before break; searching again') self._blacklist_wart() self.state = self.find_new_wart return if self.g.game.break_block(self.wart): self.break_deadline = time.monotonic() + self.BREAK_TIMEOUT self.state = self.wait_break else: print('Break request skipped; blacklisting', self.wart) self._blacklist_wart() self.state = self.find_new_wart def wait_break(self): current = self.g.world.block_at(*self.wart) if current != self.type_id: print('Wart break confirmed at {}: {} -> {}'.format( self.wart, self.type_id, current)) self.item_deadline = time.monotonic() + self.ITEM_TIMEOUT self.item_wait_logged = False self.state = self.select_wart elif time.monotonic() > self.break_deadline: print('Wart did not break; blacklisting', self.wart) self._blacklist_wart() self.state = self.find_new_wart def select_wart(self): if self.g.game.select_item([items.NETHERWART_ID]): self.state = self.wait_select return if time.monotonic() > self.item_deadline: print('No nether wart collected; skipping', self.wart) self._blacklist_wart() self.state = self.find_new_wart elif not self.item_wait_logged: print('Waiting for nether wart in inventory/hotbar') self.item_wait_logged = True def wait_select(self): if self.g.get('holding') == items.NETHERWART_ID: self.state = self.place_wart def place_wart(self): soul_sand = utils.padd(self.wart, path.BLOCK_BELOW) self.g.game.place_block(soul_sand, BlockFace.TOP) self.place_deadline = time.monotonic() + self.PLACE_TIMEOUT self.state = self.wait_place def wait_place(self): current = self.g.world.block_at(*self.wart) if current in blocks.NETHERWART_IDS and current != self.type_id: print('Nether wart replanted at', self.wart) self.state = self.cleanup elif time.monotonic() > self.place_deadline: print('Nether wart did not replant; blacklisting', self.wart) self._blacklist_wart() self.state = self.find_new_wart def cleanup(self): self.g.look_at = None self.state = self.done def done(self): return None def __init__(self, global_state): self.g = global_state self.state = self.idle self.wart = None self.type_id = None self.bad_warts = [] self.break_deadline = None self.item_deadline = None self.place_deadline = None self.item_wait_logged = False def run(self): self.state()