diff --git a/build.gradle b/build.gradle index 00e8bf2..2875566 100644 --- a/build.gradle +++ b/build.gradle @@ -60,6 +60,15 @@ repositories { } maven { url "https://repo.spongepowered.org/maven" } maven { url "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/" } + maven { // Registrate + url = "https://maven.tterrag.com/" + content { + // need to be specific here due to version overlaps + includeGroup("com.jozufozu.flywheel") + includeGroup("com.tterrag.registrate") + includeGroup("com.simibubi.create") + } + } } dependencies { @@ -70,7 +79,7 @@ dependencies { //exendedae前置 modImplementation "curse.maven:glodium-957920:${glodium_version}" //extendedAE - modImplementation files('libs/ExtendedAE-1.20-1.4.2-forge.jar') + modImplementation files('libs/ExtendedAE-1.20-1.4.7-forge.jar') modRuntimeOnly fileTree(dir: 'libs', includes: ['*.jar']) //ae2 @@ -87,9 +96,19 @@ dependencies { modCompileOnly "curse.maven:jade-324717:${jade_version}" // GregTech - modCompileOnly "curse.maven:gregtechceu-modern-890405:${gregtech_version}" - modCompileOnly "curse.maven:ldlib-626676:${ldlib_version}" - modCompileOnly files('libs/gtlcore-1.2.2.3-fix6.jar') + modImplementation "curse.maven:gregtechceu-modern-890405:${gregtech_version}" + modImplementation "curse.maven:ldlib-626676:5775541" + modImplementation files('libs/gtlcore-1.2.2.4-fix8.jar') + modImplementation("dev:gtmthings-1.3.5.b") + modImplementation("dev:resourcefullib-forge-1.20.1-2.1.29") + modImplementation("dev:resourcefulconfig-forge-1.20.1-2.1.3") + modImplementation("dev:botarium-forge-1.20.1-2.3.4") + modImplementation("dev:ad_astra-forge-1.20.1-1.15.20") + implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.2.0")) + implementation(include("io.github.llamalad7:mixinextras-forge:0.2.0")) + modImplementation("com.tterrag.registrate:Registrate:MC1.20-1.3.11") + modImplementation("curse.maven:kubejs-238086:5454840") + modImplementation("curse.maven:rhino-416294:6186971") //curios modRuntimeOnly "curse.maven:curios-309927:${curios_version}" @@ -97,7 +116,7 @@ dependencies { // Runtime test modRuntimeOnly "curse.maven:curios-309927:${curios_version}" - modRuntimeOnly "curse.maven:jade-324717:${jade_version}" + modImplementation "curse.maven:jade-324717:5339264" modRuntimeOnly "curse.maven:architectury-api-419699:${architectury_version}" modRuntimeOnly "curse.maven:applied-energistics-2-wireless-terminals-459929:${wireless_terminals_version}" modRuntimeOnly "mezz.jei:jei-${minecraft_version}-forge:${jei_version}" @@ -106,9 +125,14 @@ dependencies { //jec modCompileOnly "curse.maven:just-enough-characters-250702:6680042" + //拼音搜索 + modRuntimeOnly("dev:jecharacters-1.20.1-forge-4.5.11-dev-shadow") + //输入法冲突 + modRuntimeOnly("curse.maven:cloth-config-348521:5729105") + modRuntimeOnly("curse.maven:IMBlocker-483760:6922546") //mae2 - // modRuntimeOnly "curse.maven:modern-ae2-additions-1028068:6827727" + // modRuntimeOnly "curse.maven:modern-ae2-additions-1028068:6827727" modCompileOnly "curse.maven:modern-ae2-additions-1028068:6827727" //aea @@ -126,8 +150,10 @@ dependencies { //ftbteams modCompileOnly "curse.maven:ftb-teams-forge-404468:6130786" modCompileOnly "curse.maven:ftb-library-forge-404465:6807424" + modCompileOnly "curse.maven:ftb-chunk-forge-314906:6431735" modRuntimeOnly "curse.maven:ftb-teams-forge-404468:6130786" modRuntimeOnly "curse.maven:ftb-library-forge-404465:6807424" + modRuntimeOnly "curse.maven:ftb-chunk-forge-314906:6431735" } compileJava { diff --git a/libs/ExtendedAE-1.20-1.1.12-forge.jar b/libs/ExtendedAE-1.20-1.1.12-forge.jar deleted file mode 100644 index 067194a..0000000 Binary files a/libs/ExtendedAE-1.20-1.1.12-forge.jar and /dev/null differ diff --git a/libs/ExtendedAE-1.20-1.4.7-forge.jar b/libs/ExtendedAE-1.20-1.4.7-forge.jar new file mode 100644 index 0000000..6cd5e65 Binary files /dev/null and b/libs/ExtendedAE-1.20-1.4.7-forge.jar differ diff --git a/libs/ad_astra-forge-1.20.1-1.15.20.jar b/libs/ad_astra-forge-1.20.1-1.15.20.jar new file mode 100644 index 0000000..b0210cb Binary files /dev/null and b/libs/ad_astra-forge-1.20.1-1.15.20.jar differ diff --git a/libs/botarium-forge-1.20.1-2.3.4.jar b/libs/botarium-forge-1.20.1-2.3.4.jar new file mode 100644 index 0000000..506c8d1 Binary files /dev/null and b/libs/botarium-forge-1.20.1-2.3.4.jar differ diff --git a/libs/gtlcore-1.2.2.1-fix5.jar b/libs/gtlcore-1.2.2.4-fix8.jar similarity index 85% rename from libs/gtlcore-1.2.2.1-fix5.jar rename to libs/gtlcore-1.2.2.4-fix8.jar index f5504ee..245fe48 100644 Binary files a/libs/gtlcore-1.2.2.1-fix5.jar and b/libs/gtlcore-1.2.2.4-fix8.jar differ diff --git a/libs/gtmthings-1.3.5.b.jar b/libs/gtmthings-1.3.5.b.jar new file mode 100644 index 0000000..374ae1a Binary files /dev/null and b/libs/gtmthings-1.3.5.b.jar differ diff --git a/libs/jecharacters-1.20.1-forge-4.5.11-dev-shadow.jar b/libs/jecharacters-1.20.1-forge-4.5.11-dev-shadow.jar new file mode 100644 index 0000000..66a71ab Binary files /dev/null and b/libs/jecharacters-1.20.1-forge-4.5.11-dev-shadow.jar differ diff --git a/libs/resourcefulconfig-forge-1.20.1-2.1.3.jar b/libs/resourcefulconfig-forge-1.20.1-2.1.3.jar new file mode 100644 index 0000000..4326a1d Binary files /dev/null and b/libs/resourcefulconfig-forge-1.20.1-2.1.3.jar differ diff --git a/libs/resourcefullib-forge-1.20.1-2.1.29.jar b/libs/resourcefullib-forge-1.20.1-2.1.29.jar new file mode 100644 index 0000000..dd8e169 Binary files /dev/null and b/libs/resourcefullib-forge-1.20.1-2.1.29.jar differ diff --git a/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternTerminalMixin.java b/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternTerminalMixin.java index af13e76..3e2da46 100644 --- a/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternTerminalMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/extendedae/client/gui/GuiExPatternTerminalMixin.java @@ -67,10 +67,14 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen @Unique private boolean eap$debugLoggedOnce = false; - @Shadow(remap = false) private AETextField searchOutField; - @Shadow(remap = false) private AETextField searchInField; - @Shadow(remap = false) private Set matchedStack; - @Shadow(remap = false) private Set matchedProvider; + @Shadow(remap = false) + private AETextField searchOutField; + @Shadow(remap = false) + private AETextField searchInField; + @Shadow(remap = false) + private Set matchedStack; + @Shadow(remap = false) + private Set matchedProvider; public GuiExPatternTerminalMixin(AEBaseMenu menu, Inventory playerInventory, Component title, ScreenStyle style) { super(menu, playerInventory, title, style); @@ -137,13 +141,15 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen private void eap$quickUploadPattern(int playerSlotIndex) { if (this.minecraft.player != null) { // 获取要上传的物品 - ItemStack itemToUpload = this.minecraft.player.getInventory().getItem(playerSlotIndex); + ItemStack itemToUpload = this.minecraft.player.getInventory() + .getItem(playerSlotIndex); if (!itemToUpload.isEmpty() && PatternDetailsHelper.isEncodedPattern(itemToUpload)) { // 通过反射调用 ExtendedAE 的网络发送(软依赖) try { Class EPPNetworkHandlerClass = Class.forName("com.glodblock.github.extendedae.network.EPPNetworkHandler"); - Object handlerInstance = EPPNetworkHandlerClass.getField("INSTANCE").get(null); + Object handlerInstance = EPPNetworkHandlerClass.getField("INSTANCE") + .get(null); Class packetClass = Class.forName("com.glodblock.github.glodium.network.packet.CGenericPacket"); Constructor constructor = packetClass.getConstructor(String.class, Object[].class); @@ -193,17 +199,23 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen Object byGroup = byGroupField.get(this); // HashMultimap Object headerRow = rows.get(rowIndex); - var groupField = headerRow.getClass().getDeclaredField("group"); + var groupField = headerRow.getClass() + .getDeclaredField("group"); groupField.setAccessible(true); Object group = groupField.get(headerRow); // 调用 byGroup.get(group),再取第一个元素 - Collection containers = (Collection) byGroup.getClass().getMethod("get", Object.class).invoke(byGroup, group); + Collection containers = (Collection) byGroup.getClass() + .getMethod("get", Object.class) + .invoke(byGroup, group); if (containers == null || containers.isEmpty()) { return; } - Object firstRecord = containers.iterator().next(); // PatternContainerRecord - long serverId = (long) firstRecord.getClass().getMethod("getServerId").invoke(firstRecord); + Object firstRecord = containers.iterator() + .next(); // PatternContainerRecord + long serverId = (long) firstRecord.getClass() + .getMethod("getServerId") + .invoke(firstRecord); // 通过 infoMap 获取位置信息 var infoMapField = cls.getDeclaredField("infoMap"); @@ -220,13 +232,28 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen } // PatternProviderInfo record: pos(), face(), playerWorld() - Object pos = info.getClass().getMethod("pos").invoke(info); - Object face = info.getClass().getMethod("face").invoke(info); // 可能为 null(方块型供应器) - Object playerWorld = info.getClass().getMethod("playerWorld").invoke(info); + Object pos = info.getClass() + .getMethod("pos") + .invoke(info); + Object face = info.getClass() + .getMethod("face") + .invoke(info); // 可能为 null(方块型供应器) + Object playerWorld; + try { + playerWorld = info.getClass() + .getMethod("playerWorld") + .invoke(info); + } catch (Throwable t) { + playerWorld = info.getClass() + .getMethod("world") + .invoke(info); + } + // 避免对 MC 类进行反射,使用强制类型转换后直接调用方法(由 Forge 运行时重映射保证) long posLong = ((BlockPos) pos).asLong(); - String dimStr = ((ResourceKey) playerWorld).location().toString(); + String dimStr = ((ResourceKey) playerWorld).location() + .toString(); int faceOrd = -1; if (face != null) { faceOrd = ((Direction) face).ordinal(); @@ -271,11 +298,14 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen Method refreshMethod = null; try { // 先尝试在当前类中查找 - refreshMethod = this.getClass().getDeclaredMethod("refreshList"); + refreshMethod = this.getClass() + .getDeclaredMethod("refreshList"); } catch (NoSuchMethodException e1) { // 如果当前类没有,尝试在父类中查找 try { - refreshMethod = this.getClass().getSuperclass().getDeclaredMethod("refreshList"); + refreshMethod = this.getClass() + .getSuperclass() + .getDeclaredMethod("refreshList"); } catch (NoSuchMethodException e2) { throw e2; } @@ -309,17 +339,21 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen private void eap$onResize(Minecraft mc, int width, int height, CallbackInfo ci) { try { // 移除并清理按钮,避免旧位置残留 - this.eap$openUIButtons.values().forEach(this::removeWidget); + this.eap$openUIButtons.values() + .forEach(this::removeWidget); this.eap$openUIButtons.clear(); // 重置一次滚动条,避免可见行/偏移在缩放后与 UI 尺寸不一致 try { Method resetScrollbarMethod = null; try { - resetScrollbarMethod = this.getClass().getDeclaredMethod("resetScrollbar"); + resetScrollbarMethod = this.getClass() + .getDeclaredMethod("resetScrollbar"); } catch (NoSuchMethodException e1) { try { - resetScrollbarMethod = this.getClass().getSuperclass().getDeclaredMethod("resetScrollbar"); + resetScrollbarMethod = this.getClass() + .getSuperclass() + .getDeclaredMethod("resetScrollbar"); } catch (NoSuchMethodException e2) { resetScrollbarMethod = null; } @@ -335,10 +369,13 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen try { Method refreshMethod = null; try { - refreshMethod = this.getClass().getDeclaredMethod("refreshList"); + refreshMethod = this.getClass() + .getDeclaredMethod("refreshList"); } catch (NoSuchMethodException e1) { try { - refreshMethod = this.getClass().getSuperclass().getDeclaredMethod("refreshList"); + refreshMethod = this.getClass() + .getSuperclass() + .getDeclaredMethod("refreshList"); } catch (NoSuchMethodException e2) { refreshMethod = null; } @@ -359,7 +396,8 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen @Inject(method = "init", at = @At("TAIL"), remap = false, require = 0) private void eap$onInit(CallbackInfo ci) { // 清理旧的打开UI按钮 - this.eap$openUIButtons.values().forEach(this::removeWidget); + this.eap$openUIButtons.values() + .forEach(this::removeWidget); this.eap$openUIButtons.clear(); } @@ -372,7 +410,8 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen ))); } // 清理旧的打开UI按钮 - this.eap$openUIButtons.values().forEach(this::removeWidget); + this.eap$openUIButtons.values() + .forEach(this::removeWidget); this.eap$openUIButtons.clear(); } @@ -386,11 +425,14 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen java.lang.reflect.Field rowsField = null; try { // 先尝试在当前类中查找 - rowsField = this.getClass().getDeclaredField("rows"); + rowsField = this.getClass() + .getDeclaredField("rows"); } catch (NoSuchFieldException e1) { // 如果当前类没有,尝试在父类中查找 try { - rowsField = this.getClass().getSuperclass().getDeclaredField("rows"); + rowsField = this.getClass() + .getSuperclass() + .getDeclaredField("rows"); } catch (NoSuchFieldException e2) { throw e2; } @@ -402,11 +444,14 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen java.lang.reflect.Field highlightBtnsField = null; try { // 先尝试在当前类中查找 - highlightBtnsField = this.getClass().getDeclaredField("highlightBtns"); + highlightBtnsField = this.getClass() + .getDeclaredField("highlightBtns"); } catch (NoSuchFieldException e1) { // 如果当前类没有,尝试在父类中查找 try { - highlightBtnsField = this.getClass().getSuperclass().getDeclaredField("highlightBtns"); + highlightBtnsField = this.getClass() + .getSuperclass() + .getDeclaredField("highlightBtns"); } catch (NoSuchFieldException e2) { throw e2; } @@ -422,7 +467,8 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen // 移除所有SlotsRow,只保留GroupHeaderRow,同时重新映射高亮按钮索引 for (int i = 0; i < rows.size(); i++) { Object row = rows.get(i); - String className = row.getClass().getSimpleName(); + String className = row.getClass() + .getSimpleName(); if (className.equals("GroupHeaderRow")) { // 保留GroupHeaderRow,并重新映射对应的高亮按钮 @@ -459,11 +505,14 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen Method resetScrollbarMethod = null; try { // 先尝试在当前类中查找 - resetScrollbarMethod = this.getClass().getDeclaredMethod("resetScrollbar"); + resetScrollbarMethod = this.getClass() + .getDeclaredMethod("resetScrollbar"); } catch (NoSuchMethodException e1) { // 如果当前类没有,尝试在父类中查找 try { - resetScrollbarMethod = this.getClass().getSuperclass().getDeclaredMethod("resetScrollbar"); + resetScrollbarMethod = this.getClass() + .getSuperclass() + .getDeclaredMethod("resetScrollbar"); } catch (NoSuchMethodException e2) { throw e2; } @@ -485,7 +534,8 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen // 使用 Accessor 获取必要的字段,避免反射失败 GuiExPatternTerminalAccessor acc = (GuiExPatternTerminalAccessor) this; java.util.ArrayList rows = acc.getRows(); - int currentScroll = acc.getScrollbar().getCurrentScroll(); + int currentScroll = acc.getScrollbar() + .getCurrentScroll(); // 直接引用目标类以获取其静态常量 Class cls = GuiExPatternTerminal.class; @@ -511,7 +561,9 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen continue; } Object row = rows.get(rowIndex); - if (!row.getClass().getSimpleName().equals("GroupHeaderRow")) { + if (!row.getClass() + .getSimpleName() + .equals("GroupHeaderRow")) { continue; } @@ -522,8 +574,10 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen Button btn = eap$openUIButtons.get(rowIndex); if (btn == null) { btn = Button.builder(Component.literal("UI"), (b) -> { - eap$tryOpenProviderUI(rowIndex); - }).size(14, 12).build(); + eap$tryOpenProviderUI(rowIndex); + }) + .size(14, 12) + .build(); btn.setTooltip(Tooltip.create(Component.literal("打开该供应器目标容器的界面"))); eap$openUIButtons.put(rowIndex, btn); this.addRenderableWidget(btn); @@ -538,8 +592,10 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen // 原有的搜索高亮逻辑 // 仅当任一搜索框非空时绘制叠加层(与原版行为保持一致) - boolean searchActive = (this.searchOutField != null && !this.searchOutField.getValue().isEmpty()) - || (this.searchInField != null && !this.searchInField.getValue().isEmpty()); + boolean searchActive = (this.searchOutField != null && !this.searchOutField.getValue() + .isEmpty()) + || (this.searchInField != null && !this.searchInField.getValue() + .isEmpty()); if (!searchActive) { return; } diff --git a/src/main/java/com/extendedae_plus/network/CraftingMonitorOpenProviderC2SPacket.java b/src/main/java/com/extendedae_plus/network/CraftingMonitorOpenProviderC2SPacket.java deleted file mode 100644 index d73002a..0000000 --- a/src/main/java/com/extendedae_plus/network/CraftingMonitorOpenProviderC2SPacket.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.extendedae_plus.network; - -import appeng.api.crafting.IPatternDetails; -import appeng.api.networking.IGrid; -import appeng.api.networking.security.IActionHost; -import appeng.api.stacks.AEKey; -import appeng.helpers.patternprovider.PatternProviderLogic; -import appeng.helpers.patternprovider.PatternProviderLogicHost; -import appeng.me.service.CraftingService; -import appeng.menu.AEBaseMenu; -import appeng.menu.locator.MenuLocators; -import appeng.menu.me.crafting.CraftingCPUMenu; -import appeng.parts.AEBasePart; -import com.extendedae_plus.init.ModNetwork; -import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor; -import com.extendedae_plus.network.provider.SetProviderPageS2CPacket; -import com.extendedae_plus.util.PatternProviderDataUtil; -import com.glodblock.github.extendedae.util.FCClientUtil; -import com.glodblock.github.glodium.util.GlodUtil; -import com.gregtechceu.gtceu.api.gui.factory.MachineUIFactory; -import com.gregtechceu.gtceu.api.machine.MetaMachine; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkEvent; - -import java.util.Collection; -import java.util.Objects; -import java.util.function.Supplier; - -import static com.glodblock.github.extendedae.client.render.EAEHighlightHandler.highlight; - -/** - * 客户端从 CraftingCPUScreen 发送:鼠标下条目对应的 AEKey。 - * 服务端在当前打开的 CraftingCPUMenu 所属网络中,定位匹配该 AEKey 的样板供应器, - * 打开该供应器自身的 UI(不是目标机器的 UI)。 - */ -public class CraftingMonitorOpenProviderC2SPacket { - private final AEKey what; - - public CraftingMonitorOpenProviderC2SPacket(AEKey what) { - this.what = what; - } - - public static void encode(CraftingMonitorOpenProviderC2SPacket msg, FriendlyByteBuf buf) { - AEKey.writeKey(buf, msg.what); - } - - public static CraftingMonitorOpenProviderC2SPacket decode(FriendlyByteBuf buf) { - AEKey key = AEKey.readKey(buf); - return new CraftingMonitorOpenProviderC2SPacket(key); - } - - public static void handle(CraftingMonitorOpenProviderC2SPacket msg, Supplier ctx) { - NetworkEvent.Context context = ctx.get(); - context.enqueueWork(() -> { - ServerPlayer player = context.getSender(); - if (player == null) return; - - // 必须在 CraftingCPU 界面内 - if (!(player.containerMenu instanceof CraftingCPUMenu menu)) { - return; - } - - // 通过菜单的 target(可能是 BlockEntity/Part/ItemHost),按 IActionHost 获取 Grid - IGrid grid = null; - Object target = ((AEBaseMenu) menu).getTarget(); - if (target instanceof IActionHost host && host.getActionableNode() != null) { - grid = host.getActionableNode().getGrid(); - } - if (grid == null) { - return; - } - - var cs = grid.getCraftingService(); - if (!(cs instanceof CraftingService craftingService)) { - return; - } - - // 1) 根据 AEKey 找到可能的样板(pattern) - Collection patterns = craftingService.getCraftingFor(msg.what); - if (patterns.isEmpty()) { - return; - } - - // 2) 遍历提供该样板的 Provider,定位 PatternProviderLogic - for (var pattern : patterns) { - var providers = craftingService.getProviders(pattern); - for (var provider : providers) { - if (provider instanceof PatternProviderLogic ppl) { - // accessor 获取 host - PatternProviderLogicHost host = ((PatternProviderLogicAccessor) ppl).eap$host(); - if (host == null) continue; - var pbe = host.getBlockEntity(); - if (pbe == null) continue; - - // 跳过未连接到网格或不活跃的 provider(使用 util 判断并传入当前 grid) - if (!PatternProviderDataUtil.isProviderAvailable(ppl, grid)) continue; - - // 直接打开供应器自身的 UI(调用 Host 默认方法) - try { - // 部件与方块实体分别选择定位器并打开界面 - if (host instanceof AEBasePart part) { - host.openMenu(player, MenuLocators.forPart(part)); - highlightWithMessage(pbe.getBlockPos(), part.getSide(), Objects.requireNonNull(pbe.getLevel()).dimension(), 1.0, player); - } else { - host.openMenu(player, MenuLocators.forBlockEntity(pbe)); - highlightWithMessage(pbe.getBlockPos(), null, Objects.requireNonNull(pbe.getLevel()).dimension(), 1.0, player); - } - - // 先在该 provider 中定位 pattern 的槽位索引,以便计算页码(尽量早退出,按槽位逐个解码) - int foundSlot = PatternProviderDataUtil.findSlotForPattern(ppl, pattern.getDefinition()); - if (foundSlot >= 0) { - int pageId = foundSlot / 36; - if (pageId > 0) { - // 发送 S2C 包通知客户端切换到指定页(客户端会写入 mixin 字段并重排槽位) - ModNetwork.CHANNEL.sendTo(new SetProviderPageS2CPacket(pageId), player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - } - - // 最后发送高亮包,保证界面已打开 - if (pattern.getOutputs() != null && pattern.getOutputs().length > 0 && pattern.getOutputs()[0] != null) { - AEKey key = pattern.getOutputs()[0].what(); - ModNetwork.CHANNEL.sendTo(new SetPatternHighlightS2CPacket(key, true), player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - return; - } catch (Exception ignored) { - } - } else if (provider instanceof com.gregtechceu.gtceu.integration.ae2.machine.MEPatternBufferPartMachine machine) { - // 处理 MEPatternBufferPartMachine:打开其界面并高亮位置,尽量反射获取槽位页码 - try { - BlockPos pos = machine.getPos(); - Level level = machine.getLevel(); - if (pos == null || level == null) continue; - if (!level.isClientSide) { // 确保在服务器端执行 - MachineUIFactory.INSTANCE.openUI(MetaMachine.getMachine(level, pos), player); - } - - // 最后发送高亮包,保证界面已打开 - if (pattern.getOutputs() != null && pattern.getOutputs().length > 0 && pattern.getOutputs()[0] != null) { - AEKey key = pattern.getOutputs()[0].what(); - ModNetwork.CHANNEL.sendTo(new SetPatternHighlightS2CPacket(key, true), player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - highlightWithMessage(pos, null, level.dimension(), 1.0, player); - - } catch (Exception ignored) { - } - } else if (provider instanceof org.gtlcore.gtlcore.common.machine.multiblock.part.ae.MEPatternBufferPartMachine machine) { - // 处理 MEPatternBufferPartMachine:打开其界面并高亮位置,尽量反射获取槽位页码 - try { - BlockPos pos = machine.getPos(); - Level level = machine.getLevel(); - if (pos == null || level == null) continue; - if (!level.isClientSide) { // 确保在服务器端执行 - MachineUIFactory.INSTANCE.openUI(MetaMachine.getMachine(level, pos), player); - } - - // 最后发送高亮包,保证界面已打开 - if (pattern.getOutputs() != null && pattern.getOutputs().length > 0 && pattern.getOutputs()[0] != null) { - AEKey key = pattern.getOutputs()[0].what(); - ModNetwork.CHANNEL.sendTo(new SetPatternHighlightS2CPacket(key, true), player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); - } - - highlightWithMessage(pos, null, level.dimension(), 1.0, player); - } catch (Exception ignored) { - } - } - } - } - }); - context.setPacketHandled(true); - } - - private static void highlightWithMessage(BlockPos pos, Direction face, ResourceKey dim, double multiplier, Player player) { - if (pos == null || dim == null) { - return; - } - long endTime = System.currentTimeMillis() + (long) (6000 * GlodUtil.clamp(multiplier, 1, 30)); - if (face == null) { - highlight(pos, dim, endTime); - } else { - var origin = new AABB(2 / 16D, 2 / 16D, 0, 14 / 16D, 14 / 16D, 2 / 16D).move(pos); - var center = new AABB(pos).getCenter(); - switch (face) { - case WEST -> origin = FCClientUtil.rotor(origin, center, Direction.Axis.Y, (float) (Math.PI / 2)); - case SOUTH -> origin = FCClientUtil.rotor(origin, center, Direction.Axis.Y, (float) Math.PI); - case EAST -> origin = FCClientUtil.rotor(origin, center, Direction.Axis.Y, (float) (-Math.PI / 2)); - case UP -> origin = FCClientUtil.rotor(origin, center, Direction.Axis.X, (float) (-Math.PI / 2)); - case DOWN -> origin = FCClientUtil.rotor(origin, center, Direction.Axis.X, (float) (Math.PI / 2)); - } - highlight(pos, face, dim, endTime, origin); - } - - if (player != null) { - player.displayClientMessage(Component.translatable("chat.ex_pattern_access_terminal.pos", pos.toShortString(), dim.location().getPath()), false); - } - } -} diff --git a/src/main/java/com/extendedae_plus/network/crafting/CraftingMonitorOpenProviderC2SPacket.java b/src/main/java/com/extendedae_plus/network/crafting/CraftingMonitorOpenProviderC2SPacket.java index 7fea21f..27ee686 100644 --- a/src/main/java/com/extendedae_plus/network/crafting/CraftingMonitorOpenProviderC2SPacket.java +++ b/src/main/java/com/extendedae_plus/network/crafting/CraftingMonitorOpenProviderC2SPacket.java @@ -14,11 +14,18 @@ import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor; import com.extendedae_plus.network.SetBlockHighlightS2CPacket; import com.extendedae_plus.network.SetPatternHighlightS2CPacket; import com.extendedae_plus.network.provider.SetProviderPageS2CPacket; +import com.extendedae_plus.util.CompareModVersionUtil; import com.extendedae_plus.util.PatternProviderDataUtil; +import com.glodblock.github.extendedae.client.render.EAEHighlightHandler; +import com.glodblock.github.extendedae.util.MessageUtil; import com.glodblock.github.glodium.util.GlodUtil; +import com.gregtechceu.gtceu.api.gui.factory.MachineUIFactory; +import com.gregtechceu.gtceu.api.machine.MetaMachine; +import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent; @@ -70,11 +77,22 @@ public class CraftingMonitorOpenProviderC2SPacket { // 遍历所有样板,找到第一个可用 Provider 并打开 UI for (var pattern : patterns) { var provider = PatternLocator.findValidProvider(craftingService, pattern, grid); - if (provider == null) continue; + if (provider == null) { + for (var pd : craftingService.getProviders(pattern)) { + if (pd instanceof com.gregtechceu.gtceu.integration.ae2.machine.MEPatternBufferPartMachine machine) { + gtmOpenUI(machine, player, pattern); + return; + } else if (pd instanceof org.gtlcore.gtlcore.common.machine.multiblock.part.ae.MEPatternBufferPartMachine machine) { + gtmOpenUI(machine, player, pattern); + return; + } + } + } try { ProviderUIHelper.openProviderUI(provider, pattern, player); - } catch (Exception ignored) {} + } catch (Exception ignored) { + } } }); context.setPacketHandled(true); @@ -82,21 +100,73 @@ public class CraftingMonitorOpenProviderC2SPacket { // ===================== 内部工具类 ===================== + /** + * 兼容gtm + * @param machine 样板总成 + * @param player 玩家 + * @param pattern 样板 + */ + private static void gtmOpenUI(MetaMachine machine, ServerPlayer player, IPatternDetails pattern) { + try { + BlockPos pos = machine.getPos(); + Level level = machine.getLevel(); + if (pos == null || level == null) return; + if (!level.isClientSide) { // 确保在服务器端执行 + MachineUIFactory.INSTANCE.openUI(MetaMachine.getMachine(level, pos), player); + } + + // 聊天提示 + if (CompareModVersionUtil.compareTo("expatternprovider", "1.4.7")) { + player.displayClientMessage( + MessageUtil.createEnhancedHighlightMessage( + player, + pos, + level.dimension(), + "chat.ex_pattern_access_terminal.pos"), + false + ); + } else { + player.displayClientMessage( + Component.translatable( + "chat.ex_pattern_access_terminal.pos", + pos.toShortString(), + level.dimension() + .location() + .getPath() + ), + false + ); + } + + // 最后发送高亮包,保证界面已打开 + if (pattern.getOutputs() != null && pattern.getOutputs().length > 0 && pattern.getOutputs()[0] != null) { + AEKey key = pattern.getOutputs()[0].what(); + ModNetwork.CHANNEL.sendTo(new SetPatternHighlightS2CPacket(key, true), player.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + } + + EAEHighlightHandler.highlight(pos, level.dimension(), System.currentTimeMillis() + 15000); + } catch (Exception ignored) { + } + } + /** * GridHelper: 从菜单中获取网格实例 */ public static final class GridHelper { - private GridHelper() {} + private GridHelper() { + } /** * 获取菜单对应的 Grid + * * @param menu 当前 AEBaseMenu * @return Grid 或 null */ public static IGrid getGridFromMenu(appeng.menu.AEBaseMenu menu) { Object target = menu.getTarget(); if (target instanceof IActionHost host && host.getActionableNode() != null) { - return host.getActionableNode().getGrid(); + return host.getActionableNode() + .getGrid(); } return null; } @@ -106,13 +176,15 @@ public class CraftingMonitorOpenProviderC2SPacket { * PatternLocator: 根据样板定位可用的 Provider */ public static final class PatternLocator { - private PatternLocator() {} + private PatternLocator() { + } /** * 查找提供指定样板的可用 Provider - * @param cs CraftingService + * + * @param cs CraftingService * @param pattern 样板 - * @param grid 当前 Grid + * @param grid 当前 Grid * @return 第一个可用的 PatternProviderLogic 或 null */ public static PatternProviderLogic findValidProvider(CraftingService cs, IPatternDetails pattern, IGrid grid) { @@ -133,7 +205,8 @@ public class CraftingMonitorOpenProviderC2SPacket { * ProviderUIHelper: 打开 Provider UI 并发送客户端反馈 */ public static final class ProviderUIHelper { - private ProviderUIHelper() {} + private ProviderUIHelper() { + } /** * 打开 Provider UI @@ -143,8 +216,8 @@ public class CraftingMonitorOpenProviderC2SPacket { * 4. 发送 Pattern 输出高亮包 * * @param provider PatternProviderLogic 实例 - * @param pattern 样板 - * @param player 玩家 + * @param pattern 样板 + * @param player 玩家 */ public static void openProviderUI(PatternProviderLogic provider, IPatternDetails pattern, ServerPlayer player) { var host = ((PatternProviderLogicAccessor) provider).eap$host(); @@ -160,7 +233,9 @@ public class CraftingMonitorOpenProviderC2SPacket { new SetBlockHighlightS2CPacket( pbe.getBlockPos(), isPart ? ((AEBasePart) host).getSide() : null, - pbe.getLevel().dimension().location(), + pbe.getLevel() + .dimension() + .location(), (long) (6000 * GlodUtil.clamp(1.0, 1, 30)) ), player.connection.connection, @@ -168,15 +243,30 @@ public class CraftingMonitorOpenProviderC2SPacket { ); // 聊天提示 - player.displayClientMessage( - Component.translatable( - "chat.ex_pattern_access_terminal.pos", - pbe.getBlockPos().toShortString(), - pbe.getLevel().dimension().location().getPath() - ), - false - ); - + if (CompareModVersionUtil.compareTo("expatternprovider", "1.4.7")) { + player.displayClientMessage( + MessageUtil.createEnhancedHighlightMessage( + player, + pbe.getBlockPos(), + pbe.getLevel() + .dimension(), + "chat.ex_pattern_access_terminal.pos"), + false + ); + } else { + player.displayClientMessage( + Component.translatable( + "chat.ex_pattern_access_terminal.pos", + pbe.getBlockPos() + .toShortString(), + pbe.getLevel() + .dimension() + .location() + .getPath() + ), + false + ); + } // 页码同步 int slot = PatternProviderDataUtil.findSlotForPattern(provider, pattern.getDefinition()); if (slot >= 0) { diff --git a/src/main/java/com/extendedae_plus/util/CompareModVersionUtil.java b/src/main/java/com/extendedae_plus/util/CompareModVersionUtil.java new file mode 100644 index 0000000..98342c3 --- /dev/null +++ b/src/main/java/com/extendedae_plus/util/CompareModVersionUtil.java @@ -0,0 +1,35 @@ +package com.extendedae_plus.util; + +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.loading.LoadingModList; +import org.apache.maven.artifact.versioning.ComparableVersion; + +import java.util.Optional; + +//此类代码借鉴于gtlcore +public class CompareModVersionUtil { + private static final ModList modList = ModList.get(); + private static final LoadingModList loadingModList = LoadingModList.get(); + + public static boolean compareTo(String modId, String version) { + Optional versionStr; + if (modList == null) { + versionStr = loadingModList + .getMods() + .stream() + .filter(mi -> mi.getModId() + .equals(modId)) + .findFirst() + .map(mi -> mi.getVersion() + .toString()); + } else { + versionStr = modList.getModContainerById(modId) + .map(mc -> mc.getModInfo() + .getVersion() + .toString()); + } + return versionStr + .map(v -> new ComparableVersion(v).compareTo(new ComparableVersion(version)) >= 0) + .orElse(false); + } +}