This commit is contained in:
C-H716 2025-09-02 19:43:00 +08:00
parent 8fec6fff87
commit 146cce9de1
3 changed files with 107 additions and 54 deletions

View File

@ -1,5 +1,6 @@
package com.extendedae_plus.mixin.ae2.accessor; package com.extendedae_plus.mixin.ae2.accessor;
import appeng.api.networking.IManagedGridNode;
import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.helpers.patternprovider.PatternProviderLogic;
import appeng.helpers.patternprovider.PatternProviderLogicHost; import appeng.helpers.patternprovider.PatternProviderLogicHost;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -9,4 +10,7 @@ import org.spongepowered.asm.mixin.gen.Accessor;
public interface PatternProviderLogicAccessor { public interface PatternProviderLogicAccessor {
@Accessor("host") @Accessor("host")
PatternProviderLogicHost eap$host(); PatternProviderLogicHost eap$host();
@Accessor("mainNode")
IManagedGridNode eap$mainNode();
} }

View File

@ -85,31 +85,8 @@ public class CraftingMonitorOpenProviderC2SPacket {
var pbe = host.getBlockEntity(); var pbe = host.getBlockEntity();
if (pbe == null) continue; if (pbe == null) continue;
// 跳过未连接到网格或不活跃的 provider例如缺少频道/通道 // 跳过未连接到网格或不活跃的 provider使用 util 判断并传入当前 grid
try { if (!PatternProviderDataUtil.isProviderAvailable(ppl, grid)) continue;
var providerGrid = ppl.getGrid();
if (providerGrid == null || !providerGrid.equals(grid)) {
continue;
}
// 如果 provider 自身对外提供的通道/频道信息不可用或不活跃跳过
try {
// 尝试通过 provider 的主节点判断是否有 channel
var mainNodeField = ppl.getClass().getDeclaredField("mainNode");
mainNodeField.setAccessible(true);
var mainNode = mainNodeField.get(ppl);
if (mainNode == null) continue;
var getChannelsMethod = mainNode.getClass().getMethod("getChannels");
Object channels = null;
channels = getChannelsMethod.invoke(mainNode);
if (channels instanceof java.util.Collection) {
if (((java.util.Collection<?>) channels).isEmpty()) continue;
}
} catch (Exception ignored) {
// 无法判断 channel 时继续不因反射失败而阻止正常 provider
}
} catch (Exception e) {
continue;
}
// 直接打开供应器自身的 UI调用 Host 默认方法 // 直接打开供应器自身的 UI调用 Host 默认方法
try { try {
@ -121,7 +98,7 @@ public class CraftingMonitorOpenProviderC2SPacket {
} }
// 先在该 provider 中定位 pattern 的槽位索引以便计算页码尽量早退出按槽位逐个解码 // 先在该 provider 中定位 pattern 的槽位索引以便计算页码尽量早退出按槽位逐个解码
int foundSlot = findSlotIndexInProvider(ppl, pattern); int foundSlot = PatternProviderDataUtil.findSlotForPattern(ppl, pattern.getDefinition());
if (foundSlot >= 0) { if (foundSlot >= 0) {
int pageId = foundSlot / 36; int pageId = foundSlot / 36;
if (pageId > 0) { if (pageId > 0) {
@ -145,20 +122,4 @@ public class CraftingMonitorOpenProviderC2SPacket {
}); });
context.setPacketHandled(true); context.setPacketHandled(true);
} }
private static int findSlotIndexInProvider(PatternProviderLogic ppl, IPatternDetails pattern) {
try {
// 通过逐槽位解码并在找到匹配定义时立即返回索引避免分配大量对象
var list = PatternProviderDataUtil.getAllPatternData(ppl);
for (var pd : list) {
if (pd != null && pd.getPatternDetails() != null && pd.getPatternDetails().getDefinition().equals(pattern.getDefinition())) {
return pd.getSlotIndex();
}
}
} catch (Exception ignored) {
}
return -1;
}
} }

View File

@ -3,13 +3,14 @@ package com.extendedae_plus.util;
import appeng.api.crafting.IPatternDetails; import appeng.api.crafting.IPatternDetails;
import appeng.api.crafting.PatternDetailsHelper; import appeng.api.crafting.PatternDetailsHelper;
import appeng.api.inventories.InternalInventory; import appeng.api.inventories.InternalInventory;
import appeng.api.networking.IGrid;
import appeng.api.stacks.AEKey; import appeng.api.stacks.AEKey;
import appeng.api.stacks.GenericStack; import appeng.api.stacks.GenericStack;
import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.helpers.patternprovider.PatternProviderLogic;
import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor; import com.extendedae_plus.mixin.ae2.accessor.PatternProviderLogicAccessor;
import com.mojang.logging.LogUtils;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import appeng.helpers.patternprovider.PatternProviderLogicHost;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.ArrayList; import java.util.ArrayList;
@ -242,12 +243,15 @@ public class PatternProviderDataUtil {
// 遍历所有样板槽位 // 遍历所有样板槽位
for (int i = 0; i < patternInventory.size(); i++) { for (int i = 0; i < patternInventory.size(); i++) {
ItemStack patternStack = patternInventory.getStackInSlot(i); ItemStack patternStack = patternInventory.getStackInSlot(i);
if (!patternStack.isEmpty()) { if (patternStack.isEmpty()) continue;
try {
// 解码样板 // 解码样板
IPatternDetails patternDetails = PatternDetailsHelper.decodePattern(patternStack, level); IPatternDetails patternDetails = PatternDetailsHelper.decodePattern(patternStack, level);
if (patternDetails != null) { if (patternDetails != null) {
patternDataList.add(new PatternData(patternDetails, patternStack, i)); patternDataList.add(new PatternData(patternDetails, patternStack, i));
} }
} catch (Exception e) {
if (DEBUG) LogUtils.getLogger().debug("Pattern decode failed at slot {}: {}", i, e.toString());
} }
} }
@ -397,6 +401,59 @@ public class PatternProviderDataUtil {
return patternProvider.getGrid() != null; return patternProvider.getGrid() != null;
} }
/**
* 判断 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;
}
}
/** /**
* 检查样板供应器是否处于活跃状态 * 检查样板供应器是否处于活跃状态
* *
@ -411,18 +468,21 @@ public class PatternProviderDataUtil {
if (grid == null) { if (grid == null) {
return false; return false;
} }
// 检查网格节点是否活跃 // 检查网格节点是否活跃使用 accessor 代替反射
try { try {
// 使用反射安全地访问mainNode字段 if (patternProvider instanceof PatternProviderLogicAccessor accessor) {
var mainNodeField = patternProvider.getClass().getDeclaredField("mainNode"); var mainNode = accessor.eap$mainNode();
mainNodeField.setAccessible(true); if (mainNode != null) {
var mainNode = mainNodeField.get(patternProvider); try {
if (mainNode != null) { var isActiveMethod = mainNode.getClass().getMethod("isActive");
var isActiveMethod = mainNode.getClass().getMethod("isActive"); return (Boolean) isActiveMethod.invoke(mainNode);
return (Boolean) isActiveMethod.invoke(mainNode); } catch (Exception e) {
// 无法调用 isActive 认为活跃
return true;
}
}
} }
} catch (Exception e) { } catch (Exception ignored) {
// 如果反射失败假设是活跃的
} }
return true; return true;
} }
@ -490,6 +550,34 @@ public class PatternProviderDataUtil {
return scalePatternAmountsExtendedAEStyle(patternProvider, multiplier, true); return scalePatternAmountsExtendedAEStyle(patternProvider, multiplier, true);
} }
/**
* 查找 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 e) {
if (DEBUG) LogUtils.getLogger().debug("findSlotForPattern decode failed at {}: {}", i, e.toString());
}
}
return -1;
}
/** /**
* ExtendedAE风格的样板复制倍增 * ExtendedAE风格的样板复制倍增
* 支持更精确的样板处理和错误恢复 * 支持更精确的样板处理和错误恢复