|
|
|
@ -15,22 +15,60 @@ import ru.dbotthepony.mc.otm.core.util.ItemStackKey
|
|
|
|
|
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<Slot>, val to: Collection<Slot>, val mode: Mode) {
|
|
|
|
|
class QuickMoveInput(private val menu: MatteryMenu, val from: Collection<Slot>, val to: Collection<Slot>, val mode: Mode, val dontTouchFilteredSlots: Boolean = true) {
|
|
|
|
|
object HasItemComparator : Comparator<Slot> {
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object HasFilterComparator : Comparator<Slot> {
|
|
|
|
|
override fun compare(a: Slot, b: Slot): Int {
|
|
|
|
|
val slotA = a.containerSlotOrNull()
|
|
|
|
|
val slotB = b.containerSlotOrNull()
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum class Mode(val iconFromStorage: AbstractMatterySprite, val iconToStorage: AbstractMatterySprite) {
|
|
|
|
|
RESTOCK(
|
|
|
|
|
Widgets18.RESTOCK_FROM_STORAGE,
|
|
|
|
|
Widgets18.RESTOCK_TO_STORAGE
|
|
|
|
|
) {
|
|
|
|
|
override fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player) {
|
|
|
|
|
override fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player, dontTouchFilteredSlots: Boolean) {
|
|
|
|
|
if (from.isEmpty() || to.isEmpty()) return
|
|
|
|
|
val (_, itemsFrom) = computeSlotLists(from, true)
|
|
|
|
|
val (_, itemsFrom) = computeSlotLists(from, dontTouchFilteredSlots)
|
|
|
|
|
val (_, itemsTo) = computeSlotLists(to, false)
|
|
|
|
|
|
|
|
|
|
val intersect = if (itemsFrom.size < itemsTo.size) itemsFrom.keys.filter { it in itemsTo.keys } else itemsTo.keys.filter { it in itemsFrom.keys }
|
|
|
|
|
|
|
|
|
|
for (key in intersect) {
|
|
|
|
|
val slotsTo = itemsTo[key]!!
|
|
|
|
|
itemsFrom[key]!!.forEach { moveItemStackTo(player, it, slotsTo) }
|
|
|
|
|
val slotsFrom = itemsFrom[key]!!
|
|
|
|
|
|
|
|
|
|
if (!dontTouchFilteredSlots) {
|
|
|
|
|
// touch filtered slots last
|
|
|
|
|
slotsFrom.sortWith(HasFilterComparator.reversed())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
slotsFrom.forEach { moveItemStackTo(player, it, slotsTo) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
@ -39,9 +77,9 @@ class QuickMoveInput(private val menu: MatteryMenu, val from: Collection<Slot>,
|
|
|
|
|
Widgets18.RESTOCK_WITH_MOVE_FROM_STORAGE,
|
|
|
|
|
Widgets18.RESTOCK_WITH_MOVE_TO_STORAGE
|
|
|
|
|
) {
|
|
|
|
|
override fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player) {
|
|
|
|
|
override fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player, dontTouchFilteredSlots: Boolean) {
|
|
|
|
|
if (from.isEmpty() || to.isEmpty()) return
|
|
|
|
|
val (_, itemsFrom) = computeSlotLists(from, true)
|
|
|
|
|
val (_, itemsFrom) = computeSlotLists(from, dontTouchFilteredSlots)
|
|
|
|
|
val (emptyTo, itemsTo) = computeSlotLists(to, false)
|
|
|
|
|
|
|
|
|
|
val intersect = if (itemsFrom.size < itemsTo.size) itemsFrom.keys.filter { it in itemsTo.keys } else itemsTo.keys.filter { it in itemsFrom.keys }
|
|
|
|
@ -49,6 +87,12 @@ class QuickMoveInput(private val menu: MatteryMenu, val from: Collection<Slot>,
|
|
|
|
|
for (key in intersect) {
|
|
|
|
|
val slotsTo = prioritySortSlots(itemsTo[key]!!, key.asItemStack())
|
|
|
|
|
val slotsFrom = itemsFrom[key]!!
|
|
|
|
|
|
|
|
|
|
if (!dontTouchFilteredSlots) {
|
|
|
|
|
// touch filtered slots last
|
|
|
|
|
slotsFrom.sortWith(HasFilterComparator.reversed())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
slotsFrom.removeIf { moveItemStackTo(player, it, slotsTo, sort = false); it.item.isEmpty }
|
|
|
|
|
var moveAny = false
|
|
|
|
|
slotsFrom.forEach { moveAny = moveItemStackTo(player, it, emptyTo, sort = false) || moveAny }
|
|
|
|
@ -61,20 +105,20 @@ class QuickMoveInput(private val menu: MatteryMenu, val from: Collection<Slot>,
|
|
|
|
|
Widgets18.MOVE_EVERYTHING_FROM_STORAGE,
|
|
|
|
|
Widgets18.MOVE_EVERYTHING_TO_STORAGE
|
|
|
|
|
) {
|
|
|
|
|
override fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player) {
|
|
|
|
|
override fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player, dontTouchFilteredSlots: Boolean) {
|
|
|
|
|
if (from.isEmpty() || to.isEmpty()) return
|
|
|
|
|
val toSorted = prioritySortSlots(to)
|
|
|
|
|
|
|
|
|
|
from.forEach {
|
|
|
|
|
val slot = it.containerSlotOrNull()
|
|
|
|
|
|
|
|
|
|
if (slot !is IFilteredContainerSlot || !slot.hasFilter)
|
|
|
|
|
if (!dontTouchFilteredSlots || slot !is IFilteredContainerSlot || !slot.hasFilter)
|
|
|
|
|
moveItemStackTo(player, it, toSorted, sort = false)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
abstract fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player)
|
|
|
|
|
abstract fun move(from: Collection<Slot>, to: Collection<Slot>, player: Player, dontTouchFilteredSlots: Boolean = true)
|
|
|
|
|
|
|
|
|
|
val textFromStorage: Component get() {
|
|
|
|
|
return TranslatableComponent("otm.gui.quickmove_from.${name.lowercase()}")
|
|
|
|
@ -92,12 +136,12 @@ class QuickMoveInput(private val menu: MatteryMenu, val from: Collection<Slot>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun handle() {
|
|
|
|
|
mode.move(from, to, menu.player)
|
|
|
|
|
mode.move(from, to, menu.player, dontTouchFilteredSlots)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
fun create(menu: MatteryMenu, from: Collection<Slot>, to: Collection<Slot>): Map<Mode, QuickMoveInput> {
|
|
|
|
|
return Mode.entries.associateWith { QuickMoveInput(menu, from, to, it) }
|
|
|
|
|
fun create(menu: MatteryMenu, from: Collection<Slot>, to: Collection<Slot>, dontTouchFilteredSlots: Boolean = true): Map<Mode, QuickMoveInput> {
|
|
|
|
|
return Mode.entries.associateWith { QuickMoveInput(menu, from, to, it, dontTouchFilteredSlots) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun computeSlotLists(slots: Collection<Slot>, skipFilteredSlots: Boolean): Pair<MutableList<Slot>, MutableMap<ItemStackKey, MutableList<Slot>>> {
|
|
|
|
@ -150,40 +194,20 @@ class QuickMoveInput(private val menu: MatteryMenu, val from: Collection<Slot>,
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun prioritySortSlots(slots: Collection<Slot>, filterItem: ItemStack? = null): MutableList<Slot> {
|
|
|
|
|
val sortedSlots = ArrayList(slots)
|
|
|
|
|
private val itemFilterSlotComparator = HasItemComparator.thenComparing(HasFilterComparator)
|
|
|
|
|
|
|
|
|
|
sortedSlots.removeIf {
|
|
|
|
|
fun <T : MutableList<Slot>> prioritySortSlotsInPlace(slots: T, filterItem: ItemStack? = null): T {
|
|
|
|
|
slots.removeIf {
|
|
|
|
|
val slot = it.containerSlotOrNull()
|
|
|
|
|
it.isOverCapacity || filterItem != null && !it.mayPlace(filterItem) || slot is IFilteredContainerSlot && slot.isForbiddenForAutomation
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sortedSlots.sortWith { a, b ->
|
|
|
|
|
val hasItemA = a.item.isNotEmpty
|
|
|
|
|
val hasItemB = b.item.isNotEmpty
|
|
|
|
|
slots.sortWith(itemFilterSlotComparator)
|
|
|
|
|
return slots
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasItemA && hasItemB)
|
|
|
|
|
return@sortWith 0
|
|
|
|
|
else if (hasItemA)
|
|
|
|
|
return@sortWith -1
|
|
|
|
|
else if (hasItemB)
|
|
|
|
|
return@sortWith 1
|
|
|
|
|
|
|
|
|
|
val slotA = a.containerSlotOrNull()
|
|
|
|
|
val slotB = b.containerSlotOrNull()
|
|
|
|
|
|
|
|
|
|
val hasFilterA = slotA is IFilteredContainerSlot && slotA.hasFilter
|
|
|
|
|
val hasFilterB = slotB is IFilteredContainerSlot && slotB.hasFilter
|
|
|
|
|
|
|
|
|
|
if (hasFilterA && hasFilterB || !hasFilterA && !hasFilterB)
|
|
|
|
|
return@sortWith 0
|
|
|
|
|
else if (hasFilterA)
|
|
|
|
|
return@sortWith -1
|
|
|
|
|
else
|
|
|
|
|
return@sortWith 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sortedSlots
|
|
|
|
|
fun prioritySortSlots(slots: Collection<Slot>, filterItem: ItemStack? = null): MutableList<Slot> {
|
|
|
|
|
return prioritySortSlotsInPlace(ArrayList(slots), filterItem)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun moveItemStackToSlots(item: ItemStack, slots: Collection<Slot>, simulate: Boolean = false, sort: Boolean = true): ItemStack {
|
|
|
|
|