Skip to main content

Restocking

Restocker is a Grand Exchange helper that works with loadout depletion listeners.

Use it when a script should detect missing bank items, buy them, collect them, and then continue preparing its loadout.

Basic Flow

Restocker restocker = Restocker.create()
.defaultAmount(100)
.defaultBuyPrice(GrandExchange.Price.live().plus5())
.defaultSellPrice(GrandExchange.Price.live().minus5())
.defaultCollectionMode(GrandExchange.CollectionMode.BANK);

InventoryLoadout inventory = InventoryLoadout.create()
.add(LoadoutItem.of(ItemId.SHARK).amount(10).build())
.depletionListener(restocker);

When Loadouts.withdraw(inventory) cannot find a required item in the bank, the restocker queues a buy request.

Your script should then enter a restocking branch:

if (!restocker.empty()) {
restocker.tick();
return;
}

Loadouts.withdraw(inventory, equipment);

tick() performs at most one meaningful Grand Exchange step and returns. Call it repeatedly until restocker.empty() is true.

Register Preferred Amounts

Register items up front when depletion should buy a specific amount.

restocker
.item(ItemId.SHARK, 100)
.price(GrandExchange.Price.live().plus5())
.retryAfterTicks(100)
.maxRetries(3);

When sharks deplete, this buys 100 instead of the restocker default amount.

Queue Buys Directly

restocker.request(ItemId.SHARK, 100);

Or use the configured amount:

restocker.request(ItemId.SHARK);

Queue Sells

restocker.sell(ItemId.MAGIC_LOGS, 100, GrandExchange.Price.live().minus5());

Or:

restocker.requestSell(ItemId.MAGIC_LOGS, 100);

For selling, the restocker withdraws the item first if it is not carried. If the item is not stackable and has a noted form, it prefers withdrawing the noted ID for easier selling.

If the requested sell item is not in the bank, the sell request is cleared.

Retry Behavior

Active offers can be cancelled and retried with more aggressive prices.

Restocker restocker = Restocker.create()
.defaultRetryAfterTicks(100)
.defaultMaxRetries(3);

Per item:

restocker.item(ItemId.SHARK, 100)
.retryAfterTicks(80)
.maxRetries(5);

For buy offers, each retry applies another +5% to the configured base price.

For sell offers, each retry applies another -5% to the configured base price.

request.offerPrice();

Collection Mode

Default:

restocker.defaultCollectionMode(GrandExchange.CollectionMode.BANK);

Per request:

restocker.item(ItemId.SHARK, 100)
.collectionMode(GrandExchange.CollectionMode.ITEM);

Available modes:

  • ITEM
  • NOTE
  • BANK

Restocking State

restocker.empty();
restocker.queued();
restocker.items();
restocker.clear();

clear() removes queued work but keeps configured restock items and defaults.

Complete Script Shape

public class ExampleScript {

private final Restocker restocker = Restocker.create()
.defaultAmount(100)
.defaultBuyPrice(GrandExchange.Price.live().plus5())
.defaultSellPrice(GrandExchange.Price.live().minus5())
.defaultCollectionMode(GrandExchange.CollectionMode.BANK);

private final EquipmentLoadout equipment = EquipmentLoadout.create()
.add(EquipmentSlot.WEAPON, ItemId.ABYSSAL_WHIP);

private final InventoryLoadout inventory = InventoryLoadout.create()
.add(LoadoutItem.of(ItemId.SHARK).amount(10).build())
.add(LoadoutItem.of(ItemId.DEATHRUNE).amount(200).stackable().build())
.depletionListener(restocker);

public void tick() {
if (!restocker.empty()) {
restocker.tick();
return;
}

if (!inventory.fulfilled() || !equipment.worn()) {
Loadouts.withdraw(inventory, equipment);
return;
}

// Normal script logic.
}
}

The important part is the branch order:

  1. Finish queued restocking.
  2. Prepare loadouts.
  3. Run normal script logic.

That keeps Grand Exchange work from fighting the bank/loadout flow.