Exemplo n.º 1
0
    def drop_slot(self, slot=None, drop_stack=False):
        old_index = getattr(slot, 'slot_nr', slot)

        action_id = self.inventory.drop_slot(slot, drop_stack)
        if not action_id:
            raise TaskFailed('Drop slot failed: not clicked')
        yield 'inventory_click_response', check_key('action_id', action_id)

        new_slot = self.inventory.window.slots[old_index]
        if drop_stack and old_index is not None and new_slot.amount > 0:
            raise TaskFailed('Drop slot failed: slot %i not empty' % old_index)
Exemplo n.º 2
0
    def drop_slot(self, slot=None, *args, **kwargs):
        # TODO drop_slot is untested
        old_slot = getattr(slot, 'slot_nr', slot)

        action_id = self.inventory.drop_slot(slot, *args, **kwargs)
        if not action_id:
            raise TaskFailed('Drop slot failed: not clicked')
        yield 'inventory_click_response', check_key('action_id', action_id)

        new_slot = self.inventory.window.slots[old_slot]
        if old_slot is not None and new_slot.amount > 0:
            raise TaskFailed('Drop slot failed: slot %i not empty' % old_slot)
Exemplo n.º 3
0
 def creative_set_slot(self, slot_nr=None, slot_dict=None, slot=None):
     self.inventory.creative_set_slot(slot_nr, slot_dict, slot)
     slot_nr = slot_nr if slot is None else slot.slot_nr
     e, data = yield ('inventory_set_slot',
                      lambda e, data: data['slot'].slot_nr == slot_nr)
     if False:  # TODO implement check, for now just assume it worked
         raise TaskFailed('Creative set slot failed: not set')
Exemplo n.º 4
0
    def store_or_drop(self):
        """
        Stores the cursor item or drops it if the inventory is full.
        Tip: look directly up or down before calling this, so you can
        pick up the dropped item when the inventory frees up again.

        Returns:
            Slot: The slot used to store it, or None if dropped.
        """
        inv = self.inventory
        if inv.cursor_slot.is_empty:  # nothing to drop
            raise StopIteration(None)

        storage = inv.inv_slots_preferred
        if inv.window.is_storage:
            storage += inv.window.window_slots
        first_empty_slot = inv.find_slot(constants.INV_ITEMID_EMPTY, storage)
        if first_empty_slot is not None:
            yield self.click_slot(first_empty_slot)
        else:
            yield self.drop_slot(drop_stack=True)

        if not inv.cursor_slot.is_empty:
            raise TaskFailed('Store or Drop failed: cursor is not empty')

        raise StopIteration(first_empty_slot)
Exemplo n.º 5
0
 def click_slots(self, *slots):
     slots = unpack_slots_list(slots)
     for i, slot in enumerate(slots):
         try:
             yield self.click_slot(slot)
         except TaskFailed as e:
             raise TaskFailed('Clicking %i failed (step %i/%i): %s' %
                              (slot, i + 1, len(slots), e.args))
Exemplo n.º 6
0
 def transfer_slots(self, source_slots, target_slots):
     for slot in source_slots:
         if slot.is_empty:
             continue
         item_id_empty = constants.INV_ITEMID_EMPTY
         target = self.inventory.find_slot(item_id_empty, target_slots)
         if target is None:
             raise TaskFailed('Transfer slots failed: target slots full')
         yield self.swap_slots(slot, target)
Exemplo n.º 7
0
 def hold_item(self, wanted):
     found = self.inventory.find_slot(wanted)
     if not found:
         raise TaskFailed('Could not hold item: not found')
     elif found in self.inventory.window.hotbar_slots:
         self.inventory.select_active_slot(found)
         raise StopIteration('Found item in hotbar')
     else:
         yield self.swap_slots(found, self.inventory.active_slot)
         raise StopIteration('Found item in inventory')
Exemplo n.º 8
0
        def timeout(t, other_events):
            timer_event = 'eat_timeout_%s' % random.random

            def cb(*_):
                self.event.emit(timer_event, {})

            self.timers.reg_event_timer(t, cb, runs=1)
            event, _ = yield timer_event, other_events
            if event == timer_event:
                raise TaskFailed('Timed out after %s' % t)
Exemplo n.º 9
0
        def task_deep_failure():
            def task_deepest_failure():
                last_data[0] = yield 'cccc'
                raise TaskFailed('Low level error!')

            def task_deeper_failure():
                yield task_deepest_failure()  # error falls through

            try:
                yield task_deeper_failure()
            except TaskFailed as error:
                raise TaskFailed('High level error!').with_error(error)
Exemplo n.º 10
0
    def click_slot(self, slot, *args, **kwargs):
        if isinstance(slot, int):
            slot = self.inventory.window.slots[slot]
        old_slot = slot.copy()
        old_cursor = self.inventory.cursor_slot.copy()

        action_id = self.inventory.click_slot(slot, *args, **kwargs)
        if not action_id:
            raise TaskFailed('Click slot failed: not clicked')
        yield 'inventory_click_response', check_key('action_id', action_id)
        # TODO make sure window is not closed while clicking

        empty_cursor = old_cursor.is_empty
        if old_slot.amount == old_slot.item.stack_size and not empty_cursor \
                or old_slot.is_empty and empty_cursor:
            return  # no need to check

        new_slot = self.inventory.window.slots[old_slot.slot_nr]
        new_cursor = self.inventory.cursor_slot
        if new_slot.matches(old_slot) and new_cursor.matches(old_cursor):
            raise TaskFailed('Click slot failed: slot %i did not change (%s)' %
                             (old_slot.slot_nr, old_slot))
Exemplo n.º 11
0
        def drop_items_task(amount_left):
            while amount_left > 0:
                found_slot = self.inv.find_slot(item)
                if found_slot is None:
                    raise TaskFailed('No %s stored anymore' % item)

                if amount_left >= found_slot.amount:
                    amount_left -= found_slot.amount
                    yield self.inv. async .drop_slot(found_slot,
                                                     drop_stack=True)
                else:
                    logger.debug('Dropping %s single', amount_left)
                    for i in range(amount_left):
                        yield self.inv. async .drop_slot(found_slot)
                        amount_left -= 1
Exemplo n.º 12
0
    def swap_slots(self, a, b):
        def slot(i):
            return self.inventory.window.slots[i]

        a = getattr(a, 'slot_nr', a)
        b = getattr(b, 'slot_nr', b)
        a_old, b_old = slot(a).copy(), slot(b).copy()

        if not slot(a).is_empty or not self.inventory.cursor_slot.is_empty:
            yield self.click_slot(a)

        if not slot(b).is_empty or not self.inventory.cursor_slot.is_empty:
            yield self.click_slot(b)

        if not slot(a).is_empty or not self.inventory.cursor_slot.is_empty:
            yield self.click_slot(a)

        if not slot(a).matches(b_old) or not slot(b).matches(a_old):
            raise TaskFailed('Failed to swap slots %i and %i' % (a, b))
Exemplo n.º 13
0
    def craft_task(self, recipe, amount=1):
        """
        A task that crafts ``amount`` items with ``recipe``.
        """
        if not recipe:
            raise TaskFailed('[Craft] No recipe given: %s' % recipe)
        if amount <= 0:
            raise TaskFailed('[Craft] Nothing to craft, amount=%s' % amount)

        inv = self.inventory
        craft_times = int(ceil(amount / recipe.result.amount))

        try:  # check if open window supports crafting
            grid_slots = inv.window.craft_grid_slots
            result_slot = inv.window.craft_result_slot
        except AttributeError:
            raise TaskFailed('[Craft] %s is no crafting window' %
                             inv.window.__class__.__name__)

        num_grid_slots = len(grid_slots)
        try:
            grid_width = {4: 2, 9: 3}[num_grid_slots]
        except KeyError:
            raise TaskFailed('Crafting grid has unsupported size of'
                             ' %i instead of 4 or 9' % num_grid_slots)

        grid_height = num_grid_slots / grid_width
        row1 = recipe.in_shape[0]
        if len(recipe.in_shape) > grid_height or len(row1) > grid_width:
            raise TaskFailed('Recipe for %s does not fit in a %ix%i grid' %
                             (recipe.result, grid_width, grid_height))

        storage_slots = inv.window.persistent_slots

        # check ingredients for recipe
        total_amounts_needed = total_ingredient_amounts(recipe)
        for ingredient, needed in total_amounts_needed.items():
            needed *= craft_times
            stored = inv.total_stored(ingredient, storage_slots)
            if needed > stored:
                raise TaskFailed('Missing %s not stored, have %s of %i' %
                                 ('%s:%s' % ingredient, stored, needed))

        # put ingredients into crafting grid
        for ingredient, p in ingredient_positions(recipe).items():
            for (x, y, ingredient_amount) in p:
                slot = grid_slots[x + y * grid_width]
                for i in range(ingredient_amount * craft_times):
                    if inv.cursor_slot.is_empty:
                        ingr_slot = inv.find_slot(ingredient, storage_slots)
                        if not ingr_slot:  # should not occur, as we checked
                            raise TaskFailed('Craft: No %s:%s found'
                                             ' in inventory' % ingredient)
                        yield inv. async .click_slot(ingr_slot)
                    # TODO speed up mass crafting with left+right clicking
                    yield inv. async .click_slot(slot, right=True)
            # done putting in that item, put away
            if not inv.cursor_slot.is_empty:
                yield inv. async .store_or_drop()

        # TODO check if all items are in place
        # otherwise we will get the wrong crafting result

        # take crafted items
        prev_cursor_amt = inv.cursor_slot.amount
        crafted_amt = 0
        while amount > crafted_amt + inv.cursor_slot.amount:
            yield inv. async .click_slot(result_slot)
            # TODO check that cursor is non-empty, otherwise we did not craft
            result_stack_size = inv.cursor_slot.stack_size
            if inv.cursor_slot.amount in (prev_cursor_amt, result_stack_size):
                # cursor full, put away
                crafted_amt += inv.cursor_slot.amount
                yield inv. async .store_or_drop()
            prev_cursor_amt = inv.cursor_slot.amount
        if not inv.cursor_slot.is_empty:
            # cursor still has items left from crafting, put away
            yield inv. async .store_or_drop()

        # put ingredients left from crafting back into inventory
        yield inv. async .move_to_inventory(grid_slots)
Exemplo n.º 14
0
 def task_deepest_failure():
     last_data[0] = yield 'cccc'
     raise TaskFailed('Low level error!')
Exemplo n.º 15
0
 def task_with_failure():
     last_data[0] = yield 'bbbb'
     raise TaskFailed('Some error!')