diff --git a/CHANGELOG.md b/CHANGELOG.md index 183e3900..319fd26b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,20 @@ ### Additions -* Added visibility options for the EMI config and recipe tree buttons -* EMI config button now is visible by default when toggled, to prevent people from accidentally hiding the mod without knowing how to undo it +* Search sidebar target can be configured ### Tweaks -* EMI visibility toast is now only shown when help level is verbose, due to other features preventing accidental hiding -* EMI config enum selection screen now is consistent with the rest of the config screen on later versions +* Notable performance improvements to ingredient construction +* Wrap packet sends with a check in later versions +* Improved accuracy of EMI reloading errors ### Fixes -* Fixed JEI dependency on 1.19 versions #780 -* Fixed stack default bind not toggling in recipe tree -* #689 +* Serialization of stacks with sizes other than 1 now serialize properly #803 +* Fix tag ingredient rendering in Fabulous #811 +* Fix stack batcher causing certain recipe tree categories to render at the wrong position #790 +* Populate item groupps in correct order (fixing duplicate items) #774 #603 #621 +* Pick which sidebar search targets #377 +* Fix search baking hang #800 +* Fix certain JEI integration breaking inconsistently on NeoForge + +### API +* Added experimental API to get query if stack is disabled from EmiRegistry +* Added experimental API to get EmiTooltipMetadata from composed tooltips being rendered for mod compatibility diff --git a/gradle.properties b/gradle.properties index a7a76602..0481480a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ minecraft_version=1.19.4 enabled_platforms=fabric,forge archives_base_name=emi -mod_version=1.1.18 +mod_version=1.1.19 maven_group=dev.emi architectury_version=4.9.83 diff --git a/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java b/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java index 22b861bb..52f0b632 100644 --- a/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java +++ b/xplat/src/main/java/dev/emi/emi/EmiRenderHelper.java @@ -166,6 +166,9 @@ public static void drawTooltip(Screen screen, EmiDrawContext context, List components, int x, int y, int maxWidth) { + if (components.isEmpty()) { + return; + } y = Math.max(16, y); // Some mods assume this list will be mutable, oblige them List mutable = Lists.newArrayList(); diff --git a/xplat/src/main/java/dev/emi/emi/api/EmiRegistry.java b/xplat/src/main/java/dev/emi/emi/api/EmiRegistry.java index f90440a3..d4469443 100644 --- a/xplat/src/main/java/dev/emi/emi/api/EmiRegistry.java +++ b/xplat/src/main/java/dev/emi/emi/api/EmiRegistry.java @@ -21,6 +21,14 @@ public interface EmiRegistry { + /** + * @return Whether the provided stack is disabled. + * Generally, this is not important to check before registering recipes, EMI will handle recipe hiding. + * There are certain cases where checking this and not including stacks in recipes is desired behavior, however. + */ + @ApiStatus.Experimental + boolean isStackDisabled(EmiIngredient stack); + /** * @return The vanilla recipe manager, for iterating recipe types. */ diff --git a/xplat/src/main/java/dev/emi/emi/api/render/EmiTooltipMetadata.java b/xplat/src/main/java/dev/emi/emi/api/render/EmiTooltipMetadata.java new file mode 100644 index 00000000..6310b371 --- /dev/null +++ b/xplat/src/main/java/dev/emi/emi/api/render/EmiTooltipMetadata.java @@ -0,0 +1,64 @@ +package dev.emi.emi.api.render; + +import java.util.List; + +import org.jetbrains.annotations.ApiStatus; + +import dev.emi.emi.api.recipe.EmiRecipe; +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.api.stack.EmiStack; +import dev.emi.emi.screen.tooltip.EmiTextTooltipWrapper; +import dev.emi.emi.screen.tooltip.RecipeTooltipComponent; +import net.minecraft.client.gui.tooltip.TooltipComponent; + +/** + * Represents metadata about tooltips that EMI creates. + * Context includes what stack is having its tooltip rendered. + * This information can be useful for mods modifying the display of tooltips. + */ +@ApiStatus.Experimental +public class EmiTooltipMetadata { + private static final EmiTooltipMetadata EMPTY = new EmiTooltipMetadata(EmiStack.EMPTY, null); + private final EmiIngredient stack; + private final EmiRecipe recipe; + + private EmiTooltipMetadata(EmiIngredient stack, EmiRecipe recipe) { + this.stack = stack; + this.recipe = recipe; + } + + /** + * @return The stack responsible for the tooltip, or {@link EmiStack#EMPTY} if not present. + */ + public EmiIngredient getStack() { + return stack; + } + + /** + * @return The recipe context for the tooltip, or {@code null} if not present. + */ + public EmiRecipe getRecipe() { + return recipe; + } + + /** + * Constructs an {@link EmiTooltipMetadata} object based on a list of tooltip components. + * This can be useful for retrieving otherwised erased information, like the {@link EmiIngredient}, from a tooltip. + */ + public static EmiTooltipMetadata of(List tooltip) { + if (!tooltip.isEmpty()) { + TooltipComponent title = tooltip.get(0); + EmiRecipe recipe = null; + for (TooltipComponent comp : tooltip) { + if (comp instanceof RecipeTooltipComponent rtc) { + recipe = rtc.getRecipe(); + break; + } + } + if (title instanceof EmiTextTooltipWrapper ettw && !ettw.stack.isEmpty()) { + return new EmiTooltipMetadata(ettw.stack, recipe); + } + } + return EMPTY; + } +} diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java index f3975eb6..e4e0da0e 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/FluidEmiStack.java @@ -6,10 +6,13 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +import com.google.common.collect.Lists; + import dev.emi.emi.EmiPort; import dev.emi.emi.api.render.EmiRender; import dev.emi.emi.api.render.EmiTooltipComponents; import dev.emi.emi.platform.EmiAgnos; +import dev.emi.emi.screen.tooltip.EmiTextTooltipWrapper; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.fluid.Fluid; @@ -82,7 +85,12 @@ public List getTooltipText() { @Override public List getTooltip() { - List list = getTooltipText().stream().map(EmiTooltipComponents::of).collect(Collectors.toList()); + List list = Lists.newArrayList(); + List text = getTooltipText(); + if (!text.isEmpty()) { + list.add(new EmiTextTooltipWrapper(this, EmiPort.ordered(text.get(0)))); + } + list.addAll(text.stream().skip(1).map(EmiTooltipComponents::of).collect(Collectors.toList())); if (amount > 1) { list.add(EmiTooltipComponents.getAmount(this)); } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java index ee2285ab..5d9a94e3 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/ItemEmiStack.java @@ -14,7 +14,9 @@ import dev.emi.emi.platform.EmiAgnos; import dev.emi.emi.runtime.EmiDrawContext; import dev.emi.emi.screen.StackBatcher.Batchable; +import dev.emi.emi.screen.tooltip.EmiTextTooltipWrapper; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.tooltip.OrderedTextTooltipComponent; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.item.TooltipContext; import net.minecraft.client.render.DiffuseLighting; @@ -158,6 +160,9 @@ public List getTooltip() { List list = Lists.newArrayList(); if (!isEmpty()) { list.addAll(EmiAgnos.getItemTooltip(stack)); + if (!list.isEmpty() && list.get(0) instanceof OrderedTextTooltipComponent ottc) { + list.set(0, new EmiTextTooltipWrapper(this, ottc)); + } //String namespace = EmiPort.getItemRegistry().getId(stack.getItem()).getNamespace(); //String mod = EmiUtil.getModName(namespace); //list.add(TooltipComponent.of(EmiLang.literal(mod, Formatting.BLUE, Formatting.ITALIC))); diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java index 0297c765..2ed2f42f 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/ListEmiIngredient.java @@ -8,6 +8,7 @@ import dev.emi.emi.EmiPort; import dev.emi.emi.api.render.EmiRender; +import dev.emi.emi.screen.tooltip.EmiTextTooltipWrapper; import dev.emi.emi.screen.tooltip.IngredientTooltipComponent; import net.minecraft.client.gui.tooltip.TooltipComponent; import net.minecraft.client.util.math.MatrixStack; @@ -99,7 +100,7 @@ public void render(MatrixStack matrices, int x, int y, float delta, int flags) { @Override public List getTooltip() { List tooltip = Lists.newArrayList(); - tooltip.add(TooltipComponent.of(EmiPort.ordered(EmiPort.translatable("tooltip.emi.accepts")))); + tooltip.add(new EmiTextTooltipWrapper(this, EmiPort.ordered(EmiPort.translatable("tooltip.emi.accepts")))); tooltip.add(new IngredientTooltipComponent(ingredients)); int item = (int) (System.currentTimeMillis() / 1000 % ingredients.size()); tooltip.addAll(ingredients.get(item).copy().setAmount(amount).getTooltip()); diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java index ec2a7f09..4ede395b 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/TagEmiIngredient.java @@ -16,6 +16,7 @@ import dev.emi.emi.mixin.accessor.ItemRendererAccessor; import dev.emi.emi.registry.EmiTags; import dev.emi.emi.runtime.EmiDrawContext; +import dev.emi.emi.screen.tooltip.EmiTextTooltipWrapper; import dev.emi.emi.screen.tooltip.RemainderTooltipComponent; import dev.emi.emi.screen.tooltip.TagTooltipComponent; import net.minecraft.client.MinecraftClient; @@ -134,7 +135,7 @@ public void render(MatrixStack matrices, int x, int y, float delta, int flags) { .invokeRenderBakedItemModel(model, ItemStack.EMPTY, LightmapTextureManager.MAX_LIGHT_COORDINATE, OverlayTexture.DEFAULT_UV, ms, ItemRenderer.getDirectItemGlintConsumer(immediate, - TexturedRenderLayers.getItemEntityTranslucentCull(), true, false)); + TexturedRenderLayers.getEntityTranslucentCull(), true, false)); immediate.draw(); if (!model.isSideLit()) { @@ -163,7 +164,7 @@ public void render(MatrixStack matrices, int x, int y, float delta, int flags) { @Override public List getTooltip() { List list = Lists.newArrayList(); - list.add(TooltipComponent.of(EmiPort.ordered(EmiTags.getTagName(key)))); + list.add(new EmiTextTooltipWrapper(this, EmiPort.ordered(EmiTags.getTagName(key)))); if (EmiUtil.showAdvancedTooltips()) { list.add(TooltipComponent.of(EmiPort.ordered(EmiPort.literal("#" + id, Formatting.DARK_GRAY)))); } diff --git a/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java b/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java index 91626969..ca69dbdb 100644 --- a/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java +++ b/xplat/src/main/java/dev/emi/emi/api/stack/serializer/EmiStackSerializer.java @@ -83,6 +83,9 @@ default JsonElement serialize(T stack) { JsonObject json = new JsonObject(); json.addProperty("type", getType()); json.addProperty("id", stack.getId().toString()); + if (stack.hasNbt()) { + json.addProperty("nbt", stack.getNbt().asString()); + } if (stack.getAmount() != 1) { json.addProperty("amount", stack.getAmount()); } diff --git a/xplat/src/main/java/dev/emi/emi/config/EmiConfig.java b/xplat/src/main/java/dev/emi/emi/config/EmiConfig.java index 1bfee424..74c31ea8 100644 --- a/xplat/src/main/java/dev/emi/emi/config/EmiConfig.java +++ b/xplat/src/main/java/dev/emi/emi/config/EmiConfig.java @@ -60,6 +60,10 @@ public class EmiConfig { public static IndexSource indexSource = IndexSource.CREATIVE; @ConfigGroup("general.search") + @Comment("Which sidebar should be searched using the search bar.") + @ConfigValue("general.search-sidebar") + public static SidebarSide searchSidebar = SidebarSide.RIGHT; + @Comment("Whether normal search queries should include the tooltip.") @ConfigValue("general.search-tooltip-by-default") public static boolean searchTooltipByDefault = true; diff --git a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiIngredientFilter.java b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiIngredientFilter.java index 58df5239..f082c72f 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiIngredientFilter.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiIngredientFilter.java @@ -6,6 +6,7 @@ import dev.emi.emi.api.EmiApi; import dev.emi.emi.jemi.JemiUtil; import dev.emi.emi.screen.EmiScreenManager; +import dev.emi.emi.screen.EmiScreenManager.SidebarPanel; import mezz.jei.api.ingredients.IIngredientType; import mezz.jei.api.runtime.IIngredientFilter; @@ -23,7 +24,11 @@ public String getFilterText() { @Override public List getFilteredIngredients(IIngredientType ingredientType) { - return EmiScreenManager.getSearchPanel().space.getStacks().stream() + SidebarPanel search = EmiScreenManager.getSearchPanel(); + if (search == null || search.space == null) { + return List.of(); + } + return search.space.getStacks().stream() .map(i -> JemiUtil.getTyped(i.getEmiStacks().get(0))) .filter(Optional::isPresent).map(Optional::get) .map(i -> i.getIngredient(ingredientType)) diff --git a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java index 9e9110d5..98a66599 100644 --- a/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java +++ b/xplat/src/main/java/dev/emi/emi/jemi/runtime/JemiRecipesGui.java @@ -16,6 +16,7 @@ import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.runtime.IRecipesGui; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; public class JemiRecipesGui implements IRecipesGui { @@ -59,4 +60,9 @@ public Optional getIngredientUnderMouse(IIngredientType ingredientType } return Optional.empty(); } + + //@Override + public Optional getParentScreen() { + return Optional.empty(); + } } diff --git a/xplat/src/main/java/dev/emi/emi/mixin/jei/PluginCallerMixin.java b/xplat/src/main/java/dev/emi/emi/mixin/jei/PluginCallerMixin.java index c8821b8d..e7fdde38 100644 --- a/xplat/src/main/java/dev/emi/emi/mixin/jei/PluginCallerMixin.java +++ b/xplat/src/main/java/dev/emi/emi/mixin/jei/PluginCallerMixin.java @@ -23,7 +23,7 @@ public class PluginCallerMixin { @Unique private static final Set SKIPPED = Sets.newHashSet( - EmiPort.id("jei", "minecraft"), EmiPort.id("jei", "gui"), EmiPort.id("jei", "fabric_gui"), EmiPort.id("jei", "forge_gui") + EmiPort.id("jei", "minecraft"), EmiPort.id("jei", "gui"), EmiPort.id("jei", "fabric_gui"), EmiPort.id("jei", "forge_gui"), EmiPort.id("jei", "neoforge_gui") ); @Unique private static final Set SKIPPED_MODS = JemiUtil.getHandledMods(); diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiExclusionAreas.java b/xplat/src/main/java/dev/emi/emi/registry/EmiExclusionAreas.java index 984e3b2f..ac873837 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiExclusionAreas.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiExclusionAreas.java @@ -31,7 +31,9 @@ public static List getExclusion(EmiScreenBase base) { // EMI buttons list.add(new Bounds(0, screen.height - 22, base.bounds().left(), 22)); // Search bar - list.add(new Bounds(EmiScreenManager.search.x - 1, EmiScreenManager.search.y - 1, EmiScreenManager.search.getWidth() + 2, EmiScreenManager.search.getHeight() + 2)); + if (EmiScreenManager.search.isVisible()) { + list.add(new Bounds(EmiScreenManager.search.x - 1, EmiScreenManager.search.y - 1, EmiScreenManager.search.getWidth() + 2, EmiScreenManager.search.getHeight() + 2)); + } try { if (fromClass.containsKey(screen.getClass())) { for (EmiExclusionArea exclusion : fromClass.get(screen.getClass())) { diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiRegistryImpl.java b/xplat/src/main/java/dev/emi/emi/registry/EmiRegistryImpl.java index b1f95ccc..87bb5d84 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiRegistryImpl.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiRegistryImpl.java @@ -18,6 +18,7 @@ import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.stack.serializer.EmiIngredientSerializer; +import dev.emi.emi.runtime.EmiHidden; import dev.emi.emi.runtime.EmiReloadLog; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; @@ -28,6 +29,11 @@ public class EmiRegistryImpl implements EmiRegistry { private static final MinecraftClient client = MinecraftClient.getInstance(); + @Override + public boolean isStackDisabled(EmiIngredient stack) { + return EmiHidden.isDisabled(stack); + } + @Override public RecipeManager getRecipeManager() { return client.world.getRecipeManager(); diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java b/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java index 4205ad67..3456ed68 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiStackList.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; @@ -80,7 +81,7 @@ public static void reload() { EmiLog.info("Reloading item groups on client thread..."); Map> itemGroupToStacksMap = client.submit(() -> { Map> map = new Reference2ReferenceOpenHashMap<>(); - for (ItemGroup group : ItemGroups.getGroups()) { + Consumer itemGroupConsumer = group -> { String groupName = "null"; try { groupName = group.getDisplayName().toString(); @@ -90,7 +91,12 @@ public static void reload() { EmiLog.error("Creative item group " + groupName + " threw while EMI was attempting to construct the index, items may be missing."); EmiLog.error(e); } - } + }; + List itemGroups = ItemGroups.getGroups(); + // Category item groups must be updated before non-category ones, otherwise the search group will + // read outdated item lists + itemGroups.stream().filter(g -> g.getType() == ItemGroup.Type.CATEGORY).forEach(itemGroupConsumer); + itemGroups.stream().filter(g -> g.getType() != ItemGroup.Type.CATEGORY).forEach(itemGroupConsumer); return map; }).join(); EmiLog.info("Reloading item groups on client thread took " + (System.currentTimeMillis() - groupReloadStart) + "ms"); diff --git a/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java b/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java index 78be07ba..b9f466c9 100644 --- a/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java +++ b/xplat/src/main/java/dev/emi/emi/registry/EmiTags.java @@ -106,7 +106,7 @@ public static EmiIngredient getIngredient(Class clazz, List sta if (keys != null) { for (TagKey key : keys) { List values = (List) TAG_CONTENTS.get(key); - map.keySet().removeAll(values); + values.forEach(map::remove); } } else { keys = Lists.newArrayList(); @@ -117,7 +117,7 @@ public static EmiIngredient getIngredient(Class clazz, List sta continue; } if (map.keySet().containsAll(values)) { - map.keySet().removeAll(values); + values.forEach(map::remove); keys.add(key); } if (map.isEmpty()) { diff --git a/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java b/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java index e0cf2554..fb7d2e4b 100644 --- a/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java +++ b/xplat/src/main/java/dev/emi/emi/runtime/EmiReloadManager.java @@ -138,7 +138,10 @@ public void run() { continue; } MinecraftClient client = MinecraftClient.getInstance(); - if (client.world.getRecipeManager() == null) { + if (client.world == null) { + EmiReloadLog.warn("World is null"); + break; + } else if (client.world.getRecipeManager() == null) { EmiReloadLog.warn("Recipe Manager is null"); break; } diff --git a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java index ccb6a87b..91dfe85b 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java +++ b/xplat/src/main/java/dev/emi/emi/screen/EmiScreenManager.java @@ -355,7 +355,7 @@ private static Bounds constrainBounds(List exclusion, Bounds bounds, Scr for (int i = 0; i < exclusion.size(); i++) { Bounds overlap = exclusion.get(i).overlap(bounds); if (!overlap.empty() && !bounds.empty()) { - if (overlap.top() < bounds.top() + ENTRY_SIZE + headerOffset || overlap.width() >= bounds.width() / 2 + if (overlap.top() < bounds.top() + ENTRY_SIZE + headerOffset || overlap.width() >= bounds.width() * 2 / 3 || overlap.height() >= bounds.height() / 3) { int widthFactor = overlap.width() * 10 / bounds.width(); int heightFactor = overlap.height() * 10 / bounds.height(); @@ -400,8 +400,9 @@ private static Bounds constrainBounds(List exclusion, Bounds bounds, Scr } public static void focusSearchSidebarType(SidebarType type) { - if (getSearchPanel().supportsType(type)) { - getSearchPanel().setType(type); + SidebarPanel search = getSearchPanel(); + if (search != null && search.supportsType(type)) { + search.setType(type); } } @@ -484,7 +485,7 @@ public static SidebarPanel getSearchPanel() { return panel; } } - return panels.get(1); + return null; } public static void toggleSidebarType(SidebarType type) { @@ -501,7 +502,11 @@ public static void toggleSidebarType(SidebarType type) { } public static List getSearchSource() { - return EmiSidebars.getStacks(getSearchPanel().getType()); + SidebarPanel search = getSearchPanel(); + if (search == null) { + return List.of(); + } + return EmiSidebars.getStacks(search.getType()); } public static EmiStackInteraction getHoveredStack(int mouseX, int mouseY, boolean notClick) { @@ -883,11 +888,18 @@ public static void addWidgets(Screen screen) { search.y = screen.height - 21; search.setWidth(160); } else { - search.x = panels.get(1).space.tx; - search.y = screen.height - 21; - search.setWidth(panels.get(1).space.tw * ENTRY_SIZE); + if (EmiConfig.searchSidebar == SidebarSide.RIGHT) { + search.x = panels.get(1).space.tx; + search.y = screen.height - 21; + search.setWidth(panels.get(1).space.tw * ENTRY_SIZE); + } else { + search.x = panels.get(0).space.tx; + search.y = screen.height - 21 - 21; + search.setWidth(panels.get(0).space.tw * ENTRY_SIZE); + } } EmiPort.focus(search, false); + search.setVisible(EmiConfig.searchSidebar != SidebarSide.NONE); emi.x = 2; emi.y = screen.height - 22; @@ -1542,7 +1554,7 @@ private void wrapPage() { } public boolean isSearch() { - return side == SidebarSide.RIGHT; + return side == EmiConfig.searchSidebar; } public void updateWidgetPosition() { diff --git a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java index 52d05228..10c26db4 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java +++ b/xplat/src/main/java/dev/emi/emi/screen/StackBatcher.java @@ -151,7 +151,7 @@ public void begin(int x, int y, int z) { public void render(Batchable batchable, MatrixStack matrices, int x, int y, float delta) { if (!populated) { try { - batchable.renderForBatch(batchable.isSideLit() ? imm : unlitFacade, matrices, x-this.x, -y+this.y, z, delta); + batchable.renderForBatch(batchable.isSideLit() ? imm : unlitFacade, matrices, x-this.x, y+this.y, z, delta); } catch (Throwable t) { if (EmiConfig.devMode) { EmiLog.error("Batchable threw exception during batched rendering. See log for info"); diff --git a/xplat/src/main/java/dev/emi/emi/screen/tooltip/EmiTextTooltipWrapper.java b/xplat/src/main/java/dev/emi/emi/screen/tooltip/EmiTextTooltipWrapper.java new file mode 100644 index 00000000..60b84cdd --- /dev/null +++ b/xplat/src/main/java/dev/emi/emi/screen/tooltip/EmiTextTooltipWrapper.java @@ -0,0 +1,20 @@ +package dev.emi.emi.screen.tooltip; + +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.mixin.accessor.OrderedTextTooltipComponentAccessor; +import net.minecraft.client.gui.tooltip.OrderedTextTooltipComponent; +import net.minecraft.text.OrderedText; + +public class EmiTextTooltipWrapper extends OrderedTextTooltipComponent { + public EmiIngredient stack; + + public EmiTextTooltipWrapper(EmiIngredient stack, OrderedText text) { + super(text); + this.stack = stack; + } + + public EmiTextTooltipWrapper(EmiIngredient stack, OrderedTextTooltipComponent original) { + super(((OrderedTextTooltipComponentAccessor) original).getText()); + this.stack = stack; + } +} diff --git a/xplat/src/main/java/dev/emi/emi/screen/tooltip/RecipeTooltipComponent.java b/xplat/src/main/java/dev/emi/emi/screen/tooltip/RecipeTooltipComponent.java index fe80abe6..9cf13c54 100644 --- a/xplat/src/main/java/dev/emi/emi/screen/tooltip/RecipeTooltipComponent.java +++ b/xplat/src/main/java/dev/emi/emi/screen/tooltip/RecipeTooltipComponent.java @@ -30,6 +30,10 @@ public RecipeTooltipComponent(EmiRecipe recipe, boolean showMissing) { } } + public EmiRecipe getRecipe() { + return recipe; + } + @Override public int getHeight() { return height; diff --git a/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java b/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java index c2b92561..7df142cb 100644 --- a/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java +++ b/xplat/src/main/java/dev/emi/emi/search/EmiSearch.java @@ -93,7 +93,7 @@ public static void bake() { } } catch (Exception e) { EmiLog.error("EMI caught an exception while baking search for " + stack); - e.printStackTrace(); + EmiLog.error(e); } } for (Supplier supplier : EmiData.aliases) { diff --git a/xplat/src/main/resources/assets/emi/lang/en_us.json b/xplat/src/main/resources/assets/emi/lang/en_us.json index ecb4c042..baa4bbfd 100644 --- a/xplat/src/main/resources/assets/emi/lang/en_us.json +++ b/xplat/src/main/resources/assets/emi/lang/en_us.json @@ -98,6 +98,7 @@ "config.emi.general.cheat_mode": "Cheat Mode", "config.emi.general.help_level": "Help Level", "config.emi.general.index_source": "Index Source", + "config.emi.general.search_sidebar": "Search Sidebar", "config.emi.general.search_tooltip_by_default": "Search Tooltip by Default", "config.emi.general.search_mod_name_by_default": "Search Mod Name by Default", "config.emi.general.search_tags_by_default": "Search Tags by Default", diff --git a/xplat/src/main/resources/assets/emi/lang/ru_ru.json b/xplat/src/main/resources/assets/emi/lang/ru_ru.json index d29e8597..7b2904a8 100644 --- a/xplat/src/main/resources/assets/emi/lang/ru_ru.json +++ b/xplat/src/main/resources/assets/emi/lang/ru_ru.json @@ -73,9 +73,13 @@ "emi.effect_location.right_compressed": "Справа (сжатые)", "emi.effect_location.left": "Слева", "emi.effect_location.right": "Справа", + "emi.effect_location.hidden": "Скрыты", "emi.recipe_book_action.default": "По умолчанию", "emi.recipe_book_action.toggle_craftables": "Переключение создаваемых", "emi.recipe_book_action.toggle_visibility": "Переключение видимости", + "emi.button_visibility.auto": "Автоматически", + "emi.button_visibility.shown": "Показана", + "emi.button_visibility.hidden": "Скрыта", "config.emi.group.general": "Основное", "config.emi.group.general.search": "Поиск", @@ -149,6 +153,8 @@ "config.emi.ui.miscraft_prevention": "Предотвращение случайных крафтов", "config.emi.ui.fluid_unit": "Единицы измерения жидкостей", "config.emi.ui.show_cost_per_batch": "Показывать цену за несколько", + "config.emi.ui.emi_config_button_visibility": "Видимость кнопки настроек EMI", + "config.emi.ui.recipe_tree_button_visibility": "Видимость кнопки дерева рецептов", "config.emi.ui.recipe_default_button": "Сделать стандартным", "config.emi.ui.recipe_tree_button": "Открыть дерево", "config.emi.ui.recipe_fill_button": "Заполнить рецепт", @@ -266,7 +272,8 @@ "emi.dev.suggest_id": "Используйте синтетический идентификатор §7[пространство_имён]§b:/§7[путь]§r как\n§7%s§b:/§7%s§r", "emi.dev.null_input_or_output": "Входные или выходные данные рецепта равны §7нулю§r\nИспользуйте пустой список без каких-либо входных или выходных данных\nИспользуйте §7EmiStack.EMPTY§r для представления пустой стопки", "emi.dev.no_output_slots": "Слоты рецепта не содержат никаких выходных данных\nВызовите §7SlotWidget.recipeContext(this)§r для выходных данных§r", - + "emi.dev.synthetic_nag_explanation": "Не удалось найти идентификатор рецепта в менеджере рецептов, но он не является синтетическим\n§7%s§r\nЕсли рецепт не соответствует рецепту JSON, основанному на данных, он должен использовать синтетический идентификатор", + "emi.chess.piece.white_pawn": "Белая пешка", "emi.chess.piece.white_rook": "Белая ладья", "emi.chess.piece.white_knight": "Белый конь", diff --git a/xplat/src/main/resources/assets/emi/lang/zh_cn.json b/xplat/src/main/resources/assets/emi/lang/zh_cn.json index 82762a74..5fc0a9fa 100644 --- a/xplat/src/main/resources/assets/emi/lang/zh_cn.json +++ b/xplat/src/main/resources/assets/emi/lang/zh_cn.json @@ -99,6 +99,9 @@ "emi.recipe_book_action.default": "原版行为", "emi.recipe_book_action.toggle_craftables": "侧边栏切换至可合成物品", "emi.recipe_book_action.toggle_visibility": "显示/隐藏EMI界面", + "emi.button_visibility.auto": "自动", + "emi.button_visibility.shown": "显示", + "emi.button_visibility.hidden": "隐藏", "config.emi.group.general": "基础", "config.emi.group.general.search": "搜索", @@ -220,6 +223,10 @@ "config.emi.tooltip.ui.fluid_unit": "更改EMI使用的流体单位", "config.emi.ui.show_cost_per_batch": "显示制作一份产物的消耗", "config.emi.tooltip.ui.show_cost_per_batch": "光标悬停于配方产物上时\n显示制作一份产物的原材料消耗", + "config.emi.ui.emi_config_button_visibility": "EMI设置按钮可见性", + "config.emi.tooltip.ui.emi_config_button_visibility": "是否显示左下角的EMI设置按钮", + "config.emi.ui.recipe_tree_button_visibility": "配方树按钮可见性", + "config.emi.tooltip.ui.recipe_tree_button_visibility": "是否显示左下角的配方树按钮", "config.emi.ui.recipe_default_button": "默认配方按钮", "config.emi.tooltip.ui.recipe_default_button": "在配方右侧显示设为默认配方按钮", "config.emi.ui.recipe_tree_button": "配方树按钮", @@ -244,6 +251,7 @@ "config.emi.dev.show_recipe_ids": "显示配方ID", "config.emi.tooltip.dev.show_recipe_ids": "光标悬停于配方产物时显示配方的EMI ID", "config.emi.dev.show_recipe_decorators": "显示配方装饰", + "config.emi.tooltip.dev.show_recipe_decorators": "在其他模组添加的配方中显示额外小工具\n这通常用于模组开发和测试兼容性,\n对普通玩家并无大用", "config.emi.dev.highlight_defaulted": "高亮有默认配方的物品", "config.emi.tooltip.dev.highlight_defaulted": "高亮物品索引中设置了默认配方的物品", "config.emi.dev.highlight_exclusion_areas": "高亮禁止区", @@ -289,7 +297,7 @@ "emi.too_small": "合成表过小,无法填充配方", "emi.favorite_recipe": "按 %s 收藏物品", "emi.resolve.resolve": "按 %s 使用本配方", - "emi.resolve.default": "按 %s 设为默认配方", + "emi.resolve.default": "按 %s 设为/取消默认配方", "emi.page": "第 %s 页,共 %s 页", "emi.page.short": "%s/%s", "emi.total_cost": "总耗材",