From 7353154ff0e24606e864147c034acd29056e2161 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 16:22:09 +0800 Subject: Add option to disable compact arrows --- .../shedaniel/rei/impl/client/config/ConfigObjectImpl.java | 9 ++++++++- .../client/gui/screen/CompositeDisplayViewingScreen.java | 10 +++++++--- .../impl/client/gui/screen/DefaultDisplayViewingScreen.java | 12 ++++++++---- 3 files changed, 23 insertions(+), 8 deletions(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java index 76c7e269c..968cf4148 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java @@ -356,6 +356,11 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { return advanced.accessibility.useCompactTabs; } + @Override + public boolean isUsingCompactTabButtons() { + return advanced.accessibility.useCompactTabButtons; + } + @Override public boolean isLowerConfigButton() { return appearance.layout.configButtonLocation == ConfigButtonPosition.LOWER; @@ -521,7 +526,8 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { public static class Basics { @ConfigEntry.Gui.Excluded public List favorites = new ArrayList<>(); - @Comment("Declares whether cheating mode is on.") @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) private CheatingMode cheating = CheatingMode.OFF; + @Comment("Declares whether cheating mode is on.") @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) + private CheatingMode cheating = CheatingMode.OFF; private boolean favoritesEnabled = true; @ConfigEntry.Gui.CollapsibleObject(startExpanded = true) private KeyBindings keyBindings = new KeyBindings(); @@ -631,6 +637,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { @Comment("Declares how the scrollbar in composite screen should act.") private boolean compositeScrollBarPermanent = false; private boolean toastDisplayedOnCopyIdentifier = true; @Comment("Declares whether REI should use compact tabs for categories.") private boolean useCompactTabs = true; + @Comment("Declares whether REI should use compact tab buttons for categories.") private boolean useCompactTabButtons = true; } public static class Search { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java index b1f131197..1613d7f18 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java @@ -108,6 +108,8 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen public void init() { super.init(); boolean isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs(); + boolean isCompactTabButtons = ConfigObject.getInstance().isUsingCompactTabButtons(); + int tabButtonsSize = isCompactTabButtons ? 10 : 16; int tabSize = isCompactTabs ? 24 : 28; this.children().clear(); this.widgets.clear(); @@ -120,7 +122,7 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen DisplaySpec display = categoryMap.get(category).get(selectedRecipeIndex); int guiWidth = Mth.clamp(category.getDisplayWidth(display.provideInternalDisplay()) + 30, 0, largestWidth) + 100; int guiHeight = Mth.clamp(category.getDisplayHeight() + 40, 166, largestHeight); - this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - 20d) / tabSize)); + this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - tabButtonsSize * 2d) / tabSize)); if (this.tabsPage == -1) { this.tabsPage = selectedCategoryIndex / tabsPerPage; } @@ -207,21 +209,23 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen tab.setRenderer(tabCategory, tabCategory.getIcon(), tabCategory.getTitle(), j == selectedCategoryIndex); } } - this.widgets.add(Widgets.createButton(new Rectangle(bounds.x + 2, bounds.y - 16, 10, 10), new TranslatableComponent("text.rei.left_arrow")) + this.widgets.add(Widgets.createButton(new Rectangle(bounds.x + 2, bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), new TranslatableComponent("text.rei.left_arrow")) .onClick(button -> { tabsPage--; if (tabsPage < 0) tabsPage = Mth.ceil(categories.size() / (float) tabsPerPage) - 1; CompositeDisplayViewingScreen.this.init(); }) + .tooltipLine(new TranslatableComponent("text.rei.previous_page")) .enabled(categories.size() > tabsPerPage)); - this.widgets.add(Widgets.createButton(new Rectangle(bounds.x + bounds.width - 12, bounds.y - 16, 10, 10), new TranslatableComponent("text.rei.right_arrow")) + this.widgets.add(Widgets.createButton(new Rectangle(bounds.x + bounds.width - (isCompactTabButtons ? tabButtonsSize + 2 : tabButtonsSize + 3), bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), new TranslatableComponent("text.rei.right_arrow")) .onClick(button -> { tabsPage++; if (tabsPage > Mth.ceil(categories.size() / (float) tabsPerPage) - 1) tabsPage = 0; CompositeDisplayViewingScreen.this.init(); }) + .tooltipLine(new TranslatableComponent("text.rei.next_page")) .enabled(categories.size() > tabsPerPage)); this.widgets.add(Widgets.createClickableLabel(new Point(bounds.x + 4 + scrollListBounds.width / 2, bounds.y + 6), categories.get(selectedCategoryIndex).getTitle(), label -> { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java index 47f914e5d..a5ea0a957 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java @@ -162,28 +162,32 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { } boolean isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs(); + boolean isCompactTabButtons = ConfigObject.getInstance().isUsingCompactTabButtons(); + int tabButtonsSize = isCompactTabButtons ? 10 : 16; int tabSize = isCompactTabs ? 24 : 28; - this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - 20d) / tabSize)); + this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - tabButtonsSize * 2d) / tabSize)); if (this.categoryPages == -1) { this.categoryPages = Math.max(0, selectedCategoryIndex / tabsPerPage); } this.page = Mth.clamp(page, 0, getCurrentTotalPages() - 1); - this.widgets.add(Widgets.createButton(new Rectangle(bounds.x, bounds.y - 16, 10, 10), new TranslatableComponent("text.rei.left_arrow")) + this.widgets.add(Widgets.createButton(new Rectangle(bounds.x, bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), new TranslatableComponent("text.rei.left_arrow")) .onClick(button -> { categoryPages--; if (categoryPages < 0) categoryPages = Mth.ceil(categories.size() / (float) tabsPerPage) - 1; DefaultDisplayViewingScreen.this.init(); }) + .tooltipLine(new TranslatableComponent("text.rei.previous_page")) .enabled(categories.size() > tabsPerPage)); - this.widgets.add(Widgets.createButton(new Rectangle(bounds.x + bounds.width - 10, bounds.y - 16, 10, 10), new TranslatableComponent("text.rei.right_arrow")) + this.widgets.add(Widgets.createButton(new Rectangle(bounds.x + bounds.width - tabButtonsSize - (isCompactTabButtons ? 0 : 1), bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), new TranslatableComponent("text.rei.right_arrow")) .onClick(button -> { categoryPages++; if (categoryPages > Mth.ceil(categories.size() / (float) tabsPerPage) - 1) categoryPages = 0; DefaultDisplayViewingScreen.this.init(); }) + .tooltipLine(new TranslatableComponent("text.rei.next_page")) .enabled(categories.size() > tabsPerPage)); this.widgets.add(categoryBack = Widgets.createButton(new Rectangle(bounds.getX() + 5, bounds.getY() + 5, 12, 12), new TranslatableComponent("text.rei.left_arrow")) .onClick(button -> previousCategory()).tooltipLine(new TranslatableComponent("text.rei.previous_category"))); @@ -354,7 +358,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { } PanelWidget.render(matrices, bounds, -1, delta); fill(matrices, bounds.x + 17, bounds.y + 5, bounds.x + bounds.width - 17, bounds.y + 17, darkStripesColor.value().getColor()); - fill(matrices, bounds.x + 17, bounds.y + 19, bounds.x + bounds.width - 17, bounds.y + 30, darkStripesColor.value().getColor()); + fill(matrices, bounds.x + 17, bounds.y + 19, bounds.x + bounds.width - 17, bounds.y + 31, darkStripesColor.value().getColor()); for (TabWidget tab : tabs) { if (!tab.isSelected()) { tab.render(matrices, mouseX, mouseY, delta); -- cgit From 79b8d8d0d9774a6f23579cb5452b44b61437a305 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 16:35:59 +0800 Subject: Make craftable filter check count --- .../rei/impl/client/ClientHelperImpl.java | 29 ++++++++++++++-------- .../rei/impl/client/gui/ScreenOverlayImpl.java | 2 +- .../impl/client/gui/craftable/CraftableFilter.java | 25 +++++++++---------- .../shedaniel/rei/impl/client/view/ViewsImpl.java | 14 ++++++++++- 4 files changed, 45 insertions(+), 25 deletions(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java index f3b18ba39..8f29b8989 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java @@ -27,8 +27,9 @@ import com.google.common.base.Suppliers; import dev.architectury.networking.NetworkManager; import dev.architectury.platform.Platform; import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -import it.unimi.dsi.fastutil.longs.LongSet; +import it.unimi.dsi.fastutil.longs.Long2LongMap; +import it.unimi.dsi.fastutil.longs.Long2LongMaps; +import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; import me.shedaniel.rei.RoughlyEnoughItemsNetwork; import me.shedaniel.rei.api.client.ClientHelper; import me.shedaniel.rei.api.client.config.ConfigManager; @@ -40,6 +41,8 @@ import me.shedaniel.rei.api.client.registry.display.DisplayCategory; import me.shedaniel.rei.api.client.view.ViewSearchBuilder; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext; +import me.shedaniel.rei.api.common.entry.type.EntryDefinition; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.api.common.util.FormattingUtils; @@ -54,6 +57,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; +import net.minecraft.core.NonNullList; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.resources.ResourceLocation; @@ -221,17 +225,22 @@ public class ClientHelperImpl implements ClientHelper { } @ApiStatus.Internal - public LongSet _getInventoryItemsTypes() { + public Long2LongMap _getInventoryItemsTypes() { + EntryDefinition definition; try { - VanillaEntryTypes.ITEM.getDefinition(); + definition = VanillaEntryTypes.ITEM.getDefinition(); } catch (NullPointerException e) { - return new LongOpenHashSet(); + return Long2LongMaps.EMPTY_MAP; + } + Long2LongOpenHashMap map = new Long2LongOpenHashMap(); + for (NonNullList compartment : Minecraft.getInstance().player.getInventory().compartments) { + for (ItemStack stack : compartment) { + long hash = definition.hash(null, stack, ComparisonContext.FUZZY); + long newCount = map.getOrDefault(hash, 0) + Math.max(0, stack.getCount()); + map.put(hash, newCount); + } } - return Minecraft.getInstance().player.getInventory().compartments.stream() - .flatMap(Collection::stream) - .map(EntryStacks::of) - .mapToLong(EntryStacks::hashFuzzy) - .collect(LongOpenHashSet::new, LongOpenHashSet::add, LongOpenHashSet::addAll); + return map; } @ApiStatus.Internal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java index a34423cb0..73a5bc946 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java @@ -138,7 +138,7 @@ public class ScreenOverlayImpl extends ScreenOverlay { public void tick() { if (REIRuntimeImpl.getSearchField() != null) { REIRuntimeImpl.getSearchField().tick(); - if (Minecraft.getInstance().player != null && !PluginManager.areAnyReloading()) { + if (Minecraft.getInstance().player != null && !PluginManager.areAnyReloading() && Minecraft.getInstance().player.tickCount % 20 == 0) { CraftableFilter.INSTANCE.tick(); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java index 59c23cca0..3912829d1 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java @@ -23,20 +23,19 @@ package me.shedaniel.rei.impl.client.gui.craftable; -import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -import it.unimi.dsi.fastutil.longs.LongSet; -import it.unimi.dsi.fastutil.longs.LongSets; +import it.unimi.dsi.fastutil.longs.Long2LongMap; +import it.unimi.dsi.fastutil.longs.Long2LongMaps; +import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.transfer.info.stack.SlotAccessor; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.client.ClientHelperImpl; -import net.minecraft.client.Minecraft; public class CraftableFilter { public static final CraftableFilter INSTANCE = new CraftableFilter(); private boolean dirty = false; - private LongSet invStacks = new LongOpenHashSet(); + private Long2LongMap invStacks = new Long2LongOpenHashMap(); public void markDirty() { dirty = true; @@ -53,28 +52,28 @@ public class CraftableFilter { public void tick() { if (dirty) return; - LongSet currentStacks; + Long2LongMap currentStacks; try { currentStacks = ClientHelperImpl.getInstance()._getInventoryItemsTypes(); } catch (Throwable throwable) { throwable.printStackTrace(); - currentStacks = LongSets.EMPTY_SET; + currentStacks = Long2LongMaps.EMPTY_MAP; } if (!currentStacks.equals(this.invStacks)) { - invStacks = new LongOpenHashSet(currentStacks); + invStacks = currentStacks; markDirty(); } } - public boolean matches(EntryStack stack, Iterable inputSlots) { - if (invStacks.contains(EntryStacks.hashFuzzy(stack))) return true; - if (stack.getType() != VanillaEntryTypes.ITEM) return false; + public int matches(EntryStack stack, Iterable inputSlots, long currentUsed) { + long availableAmount = invStacks.get(EntryStacks.hashFuzzy(stack)); + if (availableAmount > currentUsed) return 1; for (SlotAccessor slot : inputSlots) { EntryStack itemStack = EntryStacks.of(slot.getItemStack()); if (!itemStack.isEmpty() && EntryStacks.equalsFuzzy(itemStack, stack)) { - return true; + return 2; } } - return false; + return 0; } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java index 4b2ce42e1..857f3aaea 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java @@ -27,6 +27,8 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import it.unimi.dsi.fastutil.longs.Long2LongMap; +import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; import me.shedaniel.rei.RoughlyEnoughItemsCore; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; @@ -40,6 +42,7 @@ import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.display.DisplayMerger; import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.transfer.info.MenuInfo; import me.shedaniel.rei.api.common.transfer.info.MenuInfoRegistry; @@ -374,13 +377,22 @@ public class ViewsImpl implements Views { Iterable inputSlots = info != null ? info.getInputSlots(context.withDisplay(display)) : Collections.emptySet(); int slotsCraftable = 0; List requiredInput = display.getRequiredEntries(); + Long2LongMap usedCount = new Long2LongOpenHashMap(); for (EntryIngredient slot : requiredInput) { if (slot.isEmpty()) { slotsCraftable++; continue; } for (EntryStack slotPossible : slot) { - if (CraftableFilter.INSTANCE.matches(slotPossible, inputSlots)) { + if (slotPossible.getType() != VanillaEntryTypes.ITEM) continue; + long hashFuzzy = EntryStacks.hashFuzzy(slotPossible); + long currentUsed = usedCount.get(hashFuzzy); + int matches = CraftableFilter.INSTANCE.matches(slotPossible, inputSlots, currentUsed); + if (matches != 0) { + if (matches == 1) { + usedCount.put(hashFuzzy, currentUsed + 1); + } + slotsCraftable++; break; } -- cgit From 6397967ecc1d2fba958c9feb59f55eff52d5a5db Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 19:03:53 +0800 Subject: Make ctrl-click transfer not suck that much --- .../rei/impl/client/config/ConfigManagerImpl.java | 2 +- .../rei/impl/client/gui/widget/EntryListWidget.java | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java index 078f46344..2d82a28c8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigManagerImpl.java @@ -293,7 +293,7 @@ public class ConfigManagerImpl implements ConfigManager { @Override public boolean isCraftableOnlyEnabled() { - return craftableOnly; + return craftableOnly && getConfig().isCraftableFilterEnabled(); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java index 28f6e2ca5..d9df0215a 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java @@ -71,6 +71,7 @@ import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.search.AsyncSearchManager; import me.shedaniel.rei.impl.client.view.ViewsImpl; import net.minecraft.ChatFormatting; +import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; @@ -601,6 +602,7 @@ public class EntryListWidget extends WidgetWithBounds implements OverlayListWidg } private class EntryListEntry extends EntryListEntryWidget { + private long lastCheckTime = -1; private Display display; private EntryStack our; private NumberAnimator size = null; @@ -654,6 +656,22 @@ public class EntryListWidget extends WidgetWithBounds implements OverlayListWidg return null; } + if (display != null) { + if (ViewsImpl.isRecipesFor(getEntries(), display)) { + AutoCraftingEvaluator.AutoCraftingResult result = AutoCraftingEvaluator.evaluateAutoCrafting(false, false, display, null); + if (result.successful) { + return result.successfulHandler; + } + } + + display = null; + lastCheckTime = -1; + } + + if (lastCheckTime != -1 && Util.getMillis() - lastCheckTime < 100) { + return null; + } + for (List displays : DisplayRegistry.getInstance().getAll().values()) { for (Display display : displays) { if (ViewsImpl.isRecipesFor(getEntries(), display)) { @@ -674,7 +692,7 @@ public class EntryListWidget extends WidgetWithBounds implements OverlayListWidg public Tooltip getCurrentTooltip(Point point) { Tooltip tooltip = super.getCurrentTooltip(point); - if (tooltip != null && getTransferHandler() != null) { + if (tooltip != null && !ClientHelper.getInstance().isCheating() && getTransferHandler() != null) { tooltip.add(new TranslatableComponent("text.auto_craft.move_items.tooltip").withStyle(ChatFormatting.YELLOW)); } -- cgit From 8902036eb80f33310079ddd8ea85212e2aebc6cb Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 19:32:33 +0800 Subject: Make craftable filter account for container changes --- .../rei/impl/client/ClientHelperImpl.java | 25 +++++++++++++++++ .../rei/impl/client/gui/ScreenOverlayImpl.java | 2 +- .../impl/client/gui/craftable/CraftableFilter.java | 29 ++++++++++---------- .../impl/client/gui/widget/EntryListWidget.java | 3 ++ .../shedaniel/rei/impl/client/view/ViewsImpl.java | 32 ++++++++++++++++------ 5 files changed, 68 insertions(+), 23 deletions(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java index 8f29b8989..09d43c2a1 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/ClientHelperImpl.java @@ -64,6 +64,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.util.LazyLoadedValue; import net.minecraft.util.Mth; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -243,6 +244,30 @@ public class ClientHelperImpl implements ClientHelper { return map; } + @ApiStatus.Internal + public Long2LongMap _getContainerItemsTypes() { + EntryDefinition definition; + try { + definition = VanillaEntryTypes.ITEM.getDefinition(); + } catch (NullPointerException e) { + return Long2LongMaps.EMPTY_MAP; + } + Long2LongOpenHashMap map = new Long2LongOpenHashMap(); + AbstractContainerMenu menu = Minecraft.getInstance().player.containerMenu; + if (menu != null) { + for (Slot slot : menu.slots) { + ItemStack stack = slot.getItem(); + + if (!stack.isEmpty()) { + long hash = definition.hash(null, stack, ComparisonContext.FUZZY); + long newCount = map.getOrDefault(hash, 0) + Math.max(0, stack.getCount()); + map.put(hash, newCount); + } + } + } + return map; + } + @ApiStatus.Internal public void openRecipeViewingScreen(Map, List> map, @Nullable CategoryIdentifier category, List> ingredientNotice, List> resultNotice) { LegacyWrapperViewSearchBuilder builder = new LegacyWrapperViewSearchBuilder(map); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java index 73a5bc946..74c010f83 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java @@ -138,7 +138,7 @@ public class ScreenOverlayImpl extends ScreenOverlay { public void tick() { if (REIRuntimeImpl.getSearchField() != null) { REIRuntimeImpl.getSearchField().tick(); - if (Minecraft.getInstance().player != null && !PluginManager.areAnyReloading() && Minecraft.getInstance().player.tickCount % 20 == 0) { + if (Minecraft.getInstance().player != null && !PluginManager.areAnyReloading() && Minecraft.getInstance().player.tickCount % 5 == 0) { CraftableFilter.INSTANCE.tick(); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java index 3912829d1..1996dc5ef 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java @@ -26,16 +26,13 @@ package me.shedaniel.rei.impl.client.gui.craftable; import it.unimi.dsi.fastutil.longs.Long2LongMap; import it.unimi.dsi.fastutil.longs.Long2LongMaps; import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; -import me.shedaniel.rei.api.common.entry.EntryStack; -import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; -import me.shedaniel.rei.api.common.transfer.info.stack.SlotAccessor; -import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.client.ClientHelperImpl; public class CraftableFilter { public static final CraftableFilter INSTANCE = new CraftableFilter(); private boolean dirty = false; private Long2LongMap invStacks = new Long2LongOpenHashMap(); + private Long2LongMap containerStacks = new Long2LongOpenHashMap(); public void markDirty() { dirty = true; @@ -63,17 +60,21 @@ public class CraftableFilter { invStacks = currentStacks; markDirty(); } - } + if (dirty) return; - public int matches(EntryStack stack, Iterable inputSlots, long currentUsed) { - long availableAmount = invStacks.get(EntryStacks.hashFuzzy(stack)); - if (availableAmount > currentUsed) return 1; - for (SlotAccessor slot : inputSlots) { - EntryStack itemStack = EntryStacks.of(slot.getItemStack()); - if (!itemStack.isEmpty() && EntryStacks.equalsFuzzy(itemStack, stack)) { - return 2; - } + try { + currentStacks = ClientHelperImpl.getInstance()._getContainerItemsTypes(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + currentStacks = Long2LongMaps.EMPTY_MAP; + } + if (!currentStacks.equals(this.containerStacks)) { + containerStacks = currentStacks; + markDirty(); } - return 0; + } + + public Long2LongMap getInvStacks() { + return invStacks; } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java index d9df0215a..a7b762833 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java @@ -77,9 +77,11 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.sounds.SoundEvents; import net.minecraft.util.Mth; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.CreativeModeTab; @@ -711,6 +713,7 @@ public class EntryListWidget extends WidgetWithBounds implements OverlayListWidg TransferHandler.Result transferResult = handler.handle(context); if (transferResult.isBlocking()) { + minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); if (transferResult.isReturningToScreen() && Minecraft.getInstance().screen != containerScreen) { Minecraft.getInstance().setScreen(containerScreen); REIRuntime.getInstance().getOverlay().ifPresent(ScreenOverlay::queueReloadOverlay); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java index 857f3aaea..ee348b71b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java @@ -42,6 +42,8 @@ import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.display.DisplayMerger; import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext; +import me.shedaniel.rei.api.common.entry.type.EntryDefinition; import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.transfer.info.MenuInfo; @@ -58,6 +60,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -377,7 +380,23 @@ public class ViewsImpl implements Views { Iterable inputSlots = info != null ? info.getInputSlots(context.withDisplay(display)) : Collections.emptySet(); int slotsCraftable = 0; List requiredInput = display.getRequiredEntries(); - Long2LongMap usedCount = new Long2LongOpenHashMap(); + Long2LongMap invCount = new Long2LongOpenHashMap(CraftableFilter.INSTANCE.getInvStacks()); + for (SlotAccessor inputSlot : inputSlots) { + ItemStack stack = inputSlot.getItemStack(); + + EntryDefinition definition; + try { + definition = VanillaEntryTypes.ITEM.getDefinition(); + } catch (NullPointerException e) { + break; + } + + if (!stack.isEmpty()) { + long hash = definition.hash(null, stack, ComparisonContext.FUZZY); + long newCount = invCount.get(hash) + Math.max(0, stack.getCount()); + invCount.put(hash, newCount); + } + } for (EntryIngredient slot : requiredInput) { if (slot.isEmpty()) { slotsCraftable++; @@ -385,14 +404,11 @@ public class ViewsImpl implements Views { } for (EntryStack slotPossible : slot) { if (slotPossible.getType() != VanillaEntryTypes.ITEM) continue; + ItemStack stack = slotPossible.castValue(); long hashFuzzy = EntryStacks.hashFuzzy(slotPossible); - long currentUsed = usedCount.get(hashFuzzy); - int matches = CraftableFilter.INSTANCE.matches(slotPossible, inputSlots, currentUsed); - if (matches != 0) { - if (matches == 1) { - usedCount.put(hashFuzzy, currentUsed + 1); - } - + long availableAmount = invCount.get(hashFuzzy); + if (availableAmount >= stack.getCount()) { + invCount.put(hashFuzzy, availableAmount - stack.getCount()); slotsCraftable++; break; } -- cgit From ed36b3a2bb3662aeba7afc57e8116706f4d25da2 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 20:28:44 +0800 Subject: Make ctrl-click transfer less laggy --- .../me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java index a7b762833..cde2ece23 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java @@ -670,10 +670,17 @@ public class EntryListWidget extends WidgetWithBounds implements OverlayListWidg lastCheckTime = -1; } - if (lastCheckTime != -1 && Util.getMillis() - lastCheckTime < 100) { + if (lastCheckTime != -1 && Util.getMillis() - lastCheckTime < 2000) { return null; } + return _getTransferHandler(); + } + + @Nullable + private TransferHandler _getTransferHandler() { + lastCheckTime = Util.getMillis(); + for (List displays : DisplayRegistry.getInstance().getAll().values()) { for (Display display : displays) { if (ViewsImpl.isRecipesFor(getEntries(), display)) { -- cgit From 5d8b72da3c3dfe386c3e0450687a4fa5162e5e18 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 20:28:53 +0800 Subject: Make craftable filter defaulted on --- .../main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java index 968cf4148..0f273b7e8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java @@ -570,7 +570,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { private SearchFieldLocation searchFieldLocation = SearchFieldLocation.CENTER; @Comment("Declares the position of the config button.") @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) private ConfigButtonPosition configButtonLocation = ConfigButtonPosition.LOWER; - @Comment("Declares whether the craftable filter button is enabled.") private boolean enableCraftableOnlyButton = false; + @Comment("Declares whether the craftable filter button is enabled.") private boolean enableCraftableOnlyButton = true; } @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double horizontalEntriesBoundaries = 1.0; -- cgit From 8d97f66088f288f90b9d408e23cfd08341f772a9 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 20:29:04 +0800 Subject: Check non-empty for craftable filter, Fix #663 --- .../src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java index ee348b71b..80b453d50 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/view/ViewsImpl.java @@ -379,6 +379,7 @@ public class ViewsImpl implements Views { Iterable inputSlots = info != null ? info.getInputSlots(context.withDisplay(display)) : Collections.emptySet(); int slotsCraftable = 0; + boolean containsNonEmpty = false; List requiredInput = display.getRequiredEntries(); Long2LongMap invCount = new Long2LongOpenHashMap(CraftableFilter.INSTANCE.getInvStacks()); for (SlotAccessor inputSlot : inputSlots) { @@ -409,12 +410,13 @@ public class ViewsImpl implements Views { long availableAmount = invCount.get(hashFuzzy); if (availableAmount >= stack.getCount()) { invCount.put(hashFuzzy, availableAmount - stack.getCount()); + containsNonEmpty = true; slotsCraftable++; break; } } } - if (slotsCraftable == display.getRequiredEntries().size()) { + if (slotsCraftable == display.getRequiredEntries().size() && containsNonEmpty) { display.getOutputEntries().stream().flatMap(Collection::stream).collect(Collectors.toCollection(() -> craftables)); } } -- cgit From 30ba1f5975f4a20ea91fad8bf4bf0b740b0ad6fb Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 13 Apr 2022 20:29:14 +0800 Subject: Fix empty checks for argument types, Fix #673 --- .../shedaniel/rei/impl/client/search/argument/type/ModArgumentType.java | 2 +- .../rei/impl/client/search/argument/type/TextArgumentType.java | 2 +- .../rei/impl/client/search/argument/type/TooltipArgumentType.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'runtime/src/main/java') diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/ModArgumentType.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/ModArgumentType.java index 06e8d35fc..510aab2ac 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/ModArgumentType.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/ModArgumentType.java @@ -75,7 +75,7 @@ public final class ModArgumentType extends ArgumentType { @Override public boolean matches(String value, EntryStack stack, String searchText, Unit filterData) { - return !value.isEmpty() && value.contains(searchText); + return value.contains(searchText); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TooltipArgumentType.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TooltipArgumentType.java index 372214b8a..99e967456 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TooltipArgumentType.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TooltipArgumentType.java @@ -79,7 +79,7 @@ public final class TooltipArgumentType extends ArgumentType { public boolean matches(String tooltip, EntryStack stack, String searchText, Unit filterData) { //noinspection StringEquality if (tooltip == INVALID) return false; - return tooltip.isEmpty() || tooltip.contains(searchText); + return tooltip.contains(searchText); } @Nullable -- cgit