修修修,优化交互逻辑,支持curios中通用终端的量子卡
This commit is contained in:
parent
f571790d5e
commit
8b66b3bb7f
|
|
@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
|
|||
loom.platform = forge
|
||||
|
||||
# Mod properties
|
||||
mod_version = 1.2.1
|
||||
mod_version = 1.2.1-fix
|
||||
maven_group = com.extendedae_plus
|
||||
archives_name = extendedae_plus
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
package com.extendedae_plus.menu.host;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import appeng.menu.ISubMenu;
|
||||
import de.mari_023.ae2wtlib.terminal.WTMenuHost;
|
||||
|
||||
// Curios API
|
||||
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
|
||||
|
||||
/**
|
||||
* 针对 Curios 槽位的 ae2wtlib WTMenuHost 适配器:
|
||||
* - 复用 wtlib 的量子卡跨维/跨距逻辑(rangeCheck/isQuantumLinked)。
|
||||
* - 覆写槽位校验与回写,改为使用 Curios 实际槽位,避免 wtlib 的 Trinkets 平台判断失效。
|
||||
*/
|
||||
public class CuriosWTMenuHost extends WTMenuHost {
|
||||
private final ICurioStacksHandler curiosHandler;
|
||||
private final int curiosIndex;
|
||||
|
||||
public CuriosWTMenuHost(Player player,
|
||||
@Nullable Integer inventorySlot,
|
||||
ItemStack is,
|
||||
ICurioStacksHandler curiosHandler,
|
||||
int curiosIndex,
|
||||
BiConsumer<Player, ISubMenu> returnToMainMenu) {
|
||||
super(player, inventorySlot, is, returnToMainMenu);
|
||||
this.curiosHandler = curiosHandler;
|
||||
this.curiosIndex = curiosIndex;
|
||||
// 初始化内部库存(含奇点槽),以便量子桥判定能够读取到频率等 NBT
|
||||
try {
|
||||
super.readFromNbt();
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean ensureItemStillInSlot() {
|
||||
try {
|
||||
ItemStack cur = curiosHandler.getStacks().getStackInSlot(curiosIndex);
|
||||
return !cur.isEmpty();
|
||||
} catch (Throwable ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBroadcastChanges(AbstractContainerMenu menu) {
|
||||
try {
|
||||
ItemStack current = getItemStack();
|
||||
curiosHandler.getStacks().setStackInSlot(curiosIndex, current);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
return super.onBroadcastChanges(menu);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,12 @@ import appeng.menu.me.common.MEStorageMenu;
|
|||
import appeng.menu.locator.MenuLocator;
|
||||
import com.extendedae_plus.menu.host.CuriosWirelessTerminalMenuHost;
|
||||
|
||||
// ae2wtlib
|
||||
import de.mari_023.ae2wtlib.wut.WUTHandler;
|
||||
import de.mari_023.ae2wtlib.wut.WTDefinition;
|
||||
import de.mari_023.ae2wtlib.terminal.WTMenuHost;
|
||||
import com.extendedae_plus.menu.host.CuriosWTMenuHost;
|
||||
|
||||
// Curios API (软依赖)
|
||||
import top.theillusivec4.curios.api.CuriosApi;
|
||||
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
|
||||
|
|
@ -35,8 +41,26 @@ public record CuriosItemLocator(String slotId, int index) implements MenuLocator
|
|||
if (stacksHandler != null) {
|
||||
ItemStack it = stacksHandler.getStacks().getStackInSlot(index);
|
||||
if (!it.isEmpty()) {
|
||||
// 1) ae2wtlib: 优先构造 WTMenuHost 以启用量子卡的跨维/跨距逻辑
|
||||
String current = WUTHandler.getCurrentTerminal(it);
|
||||
WTDefinition def = WUTHandler.wirelessTerminals.get(current);
|
||||
if (def != null) {
|
||||
WTMenuHost wtHost = new CuriosWTMenuHost(
|
||||
player,
|
||||
null,
|
||||
it,
|
||||
stacksHandler,
|
||||
index,
|
||||
(p, sub) -> MenuOpener.open(MEStorageMenu.WIRELESS_TYPE, p, this)
|
||||
);
|
||||
if (hostInterface.isInstance(wtHost)) {
|
||||
return hostInterface.cast(wtHost);
|
||||
}
|
||||
}
|
||||
|
||||
// 2) 回退:AE2 原生无线终端
|
||||
if (it.getItem() instanceof WirelessTerminalItem) {
|
||||
// 为 Curios 构建一个带回写能力的宿主
|
||||
// 首选:为 CraftAmountMenu 等需要网络/能量上下文的菜单提供 WirelessTerminalMenuHost
|
||||
WirelessTerminalMenuHost host = new CuriosWirelessTerminalMenuHost(
|
||||
player,
|
||||
it,
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@ import net.minecraft.world.level.GameType;
|
|||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import com.extendedae_plus.network.ModNetwork;
|
||||
import com.extendedae_plus.network.PickFromWirelessC2SPacket;
|
||||
// no client-side WCT gating; server will check presence (including Curios)
|
||||
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
|
|
@ -32,8 +35,35 @@ public class PickFromWirelessMixin {
|
|||
if (type == null || type.isCreative()) {
|
||||
return;
|
||||
}
|
||||
// 发送到服务端处理
|
||||
// 若背包已有该物品,让原版逻辑处理(将该物品切换到主手)
|
||||
BlockHitResult bhr = (BlockHitResult) this.hitResult;
|
||||
var level = Minecraft.getInstance().level;
|
||||
if (level != null) {
|
||||
try {
|
||||
BlockState state = level.getBlockState(bhr.getBlockPos());
|
||||
if (state != null && !state.isAir()) {
|
||||
ItemStack picked = state.getBlock().getCloneItemStack(state, bhr, level, bhr.getBlockPos(), this.player);
|
||||
if (picked.isEmpty()) {
|
||||
picked = state.getBlock().asItem().getDefaultInstance();
|
||||
}
|
||||
if (!picked.isEmpty()) {
|
||||
// 若主手已拿同一物品(含标签),则仍然走 AE 拉取逻辑进行补充/合并
|
||||
if (!ItemStack.isSameItemSameTags(picked, this.player.getMainHandItem())) {
|
||||
int slot = this.player.getInventory().findSlotMatchingItem(picked);
|
||||
if (slot != -1) {
|
||||
return; // 交给原版 pickBlock 处理
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// 若其它模组导致 getCloneItemStack 出异常,放弃拦截,保持原版行为,确保健壮性
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 不在客户端检查是否持有无线合成终端,由服务端权威校验(含 Curios 支持),以避免整合包环境下的软依赖与槽位问题
|
||||
// 背包没有:发送到服务端处理(从 AE2 网络拉取)并拦截原版
|
||||
Vec3 loc = bhr.getLocation();
|
||||
ModNetwork.CHANNEL.sendToServer(new PickFromWirelessC2SPacket(bhr.getBlockPos(), bhr.getDirection(), loc));
|
||||
ci.cancel();
|
||||
|
|
|
|||
|
|
@ -50,6 +50,17 @@ public class OpenCraftFromJeiC2SPacket {
|
|||
var located = WirelessTerminalLocator.find(player);
|
||||
if (located.isEmpty()) return;
|
||||
|
||||
// 若为 Curios 槽位:跳过 AE2 基类的距离/电量前置校验,直接打开数量界面,
|
||||
// 让菜单与宿主(WirelessTerminalMenuHost)以及 ae2wtlib 自身处理量子卡跨维/跨距逻辑。
|
||||
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;
|
||||
}
|
||||
|
||||
// 非 Curios(主手/副手/背包)仍按原先流程做前置校验,保持行为一致。
|
||||
if (!(located.stack.getItem() instanceof WirelessTerminalItem wt)) return;
|
||||
|
||||
// 基本前置校验:联网、电量
|
||||
|
|
@ -71,15 +82,7 @@ public class OpenCraftFromJeiC2SPacket {
|
|||
int initial = 1; // 初始数量,避免依赖具体 Key 的单位定义
|
||||
CraftAmountMenu.open(player, MenuLocators.forInventorySlot(slot), what, initial);
|
||||
} else {
|
||||
// Curios 槽位:使用自定义定位器携带 slotId + index 作为菜单宿主
|
||||
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);
|
||||
} else {
|
||||
// 未知宿主(回退忽略)
|
||||
}
|
||||
// 未知宿主(回退忽略)
|
||||
}
|
||||
});
|
||||
context.setPacketHandled(true);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ import appeng.api.stacks.AEItemKey;
|
|||
import appeng.api.networking.energy.IEnergyService;
|
||||
import appeng.me.helpers.PlayerSource;
|
||||
import appeng.items.tools.powered.WirelessCraftingTerminalItem;
|
||||
import appeng.items.tools.powered.WirelessTerminalItem;
|
||||
// ae2wtlib
|
||||
import de.mari_023.ae2wtlib.wut.WUTHandler;
|
||||
import de.mari_023.ae2wtlib.wut.WTDefinition;
|
||||
import de.mari_023.ae2wtlib.terminal.WTMenuHost;
|
||||
import com.extendedae_plus.util.WirelessTerminalLocator;
|
||||
import com.extendedae_plus.util.WirelessTerminalLocator.LocatedTerminal;
|
||||
|
||||
|
|
@ -68,18 +73,56 @@ public class PickFromWirelessC2SPacket {
|
|||
// 服务端权威:定位玩家任意槽位的无线终端(含 Curios)
|
||||
LocatedTerminal located = WirelessTerminalLocator.find(player);
|
||||
ItemStack terminal = located.stack;
|
||||
WirelessCraftingTerminalItem wt = terminal.getItem() instanceof WirelessCraftingTerminalItem w ? w : null;
|
||||
if (wt == null || terminal.isEmpty()) {
|
||||
if (terminal.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 校验网络与电量
|
||||
IGrid grid = wt.getLinkedGrid(terminal, level, player);
|
||||
if (grid == null) {
|
||||
return;
|
||||
}
|
||||
if (!wt.hasPower(player, 0.5, terminal)) {
|
||||
return;
|
||||
IGrid grid;
|
||||
boolean usedWtHost = false;
|
||||
// 若来自 Curios:优先通过 ae2wtlib 的 WTMenuHost 获取量子桥网络,绕过距离限制
|
||||
String curiosSlotId = located.getCuriosSlotId();
|
||||
int curiosIndex = located.getCuriosIndex();
|
||||
WTMenuHost wtHost = null;
|
||||
if (curiosSlotId != null && curiosIndex >= 0) {
|
||||
String current = WUTHandler.getCurrentTerminal(terminal);
|
||||
WTDefinition def = WUTHandler.wirelessTerminals.get(current);
|
||||
if (def != null) {
|
||||
wtHost = def.wTMenuHostFactory().create(player, null, terminal, (p, sub) -> {});
|
||||
if (wtHost != null) {
|
||||
var node = wtHost.getActionableNode();
|
||||
if (node != null) {
|
||||
grid = node.getGrid();
|
||||
if (grid == null) {
|
||||
return;
|
||||
}
|
||||
// 通过 WTMenuHost 的电力处理以兼容量子卡补能
|
||||
if (!wtHost.drainPower()) {
|
||||
return;
|
||||
}
|
||||
usedWtHost = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 非 Curios:按 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) {
|
||||
return;
|
||||
}
|
||||
grid = wt.getLinkedGrid(terminal, level, player);
|
||||
if (grid == null) {
|
||||
return;
|
||||
}
|
||||
if (!wt.hasPower(player, 0.5, terminal)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算 pick 对应的物品:使用客户端实际命中位置,保证多部件方块(AE2 CableBus/部件)能返回正确克隆物品
|
||||
|
|
@ -150,7 +193,16 @@ public class PickFromWirelessC2SPacket {
|
|||
inv.setItem(free, targetKey.toStack((int) extracted));
|
||||
}
|
||||
|
||||
wt.usePower(player, Math.max(0.5, extracted * 0.05), terminal);
|
||||
if (usedWtHost) {
|
||||
// WTMenuHost 已在 drainPower 中处理能量消耗/回充,此处不重复扣除
|
||||
} else {
|
||||
// 原生 AE2 扣能
|
||||
WirelessCraftingTerminalItem wct2 = terminal.getItem() instanceof WirelessCraftingTerminalItem c2 ? c2 : null;
|
||||
WirelessTerminalItem wt2 = wct2 != null ? wct2 : (terminal.getItem() instanceof WirelessTerminalItem t2 ? t2 : null);
|
||||
if (wt2 != null) {
|
||||
wt2.usePower(player, Math.max(0.5, extracted * 0.05), terminal);
|
||||
}
|
||||
}
|
||||
// 确保写回(若位于 Curios 等需要显式写回的容器)
|
||||
located.commit();
|
||||
player.containerMenu.broadcastChanges();
|
||||
|
|
|
|||
|
|
@ -9,12 +9,13 @@ import net.minecraftforge.fml.ModList;
|
|||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import appeng.items.tools.powered.WirelessCraftingTerminalItem;
|
||||
import appeng.items.tools.powered.WirelessTerminalItem;
|
||||
|
||||
// Curios API (软依赖)
|
||||
import top.theillusivec4.curios.api.CuriosApi;
|
||||
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
|
||||
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
|
||||
import top.theillusivec4.curios.api.type.inventory.IDynamicStackHandler;
|
||||
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
|
||||
|
||||
/**
|
||||
* 定位玩家身上的无线终端:
|
||||
|
|
@ -75,11 +76,11 @@ public final class WirelessTerminalLocator {
|
|||
|
||||
// 1) 先检查主手/副手
|
||||
var main = player.getMainHandItem();
|
||||
if (!main.isEmpty() && main.getItem() instanceof WirelessCraftingTerminalItem) {
|
||||
if (!main.isEmpty() && (main.getItem() instanceof WirelessCraftingTerminalItem || main.getItem() instanceof WirelessTerminalItem)) {
|
||||
return new LocatedTerminal(main, (ns) -> player.setItemInHand(net.minecraft.world.InteractionHand.MAIN_HAND, ns), -1, net.minecraft.world.InteractionHand.MAIN_HAND);
|
||||
}
|
||||
var off = player.getOffhandItem();
|
||||
if (!off.isEmpty() && off.getItem() instanceof WirelessCraftingTerminalItem) {
|
||||
if (!off.isEmpty() && (off.getItem() instanceof WirelessCraftingTerminalItem || off.getItem() instanceof WirelessTerminalItem)) {
|
||||
return new LocatedTerminal(off, (ns) -> player.setItemInHand(net.minecraft.world.InteractionHand.OFF_HAND, ns), -1, net.minecraft.world.InteractionHand.OFF_HAND);
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +89,7 @@ public final class WirelessTerminalLocator {
|
|||
int size = inv.getContainerSize();
|
||||
for (int i = 0; i < size; i++) {
|
||||
ItemStack st = inv.getItem(i);
|
||||
if (!st.isEmpty() && st.getItem() instanceof WirelessCraftingTerminalItem) {
|
||||
if (!st.isEmpty() && (st.getItem() instanceof WirelessCraftingTerminalItem || st.getItem() instanceof WirelessTerminalItem)) {
|
||||
final int slot = i;
|
||||
return new LocatedTerminal(st, (ns) -> inv.setItem(slot, ns), slot);
|
||||
}
|
||||
|
|
@ -97,7 +98,6 @@ public final class WirelessTerminalLocator {
|
|||
// 3) Curios 饰品槽(若已加载)
|
||||
if (ModList.get().isLoaded("curios")) {
|
||||
try {
|
||||
// Curios 1.20.x: 通过 CuriosApi.getCuriosInventory 获取 LazyOptional
|
||||
var resolved = CuriosApi.getCuriosInventory(player).resolve();
|
||||
if (resolved.isPresent()) {
|
||||
ICuriosItemHandler handler = resolved.get();
|
||||
|
|
@ -108,10 +108,10 @@ public final class WirelessTerminalLocator {
|
|||
int slots = stacks.getSlots();
|
||||
for (int i = 0; i < slots; i++) {
|
||||
ItemStack st = stacks.getStackInSlot(i);
|
||||
if (!st.isEmpty() && st.getItem() instanceof WirelessCraftingTerminalItem) {
|
||||
if (!st.isEmpty() && (st.getItem() instanceof WirelessCraftingTerminalItem || st.getItem() instanceof WirelessTerminalItem)) {
|
||||
final int slot = i;
|
||||
// 记录 Curios 槽位标识与索引,供应后续使用自定义 MenuLocator 打开菜单
|
||||
return new LocatedTerminal(st, (ns) -> stacks.setStackInSlot(slot, ns), -1, null, slotId, slot);
|
||||
java.util.function.Consumer<ItemStack> setter = (ns) -> stacks.setStackInSlot(slot, ns);
|
||||
return new LocatedTerminal(st, setter, -1, null, slotId, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user