From ac308242e2694cef7892fbc0d2720245db37b822 Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Mon, 27 Oct 2025 12:05:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CraftingMonitorOpenProviderC2SPacket.java | 13 +- .../util/PatternProviderDataUtil.java | 276 +++++++----------- 2 files changed, 113 insertions(+), 176 deletions(-) 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..cdeeb43 100644 --- a/src/main/java/com/extendedae_plus/network/crafting/CraftingMonitorOpenProviderC2SPacket.java +++ b/src/main/java/com/extendedae_plus/network/crafting/CraftingMonitorOpenProviderC2SPacket.java @@ -6,6 +6,7 @@ import appeng.api.networking.security.IActionHost; import appeng.api.stacks.AEKey; import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.me.service.CraftingService; +import appeng.menu.AEBaseMenu; import appeng.menu.locator.MenuLocators; import appeng.menu.me.crafting.CraftingCPUMenu; import appeng.parts.AEBasePart; @@ -85,7 +86,7 @@ public class CraftingMonitorOpenProviderC2SPacket { /** * GridHelper: 从菜单中获取网格实例 */ - public static final class GridHelper { + private static final class GridHelper { private GridHelper() {} /** @@ -93,7 +94,7 @@ public class CraftingMonitorOpenProviderC2SPacket { * @param menu 当前 AEBaseMenu * @return Grid 或 null */ - public static IGrid getGridFromMenu(appeng.menu.AEBaseMenu menu) { + private static IGrid getGridFromMenu(AEBaseMenu menu) { Object target = menu.getTarget(); if (target instanceof IActionHost host && host.getActionableNode() != null) { return host.getActionableNode().getGrid(); @@ -105,7 +106,7 @@ public class CraftingMonitorOpenProviderC2SPacket { /** * PatternLocator: 根据样板定位可用的 Provider */ - public static final class PatternLocator { + private static final class PatternLocator { private PatternLocator() {} /** @@ -115,7 +116,7 @@ public class CraftingMonitorOpenProviderC2SPacket { * @param grid 当前 Grid * @return 第一个可用的 PatternProviderLogic 或 null */ - public static PatternProviderLogic findValidProvider(CraftingService cs, IPatternDetails pattern, IGrid grid) { + private static PatternProviderLogic findValidProvider(CraftingService cs, IPatternDetails pattern, IGrid grid) { var providers = cs.getProviders(pattern); for (var provider : providers) { if (provider instanceof PatternProviderLogic ppl) { @@ -132,7 +133,7 @@ public class CraftingMonitorOpenProviderC2SPacket { /** * ProviderUIHelper: 打开 Provider UI 并发送客户端反馈 */ - public static final class ProviderUIHelper { + private static final class ProviderUIHelper { private ProviderUIHelper() {} /** @@ -146,7 +147,7 @@ public class CraftingMonitorOpenProviderC2SPacket { * @param pattern 样板 * @param player 玩家 */ - public static void openProviderUI(PatternProviderLogic provider, IPatternDetails pattern, ServerPlayer player) { + private static void openProviderUI(PatternProviderLogic provider, IPatternDetails pattern, ServerPlayer player) { var host = ((PatternProviderLogicAccessor) provider).eap$host(); var pbe = host.getBlockEntity(); if (pbe == null) return; diff --git a/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java b/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java index 68c3a6f..0b349bc 100644 --- a/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java +++ b/src/main/java/com/extendedae_plus/util/PatternProviderDataUtil.java @@ -4,6 +4,7 @@ import appeng.api.crafting.IPatternDetails; import appeng.api.crafting.PatternDetailsHelper; import appeng.api.inventories.InternalInventory; import appeng.api.networking.IGrid; +import appeng.api.networking.IManagedGridNode; import appeng.helpers.patternprovider.PatternContainer; import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.menu.implementations.PatternAccessTermMenu; @@ -12,210 +13,111 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; /** * 样板供应器数据工具类 * 用于获取样板供应器中的所有样板数据,包括输入输出物品的数量信息 */ public class PatternProviderDataUtil { + private static final int INVALID_SLOT = -1; + private static final String UNKNOWN_PROVIDER = "未知供应器"; + /** * 判断 provider 是否可用并属于指定网格(在线且有频道/处于活跃状态) */ - public static boolean isProviderAvailable(PatternProviderLogic provider, IGrid expectedGrid) { - if (provider == null || expectedGrid == null) return false; + public static boolean isProviderAvailable(@NotNull PatternProviderLogic provider, @NotNull IGrid expectedGrid) { try { - var grid = provider.getGrid(); + IGrid grid = provider.getGrid(); if (grid == null || !grid.equals(expectedGrid)) return false; - // 使用 accessor 获取 mainNode,再调用 isActive if (provider instanceof PatternProviderLogicAccessor accessor) { - var mainNode = accessor.eap$mainNode(); - if (mainNode == null) return false; - try { - var isActiveMethod = mainNode.getClass().getMethod("isActive"); - Object active = isActiveMethod.invoke(mainNode); - if (active instanceof Boolean && !((Boolean) active)) return false; - } catch (NoSuchMethodException nsme) { - // 没有 isActive 方法时,退回到检查 channels - try { - var getChannels = mainNode.getClass().getMethod("getChannels"); - Object channels = getChannels.invoke(mainNode); - if (channels instanceof java.util.Collection) { - if (((java.util.Collection) channels).isEmpty()) return false; - } - } catch (Exception ignored) { - // 无法判断 channels 时,认为不可用 - return false; - } - } - } else { - // 没有 accessor 的情况,尽量通过反射判断 mainNode.channels - try { - var mainNodeField = provider.getClass().getDeclaredField("mainNode"); - mainNodeField.setAccessible(true); - var mainNode = mainNodeField.get(provider); - if (mainNode == null) return false; - var getChannelsMethod = mainNode.getClass().getMethod("getChannels"); - Object channels = getChannelsMethod.invoke(mainNode); - if (channels instanceof java.util.Collection) { - return !((java.util.Collection) channels).isEmpty(); - } - } catch (Exception e) { - return false; - } - } - - return true; - } catch (Exception e) { - return false; - } - } - - /** - * 查找 provider 中匹配给定定义的样板槽位(轻量、按需解码并早退出) - * @param patternProvider 要搜索的 provider - * @param targetDefinition pattern.getDefinition() 返回的对象(用于 equals 比较) - * @return 找到的槽位索引,未找到返回 -1 - */ - public static int findSlotForPattern(PatternProviderLogic patternProvider, Object targetDefinition) { - if (patternProvider == null || targetDefinition == null) return -1; - InternalInventory inv = patternProvider.getPatternInv(); - if (inv == null) return -1; - Level level = getPatternProviderLevel(patternProvider); - if (level == null) return -1; - - for (int i = 0; i < inv.size(); i++) { - ItemStack s = inv.getStackInSlot(i); - if (s.isEmpty()) continue; - try { - IPatternDetails d = PatternDetailsHelper.decodePattern(s, level); - if (d != null && d.getDefinition().equals(targetDefinition)) { - return i; - } - } catch (Exception ignored) {} - } - return -1; - } - - /** - * ExtendedAE风格:安全获取样板供应器的Level对象 - */ - private static Level getPatternProviderLevel(PatternProviderLogic patternProvider) { - if (patternProvider == null) return null; - try { - if (patternProvider instanceof PatternProviderLogicAccessor accessor) { - var host = accessor.eap$host(); - if (host != null) { - BlockEntity be = host.getBlockEntity(); - if (be != null) { - return be.getLevel(); - } - } + IManagedGridNode mainNode = accessor.eap$mainNode(); + return mainNode != null && mainNode.isActive(); } } catch (Exception ignored) { } - return null; - } - - - /** - * 获取样板供应器中的空槽位数量 - * - * @param providerId 供应器ID - * @param menu 样板访问终端菜单(支持ExtendedAE) - * @return 空槽位数量,如果无法访问则返回-1 - */ - public static int getAvailableSlots(long providerId, PatternAccessTermMenu menu) { - PatternContainer container = PatternTerminalUtil.getPatternContainerById(menu, providerId); - if (container == null) { - return -1; - } - - InternalInventory inventory = container.getTerminalPatternInventory(); - if (inventory == null) { - return -1; - } - - int availableSlots = 0; - for (int i = 0; i < inventory.size(); i++) { - if (inventory.getStackInSlot(i).isEmpty()) { - availableSlots++; - } - } - - return availableSlots; - } - - /** - * 获取样板供应器的显示名称 - * - * @param providerId 供应器ID - * @param menu 样板访问终端菜单 - * @return 显示名称,如果无法获取则返回"未知供应器" - */ - public static String getProviderDisplayName(long providerId, PatternAccessTermMenu menu) { - PatternContainer container = PatternTerminalUtil.getPatternContainerById(menu, providerId); - if (container == null) { - return "未知供应器"; - } - - try { - // 尝试获取供应器的组信息来构建显示名称 - var group = container.getTerminalGroup(); - if (group != null) { - // 使用 Component 序列化来保持翻译键,而不是直接 getString() - // 这样客户端可以根据自己的语言设置进行翻译 - return Component.Serializer.toJson(group.name()); - } - } catch (Exception e) { - // 忽略异常,使用默认名称 - } - - return "样板供应器 #" + providerId; + return false; } /** * 验证样板供应器是否可用 * * @param providerId 供应器ID - * @param menu 样板访问终端菜单 + * @param menu 样板访问终端菜单 * @return 是否可用 */ public static boolean isProviderAvailable(long providerId, PatternAccessTermMenu menu) { PatternContainer container = PatternTerminalUtil.getPatternContainerById(menu, providerId); - if (container == null) { - return false; - } - - // 检查是否在终端中可见 - if (!container.isVisibleInTerminal()) { - return false; - } - - // 检查是否连接到网络 + if (container == null) return false; + if (!container.isVisibleInTerminal()) return false; return container.getGrid() != null; } - /** 获取供应器显示名(优先组名) */ - public static String getProviderDisplayName(PatternContainer container) { - if (container == null) return "未知供应器"; - try { - var group = container.getTerminalGroup(); - if (group != null) { - // 使用 Component 序列化来保持翻译键,而不是直接 getString() - // 这样客户端可以根据自己的语言设置进行翻译 - return Component.Serializer.toJson(group.name()); + /** + * 查找 provider 中匹配给定定义的样板槽位(轻量、按需解码并早退出) + * + * @param provider 要搜索的 provider + * @param targetDefinition pattern.getDefinition() 返回的对象(用于 equals 比较) + * @return 找到的槽位索引,未找到返回 -1 + */ + public static int findSlotForPattern(@Nullable PatternProviderLogic provider, @Nullable Object targetDefinition) { + if (provider == null || targetDefinition == null) return INVALID_SLOT; + + InternalInventory inv = provider.getPatternInv(); + if (inv == null || inv.isEmpty()) return INVALID_SLOT; + + Level level = getPatternProviderLevel(provider); + if (level == null) return INVALID_SLOT; + + for (int i = 0; i < inv.size(); i++) { + ItemStack stack = inv.getStackInSlot(i); + if (stack.isEmpty() || !stack.hasTag()) continue; // 快速跳过无Nbt样板 + try { + IPatternDetails details = PatternDetailsHelper.decodePattern(stack, level); + if (details != null && targetDefinition.equals(details.getDefinition())) { + return i; + } + } catch (Exception ignored) { } - } catch (Throwable ignored) { } - return "样板供应器"; + return INVALID_SLOT; } - /** 计算供应器空槽位数量 */ - public static int getAvailableSlots(PatternContainer container) { - if (container == null) return -1; + /** + * 获取样板供应器的 Level 对象 + */ + @Nullable + private static Level getPatternProviderLevel(@Nullable PatternProviderLogic provider) { + if (!(provider instanceof PatternProviderLogicAccessor accessor)) return null; + var host = accessor.eap$host(); + if (host == null) return null; + BlockEntity be = host.getBlockEntity(); + return be != null ? be.getLevel() : null; + } + + /** + * 获取样板供应器中的空槽位数量 + * + * @param providerId 供应器ID + * @param menu 样板访问终端菜单(支持ExtendedAE) + * @return 空槽位数量,如果无法访问则返回-1 + */ + public static int getAvailableSlots(long providerId, PatternAccessTermMenu menu) { + PatternContainer container = PatternTerminalUtil.getPatternContainerById(menu, providerId); + return getAvailableSlots(container); + } + + /** + * 计算供应器空槽位数量 + */ + public static int getAvailableSlots(@Nullable PatternContainer container) { + if (container == null) return INVALID_SLOT; InternalInventory inv = container.getTerminalPatternInventory(); - if (inv == null) return -1; + if (inv == null) return INVALID_SLOT; + int available = 0; for (int i = 0; i < inv.size(); i++) { if (inv.getStackInSlot(i).isEmpty()) available++; @@ -223,5 +125,39 @@ public class PatternProviderDataUtil { return available; } + /** + * 获取样板供应器的显示名称 + * + * @param providerId 供应器ID + * @param menu 样板访问终端菜单 + * @return 显示名称,如果无法获取则返回"未知供应器" + */ + public static String getProviderDisplayName(long providerId, PatternAccessTermMenu menu) { + PatternContainer container = PatternTerminalUtil.getPatternContainerById(menu, providerId); + return getProviderDisplayName(container, providerId); + } + /** + * 获取供应器显示名(优先组名) + */ + public static String getProviderDisplayName(@Nullable PatternContainer container) { + return getProviderDisplayName(container, -1); + } + + /** + * 实际显示名获取逻辑 + */ + private static String getProviderDisplayName(@Nullable PatternContainer container, long providerId) { + if (container == null) return UNKNOWN_PROVIDER; + try { + var group = container.getTerminalGroup(); + if (group != null) { + // 使用 Component 序列化来保持翻译键,而不是直接 getString() + // 这样客户端可以根据自己的语言设置进行翻译 + return Component.Serializer.toJson(group.name()); + } + } catch (Exception ignored) { + } + return providerId > 0 ? "样板供应器 #" + providerId : "样板供应器"; + } } \ No newline at end of file