Skip to main content

Loadouts

com.n3plugins.sdk.loadouts defines the desired state for a character's inventory and equipment. A loadout represents a target state rather than an action. Bank and production workflow builders use it to reconcile the live game state against the target configuration.

Available Types

  • LoadoutItem: An immutable item requirement specifying ID, amount, slot, and flags.
  • InventoryLoadout: The 28-slot inventory target configuration.
  • EquipmentLoadout: The worn-equipment target configuration.
  • Loadout: The shared base class for loadouts.
  • ItemDepletionListener: An optional callback triggered when a required item exhausts.

Declare vs Assert

Loadouts pair with InventoryPlan but serve a distinct purpose:

  • InventoryPlan: Asserts current state. Evaluates if the inventory meets requirements right now. Used as a guard condition.
  • InventoryLoadout: Declares target state. Specifies what the inventory should contain after restocking. BankWorkflowBuilder and ProductionWorkflowBuilder use this.
  • EquipmentLoadout: Declares target state. Specifies what the player should wear. BankWorkflowBuilder uses this.

Building Items

LoadoutItem acts as an immutable class constructed via a fluent builder. The builder(int itemId) method acts as the primary entry point.

LoadoutItem logs = LoadoutItem.builder(ItemID.YEW_LOGS)
.amount(27)
.build();

LoadoutItem natures = LoadoutItem.builder(ItemID.NATURE_RUNE)
.amount(100)
.stackable(true)
.build();

LoadoutItem staff = LoadoutItem.builder(ItemID.STAFF_OF_FIRE)
.slot(EquipmentInventorySlot.WEAPON)
.build();

Builder configuration includes: amount(int) (defaults to 1), optional(boolean), noted(boolean), stackable(boolean), and slot(EquipmentInventorySlot). The slot parameter requires a value for equipment loadouts.

Inventory Loadout

InventoryLoadout inv = new InventoryLoadout();
inv.add(LoadoutItem.builder(ItemID.YEW_LOGS).amount(27).build());
inv.add(LoadoutItem.builder(ItemID.KNIFE).amount(1).build());

boolean done = inv.isFulfilled();

The add method throws an IllegalArgumentException if the items exceed the 28-slot capacity. The fulfill method reconciles the inventory against an equipment plan.

Equipment Loadout

EquipmentLoadout eq = new EquipmentLoadout();
eq.add(LoadoutItem.builder(ItemID.STAFF_OF_FIRE)
.slot(EquipmentInventorySlot.WEAPON).build());
eq.add(LoadoutItem.builder(ItemID.AMULET_OF_GLORY)
.slot(EquipmentInventorySlot.AMULET).build());

List<LoadoutItem> missing = eq.getMissingItems();
List<LoadoutItem> toEquip = eq.getUnequippedItems();
LoadoutItem weapon = eq.get(EquipmentInventorySlot.WEAPON);

Items added to an EquipmentLoadout must specify a slot.

Shared Loadout Interface

Both loadout types expose standard methods:

  • isFulfilled(): Evaluates if the live state matches the target.
  • getRequiredItems(): Returns the declared items.
  • getExcessItems(): Returns items held above the declared amount.
  • getForeignItemIds(): Returns item IDs held outside the loadout.
  • setItemDepletionListener(ItemDepletionListener): Registers a callback for when a required item depletes.

Builder Integration

Loadouts integrate with workflow builders for automated reconciliation:

BankWorkflowBuilder.create()
.reconcile(inv, eq)
.build();

new ProductionWorkflowBuilder(services)
.waitForProductionComplete()
.bankAndRestock(inv)
.build();

Builders utilize getForeignItemIds(), getMissingItems(), and getUnequippedItems() to determine the necessary deposit, withdrawal, and equip actions.

Testing

The ItemMetadataResolver determines stackability from client metadata. In test environments without a client, explicitly set stackable(...) or inject a test resolver via ItemMetadataResolver.setResolverForTesting(...).