优化
This commit is contained in:
parent
07ef2e6461
commit
ac308242e2
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 : "样板供应器";
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user