Consumable Slots - UQcsse3200/2026-studio-4 GitHub Wiki

Overview

The consumable slots provide quick access to four equipped item types during gameplay. They display the player's current stock, selected slot and use controls along the bottom of the screen.

InventoryComponent stores quantities and slot assignments. ConsumableSelectionComponent tracks the selected position, ConsumableEffectComponent handles item use, and ConsumableHotbarDisplay renders the slots. The display does not maintain a separate inventory.

Usage

  1. Press I to open the inventory book and select its Consumables page.
  2. Equip an item from the Backpack by clicking it, or select it with WASD / arrows and press Space. This uses the first empty equipped slot.
  3. Close the book with I or Escape.
  4. Press Tab to cycle through the four slots, then Q to use the selected item.

Tab visits every slot, including empty ones, and wraps from the fourth back to the first. Selection starts at the first slot. Q does nothing when the selected slot is empty.

The slots display keyboard controls; they do not provide mouse selection or click-to-use actions. While the inventory book is open, Q and E change book pages, and Tab does not cycle the gameplay selection.

Slot assignments

Each slot holds one consumable type. Its number shows the total owned quantity of that type, rather than a quantity stored separately in the slot.

Action Result
Pick up a newly owned type Fill the first empty slot if one is available; otherwise keep the stock in the Backpack.
Pick up more of an owned type Increase its quantity without changing its assignment. A manually unequipped type stays unequipped.
Buy a consumable or receive an Item Draw reward Add stock without automatically assigning a slot.
Equip from the Backpack using click or Space Use the first empty slot. If all four are occupied, the assignment is unchanged.
Drag a Backpack item onto an equipped slot Assign it to that position. A replaced type remains owned in the Backpack.
Drag between equipped slots Swap the assignments, or move into an empty slot.
Unequip a type Clear its assignment while retaining its quantity.
Use the last copy Clear that type's slot. Selection stays on the same physical position.

InventoryComponent.CONSUMABLE_SLOT_COUNT defines four positions, with code indices 0–3. The same type cannot occupy multiple slots through the equipment API.

Display and feedback

ConsumableHotbarDisplay presents:

  • Four persistent slot frames, with icons and quantities for occupied slots.
  • A distinct selected frame and a v pointer above the selected position.
  • TAB NEXT above the group and Q USE below the selected slot when it has stock.
  • Gold: total, using the player's existing inventory balance.

Empty slots remain visible and selectable, while their icons, counts and use hints are hidden. Item textures come from ItemCatalog; selected artwork is cropped through texture regions to remove transparent padding.

Speed Potion timer

SpeedPotionTimerRing draws a blue arc in a slot assigned to SPEED_POTION. It reads ConsumableEffectComponent.getRemainingFraction(ItemIds.SPEED_POTION) directly, so the arc represents the remaining active effect, not an item-use cooldown.

The ring does not require that slot to be selected. It disappears when the tracked effect expires. It is also hidden when the Speed Potion is unequipped or its last copy is consumed and the slot clears, even if the speed effect is still active. Other consumables do not use this timer ring.

Selection and use

ConsumableSelectionComponent exposes:

Method Behaviour
int getSelectedIndex() Return the selected physical position.
String getSelectedType() Read the item ID currently assigned there, or null.
void cycle() Advance one position, wrap after the fourth, and notify listeners.
void useSelected() Request use of the assigned type when the position is not empty.

Usage

The keyboard handler sends requests through the player entity:

player.getEvents().trigger(ConsumableSelectionComponent.CYCLE_REQUEST);
player.getEvents().trigger(ConsumableSelectionComponent.USE_SELECTED_REQUEST);

useSelected() forwards the selected ID to ConsumableEffectComponent. That component checks availability and item-specific conditions, consumes one unit on a valid use, and applies the effect. The selection component and display do not remove stock themselves. See Consumables for effect rules.

Events

These events belong to the player entity:

Event Parameters Role
cycleConsumable None Request the next position.
useSelectedConsumable None Request use of the selected slot.
selectedConsumableChanged String itemId, which may be null Notify listeners after cycling.
useConsumable String itemId Ask the effect component to validate and use that type.
consumableInventoryChanged String itemId, Integer count Report quantity or equipment-assignment changes.

Cycling emits selectedConsumableChanged. Equipping, unequipping or exhausting a type instead changes inventory state; the display also listens to consumableInventoryChanged and refreshes all four slots. Gold is refreshed by comparing InventoryComponent.getGold() during the display's update() method.

Layout and lifecycle

MainGameScreen creates new ConsumableHotbarDisplay(player) on the UI entity. The constructor requires the player to have inventory, selection and effect components, which are attached by PlayerFactory.

BottomHotbarLayout supplies bottom positioning, responsive slot dimensions, spacing and the group offset. This keeps the consumable slots aligned with adjacent HUD elements without hard-coding four independent positions. The root actor does not intercept mouse or touch input.

On creation, the display loads its preloaded frame textures from ResourceService, creates its own small texture for the timer ring, builds the actors and reads the current inventory. When the book is open, the display places its own actors below the book.

Disposal removes the display's root actor and releases its timer-ring texture. Frame and item textures remain owned by the shared resource service. Event callbacks check the disposed flag before updating actors.

Testing

  • ConsumableHotbarDisplayTest
  • ConsumableSelectionComponentTest
  • SpeedPotionTimerRingTest
  • InventoryComponentTest
  • KeyboardPlayerInputComponentTest
  • InventoryDisplayTest
  • InventoryDisplayLayeringTest
  • ConsumableUseIntegrationTest

Source and related documentation