Proper sorting inputs in regular storage menus

This commit is contained in:
DBotThePony 2023-08-20 17:35:39 +07:00
parent 35b186556e
commit e7c9abcebb
Signed by: DBot
GPG Key ID: DCC23B5715498507
17 changed files with 291 additions and 107 deletions

View File

@ -806,6 +806,7 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("balance_inputs", "Balance input slots")
gui("sorting.sort_now", "Sort")
gui("sorting.sort_settings", "Right click to show settings")
gui("sorting.default", "Default sorting")
gui("sorting.name", "Sort by name")
gui("sorting.id", "Sort by ID")

View File

@ -806,6 +806,7 @@ private fun gui(provider: MatteryLanguageProvider) {
gui("balance_inputs", "Балансировать входные слоты")
gui("sorting.sort_now", "Отсортировать")
gui("sorting.sort_settings", "Нажмите правую кнопку мыши для настроек")
gui("sorting.default", "Сортировка по умолчанию")
gui("sorting.name", "Сортировка по имени")
gui("sorting.id", "Сортировка по ID")

View File

@ -23,35 +23,24 @@ import ru.dbotthepony.mc.otm.core.nbt.mapString
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.ItemSorter
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.menu.IItemSortingSettings
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.*
import java.util.stream.Stream
class MatterPanelBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.MATTER_PANEL, blockPos, blockState), IReplicationTaskProvider {
inner class PlayerSettings : INBTSerializable<CompoundTag> {
var sorter: ItemSorter = ItemSorter.DEFAULT
inner class PlayerSettings : IItemSortingSettings {
override var sorting: ItemSorter = ItemSorter.DEFAULT
set(value) {
field = value
markDirtyFast()
}
var ascending: Boolean = true
override var isAscending: Boolean = true
set(value) {
field = value
markDirtyFast()
}
override fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["sorter"] = sorter.name
it["ascending"] = ascending
}
}
override fun deserializeNBT(nbt: CompoundTag) {
sorter = nbt.mapString("sorter", ItemSorter::valueOf, ItemSorter.DEFAULT)
ascending = nbt.getBoolean("ascending", true)
}
}
var isProvidingTasks = true

View File

@ -98,6 +98,7 @@ import ru.dbotthepony.mc.otm.core.nbt.getIntList
import ru.dbotthepony.mc.otm.core.nbt.getStringList
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.IntValueCodec
import ru.dbotthepony.mc.otm.core.util.ItemStackSorter
import ru.dbotthepony.mc.otm.core.util.ItemValueCodec
import ru.dbotthepony.mc.otm.core.util.RGBCodec
import ru.dbotthepony.mc.otm.core.util.Savetables
@ -105,6 +106,7 @@ import ru.dbotthepony.mc.otm.core.util.TickList
import ru.dbotthepony.mc.otm.core.util.UUIDValueCodec
import ru.dbotthepony.mc.otm.core.util.VarIntValueCodec
import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu
import ru.dbotthepony.mc.otm.menu.IItemStackSortingSettings
import ru.dbotthepony.mc.otm.network.*
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket.Companion.makeSmoke
import ru.dbotthepony.mc.otm.network.synchronizer.FieldSynchronizer
@ -402,6 +404,11 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
return _exoPackMenu!!
}
val sortingSettings = object : IItemStackSortingSettings {
override var isAscending: Boolean = true
override var sorting: ItemStackSorter = ItemStackSorter.DEFAULT
}
fun recreateExoPackMenu() {
_exoPackMenu = ExopackInventoryMenu(this)
}
@ -591,6 +598,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
savetables.codecNullable(::exopackColor, RGBAColor.CODECRGB)
savetables.bool(::exopackGlows)
savetables.stateful(::sortingSettings)
}
fun invalidateNetworkState() {

View File

@ -38,8 +38,8 @@ object Widgets18 {
val BUTTON_DISABLED = buttonGrids.next()
private val storageGrid = WidgetLocation.STORAGE_CONTROLS.grid(rows = 4, columns = 5)
val ARROW_DOWN = storageGrid.next()
val ARROW_UP = storageGrid.next()
val SORT_DESCENDING = storageGrid.next()
val SORT_ASCENDING = storageGrid.next()
val SORT_DEFAULT = storageGrid.next()
val SORT_ALPHABET = storageGrid.next()
val SORT_COUNT = storageGrid.next()

View File

@ -308,12 +308,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
}
if (menu.sortInventoryInput != null) {
deviceControls.addButton(LargeRectangleButtonPanel.input(
this,
deviceControls,
menu.sortInventoryInput!!,
icon = Widgets18.SORT_NOW
).also { it.tooltips.add(TranslatableComponent("otm.gui.sorting.sort_now")) })
deviceControls.customSortingButtons(menu.playerSortSettings, menu.sortInventoryInput!!)
}
if (menu.exopackChargeSlots.isNotEmpty()) {

View File

@ -28,7 +28,7 @@ class CargoCrateScreen(menu: CargoCrateMenu, inventory: Inventory, title: Compon
val controls = DeviceControls(this, frame)
controls.addButton(LargeRectangleButtonPanel.input(this, frame, menu.sort, icon = Widgets18.SORT_NOW).also { it.tooltips.add(TranslatableComponent("otm.gui.sorting.sort_now")) })
controls.customSortingButtons(menu.playerSortSettings, menu.sort)
return frame
}

View File

@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.menu.decorative.MinecartCargoCrateMenu
@ -20,6 +21,10 @@ class MinecartCargoCrateScreen(menu: MinecartCargoCrateMenu, inventory: Inventor
for (slot in menu.storageSlots)
SlotPanel(this, grid, slot)
val controls = DeviceControls(this, frame)
controls.customSortingButtons(menu.playerSortSettings, menu.sort)
return frame
}
}

View File

@ -55,7 +55,7 @@ class MatterPanelScreen(
val controls = DeviceControls(this, frame)
controls.sortingButtons(menu::isAscending.asGetterSetter(), menu::sorting.asGetterSetter(), ItemSorter.DEFAULT) {
controls.sortingButtons(menu.settings::isAscending.asGetterSetter(), menu.settings::sorting.asGetterSetter(), ItemSorter.DEFAULT) {
for (v in ItemSorter.entries) {
add(v, skinElement = v.icon, tooltip = v.title)
}

View File

@ -140,7 +140,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
}
/**
* Bigger values means lesser priority while docking
* Bigger values means lesser priority while docking, rendering and processing inputs.
*/
var childrenOrder = 0
set(value) {
@ -881,7 +881,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
poseStack.popPose()
}
for (child in visibleChildrenInternal) {
for (child in visibleChildrenInternal.asReversed()) {
child.absoluteX = absoluteX + child.x + xOffset
child.absoluteY = absoluteY + child.y + yOffset

View File

@ -27,9 +27,13 @@ import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.asGetterSetter
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.util.ItemStackSorter
import ru.dbotthepony.mc.otm.core.value
import ru.dbotthepony.mc.otm.menu.IItemStackSortingSettings
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.UpgradeSlots
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
@ -314,33 +318,61 @@ class DeviceControls<out S : MatteryScreen<*>>(
val balanceInputsButton: LargeBooleanRectangleButtonPanel<S>?
val upgradesButton: LargeRectangleButtonPanel<S>?
init {
childrenOrder = -1000
}
private var upgradeWindow: FramePanel<S>? = null
private var nextY = 0f
private val buttons = ArrayList<EditablePanel<S>>()
fun alignButtons() {
buttons.removeIf { it.isRemoved || it.parent != this }
var y = 0f
for (button in buttons) {
button.setPos(button.dockLeft, y + button.dockTop)
y += button.height + button.dockMargin.vertical + 2f
width = width.coerceAtLeast(button.width + button.dockMargin.horizontal)
}
height = height.coerceAtLeast(y - 2f)
}
fun removeButton(button: EditablePanel<*>) {
buttons.remove(button)
alignButtons()
}
fun <P : EditablePanel<@UnsafeVariance S>> addButton(button: P): P {
buttons.add(button)
button.parent = this
button.x = 0f
button.y = nextY
nextY += button.height + 2f
height = nextY - 2f
width = button.width.coerceAtLeast(width)
alignButtons()
return button
}
fun <P : EditablePanel<@UnsafeVariance S>> addButton(button: P, after: EditablePanel<*>): P {
val index = buttons.indexOf(after)
if (index == -1) throw NoSuchElementException("Unknown panel to add button after: $after")
buttons.add(index + 1, button)
button.parent = this
alignButtons()
return button
}
fun <P : EditablePanel<@UnsafeVariance S>> prependButton(button: P): P {
for (child in children) {
child.y += button.height + 2f
}
buttons.add(0, button)
button.parent = this
button.x = 0f
button.y = 0f
nextY += button.height + 2f
height = nextY - 2f
width = button.width.coerceAtLeast(width)
alignButtons()
return button
}
override fun performLayout() {
super.performLayout()
alignButtons()
}
fun addStorageMode(prop: GetterSetter<FlowDirection>) {
val mode = LargeEnumRectangleButtonPanel(screen, this, prop = prop, defaultValue = FlowDirection.BI_DIRECTIONAL, enum = FlowDirection::class.java)
@ -352,24 +384,74 @@ class DeviceControls<out S : MatteryScreen<*>>(
addButton(mode)
}
inline fun <reified T : Enum<T>> sortingButtons(ascending: GetterSetter<Boolean>, sorting: GetterSetter<T>, default: T, configurator: LargeEnumRectangleButtonPanel<S, T>.() -> Unit) {
inline fun <reified T : Enum<T>> sortingButtons(ascending: GetterSetter<Boolean>, sorting: GetterSetter<T>, default: T, configurator: LargeEnumRectangleButtonPanel<S, T>.() -> Unit): List<EditablePanel<S>> {
val result = ArrayList<EditablePanel<S>>()
LargeBooleanRectangleButtonPanel(
screen,
this,
prop = ascending,
iconActive = Widgets18.ARROW_UP,
iconInactive = Widgets18.ARROW_DOWN,
iconActive = Widgets18.SORT_ASCENDING,
iconInactive = Widgets18.SORT_DESCENDING,
tooltipActive = TranslatableComponent("otm.gui.sorting.ascending"),
tooltipInactive = TranslatableComponent("otm.gui.sorting.descending"),
).also {
prependButton(it)
result.add(it)
}
LargeEnumRectangleButtonPanel(screen, this, enum = T::class.java, prop = sorting, defaultValue = default).also {
prependButton(it)
configurator.invoke(it)
it.finish()
result.add(it)
}
return result
}
fun customSortingButtons(settings: IItemStackSortingSettings, input: MatteryMenu.PlayerInput<Nothing?>) {
addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls) {
var buttons: List<EditablePanel<*>>? = null
init {
tooltips.add(TranslatableComponent("otm.gui.sorting.sort_now"))
tooltips.add(TextComponent(""))
tooltips.add(TranslatableComponent("otm.gui.sorting.sort_settings").withStyle(ChatFormatting.GRAY))
icon = Widgets18.SORT_NOW
}
override fun test(value: Int): Boolean {
return value == InputConstants.MOUSE_BUTTON_LEFT || value == InputConstants.MOUSE_BUTTON_RIGHT
}
override var isDisabled: Boolean
get() = !input.test(minecraft.player)
set(value) {}
override fun onClick(mouseButton: Int) {
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
input.accept(null)
} else {
if (buttons == null) {
buttons = sortingButtons(settings::isAscending.asGetterSetter(), settings::sorting.asGetterSetter(), ItemStackSorter.DEFAULT) {
for (v in ItemStackSorter.entries) {
add(v, v.icon, v.title)
}
finish()
}
buttons!!.forEach { removeButton(it) }
buttons!!.forEach { addButton(it as EditablePanel<S>, this) }
} else {
buttons!!.forEach { it.remove() }
buttons = null
}
}
}
})
}
init {
@ -492,7 +574,7 @@ class DeviceControls<out S : MatteryScreen<*>>(
}
if (energyConfig != null) {
energyConfigButton = addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls, y = nextY, icon = Widgets18.ENERGY_CONFIGURATION) {
energyConfigButton = addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls, icon = Widgets18.ENERGY_CONFIGURATION) {
init {
tooltips.add(TranslatableComponent("otm.gui.sides.energy_config"))
}
@ -511,7 +593,7 @@ class DeviceControls<out S : MatteryScreen<*>>(
}
if (fluidConfig != null) {
fluidConfigButton = addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls, y = nextY, icon = Widgets18.FLUID_CONFIGURATION) {
fluidConfigButton = addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls, icon = Widgets18.FLUID_CONFIGURATION) {
init {
tooltips.add(TranslatableComponent("otm.gui.sides.fluid_config"))
}

View File

@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.ints.IntIterator
import it.unimi.dsi.fastutil.ints.IntSet
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap
import it.unimi.dsi.fastutil.objects.ObjectArrayList
import net.minecraft.world.Container
import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack
@ -18,6 +19,8 @@ import ru.dbotthepony.mc.otm.container.util.ItemStackHashStrategy
import ru.dbotthepony.mc.otm.container.util.slotIterator
import ru.dbotthepony.mc.otm.core.addAll
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.collect.max
import ru.dbotthepony.mc.otm.core.collect.toList
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.map
@ -288,19 +291,6 @@ operator fun CraftingContainer.get(column: Int, row: Int, flop: Boolean): ItemSt
get(column, row)
}
private object FilteredFirst : Comparator<IContainerSlot> {
override fun compare(o1: IContainerSlot, o2: IContainerSlot): Int {
if (o1.hasFilter && o2.hasFilter)
return 0
else if (o2.hasFilter)
return -1
else if (o1.hasFilter)
return 1
else
return 0
}
}
fun Container.sort(comparator: Comparator<ItemStack> = ItemStackSorter.DEFAULT) {
if (isEmpty)
return
@ -310,8 +300,21 @@ fun Container.sort(comparator: Comparator<ItemStack> = ItemStackSorter.DEFAULT)
if (slots.isEmpty())
return
slots.sortWith(FilteredFirst.thenComparing(comparator.map(IContainerSlot::item)))
val items = slots.map { it.item.copy() }
val items = Object2ObjectOpenCustomHashMap<ItemStack, ItemStack>(ItemStackHashStrategy)
slots.forEach {
val get = items[it.item]
if (get == null) {
items[it.item] = it.item.copy()
} else {
get.count += it.item.count
}
}
val sortedItems = ObjectArrayList(items.values)
sortedItems.sortWith(comparator)
slots.forEach { it.remove() }
items.forEach { addItem(it, false) }
sortedItems.forEach { addItem(it, false) }
}

View File

@ -0,0 +1,114 @@
package ru.dbotthepony.mc.otm.menu
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.core.nbt.getBoolean
import ru.dbotthepony.mc.otm.core.nbt.mapString
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.ItemSorter
import ru.dbotthepony.mc.otm.core.util.ItemStackSorter
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
interface IBaseSortingSettings : INBTSerializable<CompoundTag?> {
var isAscending: Boolean
override fun serializeNBT(): CompoundTag {
return CompoundTag().also {
it["isAscending"] = isAscending
}
}
override fun deserializeNBT(nbt: CompoundTag?) {
nbt ?: return
isAscending = nbt.getBoolean("isAscending", true)
}
}
interface IItemStackSortingSettings : IBaseSortingSettings {
var sorting: ItemStackSorter
override fun serializeNBT(): CompoundTag {
return super.serializeNBT().also {
it["sorting"] = sorting.name
}
}
override fun deserializeNBT(nbt: CompoundTag?) {
nbt ?: return
super.deserializeNBT(nbt)
sorting = nbt.mapString("sorting", ItemStackSorter::valueOf, ItemStackSorter.DEFAULT)
}
val actualComparator: Comparator<ItemStack> get() {
if (isAscending) {
return sorting
} else {
return sorting.reversed()
}
}
companion object {
fun inputs(menu: MatteryMenu, observer: Runnable? = null) : IItemStackSortingSettings {
return object : IItemStackSortingSettings {
override var isAscending: Boolean by BooleanInputWithFeedback(menu).also { if (observer != null) it.addListener { observer.run() } }
override var sorting: ItemStackSorter by EnumInputWithFeedback<ItemStackSorter>(menu).also { if (observer != null) it.addListener { observer.run() } }
}
}
fun inputs(menu: MatteryMenu, parent: IItemStackSortingSettings?, observer: Runnable? = null) : IItemStackSortingSettings {
if (parent == null)
return inputs(menu)
return object : IItemStackSortingSettings {
override var isAscending: Boolean by BooleanInputWithFeedback(menu, parent::isAscending).also { if (observer != null) it.addListener { observer.run() } }
override var sorting: ItemStackSorter by EnumInputWithFeedback(menu, parent::sorting).also { if (observer != null) it.addListener { observer.run() } }
}
}
}
}
interface IItemSortingSettings : IBaseSortingSettings {
var sorting: ItemSorter
override fun serializeNBT(): CompoundTag {
return super.serializeNBT().also {
it["sorting"] = sorting.name
}
}
override fun deserializeNBT(nbt: CompoundTag?) {
nbt ?: return
super.deserializeNBT(nbt)
sorting = nbt.mapString("sorting", ItemSorter::valueOf, ItemSorter.DEFAULT)
}
val actualComparator: Comparator<Item> get() {
if (isAscending) {
return sorting
} else {
return sorting.reversed()
}
}
companion object {
fun inputs(menu: MatteryMenu, observer: Runnable? = null) : IItemSortingSettings {
return object : IItemSortingSettings {
override var isAscending: Boolean by BooleanInputWithFeedback(menu).also { if (observer != null) it.addListener { observer.run() } }
override var sorting: ItemSorter by EnumInputWithFeedback<ItemSorter>(menu).also { if (observer != null) it.addListener { observer.run() } }
}
}
fun inputs(menu: MatteryMenu, parent: IItemSortingSettings?, observer: Runnable? = null) : IItemSortingSettings {
if (parent == null)
return inputs(menu)
return object : IItemSortingSettings {
override var isAscending: Boolean by BooleanInputWithFeedback(menu, parent::isAscending).also { if (observer != null) it.addListener { observer.run() } }
override var sorting: ItemSorter by EnumInputWithFeedback(menu, parent::sorting).also { if (observer != null) it.addListener { observer.run() } }
}
}
}
}

View File

@ -209,6 +209,8 @@ abstract class MatteryMenu(
var sortInventoryInput: PlayerInput<Nothing?>? = null
private set
val playerSortSettings = IItemStackSortingSettings.inputs(this, player.matteryPlayer?.sortingSettings)
var offhandSlot: InventorySlot? = null
protected set
@ -352,7 +354,7 @@ abstract class MatteryMenu(
}
sortInventoryInput = PlayerInput(NullValueCodec) {
mattery.inventoryAndExopackNoHotbar.sort()
mattery.inventoryAndExopackNoHotbar.sort(playerSortSettings.actualComparator)
}
}

View File

@ -5,32 +5,28 @@ import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.container.sort
import ru.dbotthepony.mc.otm.core.util.NullValueCodec
import ru.dbotthepony.mc.otm.menu.IItemStackSortingSettings
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.UserFilteredSlot
import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.registry.MMenus
class CargoCrateMenu @JvmOverloads constructor(
p_38852_: Int,
class CargoCrateMenu(
containerId: Int,
inventory: Inventory,
tile: CargoCrateBlockEntity? = null
) : MatteryMenu(MMenus.CARGO_CRATE, p_38852_, inventory, tile) {
val storageSlots: List<UserFilteredSlot>
) : MatteryMenu(MMenus.CARGO_CRATE, containerId, inventory, tile) {
val storageSlots = makeSlots(tile?.container ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY), ::UserFilteredSlot)
private val trackedPlayerOpen = !inventory.player.isSpectator
val sort = PlayerInput(NullValueCodec) {
tile?.container?.sort()
tile?.container?.sort(playerSortSettings.actualComparator)
}
init {
val container = tile?.container ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY)
storageSlots = immutableList(CargoCrateBlockEntity.CAPACITY) {
addStorageSlot(UserFilteredSlot(container, it))
}
if (trackedPlayerOpen) {
tile?.onPlayerOpen()
}

View File

@ -1,32 +1,31 @@
package ru.dbotthepony.mc.otm.menu.decorative
import net.minecraft.world.Container
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.block.entity.decorative.CargoCrateBlockEntity
import ru.dbotthepony.mc.otm.container.sort
import ru.dbotthepony.mc.otm.core.util.NullValueCodec
import ru.dbotthepony.mc.otm.entity.MinecartCargoCrate
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.registry.MMenus
class MinecartCargoCrateMenu @JvmOverloads constructor(
p_38852_: Int,
class MinecartCargoCrateMenu(
containerId: Int,
inventory: Inventory,
val cart: MinecartCargoCrate? = null
) : MatteryMenu(MMenus.CARGO_CRATE, p_38852_, inventory) {
val storageSlots: List<MatterySlot>
) : MatteryMenu(MMenus.CARGO_CRATE, containerId, inventory) {
val storageSlots = makeSlots(cart ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY), ::MatterySlot)
private val trackedPlayerOpen = !inventory.player.isSpectator
val sort = PlayerInput(NullValueCodec) {
cart?.sort(playerSortSettings.actualComparator)
}
init {
val container = cart as Container? ?: SimpleContainer(CargoCrateBlockEntity.CAPACITY)
storageSlots = immutableList(CargoCrateBlockEntity.CAPACITY) {
addStorageSlot(MatterySlot(container, it))
}
if (trackedPlayerOpen) {
cart?.onPlayerOpen()
}

View File

@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.core.util.codec
import ru.dbotthepony.mc.otm.core.util.writeCollection
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphListener
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.menu.IItemSortingSettings
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.network.*
@ -142,10 +143,10 @@ class MatterPanelMenu(
}
private fun updateComparators() {
var p = sorting.map(PatternState::item)
var t = sorting.map(ReplicationTask::item)
var p = settings.sorting.map(PatternState::item)
var t = settings.sorting.map(ReplicationTask::item)
if (!isAscending) {
if (!settings.isAscending) {
p = p.reversed()
t = t.reversed()
}
@ -154,20 +155,7 @@ class MatterPanelMenu(
taskComparator = t
}
var sorting: ItemSorter by GetterSetter.of(
mSynchronizer.ComputedField(
getter = { tile?.getPlayerSettings(player)?.sorter ?: ItemSorter.DEFAULT },
codec = ItemSorter::class.codec(),
observer = { updateComparators() }),
PlayerInput(ItemSorter::class.codec(), allowSpectators = true) { tile?.getPlayerSettings(player)?.sorter = it }
)
var isAscending: Boolean by GetterSetter.of(
mSynchronizer.ComputedBooleanField(
getter = { tile?.getPlayerSettings(player)?.ascending ?: true },
observer = { updateComparators() }),
booleanInput(allowSpectators = true) { tile?.getPlayerSettings(player)?.ascending = it }
)
val settings = IItemSortingSettings.inputs(this, tile?.getPlayerSettings(player), ::updateComparators)
var isProvidingTasks by BooleanInputWithFeedback(this, tile?.let { it::isProvidingTasks })
val cancelAll = PlayerInput(NullValueCodec) { tile?.dropAllTasks() }
@ -196,7 +184,7 @@ class MatterPanelMenu(
}
}
private var patternComparator = sorting.map(PatternState::item)
private var patternComparator = settings.sorting.map(PatternState::item)
set(value) {
if (value != field) {
field = value
@ -205,7 +193,7 @@ class MatterPanelMenu(
}
}
private var taskComparator = sorting.map(ReplicationTask::item)
private var taskComparator = settings.sorting.map(ReplicationTask::item)
set(value) {
if (value != field) {
field = value