diff options
Diffstat (limited to 'runtime')
17 files changed, 163 insertions, 55 deletions
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..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 @@ -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,12 +57,14 @@ 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; 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; @@ -221,17 +226,46 @@ public class ClientHelperImpl implements ClientHelper { } @ApiStatus.Internal - public LongSet _getInventoryItemsTypes() { + public Long2LongMap _getInventoryItemsTypes() { + EntryDefinition<ItemStack> 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<ItemStack> 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 map; + } + + @ApiStatus.Internal + public Long2LongMap _getContainerItemsTypes() { + EntryDefinition<ItemStack> 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 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/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/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java index 76c7e269c..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 @@ -357,6 +357,11 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { } @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<FavoriteEntry> 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(); @@ -564,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; @@ -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/ScreenOverlayImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java index a34423cb0..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()) { + 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 59c23cca0..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 @@ -23,20 +23,16 @@ 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 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 it.unimi.dsi.fastutil.longs.Long2LongMap; +import it.unimi.dsi.fastutil.longs.Long2LongMaps; +import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; 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(); + private Long2LongMap containerStacks = new Long2LongOpenHashMap(); public void markDirty() { dirty = true; @@ -53,28 +49,32 @@ 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(); } - } + if (dirty) return; - public boolean matches(EntryStack<?> stack, Iterable<SlotAccessor> inputSlots) { - if (invStacks.contains(EntryStacks.hashFuzzy(stack))) return true; - if (stack.getType() != VanillaEntryTypes.ITEM) return false; - for (SlotAccessor slot : inputSlots) { - EntryStack<?> itemStack = EntryStacks.of(slot.getItemStack()); - if (!itemStack.isEmpty() && EntryStacks.equalsFuzzy(itemStack, stack)) { - return true; - } + try { + currentStacks = ClientHelperImpl.getInstance()._getContainerItemsTypes(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + currentStacks = Long2LongMaps.EMPTY_MAP; } - return false; + if (!currentStacks.equals(this.containerStacks)) { + containerStacks = currentStacks; + markDirty(); + } + } + + public Long2LongMap getInvStacks() { + return invStacks; } } 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); 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..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 @@ -71,14 +71,17 @@ 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; 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; @@ -601,6 +604,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<Double> size = null; @@ -654,6 +658,29 @@ 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 < 2000) { + return null; + } + + return _getTransferHandler(); + } + + @Nullable + private TransferHandler _getTransferHandler() { + lastCheckTime = Util.getMillis(); + for (List<Display> displays : DisplayRegistry.getInstance().getAll().values()) { for (Display display : displays) { if (ViewsImpl.isRecipesFor(getEntries(), display)) { @@ -674,7 +701,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)); } @@ -693,6 +720,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/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<Unit, ModArgumentType.@N if (pair.modName == null) { pair.modName = ClientHelper.getInstance().getModFromModId(pair.modId).toLowerCase(Locale.ROOT); } - return pair.modName.isEmpty() || pair.modName.contains(searchText); + return pair.modName.contains(searchText); } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TextArgumentType.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TextArgumentType.java index a3ee560f4..1342a2b0c 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TextArgumentType.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/search/argument/type/TextArgumentType.java @@ -61,7 +61,7 @@ public final class TextArgumentType extends ArgumentType<Unit, String> { @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<Unit, String> { 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 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..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 @@ -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,9 @@ 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; import me.shedaniel.rei.api.common.transfer.info.MenuInfoRegistry; @@ -55,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; @@ -373,20 +379,44 @@ public class ViewsImpl implements Views { Iterable<SlotAccessor> inputSlots = info != null ? info.getInputSlots(context.withDisplay(display)) : Collections.emptySet(); int slotsCraftable = 0; + boolean containsNonEmpty = false; List<EntryIngredient> requiredInput = display.getRequiredEntries(); + Long2LongMap invCount = new Long2LongOpenHashMap(CraftableFilter.INSTANCE.getInvStacks()); + for (SlotAccessor inputSlot : inputSlots) { + ItemStack stack = inputSlot.getItemStack(); + + EntryDefinition<ItemStack> 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++; continue; } for (EntryStack<?> slotPossible : slot) { - if (CraftableFilter.INSTANCE.matches(slotPossible, inputSlots)) { + if (slotPossible.getType() != VanillaEntryTypes.ITEM) continue; + ItemStack stack = slotPossible.castValue(); + long hashFuzzy = EntryStacks.hashFuzzy(slotPossible); + 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)); } } diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json index b96037482..6f8b677f0 100755 --- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json +++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json @@ -221,6 +221,7 @@ "config.roughlyenoughitems.search.asyncSearch": "Async Search:", "config.roughlyenoughitems.search.asyncSearchPartitionSize": "Async Search Partition Size:", "config.roughlyenoughitems.accessibility.useCompactTabs": "Compact Tabs:", + "config.roughlyenoughitems.accessibility.useCompactTabButtons": "Compact Tab Arrow Buttons:", "config.roughlyenoughitems.theme": "Appearance Theme:", "config.roughlyenoughitems.theme.dark": "Dark Theme", "config.roughlyenoughitems.theme.light": "Light Theme", diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/zh_cn.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/zh_cn.json index fd80fc89c..aec8aad67 100644 --- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/zh_cn.json +++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/zh_cn.json @@ -10,7 +10,7 @@ "text.rei.feedback": "想给REI的开发者提交什么建议吗?%s以反馈!", "text.rei.feedback.link": "点击此处填写Google问卷", "text.rei.support.me": "支持我继续让 REI 变得更好!", - "text.rei.support.me.desc": "作为 REI 的 Patreon 订阅会员,你可以下载适用于最新 Minecraft 快照的 REI 版本。\n你也可以通过租用 BisectHosting 服务器来支持我。", + "text.rei.support.me.desc": "作为 REI 的 Patreon 订阅会员,你可以下载适用于最新 Minecraft 快照的 REI 版本。\n你也可以通过租用 BisectHosting 服务器来支持我。\n\n%s\n%s", "text.rei.support.me.patreon": "在 Patreon 上支持我", "text.rei.support.me.bisect": "在 BisectHosting 上使用代码 SHEDANIEL", "text.rei.not.ful |
