async def _patches_for_pickup(self, provider_name: str, pickup: PickupEntry):
        inventory_resources: CurrentResources = {
            item: inv_item.capacity
            for item, inv_item in self._inventory.items()
        }
        conditional = pickup.conditional_for_resources(inventory_resources)
        if conditional.name is not None:
            item_name = conditional.name
        else:
            item_name = pickup.name

        resources_to_give = {}
        add_resource_gain_to_current_resources(conditional.resources, inventory_resources)
        add_resource_gain_to_current_resources(conditional.resources, resources_to_give)
        add_resource_gain_to_current_resources(pickup.conversion_resource_gain(inventory_resources),
                                               resources_to_give)

        # Ignore item% for received items
        resources_to_give.pop(self.game.resource_database.item_percentage, None)

        patches = [
            all_prime_dol_patches.adjust_item_amount_and_capacity_patch(self.patches.powerup_functions,
                                                                        item.index, delta)
            for item, delta in resources_to_give.items()
        ]
        return patches, f"Received {item_name} from {provider_name}."
    async def _update_magic_item(self):
        multiworld_magic_item = self.game.resource_database.multiworld_magic_item
        patches = []

        magic_inv = self._inventory[multiworld_magic_item]
        magic_capacity = magic_inv.capacity
        if magic_inv.amount > 0:
            self.logger.info(f"magic item was at {magic_inv.amount}/{magic_capacity}")
            magic_capacity -= magic_inv.amount
            await self._emit_location_collected(magic_inv.amount - 1)
            patches.append(all_prime_dol_patches.adjust_item_amount_and_capacity_patch(self.patches.powerup_functions,
                                                                                       multiworld_magic_item.index,
                                                                                       -magic_inv.amount))

        # Only attempt to give the next item if outside cooldown
        message = None
        if self.message_cooldown <= 0 and magic_capacity < len(self._permanent_pickups):
            item_patches, message = await self._patches_for_pickup(*self._permanent_pickups[magic_capacity])
            self.logger.info(f"{len(self._permanent_pickups)} permanent pickups, magic {magic_capacity}. "
                             f"Next pickup: {message}")

            patches.extend(item_patches)
            patches.append(all_prime_dol_patches.increment_item_capacity_patch(self.patches.powerup_functions,
                                                                               multiworld_magic_item.index))

        if patches:
            await self._execute_remote_patches(patches, message)
def test_give_item_patch(
        powerup_address: all_prime_dol_patches.PowerupFunctionsAddresses):
    # Run
    patch = all_prime_dol_patches.adjust_item_amount_and_capacity_patch(
        powerup_address, 10, 5)
    data = bytes(assembler.assemble_instructions(0x80008020, patch))

    # Assert
    assert data == (
        b"\x80\x7f\x15\x0c\x38\x80\x00\x0a\x38\xa0\x00\x05\x48\x06\xd8\xc5\x80\x7f\x15\x0c"
        b"\x38\x80\x00\x0a\x38\xa0\x00\x05\x48\x06\xd7\x25")
def test_create_remote_execution_body(
        string_display: all_prime_dol_patches.StringDisplayPatchAddresses,
        powerup_address: all_prime_dol_patches.PowerupFunctionsAddresses):
    # Run
    patch_address, patch_bytes = all_prime_dol_patches.create_remote_execution_body(
        string_display, [
            *all_prime_dol_patches.call_display_hud_patch(string_display),
            *all_prime_dol_patches.adjust_item_amount_and_capacity_patch(
                powerup_address, 3, 12),
        ])

    # Assert
    assert patch_address == string_display.update_hint_state + 0x60
    assert patch_bytes == (
        b'\x3c\xa0\x41\x00\x38\xc0\x00\x00\x38\xe0\x00\x01\x39\x20\x00\x09\x90\xa1\x00\x10'
        b'\x98\xe1\x00\x14\x98\xc1\x00\x15\x98\xc1\x00\x16\x98\xe1\x00\x17\x91\x21\x00\x18'
        b'\x38\x61\x00\x1c\x3c\x80\x00\x00\x60\x84\x90\x00\x48\x2c\x73\x29\x38\x81\x00\x10'
        b'\x48\x03\x33\x0d\x80\x7f\x15\x0c\x38\x80\x00\x03\x38\xa0\x00\x0c\x48\x03\xd8\x25'
        b'\x80\x7f\x15\x0c\x38\x80\x00\x03\x38\xa0\x00\x0c\x48\x03\xd6\x85\xbb\xc1\x00\x2c'
        b'\x80\x01\x00\x38\x7c\x08\x03\xa6\x38\x21\x00\x34\x4e\x80\x00\x20')