Lock upgrade slots when machine is working

This commit is contained in:
DBotThePony 2024-09-01 18:05:34 +07:00
parent d5027981ca
commit 6ce2181a95
Signed by: DBot
GPG Key ID: DCC23B5715498507
25 changed files with 146 additions and 85 deletions

View File

@ -15,8 +15,10 @@ import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
import ru.dbotthepony.mc.otm.capability.UpgradeType
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.nbt.getCompoundList import ru.dbotthepony.mc.otm.core.nbt.getCompoundList
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
@ -64,6 +66,10 @@ abstract class MatteryWorkerBlockEntity<JobType : IJob>(
open val upgrades: IMatteryUpgrade? get() = null open val upgrades: IMatteryUpgrade? get() = null
protected fun makeUpgrades(slotCount: Int, upgradeTypes: Set<UpgradeType>): UpgradeContainer {
return UpgradeContainer(slotCount, upgradeTypes, ::shouldLockUpgradeSlots, ::markDirtyFast)
}
var balanceInputs = false var balanceInputs = false
init { init {
@ -147,6 +153,9 @@ abstract class MatteryWorkerBlockEntity<JobType : IJob>(
hasWorkerState && this.blockState.getValue(WorkerState.WORKER_STATE) == WorkerState.IDLE hasWorkerState && this.blockState.getValue(WorkerState.WORKER_STATE) == WorkerState.IDLE
} }
protected open val shouldLockUpgradeSlots: Boolean
get() = jobEventLoops.any { it.currentJob != null }
override fun tick() { override fun tick() {
super.tick() super.tick()
jobEventLoops.forEach { it.think() } jobEventLoops.forEach { it.think() }

View File

@ -29,11 +29,12 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import java.util.function.BooleanSupplier
class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) : class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, blockPos, blockState) { MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, blockPos, blockState) {
val upgrades = UpgradeContainer(::markDirtyFast, 3, UpgradeType.BASIC_MATTER) val upgrades = UpgradeContainer(3, UpgradeType.BASIC_MATTER, BooleanSupplier { blockState.getValue(WorkerState.SEMI_WORKER_STATE) !== WorkerState.IDLE }, ::markDirtyFast)
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, upgrades.transform(MachinesConfig.MatterBottler.VALUES))) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, upgrades.transform(MachinesConfig.MatterBottler.VALUES)))
val energyConfig = ConfigurableEnergy(energy) val energyConfig = ConfigurableEnergy(energy)
@ -124,6 +125,7 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
var workProgress: Float = 0f var workProgress: Float = 0f
private set private set
private var lastTickWorking = false
private var initialCapacity: Decimal? = null private var initialCapacity: Decimal? = null
override fun setLevel(level: Level) { override fun setLevel(level: Level) {

View File

@ -32,6 +32,7 @@ import ru.dbotthepony.mc.otm.matter.MatterManager
import ru.dbotthepony.mc.otm.menu.matter.MatterDecomposerMenu import ru.dbotthepony.mc.otm.menu.matter.MatterDecomposerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import java.util.function.BooleanSupplier
class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
: MatteryWorkerBlockEntity<MatterDecomposerBlockEntity.DecomposerJob>(MBlockEntities.MATTER_DECOMPOSER, pos, state, DecomposerJob.CODEC) { : MatteryWorkerBlockEntity<MatterDecomposerBlockEntity.DecomposerJob>(MBlockEntities.MATTER_DECOMPOSER, pos, state, DecomposerJob.CODEC) {
@ -54,7 +55,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
} }
} }
override val upgrades = UpgradeContainer(this::markDirtyFast, 4, UpgradeType.REPLICATOR) override val upgrades = makeUpgrades(4, UpgradeType.REPLICATOR)
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, upgrades.transform(MachinesConfig.MATTER_DECOMPOSER))) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::markDirtyFast, upgrades.transform(MachinesConfig.MATTER_DECOMPOSER)))
val energyConfig = ConfigurableEnergy(energy) val energyConfig = ConfigurableEnergy(energy)

View File

@ -52,7 +52,7 @@ class MatterEntanglerBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
} }
} }
override val upgrades = UpgradeContainer(::markDirtyFast, 3, UpgradeType.BASIC_MATTER) override val upgrades = makeUpgrades(3, UpgradeType.BASIC_MATTER)
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_ENTANGLER))) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_ENTANGLER)))
val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MATTER_ENTANGLER::matterCapacity))) val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MATTER_ENTANGLER::matterCapacity)))
val node = MatterNode() val node = MatterNode()

View File

@ -34,6 +34,7 @@ import ru.dbotthepony.mc.otm.matter.IMatterValue
import ru.dbotthepony.mc.otm.matter.MatterManager import ru.dbotthepony.mc.otm.matter.MatterManager
import ru.dbotthepony.mc.otm.menu.matter.MatterReconstructorMenu import ru.dbotthepony.mc.otm.menu.matter.MatterReconstructorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.function.BooleanSupplier
class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.MATTER_RECONSTRUCTOR, blockPos, blockState) { class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.MATTER_RECONSTRUCTOR, blockPos, blockState) {
val repairContainer = MatteryContainer(::containerChanged, 1).also(::addDroppableContainer) val repairContainer = MatteryContainer(::containerChanged, 1).also(::addDroppableContainer)
@ -54,7 +55,7 @@ class MatterReconstructorBlockEntity(blockPos: BlockPos, blockState: BlockState)
var isUnableToProcess = false var isUnableToProcess = false
private set private set
val upgrades = UpgradeContainer(this::markDirtyFast, 3, UpgradeType.REPLICATOR) val upgrades = UpgradeContainer(3, UpgradeType.REPLICATOR, BooleanSupplier { repairContainer.isEmpty }, ::markDirtyFast)
val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MatterReconstructor.VALUES::matterCapacity))) val matter = ProfiledMatterStorage(MatterStorageImpl(::markDirtyFast, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MatterReconstructor.VALUES::matterCapacity)))
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::markDirtyFast, upgrades.transform(MachinesConfig.MatterReconstructor.VALUES))) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::markDirtyFast, upgrades.transform(MachinesConfig.MatterReconstructor.VALUES)))

View File

@ -46,7 +46,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
} }
} }
override val upgrades = UpgradeContainer(this::markDirtyFast, 3, UpgradeType.BASIC_MATTER) override val upgrades = makeUpgrades(3, UpgradeType.BASIC_MATTER)
val matter = ProfiledMatterStorage(MatterStorageImpl(::matterLevelUpdated, FlowDirection.OUTPUT, upgrades.matterCapacity(MachinesConfig.MatterRecycler.VALUES::matterCapacity))) val matter = ProfiledMatterStorage(MatterStorageImpl(::matterLevelUpdated, FlowDirection.OUTPUT, upgrades.matterCapacity(MachinesConfig.MatterRecycler.VALUES::matterCapacity)))
val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer) val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer)

View File

@ -67,7 +67,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} }
} }
override val upgrades = UpgradeContainer(this::markDirtyFast, 3, UpgradeType.REPLICATOR) override val upgrades = makeUpgrades(3, UpgradeType.REPLICATOR)
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_REPLICATOR))) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_REPLICATOR)))
val matter = ProfiledMatterStorage(MatterStorageImpl(::matterLevelUpdated, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MATTER_REPLICATOR::matterCapacity))) val matter = ProfiledMatterStorage(MatterStorageImpl(::matterLevelUpdated, FlowDirection.INPUT, upgrades.matterCapacity(MachinesConfig.MATTER_REPLICATOR::matterCapacity)))
val outputContainer = MatteryContainer(::itemContainerUpdated, 3).also(::addDroppableContainer) val outputContainer = MatteryContainer(::itemContainerUpdated, 3).also(::addDroppableContainer)

View File

@ -33,7 +33,7 @@ import kotlin.math.pow
class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity<ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ItemJob.CODEC) { MatteryWorkerBlockEntity<ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ItemJob.CODEC) {
override val upgrades = UpgradeContainer(this::markDirtyFast, 2, UpgradeType.BASIC) override val upgrades = makeUpgrades(2, UpgradeType.BASIC)
val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer) val container = MatteryContainer(::itemContainerUpdated, 1).also(::addDroppableContainer)
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_SCANNER))) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(::energyLevelUpdated, upgrades.transform(MachinesConfig.MATTER_SCANNER)))

View File

@ -51,7 +51,7 @@ sealed class AbstractPoweredFurnaceBlockEntity<P : AbstractCookingRecipe, S : Ma
val config: WorkerBalanceValues, val config: WorkerBalanceValues,
maxJobs: Int = 2 maxJobs: Int = 2
) : MatteryWorkerBlockEntity<ItemJob>(type, blockPos, blockState, ItemJob.CODEC, maxJobs) { ) : MatteryWorkerBlockEntity<ItemJob>(type, blockPos, blockState, ItemJob.CODEC, maxJobs) {
final override val upgrades = UpgradeContainer(this::markDirtyFast, 2, UpgradeType.BASIC_PROCESSING) final override val upgrades = makeUpgrades(2, UpgradeType.BASIC_PROCESSING)
final override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config))) final override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(config)))
val inputs = MatteryContainer(this::itemContainerUpdated, maxJobs) val inputs = MatteryContainer(this::itemContainerUpdated, maxJobs)

View File

@ -31,7 +31,7 @@ class PlatePressBlockEntity(
blockState: BlockState, blockState: BlockState,
val isTwin: Boolean = false, val isTwin: Boolean = false,
) : MatteryWorkerBlockEntity<ItemJob>(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, blockPos, blockState, ItemJob.CODEC, if (isTwin) 2 else 1) { ) : MatteryWorkerBlockEntity<ItemJob>(if (isTwin) MBlockEntities.TWIN_PLATE_PRESS else MBlockEntities.PLATE_PRESS, blockPos, blockState, ItemJob.CODEC, if (isTwin) 2 else 1) {
override val upgrades = UpgradeContainer(this::markDirtyFast, if (isTwin) 4 else 3, UpgradeType.BASIC_PROCESSING) override val upgrades = makeUpgrades(if (isTwin) 4 else 3, UpgradeType.BASIC_PROCESSING)
override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(MachinesConfig.PLATE_PRESS))) override val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::energyLevelUpdated, upgrades.transform(MachinesConfig.PLATE_PRESS)))
val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) val inputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer)
val outputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer) val outputContainer = MatteryContainer(this::itemContainerUpdated, if (isTwin) 2 else 1).also(::addDroppableContainer)

View File

@ -11,6 +11,7 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting import ru.dbotthepony.mc.otm.block.entity.RedstoneSetting
import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.addUpgradeTooltipLines import ru.dbotthepony.mc.otm.capability.addUpgradeTooltipLines
import ru.dbotthepony.mc.otm.client.CursorType
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.isCtrlDown import ru.dbotthepony.mc.otm.client.isCtrlDown
import ru.dbotthepony.mc.otm.client.isShiftDown import ru.dbotthepony.mc.otm.client.isShiftDown
@ -32,6 +33,7 @@ import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.RelativeSide import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.core.util.ItemStackSorter import ru.dbotthepony.mc.otm.core.util.ItemStackSorter
import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.UpgradeSlots import ru.dbotthepony.mc.otm.menu.UpgradeSlots
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
@ -527,7 +529,10 @@ class DeviceControls<out S : MatteryScreen<*>>(
val grid = GridPanel(screen, frame, columns = columns, rows = rows) val grid = GridPanel(screen, frame, columns = columns, rows = rows)
for (slot in upgrades.slots) { for (slot in upgrades.slots) {
SlotPanel(screen, grid, slot) object : SlotPanel<S, MatterySlot>(screen, grid, slot) {
override val cursorType: CursorType
get() = if (upgrades.areLocked.get()) CursorType.NOT_ALLOWED else super.cursorType
}
} }
grid.dock = Dock.FILL grid.dock = Dock.FILL

View File

@ -69,6 +69,8 @@ abstract class UserFilteredSlotPanel<out S : MatteryScreen<*>, out T : Slot>(
mouseY.toInt(), mouseY.toInt(),
itemstack itemstack
) )
return true
} else if (isHovered && slotFilter === Items.AIR && itemStack.isEmpty) { } else if (isHovered && slotFilter === Items.AIR && itemStack.isEmpty) {
graphics.renderComponentTooltip( graphics.renderComponentTooltip(
font, font,
@ -79,6 +81,8 @@ abstract class UserFilteredSlotPanel<out S : MatteryScreen<*>, out T : Slot>(
mouseX.toInt(), mouseX.toInt(),
mouseY.toInt() mouseY.toInt()
) )
return true
} }
return super.innerRenderTooltips(graphics, mouseX, mouseY, partialTick) return super.innerRenderTooltips(graphics, mouseX, mouseY, partialTick)

View File

@ -48,7 +48,7 @@ import kotlin.collections.ArrayList
@Suppress("UNUSED") @Suppress("UNUSED")
open class MatteryContainer(var listener: ContainerListener, private val size: Int) : IMatteryContainer, INBTSerializable<Tag?>, StackedContentsCompatible { open class MatteryContainer(var listener: ContainerListener, private val size: Int) : IMatteryContainer, INBTSerializable<Tag?>, StackedContentsCompatible {
constructor(watcher: () -> Unit, size: Int) : this({ _, _, _ -> watcher.invoke() }, size) constructor(watcher: Runnable, size: Int) : this({ _, _, _ -> watcher.run() }, size)
constructor(size: Int) : this(EmptyListener, size) constructor(size: Int) : this(EmptyListener, size)
fun interface ContainerListener { fun interface ContainerListener {

View File

@ -8,21 +8,25 @@ import ru.dbotthepony.mc.otm.config.VerboseEnergyBalanceValues
import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.collect.reduce import ru.dbotthepony.mc.otm.core.collect.reduce
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
import java.util.function.BooleanSupplier
import kotlin.math.pow import kotlin.math.pow
open class UpgradeContainer(slotCount: Int, open val allowedUpgrades: Set<UpgradeType> = UpgradeType.ALL, listener: ContainerListener = EmptyListener) : MatteryContainer(listener, slotCount), IMatteryUpgrade { class UpgradeContainer(
constructor(listener: () -> Unit, slotCount: Int, allowedUpgrades: Set<UpgradeType>) : this(slotCount, allowedUpgrades, { _, _, _ -> listener.invoke() }) slotCount: Int,
val allowedUpgrades: Set<UpgradeType> = UpgradeType.ALL,
final override val upgradeTypes: Set<UpgradeType> val shouldLockUpgradeSlots: BooleanSupplier = BooleanSupplier { false },
listener: Runnable = Runnable {}
) : MatteryContainer(listener, slotCount), IMatteryUpgrade {
override val upgradeTypes: Set<UpgradeType>
get() = setOf() get() = setOf()
protected fun positiveDecimals(fn: (IMatteryUpgrade) -> Decimal, reducer: (Decimal, Decimal) -> Decimal): Decimal { private fun positiveDecimals(fn: (IMatteryUpgrade) -> Decimal, reducer: (Decimal, Decimal) -> Decimal): Decimal {
return iterator() return iterator()
.map { (it.getCapability(MatteryCapability.UPGRADE)?.let(fn) ?: Decimal.ZERO).moreThanZero() * it.count } .map { (it.getCapability(MatteryCapability.UPGRADE)?.let(fn) ?: Decimal.ZERO).moreThanZero() * it.count }
.reduce(Decimal.ZERO, reducer) .reduce(Decimal.ZERO, reducer)
} }
protected fun anyDecimals(fn: (IMatteryUpgrade) -> Decimal, reducer: (Decimal, Decimal) -> Decimal): Decimal { private fun anyDecimals(fn: (IMatteryUpgrade) -> Decimal, reducer: (Decimal, Decimal) -> Decimal): Decimal {
return iterator() return iterator()
.map { (it.getCapability(MatteryCapability.UPGRADE)?.let(fn) ?: Decimal.ZERO) * it.count } .map { (it.getCapability(MatteryCapability.UPGRADE)?.let(fn) ?: Decimal.ZERO) * it.count }
.reduce(Decimal.ZERO, reducer) .reduce(Decimal.ZERO, reducer)

View File

@ -76,17 +76,6 @@ data class EquipmentSlots(
val curiosSlots: List<PlayerSlot<Slot, Slot>> val curiosSlots: List<PlayerSlot<Slot, Slot>>
) )
/**
* [openState] **is clientside only**, attempting to use it on server will result
* in classloading exceptions.
*/
data class UpgradeSlots(
val slots: List<MatterySlot>,
val allowedTypes: Set<UpgradeType>,
val openState: Delegate<Boolean>,
val currentStats: IMatteryUpgrade
)
abstract class MatteryMenu( abstract class MatteryMenu(
menuType: MenuType<*>?, menuType: MenuType<*>?,
containerId: Int, containerId: Int,
@ -433,7 +422,7 @@ abstract class MatteryMenu(
* *
* [condition] allows to specify when slot is invisible on GUI (hence being ignored by quick move) * [condition] allows to specify when slot is invisible on GUI (hence being ignored by quick move)
*/ */
protected fun <T : Slot> addStorageSlot(slot: T, addMapping: Boolean = true, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }): T { fun <T : Slot> addStorageSlot(slot: T, addMapping: Boolean = true, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }): T {
if (!externalSlots.actuallyContains(slot)) { if (!externalSlots.actuallyContains(slot)) {
addSlot(slot) addSlot(slot)
@ -451,7 +440,7 @@ abstract class MatteryMenu(
return slot return slot
} }
protected fun addStorageSlot(slot: Iterable<Slot>, addMapping: Boolean = true, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }) { fun addStorageSlot(slot: Iterable<Slot>, addMapping: Boolean = true, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }) {
for (value in slot) for (value in slot)
addStorageSlot(value, addMapping, prepend, condition) addStorageSlot(value, addMapping, prepend, condition)
} }
@ -459,18 +448,18 @@ abstract class MatteryMenu(
/** /**
* Marks slot as "storage" - shift clicking it will move its contents to Player's inventory * Marks slot as "storage" - shift clicking it will move its contents to Player's inventory
*/ */
protected fun mapQuickMoveToInventory(slot: Slot, prepend: Boolean = false) { fun mapQuickMoveToInventory(slot: Slot, prepend: Boolean = false) {
mapQuickMove(slot, playerInventorySlots, prepend = prepend) mapQuickMove(slot, playerInventorySlots, prepend = prepend)
} }
/** /**
* Marks slot as "inventory" - shift clicking it will move its contents to menu's storage slots * Marks slot as "inventory" - shift clicking it will move its contents to menu's storage slots
*/ */
protected fun mapQuickMoveToExternal(slot: Slot, prepend: Boolean = false) { fun mapQuickMoveToExternal(slot: Slot, prepend: Boolean = false) {
mapQuickMove(slot, externalSlots, prepend = prepend) mapQuickMove(slot, externalSlots, prepend = prepend)
} }
protected fun mapQuickMove(slot: Slot, target: Collection<Slot>, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }) { fun mapQuickMove(slot: Slot, target: Collection<Slot>, prepend: Boolean = false, condition: BooleanSupplier = BooleanSupplier { true }) {
val listing = quickMoveMapping.computeIfAbsent(slot, Reference2ObjectFunction { ReferenceArrayList(1) /* ReferenceArrayList ибо мы используем его в некотором смысле как множество */ }) val listing = quickMoveMapping.computeIfAbsent(slot, Reference2ObjectFunction { ReferenceArrayList(1) /* ReferenceArrayList ибо мы используем его в некотором смысле как множество */ })
listing.remove(target) listing.remove(target)
@ -480,7 +469,7 @@ abstract class MatteryMenu(
listing.add(target) listing.add(target)
} }
protected fun mapQuickMove(slot: Slot, vararg target: Collection<Slot>) { fun mapQuickMove(slot: Slot, vararg target: Collection<Slot>) {
for (value in target) { for (value in target) {
mapQuickMove(slot, value) mapQuickMove(slot, value)
} }
@ -743,56 +732,6 @@ abstract class MatteryMenu(
) )
} }
fun makeUpgradeSlots(count: Int, container: UpgradeContainer?): UpgradeSlots {
if (container != null) {
require(count == container.containerSize) { "Upgrade container size ${container.containerSize} does not match with provided size $count" }
}
val allowedTypes = EnumMap<UpgradeType, BooleanSupplier>(UpgradeType::class.java)
for (value in UpgradeType.ALL) {
val b = mSynchronizer.boolean().delegate.also {
if (container != null) {
it.accept(value in container.allowedUpgrades)
}
}
allowedTypes[value] = BooleanSupplier { b.get() }
}
val syncContainer = container ?: SimpleContainer(count)
val isOpen = InstantBooleanInput(this)
return UpgradeSlots(
slots = immutableList(count) {
object : MatterySlot(syncContainer, it) {
init {
mapQuickMoveToInventory(this)
}
override fun mayPlace(itemStack: ItemStack): Boolean {
return super.mayPlace(itemStack) && (itemStack.getCapability(MatteryCapability.UPGRADE)?.let { it.upgradeTypes.any { allowedTypes[it]!!.asBoolean } } == true)
}
}
}.also { for (i in it.indices.reversed()) addStorageSlot(it[i], prepend = true, condition = isOpen) },
allowedTypes = ConditionalEnumSet(allowedTypes),
openState = isOpen,
currentStats = object : IMatteryUpgrade {
override val upgradeTypes: Set<UpgradeType> = setOf()
override val speedBonus: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.speedBonus ?: 0.0 })
override val processingItems: Int by mSynchronizer.computedInt(IntSupplier { container?.processingItems ?: 0 })
override val energyStorageFlat: Decimal by mSynchronizer.computedDecimal { container?.energyStorageFlat ?: Decimal.ZERO }
override val energyStorage: Decimal by mSynchronizer.computedDecimal { container?.energyStorage ?: Decimal.ZERO }
override val energyConsumed: Decimal by mSynchronizer.computedDecimal { container?.energyConsumed ?: Decimal.ZERO }
override val energyThroughputFlat: Decimal by mSynchronizer.computedDecimal { container?.energyThroughputFlat ?: Decimal.ZERO }
override val energyThroughput: Decimal by mSynchronizer.computedDecimal { container?.energyThroughput ?: Decimal.ZERO }
override val failureMultiplier: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.failureMultiplier ?: 1.0 })
}
)
}
companion object { companion object {
val TEXTURE_EMPTY_SLOTS: List<ResourceLocation> = ImmutableList.of( val TEXTURE_EMPTY_SLOTS: List<ResourceLocation> = ImmutableList.of(
InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS, InventoryMenu.EMPTY_ARMOR_SLOT_BOOTS,

View File

@ -9,18 +9,29 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.neoforged.neoforge.capabilities.Capabilities import net.neoforged.neoforge.capabilities.Capabilities
import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.getValue
import ru.dbotthepony.kommons.util.value import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.IMatteryUpgrade
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.UpgradeType
import ru.dbotthepony.mc.otm.capability.energy import ru.dbotthepony.mc.otm.capability.energy
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.container.IMatteryContainer import ru.dbotthepony.mc.otm.container.IMatteryContainer
import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.container.ItemFilter
import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.collect.ConditionalEnumSet
import ru.dbotthepony.mc.otm.core.immutableList import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.InstantBooleanInput
import ru.dbotthepony.mc.otm.runOnClient import ru.dbotthepony.mc.otm.runOnClient
import java.util.ArrayList import java.util.*
import java.util.function.BooleanSupplier
import java.util.function.DoubleSupplier
import java.util.function.IntSupplier
import java.util.function.Predicate import java.util.function.Predicate
import java.util.function.Supplier
import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty0
/** /**
@ -223,3 +234,79 @@ fun MatteryMenu.addFilterControls(slots: Delegate<ItemFilter>?, amount: Int): Fi
fun MatteryMenu.addFilterControls(slots: KMutableProperty0<ItemFilter>?, amount: Int): FilterControls { fun MatteryMenu.addFilterControls(slots: KMutableProperty0<ItemFilter>?, amount: Int): FilterControls {
return addFilterControls(slots?.let { Delegate.Of(it) }, amount) return addFilterControls(slots?.let { Delegate.Of(it) }, amount)
} }
/**
* [openState] **is clientside only**, attempting to use it on server will result
* in classloading exceptions.
*/
data class UpgradeSlots(
val slots: List<MatterySlot>,
val allowedTypes: Set<UpgradeType>,
val openState: Delegate<Boolean>,
val currentStats: IMatteryUpgrade,
val areLocked: Supplier<Boolean>
)
fun MatteryMenu.makeUpgradeSlots(count: Int, container: UpgradeContainer?): UpgradeSlots {
if (container != null) {
require(count == container.containerSize) { "Upgrade container size ${container.containerSize} does not match with provided size $count" }
}
val shouldLockUpgradeSlots: Supplier<Boolean>
val allowedTypes = EnumMap<UpgradeType, BooleanSupplier>(UpgradeType::class.java)
if (container == null) {
shouldLockUpgradeSlots = mSynchronizer.boolean()
} else {
shouldLockUpgradeSlots = mSynchronizer.computedBoolean(container.shouldLockUpgradeSlots)
}
for (value in UpgradeType.ALL) {
val b = mSynchronizer.boolean().delegate.also {
if (container != null) {
it.accept(value in container.allowedUpgrades)
}
}
allowedTypes[value] = BooleanSupplier { b.get() }
}
val syncContainer = container ?: SimpleContainer(count)
val isOpen = InstantBooleanInput(this)
return UpgradeSlots(
slots = immutableList(count) {
object : MatterySlot(syncContainer, it) {
init {
mapQuickMoveToInventory(this)
}
override fun mayPlace(itemStack: ItemStack): Boolean {
return super.mayPlace(itemStack) &&
(itemStack.getCapability(MatteryCapability.UPGRADE)?.let { it.upgradeTypes.any { allowedTypes[it]!!.asBoolean } } == true) &&
!shouldLockUpgradeSlots.get()
}
override fun mayPickup(player: Player): Boolean {
return super.mayPickup(player) && !shouldLockUpgradeSlots.get()
}
}
}.also { for (i in it.indices.reversed()) addStorageSlot(it[i], prepend = true, condition = isOpen) },
areLocked = shouldLockUpgradeSlots,
allowedTypes = ConditionalEnumSet(allowedTypes),
openState = isOpen,
currentStats = object : IMatteryUpgrade {
override val upgradeTypes: Set<UpgradeType> = setOf()
override val speedBonus: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.speedBonus ?: 0.0 })
override val processingItems: Int by mSynchronizer.computedInt(IntSupplier { container?.processingItems ?: 0 })
override val energyStorageFlat: Decimal by mSynchronizer.computedDecimal { container?.energyStorageFlat ?: Decimal.ZERO }
override val energyStorage: Decimal by mSynchronizer.computedDecimal { container?.energyStorage ?: Decimal.ZERO }
override val energyConsumed: Decimal by mSynchronizer.computedDecimal { container?.energyConsumed ?: Decimal.ZERO }
override val energyThroughputFlat: Decimal by mSynchronizer.computedDecimal { container?.energyThroughputFlat ?: Decimal.ZERO }
override val energyThroughput: Decimal by mSynchronizer.computedDecimal { container?.energyThroughput ?: Decimal.ZERO }
override val failureMultiplier: Double by mSynchronizer.computedDouble(DoubleSupplier { container?.failureMultiplier ?: 1.0 })
}
)
}

View File

@ -16,6 +16,7 @@ import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus

View File

@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus

View File

@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget

View File

@ -8,6 +8,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget

View File

@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget

View File

@ -14,6 +14,7 @@ import ru.dbotthepony.mc.otm.menu.OutputSlot
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus
import ru.dbotthepony.mc.otm.triggers.TakeItemOutOfReplicatorTrigger import ru.dbotthepony.mc.otm.triggers.TakeItemOutOfReplicatorTrigger

View File

@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus

View File

@ -16,6 +16,7 @@ import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus

View File

@ -20,6 +20,7 @@ import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.menu.makeSlots import ru.dbotthepony.mc.otm.menu.makeSlots
import ru.dbotthepony.mc.otm.menu.makeUpgradeSlots
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
import ru.dbotthepony.mc.otm.registry.MMenus import ru.dbotthepony.mc.otm.registry.MMenus