From 5b1ae12f8551581cfa5d6098d7363ce401fe85d8 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 19 Mar 2025 16:50:43 +0700 Subject: [PATCH] Prioritize slots with filter or items across all chests --- .../dbotthepony/mc/otm/menu/QuickMoveInput.kt | 20 +++---- .../mc/otm/network/MatteryPlayerPackets.kt | 53 ++++++++++++------- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/QuickMoveInput.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/QuickMoveInput.kt index 563f9e93c..7deac409c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/QuickMoveInput.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/QuickMoveInput.kt @@ -16,20 +16,21 @@ import ru.dbotthepony.mc.otm.core.util.asKey import ru.dbotthepony.mc.otm.core.util.asKeyOrNull class QuickMoveInput(private val menu: MatteryMenu, val from: Collection, val to: Collection, val mode: Mode, val dontTouchFilteredSlots: Boolean = true) { + /** + * slots with items come first + */ object HasItemComparator : Comparator { override fun compare(a: Slot, b: Slot): Int { val hasItemA = a.item.isNotEmpty val hasItemB = b.item.isNotEmpty - if (hasItemA == hasItemB) - return 0 - else if (hasItemA) - return -1 - else - return 1 + return hasItemB.compareTo(hasItemA) } } + /** + * slots with filters come first + */ object HasFilterComparator : Comparator { override fun compare(a: Slot, b: Slot): Int { val slotA = a.containerSlotOrNull() @@ -38,12 +39,7 @@ class QuickMoveInput(private val menu: MatteryMenu, val from: Collection, val hasFilterA = slotA is IFilteredContainerSlot && slotA.hasFilter val hasFilterB = slotB is IFilteredContainerSlot && slotB.hasFilter - if (hasFilterA == hasFilterB) - return 0 - else if (hasFilterA) - return -1 - else - return 1 + return hasFilterB.compareTo(hasFilterA) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerPackets.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerPackets.kt index ab82f1c57..bf17ce3bb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerPackets.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/MatteryPlayerPackets.kt @@ -9,16 +9,12 @@ import net.minecraft.network.codec.StreamCodec import net.minecraft.network.protocol.common.custom.CustomPacketPayload import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.entity.ai.attributes.Attributes import net.minecraft.world.entity.player.Inventory import net.minecraft.world.inventory.Slot import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.ChunkPos -import net.minecraft.world.level.ClipBlockStateContext import net.minecraft.world.level.block.entity.BlockEntity -import net.minecraft.world.level.block.state.BlockState -import net.minecraft.world.phys.Vec3 -import net.neoforged.neoforge.common.NeoForgeMod import net.neoforged.neoforge.network.handling.IPayloadContext import org.apache.logging.log4j.LogManager import ru.dbotthepony.kommons.math.RGBAColor @@ -28,10 +24,11 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.player.MatteryPlayer import ru.dbotthepony.mc.otm.player.matteryPlayer import ru.dbotthepony.mc.otm.client.minecraft +import ru.dbotthepony.mc.otm.container.IFilteredContainerSlot import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.set +import ru.dbotthepony.mc.otm.container.util.containerSlotOrNull import ru.dbotthepony.mc.otm.core.ResourceLocation -import ru.dbotthepony.mc.otm.core.getChunkNow import ru.dbotthepony.mc.otm.core.math.Vector import ru.dbotthepony.mc.otm.core.math.component1 import ru.dbotthepony.mc.otm.core.math.component2 @@ -467,21 +464,41 @@ class QuickStackPacket( findCaps.sortBy { it.first.blockPos.distToCenterSqr(player.position) } val eyes = player.eyePosition - val ignoreBlockstates = HashSet() - findCaps.forEach { (b, _) -> ignoreBlockstates.add(b.blockState) } + val ignorePositions = HashSet() + findCaps.forEach { (b) -> ignorePositions.add(b.blockPos) } + val level = player.serverLevel() - for ((blockEntity, cap) in findCaps) { - // don't interact through walls - val trace = player.serverLevel().isBlockInLine(ClipBlockStateContext(eyes, Vector.atCenterOf(blockEntity.blockPos)) { - !it.isAir && it !in ignoreBlockstates - }) + // don't interact through walls + // but interact through chests + findCaps.removeIf { (b) -> + BlockGetter.traverseBlocks(eyes, Vector.atCenterOf(b.blockPos), null, { _, pos -> if (pos !in ignorePositions && !level.getBlockState(pos).isAir) true else null }, { false }) + } - if (trace.blockPos == blockEntity.blockPos) { - if (fromExopack) - mode.move(player.matteryPlayer.exoPackMenu.playerCombinedInventorySlots, cap.getSlotsFor(player), player) - else - mode.move(cap.getSlotsFor(player), player.matteryPlayer.exoPackMenu.playerInventorySlots, player, false) + if (fromExopack) { + val prioritySlots = ArrayList() + val regularSlots = ArrayList>() + + for ((_, cap) in findCaps) { + val slots = cap.getSlotsFor(player) + + slots.forEach { + val slot = it.containerSlotOrNull() + + if (it.hasItem() || slot is IFilteredContainerSlot && slot.hasFilter) + prioritySlots.add(it) + } + + regularSlots.add(slots) } + + mode.move(player.matteryPlayer.exoPackMenu.playerCombinedInventorySlots, prioritySlots, player) + + regularSlots.forEach { + mode.move(player.matteryPlayer.exoPackMenu.playerCombinedInventorySlots, it, player) + } + } else { + for ((_, cap) in findCaps) + mode.move(cap.getSlotsFor(player), player.matteryPlayer.exoPackMenu.playerInventorySlots, player, false) } }