Slot Iterator
Slot Iterator
SlotIterator is a small, stateful helper that gives you the next Slot each time you call
next().
Use it when:
- you have multiple objects to show
- each object should become one button
- the buttons should be placed in a predictable direction
This is the low-level Lotus tool for "take my data and lay it out across slots".
The Mental Model
In real menus, you often iterate two things at once:
- your data source, such as spells, relics, friends, or rewards
- the menu slots where those objects should appear
SlotIterator handles the second part.
SlotIterator slots = SlotIterator.of(size, Slot.first(), Direction.RIGHT);
Iterator<SpellScroll> scrolls = spellbook.unlockedScrolls().iterator();
while (slots.hasNext() && scrolls.hasNext()) {
Slot slot = slots.next();
SpellScroll scroll = scrolls.next();
content.set(slot, scrollButton(scroll));
}
That pattern is perfect for menus that show one button per object.
Create An Iterator
Use of(...) when you want to keep moving until the iterator reaches the edge of the menu:
SlotIterator row = SlotIterator.of(size, Slot.first(), Direction.RIGHT);
SlotIterator column = SlotIterator.of(size, Slot.at(0, 4, size), Direction.DOWN);
SlotIterator diagonal = SlotIterator.of(size, Slot.at(0, 0, size), Direction.DOWN_RIGHT);
Use bounded(...) when you want an inclusive start and end:
SlotIterator middleRow = SlotIterator.bounded(
size,
Slot.at(1, 1, size),
Slot.at(1, 7, size),
Direction.RIGHT
);
A Simple Content Example
public Content content(MenuView<?, ?> view) {
Capacity size = view.capacity();
Content content = Content.builder(size)
.fillBorder(Button.of(bookshelfPane()))
.build();
SlotIterator slots = SlotIterator.bounded(
size,
Slot.at(1, 1, size),
Slot.at(1, 7, size),
Direction.RIGHT
);
Iterator<SpellScroll> scrolls = spellbook.unlockedScrolls(view.viewer()).iterator();
while (slots.hasNext() && scrolls.hasNext()) {
SpellScroll scroll = scrolls.next();
content.set(slots.next(), scrollButton(scroll));
}
return content;
}
This could be a spellbook menu where the center row behaves like a shelf of magical scrolls.
Each unlocked scroll becomes one button, and SlotIterator walks left-to-right across that shelf.
Read it like this:
- define where the run starts
- define which direction it moves
- pair each
next()slot with the next object - stop when either side runs out
That keeps slot traversal separate from your business logic.
of(...) vs bounded(...)
| Factory | Stops when |
|---|---|
of(capacity, start, direction) |
the next step would leave the menu bounds |
bounded(capacity, start, end, direction) |
the iterator has returned end |
Both forms include the start slot.
bounded(...) also includes the end slot.
bounded(...) is still directional. Lotus does not calculate a path for you.
Your direction must actually lead from start toward end.
Important Behavior
1. It does not wrap
SlotIterator does not jump from the end of one row into the next row.
For example, on a 3-row chest:
SlotIterator.of(size, Slot.first(), Direction.RIGHT)
walks across the top row, then stops. If you need a full multi-row fill order, use pagination, a mask-driven layout, or nested loops.
2. It is stateful
A SlotIterator is a one-use object. Once it is exhausted, create a new one.
That is why menus usually create it inside content(...) or another render path.
3. Always check hasNext()
Calling next() after exhaustion throws NoSuchElementException.
The safe pattern is:
while (slots.hasNext() && data.hasNext()) {
content.set(slots.next(), renderer(data.next()));
}
When To Use It vs Other APIs
| Tool | Best for |
|---|---|
ContentBuilder.set(...) |
Fixed slots you already know ahead of time |
SlotMask |
Reusable regions or bulk fill operations |
SlotIterator |
One-by-one placement in a direction |
Pagination |
More items than one menu should show at once |
Good Fits
- spellbooks
- relic galleries
- pet stables
- reward previews
- any menu where "start here and place items one after another" is the rule
If that sounds like your layout, SlotIterator is usually the simplest low-level tool.
Next: The Menu Template.