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.
BankWorkflowBuilderandProductionWorkflowBuilderuse this. - EquipmentLoadout: Declares target state. Specifies what the player should wear.
BankWorkflowBuilderuses 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(...).