From f935e31c2fd925b20f635e15745ce64959bda6fd Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 1 Sep 2026 04:28:15 +0000 Subject: [PATCH] Make the scrolling container reach the last row of a multi-column grid ScrollingInventoryContainer supports multiple columns, but two places assume there is only one. ContainerScreenScrolling computes the scrollbar's total rows as `filteredItemCount / getColumns()`, which truncates. With one column that is exact, but with nine columns and 985 elements it gives 109 rows instead of 110, so the four elements of the last row can never be scrolled to. The division is rounded up now, in one place both call sites share. isElementVisible guards against getPageSize(), which is the number of rows, and so returns false for every element past the first row of a grid, even though getVisibleElement returns them and onScroll fills them in. It now guards against the size of the visible elements, which is rows times columns; for a single-column container the two are the same. The constructor also only null-filled the first getPageSize() entries of a list that is rows times columns long. That was harmless, as the array it wraps is already all-null, but it read as if the rest were left uninitialized. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01T9xTc8kXNRDppvXktL24aR --- .../gui/container/ContainerScreenScrolling.java | 17 +++++++++++++++-- .../container/ScrollingInventoryContainer.java | 6 +++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/client/gui/container/ContainerScreenScrolling.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/client/gui/container/ContainerScreenScrolling.java index ae3f718b3d..21f0144119 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/client/gui/container/ContainerScreenScrolling.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/client/gui/container/ContainerScreenScrolling.java @@ -4,6 +4,7 @@ import net.minecraft.client.gui.components.EditBox; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.Slot; import org.cyclops.cyclopscore.client.gui.component.WidgetScrollBar; @@ -62,7 +63,7 @@ public void init() { this.scrollbar = new WidgetScrollBar(this.leftPos + getScrollX(), this.topPos + getScrollY(), getScrollHeight(), Component.translatable("gui.cyclopscore.scrollbar"), getMenu(), getMenu().getPageSize(), getScrollRegion()); - this.scrollbar.setTotalRows(getMenu().getFilteredItemCount() / getMenu().getColumns()); + this.scrollbar.setTotalRows(getTotalRows()); } else { this.scrollbar.setX(this.leftPos + getScrollX()); this.scrollbar.setY(this.topPos + getScrollY()); @@ -147,10 +148,22 @@ public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, doubl protected void updateSearch(String searchString) { getMenu().updateFilter(searchString); - this.scrollbar.setTotalRows(getMenu().getFilteredItemCount() / getMenu().getColumns()); + this.scrollbar.setTotalRows(getTotalRows()); this.scrollbar.scrollTo(0); } + /** + * The number of rows that the filtered elements occupy. + * + * This is rounded up, as a last row that is only partially filled + * must still be reachable by the scrollbar. + * + * @return The number of rows. + */ + protected int getTotalRows() { + return Mth.ceil((double) getMenu().getFilteredItemCount() / getMenu().getColumns()); + } + public EditBox getSearchField() { return searchField; } diff --git a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/inventory/container/ScrollingInventoryContainer.java b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/inventory/container/ScrollingInventoryContainer.java index 29db532e0a..6563a67a65 100644 --- a/loader-neoforge/src/main/java/org/cyclops/cyclopscore/inventory/container/ScrollingInventoryContainer.java +++ b/loader-neoforge/src/main/java/org/cyclops/cyclopscore/inventory/container/ScrollingInventoryContainer.java @@ -40,7 +40,7 @@ public ScrollingInventoryContainer(@Nullable MenuType type, int id, Inventory this.unfilteredItems = Lists.newArrayList(items); this.filteredItems = Lists.newLinkedList(); this.visibleItems = (List) Arrays.asList(new Object[getPageSize() * getColumns()]); - for(int i = 0; i < getPageSize(); i++) { + for(int i = 0; i < this.visibleItems.size(); i++) { this.visibleItems.set(i, null); } this.itemSearchPredicate = filterer; @@ -114,11 +114,11 @@ protected void enableElementAt(int visibleIndex, int elementIndex, E element) { /** * Check if the given element is visible. - * @param row The row the the given element is at. + * @param row The index of the given element within the visible elements. * @return If it is visible. */ public boolean isElementVisible(int row) { - return row < getPageSize() && getVisibleElement(row) != null; + return row < getPageSize() * getColumns() && getVisibleElement(row) != null; } /**