修复curios中无线终端相关操作异常
This commit is contained in:
parent
02c936ea0f
commit
8e74d13d73
|
|
@ -79,6 +79,18 @@ public class ExtendedAEPlus {
|
|||
// 绑定 AE2 的 CraftingBlockEntity 到本模组的自定义加速器方块,避免 AEBaseEntityBlock.blockEntityType 为空
|
||||
event.enqueueWork(() -> {
|
||||
try {
|
||||
// 注册自定义 AE2 MenuLocator(用于 Curios 槽位打开菜单)
|
||||
try {
|
||||
appeng.menu.locator.MenuLocators.register(
|
||||
com.extendedae_plus.menu.locator.CuriosItemLocator.class,
|
||||
com.extendedae_plus.menu.locator.CuriosItemLocator::writeToPacket,
|
||||
com.extendedae_plus.menu.locator.CuriosItemLocator::readFromPacket
|
||||
);
|
||||
LOGGER.info("Registered AE2 MenuLocator: CuriosItemLocator");
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warn("Failed to register CuriosItemLocator with AE2 MenuLocators: {}", t.toString());
|
||||
}
|
||||
|
||||
AEBaseEntityBlock<CraftingBlockEntity> b4 = (AEBaseEntityBlock<CraftingBlockEntity>) ModBlocks.ACCELERATOR_4x.get();
|
||||
AEBaseEntityBlock<CraftingBlockEntity> b16 = (AEBaseEntityBlock<CraftingBlockEntity>) ModBlocks.ACCELERATOR_16x.get();
|
||||
AEBaseEntityBlock<CraftingBlockEntity> b64 = (AEBaseEntityBlock<CraftingBlockEntity>) ModBlocks.ACCELERATOR_64x.get();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package com.extendedae_plus.menu.host;
|
||||
|
||||
import appeng.menu.ISubMenu;
|
||||
import appeng.menu.locator.ItemMenuHostLocator;
|
||||
import appeng.api.storage.ISubMenuHost;
|
||||
import de.mari_023.ae2wtlib.api.terminal.ItemWT;
|
||||
import de.mari_023.ae2wtlib.api.terminal.WTMenuHost;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
/**
|
||||
* 适配 ae2wtlib 的 WTMenuHost 到 AE2 期望的 ISubMenuHost。
|
||||
* 仅作为类型桥接,具体行为由 WTMenuHost 超类实现。
|
||||
*/
|
||||
public class CuriosWTSubMenuHost extends WTMenuHost implements ISubMenuHost {
|
||||
public CuriosWTSubMenuHost(ItemWT item,
|
||||
Player player,
|
||||
ItemMenuHostLocator locator,
|
||||
java.util.function.BiConsumer<Player, ISubMenu> returnToMainMenu) {
|
||||
super(item, player, locator, returnToMainMenu);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.extendedae_plus.menu.host;
|
||||
|
||||
import appeng.items.tools.powered.WirelessTerminalItem;
|
||||
import appeng.helpers.WirelessTerminalMenuHost;
|
||||
import appeng.api.storage.ISubMenuHost;
|
||||
import appeng.menu.ISubMenu;
|
||||
import appeng.menu.locator.ItemMenuHostLocator;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
/**
|
||||
* 使用 AE2 原生 WirelessTerminalItem 作为泛型参数,避免在运行时因为 wtlib API 类加载差异而无法强转为 ItemWT。
|
||||
* 实现 ISubMenuHost 以满足 CraftAmountMenu.open 所需宿主接口。
|
||||
*/
|
||||
public class CuriosWTSubMenuHost2 extends WirelessTerminalMenuHost<WirelessTerminalItem> implements ISubMenuHost {
|
||||
public CuriosWTSubMenuHost2(WirelessTerminalItem item,
|
||||
Player player,
|
||||
ItemMenuHostLocator locator,
|
||||
java.util.function.BiConsumer<Player, ISubMenu> returnToMainMenu) {
|
||||
super(item, player, locator, returnToMainMenu);
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,55 @@ public record CuriosItemLocator(String slotId, int index) implements ItemMenuHos
|
|||
@Nullable
|
||||
public <T> T locate(Player player, Class<T> hostInterface) {
|
||||
try {
|
||||
// 先用 locateItem 取得实际物品,避免某些情况下 stacksHandler 为空
|
||||
ItemStack it0 = locateItem(player);
|
||||
if (it0 != null && !it0.isEmpty()) {
|
||||
// 0) AE2 原生:若是 WirelessTerminalItem,先尝试其原生 Host(与背包一致)
|
||||
if (it0.getItem() instanceof appeng.items.tools.powered.WirelessTerminalItem wtAe2) {
|
||||
var aeHost = wtAe2.getMenuHost(player, this, null);
|
||||
if (aeHost != null && hostInterface.isInstance(aeHost)) {
|
||||
try { return hostInterface.cast(aeHost); } catch (Throwable t) { }
|
||||
}
|
||||
if ("appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost2 = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost2(wtAe2, player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost2); } catch (Throwable t) { }
|
||||
}
|
||||
}
|
||||
|
||||
WTDefinition def0 = WTDefinition.ofOrNull(it0);
|
||||
if (def0 != null) {
|
||||
WTMenuHost wtHost = def0.wTMenuHostFactory().create(def0.item(), player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
if (wtHost != null && hostInterface.isInstance(wtHost)) {
|
||||
try { return hostInterface.cast(wtHost); } catch (Throwable t) { }
|
||||
}
|
||||
if ("appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost(def0.item(), player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost); } catch (Throwable t) { }
|
||||
}
|
||||
} else if (it0.getItem() instanceof de.mari_023.ae2wtlib.api.terminal.ItemWT wtItem0) {
|
||||
if ("appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost(wtItem0, player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost); } catch (Throwable t) { }
|
||||
}
|
||||
} else {
|
||||
// 额外兜底:尝试使用 WTDefinition.of(it0)(可能在 ofOrNull 为 null 时仍可获取)
|
||||
try {
|
||||
WTDefinition defStrict = WTDefinition.of(it0);
|
||||
if (defStrict != null && "appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost(defStrict.item(), player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost); } catch (Throwable t) { }
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var opt = CuriosApi.getCuriosInventory(player);
|
||||
if (opt.isPresent()) {
|
||||
var handler = opt.get();
|
||||
|
|
@ -33,36 +82,72 @@ public record CuriosItemLocator(String slotId, int index) implements ItemMenuHos
|
|||
if (stacksHandler != null) {
|
||||
ItemStack it = stacksHandler.getStacks().getStackInSlot(index);
|
||||
if (!it.isEmpty()) {
|
||||
// 1) ae2wtlib: 优先通过 WTDefinition 工厂创建 WTMenuHost(支持量子桥逻辑)
|
||||
WTDefinition def = WTDefinition.ofOrNull(it);
|
||||
if (def != null) {
|
||||
WTMenuHost wtHost = def.wTMenuHostFactory().create(
|
||||
def.item(),
|
||||
player,
|
||||
this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this)
|
||||
);
|
||||
if (hostInterface.isInstance(wtHost)) {
|
||||
return hostInterface.cast(wtHost);
|
||||
// 1) wtlib 优先:WTDefinition 构造 WTMenuHost
|
||||
// 0) AE2 原生:若是 WirelessTerminalItem,先尝试其原生 Host(与背包一致)
|
||||
if (it.getItem() instanceof appeng.items.tools.powered.WirelessTerminalItem wtAe2) {
|
||||
var aeHost = wtAe2.getMenuHost(player, this, null);
|
||||
if (aeHost != null && hostInterface.isInstance(aeHost)) {
|
||||
try { return hostInterface.cast(aeHost); } catch (Throwable t) { }
|
||||
}
|
||||
if ("appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost2 = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost2(wtAe2, player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost2); } catch (Throwable t) { }
|
||||
}
|
||||
}
|
||||
|
||||
// 2) 回退:AE2 原生无线终端(IMenuItem)
|
||||
WTDefinition def = WTDefinition.ofOrNull(it);
|
||||
if (def != null) {
|
||||
WTMenuHost wtHost = def.wTMenuHostFactory().create(
|
||||
def.item(), player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
if (wtHost != null && hostInterface.isInstance(wtHost)) {
|
||||
try { return hostInterface.cast(wtHost); } catch (Throwable t) { }
|
||||
}
|
||||
// 桥接 ISubMenuHost
|
||||
if ("appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost(def.item(), player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost); } catch (Throwable t) { }
|
||||
}
|
||||
} else {
|
||||
// 2) def==null,但物品是 wtlib 的 ItemWT:直接桥接 ISubMenuHost
|
||||
if (it.getItem() instanceof de.mari_023.ae2wtlib.api.terminal.ItemWT wtItem) {
|
||||
if ("appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost(wtItem, player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost); } catch (Throwable t) { }
|
||||
}
|
||||
} else {
|
||||
// 再次兜底:尝试 WTDefinition.of(it) 强制获取
|
||||
try {
|
||||
WTDefinition defStrict2 = WTDefinition.of(it);
|
||||
if (defStrict2 != null && "appeng.api.storage.ISubMenuHost".equals(hostInterface.getName())) {
|
||||
var subHost = new com.extendedae_plus.menu.host.CuriosWTSubMenuHost(defStrict2.item(), player, this,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this));
|
||||
try { return hostInterface.cast(subHost); } catch (Throwable t) { }
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3) 回退:AE2 原生无线终端(IMenuItem)
|
||||
if (it.getItem() instanceof WirelessTerminalItem) {
|
||||
// 由 IMenuItem 提供菜单宿主,定位器传入当前 CuriosItemLocator
|
||||
if (it.getItem() instanceof IMenuItem guiItem) {
|
||||
ItemMenuHost menuHost = guiItem.getMenuHost(player, this, null);
|
||||
if (hostInterface.isInstance(menuHost)) {
|
||||
return hostInterface.cast(menuHost);
|
||||
if (menuHost != null && hostInterface.isInstance(menuHost)) {
|
||||
try { return hostInterface.cast(menuHost); } catch (Throwable t) { }
|
||||
}
|
||||
}
|
||||
} else if (it.getItem() instanceof IMenuItem guiItem) {
|
||||
// 回退:非无线终端,按常规 IMenuItem 处理
|
||||
ItemMenuHost menuHost = guiItem.getMenuHost(player, this, null);
|
||||
if (hostInterface.isInstance(menuHost)) {
|
||||
return hostInterface.cast(menuHost);
|
||||
if (menuHost != null && hostInterface.isInstance(menuHost)) {
|
||||
try { return hostInterface.cast(menuHost); } catch (Throwable t) { }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +164,8 @@ public record CuriosItemLocator(String slotId, int index) implements ItemMenuHos
|
|||
ICuriosItemHandler handler = opt.get();
|
||||
ICurioStacksHandler stacksHandler = handler.getCurios().get(slotId);
|
||||
if (stacksHandler != null) {
|
||||
return stacksHandler.getStacks().getStackInSlot(index);
|
||||
ItemStack s = stacksHandler.getStacks().getStackInSlot(index);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
|
|
|
|||
|
|
@ -50,13 +50,46 @@ public class OpenCraftFromJeiC2SPacket implements CustomPacketPayload {
|
|||
var located = WirelessTerminalLocator.find(player);
|
||||
if (located.isEmpty()) return;
|
||||
|
||||
// 若为 Curios 槽位:直接用 CuriosItemLocator 作为宿主打开数量界面
|
||||
// 若为 Curios 槽位:根据终端类型分别处理
|
||||
String curiosSlotId = located.getCuriosSlotId();
|
||||
int curiosIndex = located.getCuriosIndex();
|
||||
if (curiosSlotId != null && curiosIndex >= 0) {
|
||||
int initial = 1;
|
||||
CraftAmountMenu.open(player, new CuriosItemLocator(curiosSlotId, curiosIndex), what, initial);
|
||||
return;
|
||||
// 兼容 ae2wtlib 与 AE2 原生无线终端
|
||||
var stack = located.stack;
|
||||
// AE2 原生无线终端路径需要做与背包一致的前置校验,避免打开后立即失败
|
||||
if (stack.getItem() instanceof WirelessTerminalItem wt) {
|
||||
var grid = wt.getLinkedGrid(stack, player.level(), null);
|
||||
if (grid == null) { return; }
|
||||
if (!wt.hasPower(player, 0.5, stack)) { return; }
|
||||
var craftingService = grid.getCraftingService();
|
||||
if (!craftingService.isCraftable(what)) { return; }
|
||||
int initial = 1;
|
||||
CraftAmountMenu.open(player, new CuriosItemLocator(curiosSlotId, curiosIndex), what, initial);
|
||||
return;
|
||||
}
|
||||
|
||||
// wtlib 路径:先通过 WTMenuHost 获取 Grid 并检查是否可合成,再打开数量界面
|
||||
try {
|
||||
de.mari_023.ae2wtlib.api.registration.WTDefinition def = de.mari_023.ae2wtlib.api.registration.WTDefinition.ofOrNull(stack);
|
||||
if (def == null) { return; }
|
||||
var wtHost = def.wTMenuHostFactory().create(
|
||||
def.item(),
|
||||
player,
|
||||
new com.extendedae_plus.menu.locator.CuriosItemLocator(curiosSlotId, curiosIndex),
|
||||
(p, sub) -> {}
|
||||
);
|
||||
if (wtHost == null) { return; }
|
||||
if (wtHost.getActionableNode() == null) { return; }
|
||||
if (wtHost.getActionableNode().getGrid() == null) { return; }
|
||||
var grid2 = wtHost.getActionableNode().getGrid();
|
||||
boolean craftable = grid2.getCraftingService().isCraftable(what);
|
||||
if (!craftable) return;
|
||||
int initial = 1;
|
||||
CraftAmountMenu.open(player, new CuriosItemLocator(curiosSlotId, curiosIndex), what, initial);
|
||||
return;
|
||||
} catch (Throwable ignored) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 非 Curios(主手/副手/背包)仍按原先流程做前置校验,保持行为一致。
|
||||
|
|
|
|||
|
|
@ -80,22 +80,26 @@ public class PickFromWirelessC2SPacket implements CustomPacketPayload {
|
|||
String curiosSlotId = located.getCuriosSlotId();
|
||||
int curiosIndex = located.getCuriosIndex();
|
||||
if (curiosSlotId != null && curiosIndex >= 0) {
|
||||
WTDefinition def = WTDefinition.ofOrNull(terminal);
|
||||
if (def != null) {
|
||||
// 与 PullFromJeiOrCraftC2SPacket 保持一致:优先走 AE2 原生路径
|
||||
WirelessCraftingTerminalItem wct = terminal.getItem() instanceof WirelessCraftingTerminalItem c ? c : null;
|
||||
WirelessTerminalItem wt = wct != null ? wct : (terminal.getItem() instanceof WirelessTerminalItem t ? t : null);
|
||||
if (wt != null) {
|
||||
grid = wt.getLinkedGrid(terminal, level, null);
|
||||
if (grid == null) return;
|
||||
if (!wt.hasPower(player, 0.5, terminal)) return;
|
||||
} else {
|
||||
// 非 AE2 原生无线终端(极少数情况),再尝试 wtlib host
|
||||
WTDefinition def = WTDefinition.ofOrNull(terminal);
|
||||
if (def == null) return;
|
||||
WTMenuHost wtHost = def.wTMenuHostFactory().create(
|
||||
def.item(),
|
||||
player,
|
||||
new CuriosItemLocator(curiosSlotId, curiosIndex),
|
||||
(p, sub) -> {}
|
||||
);
|
||||
if (wtHost != null && wtHost.getActionableNode() != null && wtHost.getActionableNode().getGrid() != null) {
|
||||
grid = wtHost.getActionableNode().getGrid();
|
||||
usedWtHost = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
if (wtHost == null || wtHost.getActionableNode() == null || wtHost.getActionableNode().getGrid() == null) return;
|
||||
grid = wtHost.getActionableNode().getGrid();
|
||||
usedWtHost = true;
|
||||
}
|
||||
} else {
|
||||
// AE2 原生路径
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import appeng.items.tools.powered.WirelessTerminalItem;
|
|||
import appeng.me.helpers.PlayerSource;
|
||||
import appeng.menu.locator.MenuLocators;
|
||||
import appeng.menu.me.crafting.CraftAmountMenu;
|
||||
import com.extendedae_plus.menu.locator.CuriosItemLocator;
|
||||
import com.extendedae_plus.util.WirelessTerminalLocator;
|
||||
import com.extendedae_plus.util.WirelessTerminalLocator.LocatedTerminal;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
|
|
@ -89,6 +90,14 @@ public class PullFromJeiOrCraftC2SPacket implements CustomPacketPayload {
|
|||
var craftingService = grid.getCraftingService();
|
||||
if (!craftingService.isCraftable(what)) return;
|
||||
|
||||
// Curios 槽位优先:使用 CuriosItemLocator 打开数量界面
|
||||
String curiosSlotId = located.getCuriosSlotId();
|
||||
int curiosIndex = located.getCuriosIndex();
|
||||
if (curiosSlotId != null && curiosIndex >= 0) {
|
||||
CraftAmountMenu.open(player, new CuriosItemLocator(curiosSlotId, curiosIndex), what, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
var hand = located.getHand();
|
||||
int slot = located.getSlotIndex();
|
||||
if (hand != null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user