diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f366c356..760cf0ea1 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - The Crafter can now only store 1 stack size pattern per slot (raoulvdberge) - You can now re-insert a Pattern in the pattern output slot in the Pattern Grid to modify an existing pattern (raoulvdberge) - Fixed not being able to use JEI R and U keys on Grid with tabs (raoulvdberge) +- Fixed lag when opening a Grid with lots of items by offloading the grid sorting to another thread (raoulvdberge) - The Refined Storage jar is now signed (raoulvdberge) ### 1.5.21 diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java index bab8a2013..8cac89a7d 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java @@ -41,7 +41,6 @@ public class StackListItem implements IStackList { public boolean remove(@Nonnull ItemStack stack, int size) { for (ItemStack otherStack : stacks.get(stack.getItem())) { if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) { - boolean success = otherStack.getCount() - size >= 0; otherStack.shrink(size); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java index 82181a7be..d212e0516 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/GuiGrid.java @@ -13,8 +13,7 @@ import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNodeGrid; import com.raoulvdberge.refinedstorage.container.ContainerGrid; import com.raoulvdberge.refinedstorage.gui.GuiBase; import com.raoulvdberge.refinedstorage.gui.Scrollbar; -import com.raoulvdberge.refinedstorage.gui.grid.filtering.GridFilterParser; -import com.raoulvdberge.refinedstorage.gui.grid.sorting.*; +import com.raoulvdberge.refinedstorage.gui.grid.sorting.Sorter; import com.raoulvdberge.refinedstorage.gui.grid.stack.GridStackFluid; import com.raoulvdberge.refinedstorage.gui.grid.stack.GridStackItem; import com.raoulvdberge.refinedstorage.gui.grid.stack.IGridStack; @@ -44,14 +43,8 @@ import org.lwjgl.input.Keyboard; import java.io.IOException; import java.util.*; import java.util.concurrent.ThreadLocalRandom; -import java.util.function.Predicate; public class GuiGrid extends GuiBase implements IGridDisplay { - private static final GridSorting SORTING_QUANTITY = new GridSortingQuantity(); - private static final GridSorting SORTING_NAME = new GridSortingName(); - private static final GridSorting SORTING_ID = new GridSortingID(); - private static final GridSorting SORTING_INVENTORYTWEAKS = new GridSortingInventoryTweaks(); - private static final List SEARCH_HISTORY = new ArrayList<>(); public static final ListMultimap ITEMS = Multimaps.synchronizedListMultimap(ArrayListMultimap.create()); @@ -60,7 +53,8 @@ public class GuiGrid extends GuiBase implements IGridDisplay { public static List STACKS = new ArrayList<>(); public static boolean CAN_CRAFT; - private static boolean markedForSorting; + private static boolean SCHEDULE_SORT = false; + private Queue sortingQueue = new ArrayDeque<>(); private boolean wasConnected; @@ -98,10 +92,6 @@ public class GuiGrid extends GuiBase implements IGridDisplay { private int[] konamiOffsetsX; private int[] konamiOffsetsY; - public static void markForSorting() { - markedForSorting = true; - } - public GuiGrid(ContainerGrid container, IGrid grid) { super(container, grid.getType() == GridType.FLUID ? 193 : 227, 0); @@ -169,7 +159,7 @@ public class GuiGrid extends GuiBase implements IGridDisplay { addSideButton(new SideButtonGridSearchBoxMode(this)); addSideButton(new SideButtonGridSize(this, grid)); - sortItems(); + scheduleSort(); } @Override @@ -181,62 +171,8 @@ public class GuiGrid extends GuiBase implements IGridDisplay { return grid; } - private void sortItems() { - List stacks = new ArrayList<>(); - - if (grid.isActive()) { - stacks.addAll(grid.getType() == GridType.FLUID ? FLUIDS.values() : ITEMS.values()); - - List> filters = GridFilterParser.getFilters( - grid, - searchField != null ? searchField.getText() : "", - (grid.getTabSelected() >= 0 && grid.getTabSelected() < grid.getTabs().size()) ? grid.getTabs().get(grid.getTabSelected()).getFilters() : grid.getFilters() - ); - - Iterator t = stacks.iterator(); - - while (t.hasNext()) { - IGridStack stack = t.next(); - - for (Predicate filter : filters) { - if (!filter.test(stack)) { - t.remove(); - - break; - } - } - } - - SORTING_NAME.setSortingDirection(grid.getSortingDirection()); - SORTING_QUANTITY.setSortingDirection(grid.getSortingDirection()); - SORTING_ID.setSortingDirection(grid.getSortingDirection()); - SORTING_INVENTORYTWEAKS.setSortingDirection(grid.getSortingDirection()); - - stacks.sort(SORTING_NAME); - - if (grid.getSortingType() == IGrid.SORTING_TYPE_QUANTITY) { - stacks.sort(SORTING_QUANTITY); - } else if (grid.getSortingType() == IGrid.SORTING_TYPE_ID) { - stacks.sort(SORTING_ID); - } else if (grid.getSortingType() == IGrid.SORTING_TYPE_INVENTORYTWEAKS) { - stacks.sort(SORTING_INVENTORYTWEAKS); - } - } - - STACKS = stacks; - - if (scrollbar != null) { - scrollbar.setEnabled(getRows() > getVisibleRows()); - scrollbar.setMaxOffset(getRows() - getVisibleRows()); - } - - if (tabPageLeft != null) { - tabPageLeft.visible = grid.getTotalTabPages() > 0; - } - - if (tabPageRight != null) { - tabPageRight.visible = grid.getTotalTabPages() > 0; - } + public static void scheduleSort() { + SCHEDULE_SORT = true; } @Override @@ -251,13 +187,7 @@ public class GuiGrid extends GuiBase implements IGridDisplay { if (wasConnected != grid.isActive()) { wasConnected = grid.isActive(); - markForSorting(); - } - - if (markedForSorting) { - markedForSorting = false; - - sortItems(); + scheduleSort(); } boolean hasTabs = !getGrid().getTabs().isEmpty(); @@ -267,6 +197,21 @@ public class GuiGrid extends GuiBase implements IGridDisplay { initGui(); } + + if (SCHEDULE_SORT) { + SCHEDULE_SORT = false; + + sortingQueue.add(new Sorter(this)); + } + + Sorter sorter = sortingQueue.peek(); + if (sorter != null) { + if (!sorter.isStarted()) { + sorter.start(); + } else if (sorter.isDone()) { + sortingQueue.poll(); + } + } } @Override @@ -478,7 +423,7 @@ public class GuiGrid extends GuiBase implements IGridDisplay { @Override public void drawForeground(int mouseX, int mouseY) { - drawString(7, 7 + getTabHeight(), t(grid.getGuiTitle())); + drawString(7, 7 + getTabHeight(), t(grid.getGuiTitle()) + " " + STACKS.size() + "," + sortingQueue.size()); drawString(7, getYPlayerInventory() - 12, t("container.inventory")); if (grid.getTotalTabPages() > 0) { @@ -585,7 +530,7 @@ public class GuiGrid extends GuiBase implements IGridDisplay { searchField.setText(""); searchField.setFocused(true); - sortItems(); + scheduleSort(); updateJEI(); } else if (wasSearchFieldFocused != searchField.isFocused()) { @@ -659,8 +604,8 @@ public class GuiGrid extends GuiBase implements IGridDisplay { // NO OP } else if (searchField.textboxKeyTyped(character, keyCode)) { updateJEI(); + scheduleSort(); - sortItems(); keyHandled = true; } else if (searchField.isFocused() && (keyCode == Keyboard.KEY_UP || keyCode == Keyboard.KEY_DOWN || keyCode == Keyboard.KEY_RETURN)) { if (keyCode == Keyboard.KEY_UP) { @@ -706,7 +651,7 @@ public class GuiGrid extends GuiBase implements IGridDisplay { if (delta == 1) { searchField.setText(""); - sortItems(); + scheduleSort(); updateJEI(); @@ -716,7 +661,7 @@ public class GuiGrid extends GuiBase implements IGridDisplay { searchField.setText(SEARCH_HISTORY.get(searchHistory)); - sortItems(); + scheduleSort(); updateJEI(); } @@ -759,4 +704,12 @@ public class GuiGrid extends GuiBase implements IGridDisplay { blockingPattern.setIsChecked(checked); } } + + public GuiButton getTabPageLeft() { + return tabPageLeft; + } + + public GuiButton getTabPageRight() { + return tabPageRight; + } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/sorting/Sorter.java b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/sorting/Sorter.java new file mode 100644 index 000000000..07ef15fe5 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/gui/grid/sorting/Sorter.java @@ -0,0 +1,105 @@ +package com.raoulvdberge.refinedstorage.gui.grid.sorting; + +import com.raoulvdberge.refinedstorage.api.network.grid.GridType; +import com.raoulvdberge.refinedstorage.api.network.grid.IGrid; +import com.raoulvdberge.refinedstorage.gui.grid.GuiGrid; +import com.raoulvdberge.refinedstorage.gui.grid.filtering.GridFilterParser; +import com.raoulvdberge.refinedstorage.gui.grid.stack.IGridStack; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Predicate; + +public class Sorter implements Runnable { + private static final GridSorting SORTING_QUANTITY = new GridSortingQuantity(); + private static final GridSorting SORTING_NAME = new GridSortingName(); + private static final GridSorting SORTING_ID = new GridSortingID(); + private static final GridSorting SORTING_INVENTORY_TWEAKS = new GridSortingInventoryTweaks(); + + private boolean done; + private boolean started; + + private GuiGrid gui; + + public Sorter(GuiGrid gui) { + this.gui = gui; + } + + @Override + public void run() { + IGrid grid = gui.getGrid(); + + List stacks = new ArrayList<>(); + + if (grid.isActive()) { + stacks.addAll(grid.getType() == GridType.FLUID ? GuiGrid.FLUIDS.values() : GuiGrid.ITEMS.values()); + + List> filters = GridFilterParser.getFilters( + grid, + gui.getSearchField() != null ? gui.getSearchField().getText() : "", + (grid.getTabSelected() >= 0 && grid.getTabSelected() < grid.getTabs().size()) ? grid.getTabs().get(grid.getTabSelected()).getFilters() : grid.getFilters() + ); + + Iterator t = stacks.iterator(); + + while (t.hasNext()) { + IGridStack stack = t.next(); + + for (Predicate filter : filters) { + if (!filter.test(stack)) { + t.remove(); + + break; + } + } + } + + SORTING_NAME.setSortingDirection(grid.getSortingDirection()); + SORTING_QUANTITY.setSortingDirection(grid.getSortingDirection()); + SORTING_ID.setSortingDirection(grid.getSortingDirection()); + SORTING_INVENTORY_TWEAKS.setSortingDirection(grid.getSortingDirection()); + + stacks.sort(SORTING_NAME); + + if (grid.getSortingType() == IGrid.SORTING_TYPE_QUANTITY) { + stacks.sort(SORTING_QUANTITY); + } else if (grid.getSortingType() == IGrid.SORTING_TYPE_ID) { + stacks.sort(SORTING_ID); + } else if (grid.getSortingType() == IGrid.SORTING_TYPE_INVENTORYTWEAKS) { + stacks.sort(SORTING_INVENTORY_TWEAKS); + } + } + + GuiGrid.STACKS = stacks; + + if (gui.getScrollbar() != null) { + gui.getScrollbar().setEnabled(gui.getRows() > gui.getVisibleRows()); + gui.getScrollbar().setMaxOffset(gui.getRows() - gui.getVisibleRows()); + } + + if (gui.getTabPageLeft() != null) { + gui.getTabPageLeft().visible = grid.getTotalTabPages() > 0; + } + + if (gui.getTabPageRight() != null) { + gui.getTabPageRight().visible = grid.getTotalTabPages() > 0; + } + + this.done = true; + } + + public void start() { + this.started = true; + + new Thread(this, "RS grid sorting").start(); + } + + public boolean isStarted() { + return started; + } + + public boolean isDone() { + return done; + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFilter.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFilter.java index aa4d0026e..008ec823e 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFilter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/ItemHandlerFilter.java @@ -43,7 +43,7 @@ public class ItemHandlerFilter extends ItemHandlerBase { } if (FMLCommonHandler.instance().getSide() == Side.CLIENT) { - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java index ae379fcb1..96402735d 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridFluidDelta.java @@ -48,14 +48,14 @@ public class MessageGridFluidDelta implements IMessage, IMessageHandler process(p.getLeft(), p.getRight())); } - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); return null; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java index 3558681d4..bf549b0f8 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java @@ -99,7 +99,7 @@ public class MessageGridItemUpdate implements IMessage, IMessageHandler { t.getNode().setViewType(v); t.getNode().markDirty(); } - }, p -> GuiGrid.markForSorting()); + }, p -> GuiGrid.scheduleSort()); public static final TileDataParameter SORTING_DIRECTION = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> t.getNode().getSortingDirection(), (t, v) -> { if (IGrid.isValidSortingDirection(v)) { t.getNode().setSortingDirection(v); t.getNode().markDirty(); } - }, p -> GuiGrid.markForSorting()); + }, p -> GuiGrid.scheduleSort()); public static final TileDataParameter SORTING_TYPE = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> t.getNode().getSortingType(), (t, v) -> { if (IGrid.isValidSortingType(v)) { t.getNode().setSortingType(v); t.getNode().markDirty(); } - }, p -> GuiGrid.markForSorting()); + }, p -> GuiGrid.scheduleSort()); public static final TileDataParameter SEARCH_BOX_MODE = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> t.getNode().getSearchBoxMode(), (t, v) -> { if (IGrid.isValidSearchBoxMode(v)) { t.getNode().setSearchBoxMode(v); @@ -62,7 +62,7 @@ public class TileGrid extends TileNode { t.getNode().markDirty(); }, p -> { if (Minecraft.getMinecraft().currentScreen instanceof GuiGrid) { - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } }); public static final TileDataParameter TAB_PAGE = new TileDataParameter<>(DataSerializers.VARINT, 0, t -> t.getNode().getTabPage(), (t, v) -> { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java index 7db02bb37..0c4e6fb50 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessFluidGrid.java @@ -128,7 +128,7 @@ public class WirelessFluidGrid implements IGrid { this.sortingType = type; - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override @@ -137,7 +137,7 @@ public class WirelessFluidGrid implements IGrid { this.sortingDirection = direction; - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java index 09fb570f1..85cdf4a02 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/WirelessGrid.java @@ -151,7 +151,7 @@ public class WirelessGrid implements IGrid { this.viewType = type; - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override @@ -160,7 +160,7 @@ public class WirelessGrid implements IGrid { this.sortingType = type; - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override @@ -169,7 +169,7 @@ public class WirelessGrid implements IGrid { this.sortingDirection = direction; - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override @@ -196,7 +196,7 @@ public class WirelessGrid implements IGrid { RS.INSTANCE.network.sendToServer(new MessageGridSettingsUpdate(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage())); - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java index a69bbc41d..8581a7d42 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/PortableGrid.java @@ -262,7 +262,7 @@ public class PortableGrid implements IGrid, IPortableGrid { this.sortingType = type; - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override @@ -271,7 +271,7 @@ public class PortableGrid implements IGrid, IPortableGrid { this.sortingDirection = direction; - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override @@ -298,7 +298,7 @@ public class PortableGrid implements IGrid, IPortableGrid { RS.INSTANCE.network.sendToServer(new MessageGridSettingsUpdate(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage())); - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java index 2db0f428c..eb16b3375 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java @@ -62,13 +62,13 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid, t.setSortingDirection(v); t.markDirty(); } - }, p -> GuiGrid.markForSorting()); + }, p -> GuiGrid.scheduleSort()); public static final TileDataParameter SORTING_TYPE = new TileDataParameter<>(DataSerializers.VARINT, 0, TilePortableGrid::getSortingType, (t, v) -> { if (IGrid.isValidSortingType(v)) { t.setSortingType(v); t.markDirty(); } - }, p -> GuiGrid.markForSorting()); + }, p -> GuiGrid.scheduleSort()); public static final TileDataParameter SEARCH_BOX_MODE = new TileDataParameter<>(DataSerializers.VARINT, 0, TilePortableGrid::getSearchBoxMode, (t, v) -> { if (IGrid.isValidSearchBoxMode(v)) { t.setSearchBoxMode(v); @@ -94,7 +94,7 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid, t.markDirty(); }, p -> { if (Minecraft.getMinecraft().currentScreen instanceof GuiGrid) { - GuiGrid.markForSorting(); + GuiGrid.scheduleSort(); } }); public static final TileDataParameter TAB_PAGE = new TileDataParameter<>(DataSerializers.VARINT, 0, TilePortableGrid::getTabPage, (t, v) -> {