diff --git a/src/main/java/com/extendedae_plus/mixin/PickFromWirelessMixin.java b/src/main/java/com/extendedae_plus/mixin/PickFromWirelessMixin.java index b6bb81a..99d41a4 100644 --- a/src/main/java/com/extendedae_plus/mixin/PickFromWirelessMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/PickFromWirelessMixin.java @@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; 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 com.extendedae_plus.network.ModNetwork; @@ -33,7 +34,8 @@ public class PickFromWirelessMixin { } // 发送到服务端处理 BlockHitResult bhr = (BlockHitResult) this.hitResult; - ModNetwork.CHANNEL.sendToServer(new PickFromWirelessC2SPacket(bhr.getBlockPos(), bhr.getDirection())); + Vec3 loc = bhr.getLocation(); + ModNetwork.CHANNEL.sendToServer(new PickFromWirelessC2SPacket(bhr.getBlockPos(), bhr.getDirection(), loc)); ci.cancel(); } } diff --git a/src/main/java/com/extendedae_plus/network/PickFromWirelessC2SPacket.java b/src/main/java/com/extendedae_plus/network/PickFromWirelessC2SPacket.java index 4416d65..7c5d599 100644 --- a/src/main/java/com/extendedae_plus/network/PickFromWirelessC2SPacket.java +++ b/src/main/java/com/extendedae_plus/network/PickFromWirelessC2SPacket.java @@ -10,6 +10,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.network.NetworkEvent; import net.minecraft.network.FriendlyByteBuf; @@ -26,21 +27,29 @@ import com.extendedae_plus.util.WirelessTerminalLocator.LocatedTerminal; public class PickFromWirelessC2SPacket { private final BlockPos pos; private final Direction face; + private final Vec3 hitLoc; - public PickFromWirelessC2SPacket(BlockPos pos, Direction face) { + public PickFromWirelessC2SPacket(BlockPos pos, Direction face, Vec3 hitLoc) { this.pos = pos; this.face = face; + this.hitLoc = hitLoc; } public static void encode(PickFromWirelessC2SPacket msg, FriendlyByteBuf buf) { buf.writeBlockPos(msg.pos); buf.writeEnum(msg.face); + buf.writeDouble(msg.hitLoc.x); + buf.writeDouble(msg.hitLoc.y); + buf.writeDouble(msg.hitLoc.z); } public static PickFromWirelessC2SPacket decode(FriendlyByteBuf buf) { BlockPos pos = buf.readBlockPos(); Direction face = buf.readEnum(Direction.class); - return new PickFromWirelessC2SPacket(pos, face); + double x = buf.readDouble(); + double y = buf.readDouble(); + double z = buf.readDouble(); + return new PickFromWirelessC2SPacket(pos, face, new Vec3(x, y, z)); } public static void handle(PickFromWirelessC2SPacket msg, Supplier ctx) { @@ -73,8 +82,8 @@ public class PickFromWirelessC2SPacket { return; } - // 计算 pick 对应的物品 - BlockHitResult bhr = new BlockHitResult(player.position(), msg.face, msg.pos, true); + // 计算 pick 对应的物品:使用客户端实际命中位置,保证多部件方块(AE2 CableBus/部件)能返回正确克隆物品 + BlockHitResult bhr = new BlockHitResult(msg.hitLoc, msg.face, msg.pos, true); ItemStack picked = state.getBlock().getCloneItemStack(state, bhr, level, msg.pos, player); if (picked.isEmpty()) { // 兜底用方块本身 @@ -91,27 +100,56 @@ public class PickFromWirelessC2SPacket { MEStorage storage = grid.getStorageService().getInventory(); ItemStack inHand = player.getMainHandItem(); + var inv = player.getInventory(); - // 若主手有物品:尝试将其移动到玩家背包的空槽位;若没有空位则中止 - if (!inHand.isEmpty()) { - var inv = player.getInventory(); + // 决定放置目标: + // 1) 若主手为空 -> 放主手,空间为整组 + // 2) 若主手为同一物品且未满 -> 合并到主手,空间为主手剩余空间 + // 3) 其他情况(主手不为空且不是同物品)-> 放入背包空槽,空间为整组 + boolean handIsSameItem = !inHand.isEmpty() && AEItemKey.of(inHand).equals(targetKey); + boolean placeToMainHand = inHand.isEmpty() || (handIsSameItem && inHand.getCount() < inHand.getMaxStackSize()); + + int space; + if (placeToMainHand) { + space = inHand.isEmpty() ? targetMax : Math.min(targetMax, inHand.getMaxStackSize() - inHand.getCount()); + } else { int free = inv.getFreeSlot(); if (free == -1) { return; // 背包已满,不进行拉取 } - // 将主手整组移动到空槽位 - inv.setItem(free, inHand.copy()); - inv.setItem(inv.selected, ItemStack.EMPTY); + space = targetMax; + } + + if (space <= 0) { + return; } - // 现在主手应为空:拉取目标物品,尽量填满一组 - int space = targetMax; // 主手为空,目标为一整组 long extracted = StorageHelper.poweredExtraction(energy, storage, targetKey, space, new PlayerSource(player)); if (extracted <= 0) { return; } - player.getInventory().setItem(player.getInventory().selected, targetKey.toStack((int) extracted)); + if (placeToMainHand) { + if (inHand.isEmpty()) { + inv.setItem(inv.selected, targetKey.toStack((int) extracted)); + } else { + // 合并到主手 + int add = (int) Math.min(extracted, inHand.getMaxStackSize() - inHand.getCount()); + if (add > 0) { + inHand.grow(add); + inv.setItem(inv.selected, inHand); // 写回以确保同步 + } + } + } else { + int free = inv.getFreeSlot(); + if (free == -1) { + // 理论上不会发生(上面已判断),为安全起见:将提取物退回网络 + StorageHelper.poweredInsert(energy, storage, targetKey, extracted, new PlayerSource(player)); + return; + } + inv.setItem(free, targetKey.toStack((int) extracted)); + } + wt.usePower(player, Math.max(0.5, extracted * 0.05), terminal); // 确保写回(若位于 Curios 等需要显式写回的容器) located.commit();