Update pattern monitor
This commit is contained in:
parent
182bb4c8ba
commit
0428b60561
@ -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")
|
||||
|
@ -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", "Шаблоны")
|
||||
|
@ -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<CompoundTag> {
|
||||
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<CompoundTag> {
|
||||
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<UUID, PlayerSettings>()
|
||||
|
||||
fun getPlayerSettings(ply: Player): PlayerSettings {
|
||||
return playerSettings.computeIfAbsent(ply.uuid, Object2ObjectFunction { PlayerSettings() })
|
||||
}
|
||||
|
||||
private val listeners = ArrayList<MatterPanelMenu>()
|
||||
private val listeners = WeakHashSet<MatterPanelMenu>()
|
||||
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()
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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<out S : Screen>(
|
||||
width: Float,
|
||||
height: Float,
|
||||
val prop: GetterSetter<Boolean>,
|
||||
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<out S : Screen>(
|
||||
}
|
||||
|
||||
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<out S : Screen>(
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<out S : MatteryScreen<*>>(
|
||||
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<out S : MatteryScreen<*>>(
|
||||
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 {
|
||||
|
@ -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<out S : Screen>(
|
||||
width: Float = SIZE,
|
||||
height: Float = SIZE,
|
||||
prop: GetterSetter<Boolean>,
|
||||
skinElementActive: AbstractMatterySprite? = null,
|
||||
skinElementInactive: AbstractMatterySprite? = null,
|
||||
iconActive: IGUIRenderable? = null,
|
||||
iconInactive: IGUIRenderable? = null,
|
||||
onChange: ((newValue: Boolean) -> Unit)? = null,
|
||||
tooltipActive: Component? = null,
|
||||
tooltipInactive: Component? = null,
|
||||
) : BooleanRectangleButtonPanel<S>(screen, parent, x, y, width, height, prop, skinElementActive, skinElementInactive, onChange, tooltipActive, tooltipInactive) {
|
||||
) : BooleanRectangleButtonPanel<S>(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
|
||||
|
@ -375,12 +375,30 @@ fun <T> Comparator<in T>.nullsLast(): Comparator<T?> {
|
||||
return Comparator.nullsLast(this as Comparator<in T?>)
|
||||
}
|
||||
|
||||
class MappedComparator<T, O>(private val parent: Comparator<O>, private val mapper: (T) -> O) : Comparator<T> {
|
||||
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 <A, B> Comparator<A>.map(mapper: (B) -> A): Comparator<B> {
|
||||
return Comparator { a, b -> this@map.compare(mapper.invoke(a), mapper.invoke(b)) }
|
||||
return MappedComparator(this, mapper)
|
||||
}
|
||||
|
||||
fun <T> Comparator<T>.suppliers(): Comparator<Supplier<T>> {
|
||||
return Comparator { o1, o2 -> this@suppliers.compare(o1.get(), o2.get()) }
|
||||
return MappedComparator(this) { it.get() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,11 +43,7 @@ interface GetterSetter<V> : Supplier<V>, Consumer<V>, ReadWriteProperty<Any?, V>
|
||||
fun watch(watch: (old: V, new: V) -> Unit): GetterSetter<V> {
|
||||
val self = this
|
||||
|
||||
return object : GetterSetter<V> {
|
||||
override fun get(): V {
|
||||
return self.get()
|
||||
}
|
||||
|
||||
return object : GetterSetter<V> by self {
|
||||
override fun accept(t: V) {
|
||||
val old = get()
|
||||
self.accept(t)
|
||||
@ -116,7 +112,20 @@ interface GetterSetter<V> : Supplier<V>, Consumer<V>, ReadWriteProperty<Any?, V>
|
||||
}
|
||||
}
|
||||
|
||||
interface SentientGetterSetter<V> : GetterSetter<V>, ISubscriptable<V>
|
||||
interface SentientGetterSetter<V> : GetterSetter<V>, ISubscriptable<V> {
|
||||
override fun watch(watch: (old: V, new: V) -> Unit): SentientGetterSetter<V> {
|
||||
val self = this
|
||||
|
||||
return object : SentientGetterSetter<V> by self {
|
||||
override fun accept(t: V) {
|
||||
val old = get()
|
||||
self.accept(t)
|
||||
watch.invoke(old, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
operator fun <T> Supplier<T>.getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
return get()
|
||||
|
@ -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) {}
|
||||
}
|
||||
|
@ -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<PatternState> { o1, o2 -> sorting.compare(o1.item, o2.item) * (if (isAscending) 1 else -1) }
|
||||
private val actualTaskComparator = Comparator<ReplicationTask> { 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<PatternState>()
|
||||
private val tasks = ArrayList<ReplicationTask>()
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
@ -1092,12 +1092,18 @@ class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCa
|
||||
inner class ComputedField<V>(
|
||||
private val getter: () -> V,
|
||||
private val codec: IStreamCodec<V>,
|
||||
private val observer: (new: V) -> Unit = {}
|
||||
observer: ((new: V) -> Unit)? = null
|
||||
) : AbstractField<V>(), IField<V> {
|
||||
private var remote: Any? = Mark
|
||||
private var clientValue: Any? = Mark
|
||||
private val subs = ISubscriptable.Impl<V>()
|
||||
|
||||
init {
|
||||
if (observer != null) {
|
||||
subs.addListener(observer)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addListener(listener: Consumer<V>): 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)
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 981 B After Width: | Height: | Size: 1020 B |
Binary file not shown.
Loading…
Reference in New Issue
Block a user