116 lines
5.0 KiB
Java
116 lines
5.0 KiB
Java
package com.extendedae_plus.util;
|
||
|
||
import appeng.api.crafting.IPatternDetails;
|
||
import appeng.api.crafting.PatternDetailsHelper;
|
||
import appeng.api.inventories.InternalInventory;
|
||
import appeng.api.networking.IGrid;
|
||
import appeng.helpers.patternprovider.PatternProviderLogic;
|
||
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor;
|
||
import net.minecraft.world.item.ItemStack;
|
||
import net.minecraft.world.level.Level;
|
||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||
|
||
/**
|
||
* 样板供应器数据工具类
|
||
* 用于获取样板供应器中的所有样板数据,包括输入输出物品的数量信息
|
||
*/
|
||
public class PatternProviderDataUtil {
|
||
/**
|
||
* 判断 provider 是否可用并属于指定网格(在线且有频道/处于活跃状态)
|
||
*/
|
||
public static boolean isProviderAvailable(PatternProviderLogic provider, IGrid expectedGrid) {
|
||
if (provider == null || expectedGrid == null) return false;
|
||
try {
|
||
var 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();
|
||
}
|
||
}
|
||
}
|
||
} catch (Exception ignored) {
|
||
}
|
||
return null;
|
||
}
|
||
} |