From 3e59f3577465dc0ab2d2b19e8d00a80b0d50c5ec Mon Sep 17 00:00:00 2001 From: link-fgfgui Date: Sun, 15 Mar 2026 17:10:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B7=E6=9D=BF=E5=B7=A5=E5=85=B7=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E7=8E=B0=E5=9C=A8=E4=BC=9A=E6=98=BE=E7=A4=BA=E5=8A=A0?= =?UTF-8?q?=E5=B7=A5=E9=9C=80=E8=A6=81=E7=9A=84=E6=9C=BA=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在编码样板的悬停文本中,新增了对其加工机器的显示。 - 重构了代码,将与 EMI 相关的功能剥离到独立文件。 - 增加了对 EMI 是否存在的检查,以避免在未安装 EMI 时出现兼容性问题。 - 在非样板编码终端界面使用 EMI 配方填充时,将不会再向服务端发送配方 ID。 --- .../integration/jei/EmiRuntimeProxy.java | 7 ++ .../mixin/ExtendedAEPlusMixinPlugin.java | 7 ++ .../mixin/ae2/EncodedPatternItemMixin.java | 15 ++-- ...ContainerPatternEncodingTermMenuMixin.java | 24 ++---- .../mixin/emi/EmiRecipeFillerMixin.java | 5 +- .../util/RecipeFinderUtilEMI.java | 85 ++++++++++++------- .../util/RecipeFinderUtilJEI.java | 24 ++++++ .../assets/extendedae_plus/lang/en_us.json | 1 + .../assets/extendedae_plus/lang/zh_cn.json | 1 + 9 files changed, 109 insertions(+), 60 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/integration/jei/EmiRuntimeProxy.java create mode 100644 src/main/java/com/extendedae_plus/util/RecipeFinderUtilJEI.java diff --git a/src/main/java/com/extendedae_plus/integration/jei/EmiRuntimeProxy.java b/src/main/java/com/extendedae_plus/integration/jei/EmiRuntimeProxy.java new file mode 100644 index 0000000..28278f9 --- /dev/null +++ b/src/main/java/com/extendedae_plus/integration/jei/EmiRuntimeProxy.java @@ -0,0 +1,7 @@ +package com.extendedae_plus.integration.jei; + +import net.neoforged.fml.ModList; + +public final class EmiRuntimeProxy { + public static boolean isInstalled = ModList.get().isLoaded("emi"); +} diff --git a/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java b/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java index 1b56ca2..c341bd8 100644 --- a/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java +++ b/src/main/java/com/extendedae_plus/mixin/ExtendedAEPlusMixinPlugin.java @@ -22,6 +22,10 @@ public class ExtendedAEPlusMixinPlugin implements IMixinConfigPlugin { return isClassPresent("mezz.jei.api.IModPlugin"); } + private static boolean isEmiPresent() { + return isClassPresent("dev.emi.emi.api.EmiPlugin"); + } + private static boolean isAdvancedAePresent() { return isClassPresent("net.pedroksl.advanced_ae.AdvancedAE"); } @@ -51,6 +55,9 @@ public class ExtendedAEPlusMixinPlugin implements IMixinConfigPlugin { if (mixinClassName.startsWith("com.extendedae_plus.mixin.jei")) return false; if (mixinClassName.equals("com.extendedae_plus.mixin.ae2.menu.CraftConfirmMenuGoBackMixin")) return false; } + if (!isEmiPresent()){ + if (mixinClassName.startsWith("com.extendedae_plus.mixin.emi")) return false; + } if (!isAdvancedAePresent()) { if (mixinClassName.equals("com.extendedae_plus.mixin.advancedae.compat.PatternProviderLogicVirtualCompletionMixin")) { return false; diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/EncodedPatternItemMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/EncodedPatternItemMixin.java index 106ffd3..b73e1c0 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/EncodedPatternItemMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/EncodedPatternItemMixin.java @@ -2,10 +2,11 @@ package com.extendedae_plus.mixin.ae2; import appeng.crafting.pattern.EncodedPatternItem; import com.extendedae_plus.config.ModConfigs; +import com.extendedae_plus.integration.jei.EmiRuntimeProxy; +import com.extendedae_plus.util.RecipeFinderUtilEMI; import net.minecraft.ChatFormatting; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; @@ -19,7 +20,7 @@ import java.util.List; @Mixin(EncodedPatternItem.class) public class EncodedPatternItemMixin { - // 客户端:在 HoverText 显示样板的编码玩家 + // 客户端:在 HoverText 显示样板的编码玩家 和 加工机器 @Inject(method = "appendHoverText", at = @At("TAIL")) public void epp$appendHoverText(ItemStack stack, Item.TooltipContext context, List lines, TooltipFlag advancedTooltips, CallbackInfo ci){ if (ModConfigs.SHOW_ENCODER_PATTERN_PLAYER.get()) { @@ -29,11 +30,11 @@ public class EncodedPatternItemMixin { String name = tag.getString("encodePlayer"); lines.add(Component.translatable("extendedae_plus.pattern.hovertext.player", name).withStyle(ChatFormatting.GRAY)); } - if (tag.contains("recipeId")) { - String id = tag.getString("recipeId"); - ResourceLocation location = ResourceLocation.tryParse(id); - if (location == null) return; - lines.add(Component.translatable("extendedae_plus.pattern.hovertext.player", Component.translatable("recipe." + location.getNamespace() + "." + location.getPath())).withStyle(ChatFormatting.GRAY)); + if (EmiRuntimeProxy.isInstalled && tag.contains("recipeId")) { + Component c = RecipeFinderUtilEMI.getWorkstationComponentByRecipeId(tag.getString("recipeId")); + if (c != null) { + lines.add(Component.translatable("extendedae_plus.pattern.hovertext.workstation", c).withStyle(ChatFormatting.GRAY)); + } } } } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/menu/ContainerPatternEncodingTermMenuMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/menu/ContainerPatternEncodingTermMenuMixin.java index 9ff46b2..82853ba 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/menu/ContainerPatternEncodingTermMenuMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/menu/ContainerPatternEncodingTermMenuMixin.java @@ -1,18 +1,16 @@ package com.extendedae_plus.mixin.ae2.menu; import appeng.api.crafting.PatternDetailsHelper; -import appeng.api.stacks.GenericStack; import appeng.menu.me.items.PatternEncodingTermMenu; import appeng.menu.slot.RestrictedInputSlot; import appeng.parts.encoding.EncodingMode; import com.extendedae_plus.api.upload.IPatternEncodingIdSync; import com.extendedae_plus.api.upload.IPatternEncodingShiftUploadSync; +import com.extendedae_plus.integration.jei.EmiRuntimeProxy; import com.extendedae_plus.util.RecipeFinderUtilEMI; import com.extendedae_plus.util.uploadPattern.ExtendedAEPatternUploadUtil; import com.glodblock.github.glodium.network.packet.sync.ActionMap; import com.glodblock.github.glodium.network.packet.sync.IActionHolder; -import dev.emi.emi.api.recipe.EmiRecipe; -import dev.emi.emi.api.stack.EmiStack; import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; @@ -28,8 +26,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.List; - /** * 给 AE2 的 PatternEncodingTermMenu 增加一个通用动作持有者,实现接收 EPP 的 CGenericPacket 动作。 * 注册动作 "upload_to_matrix":仅上传“合成图样”到 ExtendedAE 装配矩阵。 @@ -155,21 +151,11 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo if (itemStack != null && !itemStack.isEmpty()) { CustomData.update(DataComponents.CUSTOM_DATA, itemStack, tag -> { tag.putString("encodePlayer", this.epp$player.getGameProfile().getName()); - if (this.eap$pendingRecipeIdUpload !=null) { - EmiRecipe recipe = RecipeFinderUtilEMI.findRecipeById(this.eap$pendingRecipeIdUpload); - // 检查样板与配方是否对应 - List stacks = PatternDetailsHelper.decodePattern(itemStack, this.epp$player.level()).getOutputs(); - if (stacks != null && recipe != null) { - List stacks2 = recipe.getOutputs(); - - List ids1 = stacks.stream().map(s -> s.what().getId()).sorted().toList(); - List ids2 = stacks2.stream().map(EmiStack::getId).sorted().toList(); - - if (ids1.equals(ids2)) { - tag.putString("recipeId", this.eap$pendingRecipeIdUpload.toString()); - } + if (EmiRuntimeProxy.isInstalled && this.eap$pendingRecipeIdUpload != null) { + if (RecipeFinderUtilEMI.isRecipeEqualToPattern(itemStack, this.eap$pendingRecipeIdUpload, this.epp$player.level())) { + tag.putString("recipeId", this.eap$pendingRecipeIdUpload.toString()); } - this.eap$pendingRecipeIdUpload =null; + this.eap$pendingRecipeIdUpload = null; } }); diff --git a/src/main/java/com/extendedae_plus/mixin/emi/EmiRecipeFillerMixin.java b/src/main/java/com/extendedae_plus/mixin/emi/EmiRecipeFillerMixin.java index 8cac166..0325546 100644 --- a/src/main/java/com/extendedae_plus/mixin/emi/EmiRecipeFillerMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/emi/EmiRecipeFillerMixin.java @@ -1,5 +1,6 @@ package com.extendedae_plus.mixin.emi; +import appeng.client.gui.me.items.PatternEncodingTermScreen; import com.extendedae_plus.network.upload.EncodeWithRecipeIdC2SPacket; import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.recipe.handler.EmiCraftContext; @@ -16,6 +17,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; public class EmiRecipeFillerMixin { @Inject(method = "performFill", at = @At("RETURN"), remap = false) private static void onPerformFill(EmiRecipe recipe, AbstractContainerScreen screen, EmiCraftContext.Type type, EmiCraftContext.Destination destination, int amount, CallbackInfoReturnable cir) { - PacketDistributor.sendToServer(new EncodeWithRecipeIdC2SPacket(recipe.getId())); + if (screen instanceof PatternEncodingTermScreen) { + PacketDistributor.sendToServer(new EncodeWithRecipeIdC2SPacket(recipe.getId())); + } } } diff --git a/src/main/java/com/extendedae_plus/util/RecipeFinderUtilEMI.java b/src/main/java/com/extendedae_plus/util/RecipeFinderUtilEMI.java index 783e6a4..f7293cf 100644 --- a/src/main/java/com/extendedae_plus/util/RecipeFinderUtilEMI.java +++ b/src/main/java/com/extendedae_plus/util/RecipeFinderUtilEMI.java @@ -1,52 +1,71 @@ package com.extendedae_plus.util; -import appeng.api.stacks.AEFluidKey; -import appeng.api.stacks.AEItemKey; +import appeng.api.crafting.IPatternDetails; +import appeng.api.crafting.PatternDetailsHelper; import appeng.api.stacks.GenericStack; -import com.extendedae_plus.integration.jei.JeiRuntimeProxy; +import com.mojang.logging.LogUtils; import dev.emi.emi.api.EmiApi; import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.recipe.EmiRecipeManager; -import mezz.jei.api.constants.RecipeTypes; -import mezz.jei.api.constants.VanillaTypes; -import mezz.jei.api.gui.IRecipeLayoutDrawable; -import mezz.jei.api.gui.ingredient.IRecipeSlotView; -import mezz.jei.api.gui.ingredient.IRecipeSlotsView; -import mezz.jei.api.helpers.IJeiHelpers; -import mezz.jei.api.ingredients.ITypedIngredient; -import mezz.jei.api.neoforge.NeoForgeTypes; -import mezz.jei.api.recipe.*; -import mezz.jei.api.recipe.category.IRecipeCategory; -import mezz.jei.api.runtime.IJeiRuntime; +import dev.emi.emi.api.stack.EmiIngredient; +import dev.emi.emi.api.stack.EmiStack; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.neoforged.neoforge.fluids.FluidStack; +import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.util.ArrayList; import java.util.List; -import java.util.Optional; /** - * 基于 EMI 查找配方,提取输入输出槽位与数量信息。 + * 基于 EMI 查找配方 */ public final class RecipeFinderUtilEMI { - private static final Logger LOGGER = LoggerFactory.getLogger("ExtendedAE Plus - RecipeFinder"); - static EmiRecipeManager manager = EmiApi.getRecipeManager(); - private RecipeFinderUtilEMI() { - } + private static final Logger LOGGER = LogUtils.getLogger(); + public static EmiRecipeManager manager = EmiApi.getRecipeManager(); - @Nullable - public static EmiRecipe findRecipeById(ResourceLocation location) { - return manager.getRecipe(location); - } - @Nullable - public static EmiRecipe findRecipeById(String id) { - return findRecipeById(ResourceLocation.parse(id)); - } + @Nullable + public static EmiRecipe findRecipeById(ResourceLocation location) { + return manager.getRecipe(location); + } + @Nullable + public static EmiRecipe findRecipeById(String id) { + return findRecipeById(ResourceLocation.parse(id)); + } + + @Nullable + public static Component getWorkstationComponentByRecipeId(String id) { + EmiRecipe recipe = RecipeFinderUtilEMI.findRecipeById(id); + if (recipe != null) { + List workstations = EmiApi.getRecipeManager().getWorkstations(recipe.getCategory()); + Component c; + if (!workstations.isEmpty()) { + c = workstations.getFirst().getEmiStacks().getFirst().getName(); + } else { + c = recipe.getCategory().getName(); + } + return c; + } + return null; + } + + public static boolean isRecipeEqualToPattern(ItemStack itemStack, ResourceLocation location, Level level) { + EmiRecipe recipe = findRecipeById(location); + // 检查样板与配方是否对应 + IPatternDetails pattern = PatternDetailsHelper.decodePattern(itemStack, level); + if (pattern != null) { + List stacks = pattern.getOutputs(); + if (stacks != null && recipe != null) { + List stacks2 = recipe.getOutputs(); + + List ids1 = stacks.stream().map(s -> s.what().getId()).sorted().toList(); + List ids2 = stacks2.stream().map(EmiStack::getId).sorted().toList(); + + return ids1.equals(ids2); + } + } + return false; + } } diff --git a/src/main/java/com/extendedae_plus/util/RecipeFinderUtilJEI.java b/src/main/java/com/extendedae_plus/util/RecipeFinderUtilJEI.java new file mode 100644 index 0000000..67be0ef --- /dev/null +++ b/src/main/java/com/extendedae_plus/util/RecipeFinderUtilJEI.java @@ -0,0 +1,24 @@ +package com.extendedae_plus.util; + +import com.mojang.logging.LogUtils; +import org.slf4j.Logger; + +/** + * 基于 EMI 查找配方,提取输入输出槽位与数量信息。 + */ +public final class RecipeFinderUtilJEI { + private static final Logger LOGGER = LogUtils.getLogger(); +// static EmiRecipeManager manager = EmiApi.getRecipeManager(); + private RecipeFinderUtilJEI() { + } +// +// @Nullable +// public static EmiRecipe findRecipeById(ResourceLocation location) { +// return manager.getRecipe(location); +// } +// @Nullable +// public static EmiRecipe findRecipeById(String id) { +// return findRecipeById(ResourceLocation.parse(id)); +// } + +} diff --git a/src/main/resources/assets/extendedae_plus/lang/en_us.json b/src/main/resources/assets/extendedae_plus/lang/en_us.json index c675a17..9eae554 100644 --- a/src/main/resources/assets/extendedae_plus/lang/en_us.json +++ b/src/main/resources/assets/extendedae_plus/lang/en_us.json @@ -71,6 +71,7 @@ "message.extendedae_plus.pattern_creation_failed": "Failed to create encoded pattern.", "message.extendedae_plus.no_network": "Unable to access AE network.", "extendedae_plus.pattern.hovertext.player": "Encoded by %s", + "extendedae_plus.pattern.hovertext.workstation": "Craftable by %s", "item.extendedae_plus.entity_speed_ticker": "Entity Accelerator", "screen.extendedae_plus.entity_speed_ticker.enable": "§c§lMachine Has Been Disabled", diff --git a/src/main/resources/assets/extendedae_plus/lang/zh_cn.json b/src/main/resources/assets/extendedae_plus/lang/zh_cn.json index 52d65eb..c161b28 100644 --- a/src/main/resources/assets/extendedae_plus/lang/zh_cn.json +++ b/src/main/resources/assets/extendedae_plus/lang/zh_cn.json @@ -71,6 +71,7 @@ "message.extendedae_plus.pattern_creation_failed": "创建编码样板失败。", "message.extendedae_plus.no_network": "无法访问 AE 网络。", "extendedae_plus.pattern.hovertext.player": "由 %s 编码", + "extendedae_plus.pattern.hovertext.workstation": "可由 %s 加工", "item.extendedae_plus.entity_speed_ticker": "实体加速器", "screen.extendedae_plus.entity_speed_ticker.enable": "§c§l机器已被禁用",