From 0428b60561743af122a23f6be823fee4f81deff1 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 18 Aug 2023 21:05:35 +0700 Subject: [PATCH] Update pattern monitor --- .../mc/otm/datagen/lang/English.kt | 4 + .../mc/otm/datagen/lang/Russian.kt | 4 + .../entity/matter/MatterPanelBlockEntity.kt | 66 ++++++++----- .../mc/otm/client/render/Widgets18.kt | 3 + .../client/screen/matter/MatterPanelScreen.kt | 32 ++++++- .../button/BooleanRectangleButtonPanel.kt | 19 ++-- .../client/screen/panels/button/Buttons.kt | 10 +- .../LargeBooleanRectangleButtonPanel.kt | 8 +- .../kotlin/ru/dbotthepony/mc/otm/core/Ext.kt | 22 ++++- .../dbotthepony/mc/otm/core/GetterSetter.kt | 21 +++-- .../otm/graph/matter/IMatterGraphListener.kt | 15 +++ .../mc/otm/menu/matter/MatterPanelMenu.kt | 89 +++++++++++------- .../network/synchronizer/FieldSynchronizer.kt | 9 +- .../textures/gui/widgets/storage_controls.png | Bin 981 -> 1020 bytes .../textures/gui/widgets/storage_controls.xcf | Bin 7924 -> 9801 bytes 15 files changed, 218 insertions(+), 84 deletions(-) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt index 552ad9e19..cbc045636 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt @@ -824,6 +824,10 @@ private fun gui(provider: MatteryLanguageProvider) { gui("matter_panel.label", "Replication request") gui("matter_panel.task", "Ongoing replication task") gui("matter_panel.task_line", "%s: %s | %s / %s") + gui("matter_panel.is_providing_tasks", "Tasks are dispatched to replicators") + gui("matter_panel.not_providing_tasks", "Tasks are NOT dispatched to replicators") + gui("matter_panel.cancel_all", "Cancel all tasks") + gui("matter_panel.cancel_all.desc", "Do you really want to cancel all replication tasks?") gui("matter_panel.tasks", "Tasks") gui("matter_panel.patterns", "Patterns") diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt index 6aea07d4d..0bd7a8786 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt @@ -821,6 +821,10 @@ private fun gui(provider: MatteryLanguageProvider) { gui("matter_panel.cancel", "Отмена") gui("matter_panel.label", "Запрос на репликацию") gui("matter_panel.task", "Будущий запрос на репликацию") + gui("matter_panel.is_providing_tasks", "Задачи передаются на репликаторы") + gui("matter_panel.not_providing_tasks", "Задачи НЕ передаются на репликаторы") + gui("matter_panel.cancel_all", "Отменить все задачи") + gui("matter_panel.cancel_all.desc", "Вы действительно хотите отменить все задачи репликации?") gui("matter_panel.tasks", "Задачи") gui("matter_panel.patterns", "Шаблоны") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt index 427dc6b5c..7b96e91f1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt @@ -15,22 +15,32 @@ import net.minecraft.world.level.Level import net.minecraftforge.common.util.INBTSerializable import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.matter.* +import ru.dbotthepony.mc.otm.core.collect.WeakHashSet import ru.dbotthepony.mc.otm.core.nbt.getBoolean import ru.dbotthepony.mc.otm.core.nbt.getCompoundList import ru.dbotthepony.mc.otm.core.nbt.map 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.MatterGraph import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode import ru.dbotthepony.mc.otm.registry.MBlockEntities import java.util.* import java.util.stream.Stream -class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : - MatteryDeviceBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IReplicationTaskProvider { +class MatterPanelBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.MATTER_PANEL, blockPos, blockState), IReplicationTaskProvider { + inner class PlayerSettings : INBTSerializable { + var sorter: ItemSorter = ItemSorter.DEFAULT + set(value) { + field = value + markDirtyFast() + } + + var ascending: Boolean = true + set(value) { + field = value + markDirtyFast() + } - class PlayerSettings(var sorter: ItemSorter = ItemSorter.DEFAULT, var ascending: Boolean = true) : INBTSerializable { override fun serializeNBT(): CompoundTag { return CompoundTag().also { it["sorter"] = sorter.name @@ -44,20 +54,35 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } } + var isProvidingTasks = true + set(value) { + if (field != value) { + field = value + + if (value) { + _tasks.values.forEach { matterNode.graph.onMatterTaskCreated(it) } + } else { + _tasks.values.forEach { if (it.inProgress == 0) matterNode.graph.onMatterTaskRemoved(it) } + } + + markDirtyFast() + } + } + private val playerSettings = Object2ObjectOpenHashMap() fun getPlayerSettings(ply: Player): PlayerSettings { return playerSettings.computeIfAbsent(ply.uuid, Object2ObjectFunction { PlayerSettings() }) } - private val listeners = ArrayList() + private val listeners = WeakHashSet() val matterNode = SimpleMatterNode(tasks = this) fun attachMenu(menu: MatterPanelMenu) { listeners.add(menu) } - fun deatachMenu(menu: MatterPanelMenu) { + fun detachMenu(menu: MatterPanelMenu) { listeners.remove(menu) } @@ -91,18 +116,18 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : } override fun allocateTask(simulate: Boolean): ReplicationTaskAllocation? { - val graph = matterNode.graph as MatterGraph? ?: return null + if (!isProvidingTasks) return null for ((key, task) in _tasks) { if (task.required > 0) { - val pattern = task.patternId.map(graph::getPattern).orElse(null) ?: continue + val pattern = task.patternId.map(matterNode.graph::getPattern).orElse(null) ?: continue if (!simulate) { val new = task.allocate() _tasks[key] = new listeners.forEach { it.taskUpdated(new) } - graph.onMatterTaskUpdated(new, task) - setChanged() + matterNode.graph.onMatterTaskUpdated(new, task) + markDirtyFast() } return ReplicationTaskAllocation(task, pattern) @@ -115,23 +140,21 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : override fun notifyTaskCompletion(taskId: UUID): Boolean { var localTask = _tasks[taskId] ?: return false val oldTask = localTask - localTask = localTask.finish() - val graph = matterNode.graph as MatterGraph? // Задача полностью выполнена if (localTask.required <= 0 && localTask.inProgress <= 0) { _tasks.remove(taskId) - graph?.onMatterTaskFinished(localTask) + matterNode.graph.onMatterTaskFinished(localTask) listeners.forEach { it.taskRemoved(localTask) } } else { // Задача обновлена _tasks[taskId] = localTask - graph?.onMatterTaskUpdated(localTask, oldTask) + matterNode.graph.onMatterTaskUpdated(localTask, oldTask) listeners.forEach { it.taskUpdated(localTask) } } - setChanged() + markDirtyFast() return true } @@ -189,27 +212,26 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : matterNode.graph.onMatterTaskRemoved(task) listeners.forEach { it.taskRemoved(task) } - setChanged() + markDirtyFast() } fun addTask(state: PatternState, count: Int): ReplicationTask { val task = ReplicationTask(UUID.randomUUID(), Optional.of(state.id), state.item, 0, 0, count) _tasks[task.id] = task - matterNode.graph.onMatterTaskCreated(task) + if (isProvidingTasks) + matterNode.graph.onMatterTaskCreated(task) listeners.forEach { it.taskUpdated(task) } - setChanged() + markDirtyFast() return task } override fun dropAllTasks() { - val graph = matterNode.graph as MatterGraph? - for (task in _tasks.values) { - graph?.onMatterTaskRemoved(task) - listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(task) } + matterNode.graph.onMatterTaskRemoved(task) + listeners.forEach { it.taskRemoved(task) } } _tasks.clear() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt index 82d7bb6eb..d25039af3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Widgets18.kt @@ -50,6 +50,9 @@ object Widgets18 { val ONLY_STORE = storageGrid.next() val ONLY_EXTRACT = storageGrid.next() val STORE_EXTRACT = storageGrid.next() + val PAUSE = storageGrid.next() + val PLAY = storageGrid.next() + val STOP = storageGrid.next() private val miscGrid = WidgetLocation.MISC_18.grid(4, 4) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt index 6b03bc50e..89829584b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/matter/MatterPanelScreen.kt @@ -14,13 +14,14 @@ import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeBooleanRectangleButtonPanel -import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeEnumRectangleButtonPanel +import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeRectangleButtonPanel import ru.dbotthepony.mc.otm.client.screen.panels.input.TextInputPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollBarConstants 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.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.integerDivisionDown import ru.dbotthepony.mc.otm.core.util.ItemSorter @@ -54,12 +55,39 @@ class MatterPanelScreen( val controls = DeviceControls(this, frame) - controls.sortingButtons(menu.isAscendingGS, menu.sortingGS, ItemSorter.DEFAULT) { + controls.sortingButtons(menu::isAscending.asGetterSetter(), menu::sorting.asGetterSetter(), ItemSorter.DEFAULT) { for (v in ItemSorter.entries) { add(v, skinElement = v.icon, tooltip = v.title) } } + controls.addButton( + LargeBooleanRectangleButtonPanel( + this, + frame, + prop = menu::isProvidingTasks.asGetterSetter(), + iconActive = Widgets18.PLAY, + iconInactive = Widgets18.PAUSE, + tooltipActive = TranslatableComponent("otm.gui.matter_panel.is_providing_tasks"), + tooltipInactive = TranslatableComponent("otm.gui.matter_panel.not_providing_tasks"), + ) + ) + + controls.addButton( + LargeRectangleButtonPanel( + this, + frame, + skinElement = Widgets18.STOP, + onPress = { + frame.queryUser( + TranslatableComponent("otm.gui.matter_panel.cancel_all"), + listOf(TranslatableComponent("otm.gui.matter_panel.cancel_all.desc")), + { menu.cancelAll.accept(null) } + ) + } + ) + ) + val scrollBar = DiscreteScrollBarPanel(this, frame, { if (isPatternView) { integerDivisionDown(menu.patternsFiltered.size, GRID_WIDTH) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt index d6000d0a5..52e2c716d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/BooleanRectangleButtonPanel.kt @@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel 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.value import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback @@ -20,8 +21,8 @@ abstract class BooleanRectangleButtonPanel( width: Float, height: Float, val prop: GetterSetter, - var skinElementActive: IGUIRenderable? = null, - var skinElementInactive: IGUIRenderable? = null, + var iconActive: IGUIRenderable? = null, + var iconInactive: IGUIRenderable? = null, val onChange: ((newValue: Boolean) -> Unit)? = null, var tooltipActive: Component? = null, var tooltipInactive: Component? = null, @@ -48,11 +49,17 @@ abstract class BooleanRectangleButtonPanel( } if (tooltipActive != null) { - tooltips.add(tooltipActive.copy().withStyle(if (prop.get()) ChatFormatting.WHITE else ChatFormatting.GRAY)) + if (prop.get()) + tooltips.add(TranslatableComponent("otm.gui.tooltip.enum.active", tooltipActive.copy().withStyle(ChatFormatting.WHITE))) + else + tooltips.add(tooltipActive.copy().withStyle(ChatFormatting.GRAY)) } if (tooltipInactive != null) { - tooltips.add(tooltipInactive.copy().withStyle(if (!prop.get()) ChatFormatting.WHITE else ChatFormatting.GRAY)) + if (prop.get()) + tooltips.add(tooltipInactive.copy().withStyle(ChatFormatting.GRAY)) + else + tooltips.add(TranslatableComponent("otm.gui.tooltip.enum.active", tooltipInactive.copy().withStyle(ChatFormatting.WHITE))) } graphics.renderComponentTooltip(font, tooltips, mouseX.toInt(), mouseY.toInt()) @@ -76,9 +83,9 @@ abstract class BooleanRectangleButtonPanel( super.innerRender(graphics, mouseX, mouseY, partialTick) if (prop.value) { - skinElementActive?.render(graphics, width = width, height = height) + iconActive?.render(graphics, width = width, height = height) } else { - skinElementInactive?.render(graphics, width = width, height = height) + iconInactive?.render(graphics, width = width, height = height) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt index 4bc9763ea..08a59178e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/Buttons.kt @@ -18,7 +18,6 @@ import ru.dbotthepony.mc.otm.client.render.ItemStackIcon import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.Dock -import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel @@ -30,7 +29,6 @@ import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.math.RelativeSide -import ru.dbotthepony.mc.otm.core.util.ItemSorter import ru.dbotthepony.mc.otm.core.value import ru.dbotthepony.mc.otm.menu.UpgradeSlots import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback @@ -359,8 +357,8 @@ class DeviceControls>( screen, this, prop = ascending, - skinElementActive = Widgets18.ARROW_UP, - skinElementInactive = Widgets18.ARROW_DOWN, + iconActive = Widgets18.ARROW_UP, + iconInactive = Widgets18.ARROW_DOWN, tooltipActive = TranslatableComponent("otm.gui.sorting.ascending"), tooltipInactive = TranslatableComponent("otm.gui.sorting.descending"), ).also { @@ -466,8 +464,8 @@ class DeviceControls>( balanceInputsButton = addButton(LargeBooleanRectangleButtonPanel( screen, this, prop = balanceInputs, - skinElementActive = Widgets18.BALANCING_ENABLED, - skinElementInactive = Widgets18.BALANCING_DISABLED).also { + iconActive = Widgets18.BALANCING_ENABLED, + iconInactive = Widgets18.BALANCING_DISABLED).also { it.tooltips.add(TranslatableComponent("otm.gui.balance_inputs")) }) } else { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt index fb36e1996..714d701b9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/panels/button/LargeBooleanRectangleButtonPanel.kt @@ -2,7 +2,7 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button import net.minecraft.client.gui.screens.Screen import net.minecraft.network.chat.Component -import ru.dbotthepony.mc.otm.client.render.sprites.AbstractMatterySprite +import ru.dbotthepony.mc.otm.client.render.IGUIRenderable import ru.dbotthepony.mc.otm.client.render.Widgets18 import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel import ru.dbotthepony.mc.otm.core.GetterSetter @@ -15,12 +15,12 @@ open class LargeBooleanRectangleButtonPanel( width: Float = SIZE, height: Float = SIZE, prop: GetterSetter, - skinElementActive: AbstractMatterySprite? = null, - skinElementInactive: AbstractMatterySprite? = null, + iconActive: IGUIRenderable? = null, + iconInactive: IGUIRenderable? = null, onChange: ((newValue: Boolean) -> Unit)? = null, tooltipActive: Component? = null, tooltipInactive: Component? = null, -) : BooleanRectangleButtonPanel(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange, tooltipActive, tooltipInactive) { +) : BooleanRectangleButtonPanel(screen, parent, x, y, width, height, prop, iconActive, iconInactive, onChange, tooltipActive, tooltipInactive) { final override val IDLE = Widgets18.BUTTON_IDLE final override val HOVERED = Widgets18.BUTTON_HOVERED final override val PRESSED = Widgets18.BUTTON_PRESSED diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt index af897288a..5e7847a5c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt @@ -375,12 +375,30 @@ fun Comparator.nullsLast(): Comparator { return Comparator.nullsLast(this as Comparator) } +class MappedComparator(private val parent: Comparator, private val mapper: (T) -> O) : Comparator { + override fun compare(o1: T, o2: T): Int { + return parent.compare(mapper.invoke(o1), mapper.invoke(o2)) + } + + override fun equals(other: Any?): Boolean { + return other is MappedComparator<*, *> && parent == other.parent + } + + override fun hashCode(): Int { + return parent.hashCode() + } + + override fun toString(): String { + return "MappedComparator[$parent]" + } +} + fun Comparator.map(mapper: (B) -> A): Comparator { - return Comparator { a, b -> this@map.compare(mapper.invoke(a), mapper.invoke(b)) } + return MappedComparator(this, mapper) } fun Comparator.suppliers(): Comparator> { - return Comparator { o1, o2 -> this@suppliers.compare(o1.get(), o2.get()) } + return MappedComparator(this) { it.get() } } /** diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt index 258840f95..a0bac0048 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt @@ -43,11 +43,7 @@ interface GetterSetter : Supplier, Consumer, ReadWriteProperty fun watch(watch: (old: V, new: V) -> Unit): GetterSetter { val self = this - return object : GetterSetter { - override fun get(): V { - return self.get() - } - + return object : GetterSetter by self { override fun accept(t: V) { val old = get() self.accept(t) @@ -116,7 +112,20 @@ interface GetterSetter : Supplier, Consumer, ReadWriteProperty } } -interface SentientGetterSetter : GetterSetter, ISubscriptable +interface SentientGetterSetter : GetterSetter, ISubscriptable { + override fun watch(watch: (old: V, new: V) -> Unit): SentientGetterSetter { + val self = this + + return object : SentientGetterSetter by self { + override fun accept(t: V) { + val old = get() + self.accept(t) + watch.invoke(old, t) + } + } + } + +} operator fun Supplier.getValue(thisRef: Any?, property: KProperty<*>): T { return get() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/IMatterGraphListener.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/IMatterGraphListener.kt index 171668334..f4aebfb66 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/IMatterGraphListener.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/IMatterGraphListener.kt @@ -7,8 +7,23 @@ interface IMatterGraphListener { fun onPatternRemoved(state: PatternState) {} fun onPatternUpdated(newState: PatternState, oldState: PatternState) {} + /** + * This can be called any amount of times with the same task + */ fun onMatterTaskCreated(task: ReplicationTask) {} + + /** + * This can be called any amount of times with the same task + */ fun onMatterTaskUpdated(newState: ReplicationTask, oldState: ReplicationTask) {} + + /** + * This can be called any amount of times with the same task + */ fun onMatterTaskFinished(state: ReplicationTask) {} + + /** + * This can be called any amount of times with the same task + */ fun onMatterTaskRemoved(state: ReplicationTask) {} } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt index 86d586ee0..98e96e49d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/matter/MatterPanelMenu.kt @@ -13,21 +13,22 @@ import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.core.GetterSetter import ru.dbotthepony.mc.otm.core.addSorted +import ru.dbotthepony.mc.otm.core.map import ru.dbotthepony.mc.otm.core.math.Decimal -import ru.dbotthepony.mc.otm.core.util.BooleanValueCodec import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec import ru.dbotthepony.mc.otm.core.util.ItemSorter +import ru.dbotthepony.mc.otm.core.util.NullValueCodec 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.MatteryMenu +import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.network.* import ru.dbotthepony.mc.otm.registry.MMenus import java.util.* import java.util.function.Predicate import java.util.function.Supplier -import kotlin.Comparator import kotlin.collections.ArrayList class CancelTaskPacket(val id: UUID) : MatteryPacket { @@ -128,10 +129,10 @@ class ReplicationRequestPacket(val id: UUID, amount: Int) : MatteryPacket { } class MatterPanelMenu( - p_38852_: Int, + containerId: Int, inventory: Inventory, tile: MatterPanelBlockEntity? = null -) : MatteryMenu(MMenus.MATTER_PANEL, p_38852_, inventory, tile), IMatterGraphListener { +) : MatteryMenu(MMenus.MATTER_PANEL, containerId, inventory, tile), IMatterGraphListener { fun taskUpdated(task: ReplicationTask) { sendNetwork(TasksChangePacket(true, listOf(task))) } @@ -140,25 +141,36 @@ class MatterPanelMenu( sendNetwork(TasksChangePacket(false, listOf(task))) } - val sorting: ItemSorter by mSynchronizer.ComputedField( - getter = { tile?.getPlayerSettings(player)?.sorter ?: ItemSorter.DEFAULT }, - codec = ItemSorter::class.codec(), - observer = { - patterns.sortWith(actualComparator) - patternsFiltered.sortWith(actualComparator) - tasks.sortWith(actualTaskComparator) - tasksFiltered.sortWith(actualTaskComparator) - }) + private fun updateComparators() { + var p = sorting.map(PatternState::item) + var t = sorting.map(ReplicationTask::item) - val isAscending: Boolean by mSynchronizer.ComputedField( - getter = { tile?.getPlayerSettings(player)?.ascending ?: true }, - codec = BooleanValueCodec, - observer = { - patterns.sortWith(actualComparator) - patternsFiltered.sortWith(actualComparator) - tasks.sortWith(actualTaskComparator) - tasksFiltered.sortWith(actualTaskComparator) - }) + if (!isAscending) { + p = p.reversed() + t = t.reversed() + } + + patternComparator = p + 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 } + ) + + var isProvidingTasks by BooleanInputWithFeedback(this, tile?.let { it::isProvidingTasks }) + val cancelAll = PlayerInput(NullValueCodec) { tile?.dropAllTasks() } val totalMatterStored: Decimal by mSynchronizer.ComputedField( getter = { tile?.matterNode?.graph?.getMatterStorageLevel() ?: Decimal.ZERO }, @@ -184,14 +196,23 @@ class MatterPanelMenu( } } - val changeIsAscending = booleanInput(allowSpectators = true) { tile?.getPlayerSettings(player)?.ascending = it } - val changeSorting = PlayerInput(ItemSorter::class.codec(), allowSpectators = true) { tile?.getPlayerSettings(player)?.sorter = it } + private var patternComparator = sorting.map(PatternState::item) + set(value) { + if (value != field) { + field = value + patterns.sortWith(value) + patternsFiltered.sortWith(value) + } + } - val sortingGS = GetterSetter.of(::sorting, changeSorting::accept) - val isAscendingGS = GetterSetter.of(::isAscending, changeIsAscending::accept) - - private val actualComparator = Comparator { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } - private val actualTaskComparator = Comparator { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) } + private var taskComparator = sorting.map(ReplicationTask::item) + set(value) { + if (value != field) { + field = value + tasks.sortWith(value) + tasksFiltered.sortWith(value) + } + } private val patterns = ArrayList() private val tasks = ArrayList() @@ -206,7 +227,7 @@ class MatterPanelMenu( if (index != -1) { this.patterns[index] = pattern } else { - this.patterns.addSorted(pattern, actualComparator) + this.patterns.addSorted(pattern, patternComparator) } if (filter.test(pattern.item)) { @@ -215,7 +236,7 @@ class MatterPanelMenu( if (index != -1) { this.patternsFiltered[index] = pattern } else { - this.patternsFiltered.addSorted(pattern, actualComparator) + this.patternsFiltered.addSorted(pattern, patternComparator) } } } @@ -234,7 +255,7 @@ class MatterPanelMenu( if (index != -1) { this.tasks[index] = task } else { - this.tasks.addSorted(task, actualTaskComparator) + this.tasks.addSorted(task, taskComparator) } if (filter.test(task.item)) { @@ -243,7 +264,7 @@ class MatterPanelMenu( if (index != -1) { this.tasksFiltered[index] = task } else { - this.tasksFiltered.addSorted(task, actualTaskComparator) + this.tasksFiltered.addSorted(task, taskComparator) } } } @@ -320,7 +341,7 @@ class MatterPanelMenu( override fun removed(p_38940_: Player) { super.removed(p_38940_) - (tile as MatterPanelBlockEntity?)?.deatachMenu(this) + (tile as MatterPanelBlockEntity?)?.detachMenu(this) listeningGrid?.removeListener(this) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt index 2e0051b61..c8140a121 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/synchronizer/FieldSynchronizer.kt @@ -1092,12 +1092,18 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa inner class ComputedField( private val getter: () -> V, private val codec: IStreamCodec, - private val observer: (new: V) -> Unit = {} + observer: ((new: V) -> Unit)? = null ) : AbstractField(), IField { private var remote: Any? = Mark private var clientValue: Any? = Mark private val subs = ISubscriptable.Impl() + init { + if (observer != null) { + subs.addListener(observer) + } + } + override fun addListener(listener: Consumer): ISubscriptable.L { return subs.addListener(listener) } @@ -1141,7 +1147,6 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa check(!isRemoved) { "Field was removed" } val newValue = codec.read(stream) clientValue = newValue - observer.invoke(newValue) subs.accept(newValue) } } diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/storage_controls.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets/storage_controls.png index d12fd2d82aeeed5f03e5e0b35b1ae681c3cb7ba2..6b7c5ba65030166100d8b301f4077f2dad46f020 100644 GIT binary patch delta 548 zcmV+<0^9x72mA-HEr*{77%RXOdi!mnYWxokD+p?{kmj^8Hzf5>M-0 zx5jgiwCElIwPk6P*qb0VY;crbzPEKvvS`W+DfdtYEwN^)Mc4P$mM9&IDs=Q-d|K8Z zA=xB!^x`MgMMuYa>v5E1aXgU|IxcQJlTL1hl4g2?nCKSS8j?;V+N@w{<-Y&`00000 zz^YuDQY{BiwLyO#4NN3j(-7A*)az%oEmf_Ytu4B2v`dIDcTp%rzTHQWqcy58+*Gox z$*1+L6Qr;RFy(;zxBM!z-rxkPZ}Xm@I`7#gQ_90d$r3{N8QE&SEbym`YtW59L% zvyAb4lg}e>34q){MP3d$ub&KhvXI0H|kaI&Clf z4I_|ELPslpa);>bSa02q9F}AxN#G5VWQst|_R~YqTX*t({MMbY5s50iW-pa6s11q?I}YptFc})Bb&?L4IvMT+u@?U5HMP;;S2UQ$ zKg-y!+2pO+;qJ0n*6X3p$mV|UfzWoc9!~EdS^UNl9D;Np2!gEh$G7bKs~k6#v4VtG zD;Pik+ZeRPD-pew)M>DtWNB$x2!cmn{Z}FY`(sP+le3JapaFXk=u;=YS3DZK4g|Dx yZ#klN$9jAM?$LepB7!5(tj`{)j{VM{B6#yLo0000$;~PNDFT)getItlHIEkv99qEkv?ZLM@ks zEt#lRc!dZN-I564-tWZn);!m(BKgZMm9=T}hc4qpc9j)kob-FQk2Qm1UT;r1RS)AM z+jOeVReR2!wI6%gJmMTcoC7{Fp`nt8GX^h8qTE@w!NBLwF^;~l@Y&87JY)H>2=$)*pr)fXd z^<9BFYe=Wef_#`l^bIzNe)2XYsAkTrI|C5AfM#rhpM=|sd(M^@OtEBe&@7^81Yfi?eDP$&bLuMY2WnP$PdrnZuZbvse zf^PPtsV44F$SLUNisT4Ws(R+Sid68Nh&LIfP~}fzVu{5Sph3Li6W9Xu%l}TEq@Qi=Khd;%gwZ z^28*)328uc|Zm#4DVPxWH0!wks14(gnY=fB2z@R<(p_1_A4?tsU1mOgD(wIg<(7_s`N4LwBd^$GUgf&UKb1T;cPqy*GRe*XE0x^= NHbC~mW?5AoMgWg3W>)|J