Configurable energy handler working
This commit is contained in:
parent
9959f72db3
commit
3b53d65b29
@ -613,6 +613,7 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
gui("stored_amount", "Exact amount stored: %s")
|
gui("stored_amount", "Exact amount stored: %s")
|
||||||
|
|
||||||
gui("sides.item_config", "Item Configuration")
|
gui("sides.item_config", "Item Configuration")
|
||||||
|
gui("sides.energy_config", "Energy Configuration")
|
||||||
|
|
||||||
gui("sides.top", "Top")
|
gui("sides.top", "Top")
|
||||||
gui("sides.bottom", "Bottom")
|
gui("sides.bottom", "Bottom")
|
||||||
|
@ -618,6 +618,7 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
gui("stored_amount", "Точное количество в хранилище: %s шт.")
|
gui("stored_amount", "Точное количество в хранилище: %s шт.")
|
||||||
|
|
||||||
gui("sides.item_config", "Настройка Предметов")
|
gui("sides.item_config", "Настройка Предметов")
|
||||||
|
gui("sides.energy_config", "Настройка Энергии")
|
||||||
|
|
||||||
gui("sides.top", "Верхняя сторона")
|
gui("sides.top", "Верхняя сторона")
|
||||||
gui("sides.bottom", "Нижняя сторона")
|
gui("sides.bottom", "Нижняя сторона")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.dbotthepony.mc.otm.block.entity
|
package ru.dbotthepony.mc.otm.block.entity
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
|
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
|
||||||
@ -52,7 +53,9 @@ import ru.dbotthepony.mc.otm.core.forValidRefs
|
|||||||
import ru.dbotthepony.mc.otm.core.get
|
import ru.dbotthepony.mc.otm.core.get
|
||||||
import ru.dbotthepony.mc.otm.core.getValue
|
import ru.dbotthepony.mc.otm.core.getValue
|
||||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||||
|
import ru.dbotthepony.mc.otm.core.immutableList
|
||||||
import ru.dbotthepony.mc.otm.core.immutableMap
|
import ru.dbotthepony.mc.otm.core.immutableMap
|
||||||
|
import ru.dbotthepony.mc.otm.core.immutableSet
|
||||||
import ru.dbotthepony.mc.otm.core.math.BlockRotation
|
import ru.dbotthepony.mc.otm.core.math.BlockRotation
|
||||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||||
import ru.dbotthepony.mc.otm.core.math.minus
|
import ru.dbotthepony.mc.otm.core.math.minus
|
||||||
@ -170,14 +173,16 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun exposeEnergy(side: RelativeSide, value: IMatteryEnergyStorage) {
|
protected fun exposeEnergy(side: RelativeSide, value: IMatteryEnergyStorage): ImmutableList<Side.Cap<*>> {
|
||||||
|
return immutableList {
|
||||||
val thisSide = _sides[side]!!
|
val thisSide = _sides[side]!!
|
||||||
|
|
||||||
thisSide.Cap(ForgeCapabilities.ENERGY, value)
|
accept(thisSide.Cap(ForgeCapabilities.ENERGY, value))
|
||||||
thisSide.Cap(MatteryCapability.ENERGY, value)
|
accept(thisSide.Cap(MatteryCapability.ENERGY, value))
|
||||||
|
|
||||||
if (isMekanismLoaded) {
|
if (isMekanismLoaded) {
|
||||||
thisSide.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value))
|
accept(thisSide.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,16 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities
|
|||||||
import net.minecraftforge.items.IItemHandler
|
import net.minecraftforge.items.IItemHandler
|
||||||
import ru.dbotthepony.mc.otm.capability.CombinedItemHandler
|
import ru.dbotthepony.mc.otm.capability.CombinedItemHandler
|
||||||
import ru.dbotthepony.mc.otm.capability.EmptyItemHandler
|
import ru.dbotthepony.mc.otm.capability.EmptyItemHandler
|
||||||
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.capability.UnmodifiableItemHandler
|
import ru.dbotthepony.mc.otm.capability.UnmodifiableItemHandler
|
||||||
|
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.moveBetweenSlots
|
import ru.dbotthepony.mc.otm.capability.moveBetweenSlots
|
||||||
|
import ru.dbotthepony.mc.otm.capability.moveEnergy
|
||||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||||
import ru.dbotthepony.mc.otm.core.getValue
|
import ru.dbotthepony.mc.otm.core.getValue
|
||||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||||
import ru.dbotthepony.mc.otm.core.immutableMap
|
import ru.dbotthepony.mc.otm.core.immutableMap
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.getJson
|
import ru.dbotthepony.mc.otm.core.nbt.getJson
|
||||||
import ru.dbotthepony.mc.otm.core.nbt.putJson
|
import ru.dbotthepony.mc.otm.core.nbt.putJson
|
||||||
@ -68,6 +72,135 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
redstoneControl.deserializeNBT(nbt[REDSTONE_CONTROL_KEY] as? CompoundTag)
|
redstoneControl.deserializeNBT(nbt[REDSTONE_CONTROL_KEY] as? CompoundTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class ConfigurableEnergy<T : IMatteryEnergyStorage>(
|
||||||
|
val capability: T,
|
||||||
|
|
||||||
|
val possibleModes: FlowDirection = capability.energyFlow,
|
||||||
|
|
||||||
|
val frontDefault: FlowDirection = possibleModes,
|
||||||
|
val backDefault: FlowDirection = possibleModes,
|
||||||
|
val leftDefault: FlowDirection = possibleModes,
|
||||||
|
val rightDefault: FlowDirection = possibleModes,
|
||||||
|
val topDefault: FlowDirection = possibleModes,
|
||||||
|
val bottomDefault: FlowDirection = possibleModes,
|
||||||
|
) {
|
||||||
|
init {
|
||||||
|
exposeEnergySideless(capability)
|
||||||
|
}
|
||||||
|
|
||||||
|
val front = Piece(RelativeSide.FRONT).also { it.energyFlow = frontDefault }
|
||||||
|
val back = Piece(RelativeSide.BACK).also { it.energyFlow = backDefault }
|
||||||
|
val left = Piece(RelativeSide.LEFT).also { it.energyFlow = leftDefault }
|
||||||
|
val right = Piece(RelativeSide.RIGHT).also { it.energyFlow = rightDefault }
|
||||||
|
val top = Piece(RelativeSide.TOP).also { it.energyFlow = topDefault }
|
||||||
|
val bottom = Piece(RelativeSide.BOTTOM).also { it.energyFlow = bottomDefault }
|
||||||
|
|
||||||
|
val pieces = immutableMap {
|
||||||
|
put(RelativeSide.FRONT, front)
|
||||||
|
put(RelativeSide.BACK, back)
|
||||||
|
put(RelativeSide.LEFT, left)
|
||||||
|
put(RelativeSide.RIGHT, right)
|
||||||
|
put(RelativeSide.TOP, top)
|
||||||
|
put(RelativeSide.BOTTOM, bottom)
|
||||||
|
}
|
||||||
|
|
||||||
|
val defaults = immutableMap {
|
||||||
|
put(RelativeSide.FRONT, frontDefault)
|
||||||
|
put(RelativeSide.BACK, backDefault)
|
||||||
|
put(RelativeSide.LEFT, leftDefault)
|
||||||
|
put(RelativeSide.RIGHT, rightDefault)
|
||||||
|
put(RelativeSide.TOP, topDefault)
|
||||||
|
put(RelativeSide.BOTTOM, bottomDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Piece(val side: RelativeSide) : IMatteryEnergyStorage, ITickable {
|
||||||
|
private val capControllers = exposeEnergy(side, this@Piece)
|
||||||
|
private val neighbour by sides[side]!!.track(ForgeCapabilities.ENERGY)
|
||||||
|
|
||||||
|
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
|
return capability.extractEnergy(howMuch, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
|
return capability.receiveEnergy(howMuch, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun extractEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
|
if (energyFlow.output)
|
||||||
|
return capability.extractEnergyChecked(howMuch, simulate)
|
||||||
|
|
||||||
|
return Decimal.ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun receiveEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
|
if (energyFlow.input)
|
||||||
|
return capability.receiveEnergyChecked(howMuch, simulate)
|
||||||
|
|
||||||
|
return Decimal.ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
override var batteryLevel: Decimal by capability::batteryLevel
|
||||||
|
override val maxBatteryLevel: Decimal by capability::maxBatteryLevel
|
||||||
|
override val missingPower: Decimal by capability::missingPower
|
||||||
|
|
||||||
|
override val canSetBatteryLevel: Boolean by capability::canSetBatteryLevel
|
||||||
|
|
||||||
|
override fun drainBattery(): Boolean {
|
||||||
|
return capability.drainBattery()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fillBattery(): Boolean {
|
||||||
|
return capability.fillBattery()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
if (energyFlow == FlowDirection.NONE || !automatePull && !automatePush)
|
||||||
|
return
|
||||||
|
|
||||||
|
neighbour.ifPresentK {
|
||||||
|
if (energyFlow.input && automatePull) {
|
||||||
|
moveEnergy(source = it, destination = capability, simulate = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (energyFlow.output && automatePush) {
|
||||||
|
moveEnergy(source = capability, destination = it, simulate = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
tickList.always(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override var energyFlow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote ->
|
||||||
|
require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" }
|
||||||
|
|
||||||
|
if (access.read() != value) {
|
||||||
|
access.write(value)
|
||||||
|
|
||||||
|
if (value == FlowDirection.NONE) {
|
||||||
|
for (controller in capControllers)
|
||||||
|
controller.close()
|
||||||
|
} else {
|
||||||
|
for (controller in capControllers) {
|
||||||
|
controller.close()
|
||||||
|
controller.expose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var automatePull by synchronizer.bool()
|
||||||
|
var automatePush by synchronizer.bool()
|
||||||
|
|
||||||
|
init {
|
||||||
|
savetables.enum(::energyFlow, "energy_${side}_flow", FlowDirection::valueOf)
|
||||||
|
savetables.bool(::automatePull, "energy_${side}_pull")
|
||||||
|
savetables.bool(::automatePush, "energy_${side}_push")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class ItemHandlerMode(val translationKey: String) {
|
enum class ItemHandlerMode(val translationKey: String) {
|
||||||
DISABLED("otm.gui.side_mode.disabled"),
|
DISABLED("otm.gui.side_mode.disabled"),
|
||||||
INPUT("otm.gui.side_mode.input"),
|
INPUT("otm.gui.side_mode.input"),
|
||||||
@ -107,7 +240,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
val top = Piece(RelativeSide.TOP, input, output, battery).also { it.mode = topDefault }
|
val top = Piece(RelativeSide.TOP, input, output, battery).also { it.mode = topDefault }
|
||||||
val bottom = Piece(RelativeSide.BOTTOM, input, output, battery).also { it.mode = bottomDefault }
|
val bottom = Piece(RelativeSide.BOTTOM, input, output, battery).also { it.mode = bottomDefault }
|
||||||
|
|
||||||
val sides = immutableMap {
|
val pieces = immutableMap {
|
||||||
put(RelativeSide.FRONT, front)
|
put(RelativeSide.FRONT, front)
|
||||||
put(RelativeSide.BACK, back)
|
put(RelativeSide.BACK, back)
|
||||||
put(RelativeSide.LEFT, left)
|
put(RelativeSide.LEFT, left)
|
||||||
@ -126,14 +259,14 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class Piece(
|
inner class Piece(
|
||||||
side: RelativeSide,
|
val side: RelativeSide,
|
||||||
val input: IItemHandler? = null,
|
val input: IItemHandler? = null,
|
||||||
val output: IItemHandler? = null,
|
val output: IItemHandler? = null,
|
||||||
val battery: IItemHandler? = null,
|
val battery: IItemHandler? = null,
|
||||||
) : IItemHandler, ITickable {
|
) : IItemHandler, ITickable {
|
||||||
private var currentHandler: IItemHandler = EmptyItemHandler
|
private var currentHandler: IItemHandler = EmptyItemHandler
|
||||||
val capController = this@MatteryDeviceBlockEntity.sides[side]!!.Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
private val capController = sides[side]!!.Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
||||||
private val neighbour by this@MatteryDeviceBlockEntity.sides[side]!!.track(ForgeCapabilities.ITEM_HANDLER)
|
private val neighbour by sides[side]!!.track(ForgeCapabilities.ITEM_HANDLER)
|
||||||
|
|
||||||
val possibleViews: ImmutableSet<ItemHandlerMode>
|
val possibleViews: ImmutableSet<ItemHandlerMode>
|
||||||
val inputOutput: IItemHandler?
|
val inputOutput: IItemHandler?
|
||||||
@ -184,29 +317,27 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var automatePull = false
|
var automatePull by synchronizer.bool(setter = { value, access, _ ->
|
||||||
set(value) {
|
if (access.read() != value) {
|
||||||
if (field != value) {
|
access.write(value)
|
||||||
field = value
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
innerSlotPull = 0
|
|
||||||
outerSlotPull = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var automatePush = false
|
|
||||||
set(value) {
|
|
||||||
if (field != value) {
|
|
||||||
field = value
|
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
innerSlotPush = 0
|
innerSlotPush = 0
|
||||||
outerSlotPush = 0
|
outerSlotPush = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var automatePush by synchronizer.bool(setter = { value, access, _ ->
|
||||||
|
if (access.read() != value) {
|
||||||
|
access.write(value)
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
innerSlotPush = 0
|
||||||
|
outerSlotPush = 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
init {
|
init {
|
||||||
savetables.bool(::automatePull, "itemhandler_${side}_automatePull")
|
savetables.bool(::automatePull, "itemhandler_${side}_automatePull")
|
||||||
|
@ -47,20 +47,21 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
|
|||||||
battery = batteryItemHandler,
|
battery = batteryItemHandler,
|
||||||
backDefault = ItemHandlerMode.BATTERY)
|
backDefault = ItemHandlerMode.BATTERY)
|
||||||
|
|
||||||
|
val energyConfig = ConfigurableEnergy(energy)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
for (piece in energyConfig.pieces.values)
|
||||||
|
piece.automatePush = true
|
||||||
|
|
||||||
savetable(::energy, ENERGY_KEY)
|
savetable(::energy, ENERGY_KEY)
|
||||||
savetable(::batteryContainer)
|
savetable(::batteryContainer)
|
||||||
savetable(::residueContainer)
|
savetable(::residueContainer)
|
||||||
savetable(::fuelContainer)
|
savetable(::fuelContainer)
|
||||||
|
|
||||||
exposeEnergyGlobally(energy)
|
|
||||||
|
|
||||||
savetables.int(::workTicks, WORK_TICKS_KEY)
|
savetables.int(::workTicks, WORK_TICKS_KEY)
|
||||||
savetables.int(::workTicksTotal, WORK_TICKS_TOTAL_KEY)
|
savetables.int(::workTicksTotal, WORK_TICKS_TOTAL_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val consumers = trackGlobally(ForgeCapabilities.ENERGY)
|
|
||||||
|
|
||||||
override fun setChangedLight() {
|
override fun setChangedLight() {
|
||||||
super.setChangedLight()
|
super.setChangedLight()
|
||||||
checkFuelSlot = true
|
checkFuelSlot = true
|
||||||
@ -74,15 +75,6 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
|
|||||||
|
|
||||||
private var checkFuelSlot = true
|
private var checkFuelSlot = true
|
||||||
|
|
||||||
private fun workWithPower(it: IEnergyStorage) {
|
|
||||||
val extracted = energy.extractEnergy(THROUGHPUT, true)
|
|
||||||
val received = it.receiveEnergy(extracted, false)
|
|
||||||
|
|
||||||
if (!received.isZero) {
|
|
||||||
energy.extractEnergy(received, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
super.tick()
|
super.tick()
|
||||||
|
|
||||||
@ -133,12 +125,9 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe
|
|||||||
val item = batteryContainer[0]
|
val item = batteryContainer[0]
|
||||||
|
|
||||||
if (!item.isEmpty) {
|
if (!item.isEmpty) {
|
||||||
item.energy?.let(this::workWithPower)
|
item.energy?.also {
|
||||||
if (energy.batteryLevel.isZero) return
|
moveEnergy(energy, it, THROUGHPUT, simulate = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (consumer in consumers) {
|
|
||||||
consumer.ifPresentK(::workWithPower)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ru.dbotthepony.mc.otm.capability
|
package ru.dbotthepony.mc.otm.capability
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,35 +21,84 @@ import java.util.function.Predicate
|
|||||||
* * `BI_DIRECTIONAL.test(OUTPUT)` = `false`
|
* * `BI_DIRECTIONAL.test(OUTPUT)` = `false`
|
||||||
* * `BI_DIRECTIONAL.test(INPUT)` = `false`
|
* * `BI_DIRECTIONAL.test(INPUT)` = `false`
|
||||||
*/
|
*/
|
||||||
enum class FlowDirection(val input: Boolean, val output: Boolean) : Predicate<FlowDirection> {
|
enum class FlowDirection(val input: Boolean, val output: Boolean, val translationKey: String) : Predicate<FlowDirection> {
|
||||||
/**
|
/**
|
||||||
* Can only be inputted (consumer)
|
* Can only be inputted (consumer)
|
||||||
*/
|
*/
|
||||||
INPUT(true, false),
|
INPUT(true, false, "otm.gui.side_mode.input"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can only be outputted/transmitted (producer)
|
* Can only be outputted/transmitted (producer)
|
||||||
*/
|
*/
|
||||||
OUTPUT(false, true),
|
OUTPUT(false, true, "otm.gui.side_mode.output"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can both consume and produce (capacitor)
|
* Can both consume and produce (capacitor)
|
||||||
*/
|
*/
|
||||||
BI_DIRECTIONAL(true, true),
|
BI_DIRECTIONAL(true, true, "otm.gui.side_mode.input_output"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Why would you want to use this
|
* Why would you want to use this
|
||||||
*/
|
*/
|
||||||
NONE(false, false);
|
NONE(false, false, "otm.gui.side_mode.disabled");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All values that pass [isSupertype]
|
||||||
|
*/
|
||||||
|
val family: ImmutableSet<FlowDirection> by lazy {
|
||||||
|
ImmutableSet.Builder<FlowDirection>().also {
|
||||||
|
when (this) {
|
||||||
|
INPUT -> it.add(INPUT)
|
||||||
|
OUTPUT -> it.add(OUTPUT)
|
||||||
|
BI_DIRECTIONAL -> {
|
||||||
|
it.add(INPUT)
|
||||||
|
it.add(OUTPUT)
|
||||||
|
it.add(BI_DIRECTIONAL)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
it.add(NONE)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtype test (returns true if we can assign [t] to this, e.g. we can assign [BI_DIRECTIONAL] to [INPUT])
|
||||||
|
*/
|
||||||
override fun test(t: FlowDirection): Boolean {
|
override fun test(t: FlowDirection): Boolean {
|
||||||
return t === this || (!input || t.input) && (!output || t.output)
|
return t === this || (!input || t.input) && (!output || t.output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtype test (returns true if we can assign [value] to this, e.g. we can assign [BI_DIRECTIONAL] to [INPUT])
|
||||||
|
*/
|
||||||
|
fun isSubtype(value: FlowDirection) = test(value)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supertype test (e.g. [INPUT] is supertype to [BI_DIRECTIONAL], so if this is [BI_DIRECTIONAL] then calling [isSupertype] with [INPUT] will return `true`)
|
||||||
|
*/
|
||||||
|
fun isSupertype(value: FlowDirection): Boolean {
|
||||||
|
return value === this || value in family
|
||||||
|
}
|
||||||
|
|
||||||
fun intersect(other: FlowDirection): FlowDirection {
|
fun intersect(other: FlowDirection): FlowDirection {
|
||||||
return of(other.input && input, other.output && output)
|
return of(other.input && input, other.output && output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun withInput(flag: Boolean): FlowDirection {
|
||||||
|
if (flag == input)
|
||||||
|
return this
|
||||||
|
|
||||||
|
return of(flag, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withOutput(flag: Boolean): FlowDirection {
|
||||||
|
if (flag == output)
|
||||||
|
return this
|
||||||
|
|
||||||
|
return of(input, flag)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun of(input: Boolean, output: Boolean): FlowDirection {
|
fun of(input: Boolean, output: Boolean): FlowDirection {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package ru.dbotthepony.mc.otm.capability
|
package ru.dbotthepony.mc.otm.capability
|
||||||
|
|
||||||
|
import net.minecraftforge.energy.IEnergyStorage
|
||||||
import net.minecraftforge.items.IItemHandler
|
import net.minecraftforge.items.IItemHandler
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to safely exchange/move item between slots of two handlers
|
* Attempts to safely exchange/move item between slots of two handlers
|
||||||
@ -41,3 +43,27 @@ fun moveBetweenSlots(source: IItemHandler, sourceSlot: Int, destination: IItemHa
|
|||||||
|
|
||||||
return sourceSlot to destinationSlot
|
return sourceSlot to destinationSlot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("name_shadowing")
|
||||||
|
fun moveEnergy(source: IEnergyStorage, destination: IEnergyStorage, amount: Decimal = Decimal.LONG_MAX_VALUE, simulate: Boolean): Decimal {
|
||||||
|
val extracted = source.extractEnergy(amount, true)
|
||||||
|
|
||||||
|
if (extracted.isPositive) {
|
||||||
|
val received = destination.receiveEnergy(extracted, true)
|
||||||
|
|
||||||
|
if (received.isPositive) {
|
||||||
|
val extracted = source.extractEnergy(received, true)
|
||||||
|
|
||||||
|
if (extracted.isPositive) {
|
||||||
|
if (simulate) {
|
||||||
|
return extracted
|
||||||
|
}
|
||||||
|
|
||||||
|
val received = destination.receiveEnergy(extracted, false)
|
||||||
|
return source.extractEnergy(received, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Decimal.ZERO
|
||||||
|
}
|
||||||
|
@ -68,4 +68,5 @@ object Widgets18 {
|
|||||||
val INPUT_OUTPUT = controlsGrid.next()
|
val INPUT_OUTPUT = controlsGrid.next()
|
||||||
val BATTERY_ONLY = controlsGrid.next()
|
val BATTERY_ONLY = controlsGrid.next()
|
||||||
val ITEMS_CONFIGURATION = controlsGrid.next()
|
val ITEMS_CONFIGURATION = controlsGrid.next()
|
||||||
|
val ENERGY_CONFIGURATION = controlsGrid.next()
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.client.screen.panels.button
|
|||||||
import com.mojang.blaze3d.platform.InputConstants
|
import com.mojang.blaze3d.platform.InputConstants
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
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.client.minecraft
|
import ru.dbotthepony.mc.otm.client.minecraft
|
||||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||||
@ -10,6 +11,8 @@ 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.FramePanel
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.EnergyPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemHandlerPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemHandlerPlayerInput
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
@ -59,57 +62,33 @@ private fun <S : MatteryScreen<*>> makeItemModeButton(screen: S, parent: FramePa
|
|||||||
return button
|
return button
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <S : MatteryScreen<*>> makeItemHandlerControlPanel(
|
private fun <S : MatteryScreen<*>> makeEnergyModeButton(screen: S, parent: FramePanel<S>, input: EnergyPlayerInput.Piece): LargeEnumRectangleButtonPanel<S, FlowDirection> {
|
||||||
screen: S,
|
val button = LargeEnumRectangleButtonPanel(screen, parent, enum = FlowDirection::class.java, prop = input.input, defaultValue = input.default)
|
||||||
inputs: ItemHandlerPlayerInput
|
|
||||||
): FramePanel<S> {
|
|
||||||
val frame = object : FramePanel<S>(screen, 78f, 80f, TranslatableComponent("otm.gui.sides.item_config")) {
|
|
||||||
override fun tickInner() {
|
|
||||||
super.tickInner()
|
|
||||||
|
|
||||||
if (!isEverFocused()) {
|
val values = listOf(
|
||||||
remove()
|
FlowDirection.NONE to Widgets18.DISABLED,
|
||||||
}
|
FlowDirection.INPUT to Widgets18.INPUT_ONLY,
|
||||||
}
|
FlowDirection.OUTPUT to Widgets18.OUTPUT_ONLY,
|
||||||
}
|
FlowDirection.BI_DIRECTIONAL to Widgets18.INPUT_OUTPUT,
|
||||||
|
|
||||||
val front = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.FRONT]!!)
|
|
||||||
val back = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.BACK]!!)
|
|
||||||
val left = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.LEFT]!!)
|
|
||||||
val right = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.RIGHT]!!)
|
|
||||||
val top = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.TOP]!!)
|
|
||||||
val bottom = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.BOTTOM]!!)
|
|
||||||
|
|
||||||
if (inputs.pull.test(minecraft.player)) {
|
|
||||||
val pull = LargeBooleanRectangleButtonPanel(
|
|
||||||
screen,
|
|
||||||
frame,
|
|
||||||
skinElementActive = Widgets18.PULL,
|
|
||||||
skinElementInactive = Widgets18.PULL_DISABLED,
|
|
||||||
prop = inputs.pull,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
pull.tooltip = TranslatableComponent("otm.gui.side_mode.pull")
|
for ((k, v) in values) {
|
||||||
|
button.add(k, skinElement = v, tooltip = TranslatableComponent(k.translationKey))
|
||||||
pull.x = 30f - 20f
|
|
||||||
pull.y = 14f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputs.push.test(minecraft.player)) {
|
button.finish()
|
||||||
val push = LargeBooleanRectangleButtonPanel(
|
|
||||||
screen,
|
|
||||||
frame,
|
|
||||||
skinElementActive = Widgets18.PUSH,
|
|
||||||
skinElementInactive = Widgets18.PUSH_DISABLED,
|
|
||||||
prop = inputs.push,
|
|
||||||
)
|
|
||||||
|
|
||||||
push.tooltip = TranslatableComponent("otm.gui.side_mode.push")
|
return button
|
||||||
|
|
||||||
push.x = 30f + 20f
|
|
||||||
push.y = 14f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun moveButtons(
|
||||||
|
front: EditablePanel<*>,
|
||||||
|
back: EditablePanel<*>,
|
||||||
|
left: EditablePanel<*>,
|
||||||
|
right: EditablePanel<*>,
|
||||||
|
top: EditablePanel<*>,
|
||||||
|
bottom: EditablePanel<*>,
|
||||||
|
) {
|
||||||
top.tooltip = TranslatableComponent("otm.gui.sides.top")
|
top.tooltip = TranslatableComponent("otm.gui.sides.top")
|
||||||
bottom.tooltip = TranslatableComponent("otm.gui.sides.bottom")
|
bottom.tooltip = TranslatableComponent("otm.gui.sides.bottom")
|
||||||
back.tooltip = TranslatableComponent("otm.gui.sides.back")
|
back.tooltip = TranslatableComponent("otm.gui.sides.back")
|
||||||
@ -134,9 +113,94 @@ private fun <S : MatteryScreen<*>> makeItemHandlerControlPanel(
|
|||||||
|
|
||||||
back.x = 30f - 20f
|
back.x = 30f - 20f
|
||||||
back.y = 14f + 42f
|
back.y = 14f + 42f
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("name_shadowing")
|
||||||
|
private fun pullPush(frame: FramePanel<*>, pull: BooleanInputWithFeedback, push: BooleanInputWithFeedback) {
|
||||||
|
if (pull.test(minecraft.player)) {
|
||||||
|
val pull = LargeBooleanRectangleButtonPanel(
|
||||||
|
frame.screen,
|
||||||
|
frame,
|
||||||
|
skinElementActive = Widgets18.PULL,
|
||||||
|
skinElementInactive = Widgets18.PULL_DISABLED,
|
||||||
|
prop = pull,
|
||||||
|
)
|
||||||
|
|
||||||
|
pull.tooltip = TranslatableComponent("otm.gui.side_mode.pull")
|
||||||
|
|
||||||
|
pull.x = 30f - 20f
|
||||||
|
pull.y = 14f
|
||||||
|
}
|
||||||
|
|
||||||
|
if (push.test(minecraft.player)) {
|
||||||
|
val push = LargeBooleanRectangleButtonPanel(
|
||||||
|
frame.screen,
|
||||||
|
frame,
|
||||||
|
skinElementActive = Widgets18.PUSH,
|
||||||
|
skinElementInactive = Widgets18.PUSH_DISABLED,
|
||||||
|
prop = push,
|
||||||
|
)
|
||||||
|
|
||||||
|
push.tooltip = TranslatableComponent("otm.gui.side_mode.push")
|
||||||
|
|
||||||
|
push.x = 30f + 20f
|
||||||
|
push.y = 14f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <S : MatteryScreen<*>> makeItemHandlerControlPanel(
|
||||||
|
screen: S,
|
||||||
|
inputs: ItemHandlerPlayerInput
|
||||||
|
): FramePanel<S> {
|
||||||
|
val frame = object : FramePanel<S>(screen, 78f, 80f, TranslatableComponent("otm.gui.sides.item_config")) {
|
||||||
|
override fun tickInner() {
|
||||||
|
super.tickInner()
|
||||||
|
|
||||||
|
if (!isEverFocused()) {
|
||||||
|
remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val front = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.FRONT]!!)
|
||||||
|
val back = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.BACK]!!)
|
||||||
|
val left = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.LEFT]!!)
|
||||||
|
val right = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.RIGHT]!!)
|
||||||
|
val top = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.TOP]!!)
|
||||||
|
val bottom = makeItemModeButton(screen, frame, inputs.pieces[RelativeSide.BOTTOM]!!)
|
||||||
|
|
||||||
|
pullPush(frame, inputs.pull, inputs.push)
|
||||||
|
moveButtons(front, back, left, right, top, bottom)
|
||||||
screen.addPanel(frame)
|
screen.addPanel(frame)
|
||||||
|
frame.requestFocus()
|
||||||
|
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <S : MatteryScreen<*>> makeEnergyConfigPanel(
|
||||||
|
screen: S,
|
||||||
|
inputs: EnergyPlayerInput
|
||||||
|
): FramePanel<S> {
|
||||||
|
val frame = object : FramePanel<S>(screen, 78f, 80f, TranslatableComponent("otm.gui.sides.energy_config")) {
|
||||||
|
override fun tickInner() {
|
||||||
|
super.tickInner()
|
||||||
|
|
||||||
|
if (!isEverFocused()) {
|
||||||
|
remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val front = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.FRONT]!!).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val back = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.BACK]!!).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val left = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.LEFT]!!).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val right = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.RIGHT]!!).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val top = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.TOP]!!).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val bottom = makeEnergyModeButton(screen, frame, inputs.pieces[RelativeSide.BOTTOM]!!).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
|
||||||
|
pullPush(frame, inputs.pull, inputs.push)
|
||||||
|
moveButtons(front, back, left, right, top, bottom)
|
||||||
|
screen.addPanel(frame)
|
||||||
frame.requestFocus()
|
frame.requestFocus()
|
||||||
|
|
||||||
return frame
|
return frame
|
||||||
@ -146,7 +210,8 @@ fun <S : MatteryScreen<*>> makeDeviceControls(
|
|||||||
screen: S,
|
screen: S,
|
||||||
parent: FramePanel<S>,
|
parent: FramePanel<S>,
|
||||||
redstone: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
redstone: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
||||||
itemConfig: ItemHandlerPlayerInput? = null
|
itemConfig: ItemHandlerPlayerInput? = null,
|
||||||
|
energyConfig: EnergyPlayerInput? = null,
|
||||||
): EditablePanel<S> {
|
): EditablePanel<S> {
|
||||||
val panel = object : EditablePanel<S>(screen, parent, width = LargeEnumRectangleButtonPanel.SIZE, height = 0f, x = parent.width + 3f) {
|
val panel = object : EditablePanel<S>(screen, parent, width = LargeEnumRectangleButtonPanel.SIZE, height = 0f, x = parent.width + 3f) {
|
||||||
override fun tickInner() {
|
override fun tickInner() {
|
||||||
@ -179,6 +244,23 @@ fun <S : MatteryScreen<*>> makeDeviceControls(
|
|||||||
}.height + 2f
|
}.height + 2f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (energyConfig != null) {
|
||||||
|
y += object : LargeRectangleButtonPanel<S>(screen, panel, y = y, skinElement = Widgets18.ENERGY_CONFIGURATION) {
|
||||||
|
init {
|
||||||
|
tooltip = TranslatableComponent("otm.gui.sides.energy_config")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(mouseButton: Int) {
|
||||||
|
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||||
|
val frame = makeEnergyConfigPanel(screen, energyConfig)
|
||||||
|
|
||||||
|
frame.x = absoluteX + width / 2f - frame.width / 2f
|
||||||
|
frame.y = absoluteY + height + 8f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.height + 2f
|
||||||
|
}
|
||||||
|
|
||||||
panel.height = (y - 2f).coerceAtLeast(0f)
|
panel.height = (y - 2f).coerceAtLeast(0f)
|
||||||
return panel
|
return panel
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ class ChemicalGeneratorScreen(menu: ChemicalGeneratorMenu, inventory: Inventory,
|
|||||||
SlotPanel(this, frame, menu.residueSlot, 56f, PROGRESS_SLOT_TOP)
|
SlotPanel(this, frame, menu.residueSlot, 56f, PROGRESS_SLOT_TOP)
|
||||||
SlotPanel(this, frame, menu.fuelSlot, 104f, PROGRESS_SLOT_TOP)
|
SlotPanel(this, frame, menu.fuelSlot, 104f, PROGRESS_SLOT_TOP)
|
||||||
|
|
||||||
makeDeviceControls(this, frame, redstone = menu.redstone, itemConfig = menu.itemConfig)
|
makeDeviceControls(this, frame, redstone = menu.redstone, itemConfig = menu.itemConfig, energyConfig = menu.energyConfig)
|
||||||
|
|
||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ package ru.dbotthepony.mc.otm.core
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableMap
|
import com.google.common.collect.ImmutableMap
|
||||||
|
import com.google.common.collect.ImmutableSet
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
@ -35,6 +36,7 @@ import java.math.BigInteger
|
|||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
import java.util.Spliterators
|
import java.util.Spliterators
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import java.util.function.Consumer
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
import java.util.stream.StreamSupport
|
import java.util.stream.StreamSupport
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
@ -135,6 +137,18 @@ inline fun <K : Any, V : Any> immutableMap(initializer: ImmutableMap.Builder<K,
|
|||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <V : Any> immutableSet(initializer: Consumer<V>.() -> Unit): ImmutableSet<V> {
|
||||||
|
val builder = ImmutableSet.Builder<V>()
|
||||||
|
initializer.invoke(builder::add)
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <V : Any> immutableList(initializer: Consumer<V>.() -> Unit): ImmutableList<V> {
|
||||||
|
val builder = ImmutableList.Builder<V>()
|
||||||
|
initializer.invoke(builder::add)
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> IForgeRegistry<T>.getID(value: T): Int {
|
fun <T> IForgeRegistry<T>.getID(value: T): Int {
|
||||||
return (this as ForgeRegistry<T>).getID(value)
|
return (this as ForgeRegistry<T>).getID(value)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.menu.input
|
||||||
|
|
||||||
|
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||||
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
|
import ru.dbotthepony.mc.otm.core.immutableMap
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||||
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [allowPull] and [allowPush] controls whenever player is allowed to change these options
|
||||||
|
*/
|
||||||
|
class EnergyPlayerInput(val menu: MatteryMenu, val allowPull: Boolean = true, val allowPush: Boolean = true) {
|
||||||
|
var possibleModes by menu.mSynchronizer.enum(FlowDirection::class.java)
|
||||||
|
private set
|
||||||
|
|
||||||
|
inner class Piece(val side: RelativeSide) {
|
||||||
|
val pull = BooleanInputWithFeedback(menu)
|
||||||
|
val push = BooleanInputWithFeedback(menu)
|
||||||
|
val input = EnumInputWithFeedback<FlowDirection>(menu)
|
||||||
|
|
||||||
|
var default by menu.mSynchronizer.enum(FlowDirection.NONE)
|
||||||
|
|
||||||
|
init {
|
||||||
|
pull.filter { allowPull }
|
||||||
|
push.filter { allowPush }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun configure(config: MatteryDeviceBlockEntity.ConfigurableEnergy<*>.Piece, parent: MatteryDeviceBlockEntity.ConfigurableEnergy<*>) {
|
||||||
|
pull.with(config::automatePull)
|
||||||
|
push.with(config::automatePush)
|
||||||
|
input.withSupplier { config.energyFlow }.withConsumer { if (parent.possibleModes.isSupertype(it)) config.energyFlow = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val pieces = immutableMap { for (side in RelativeSide.values()) put(side, Piece(side)) }
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
val pull = BooleanInputWithFeedback(menu)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
val push = BooleanInputWithFeedback(menu)
|
||||||
|
|
||||||
|
init {
|
||||||
|
pull.filter { allowPull }
|
||||||
|
push.filter { allowPush }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun configure(config: MatteryDeviceBlockEntity.ConfigurableEnergy<*>) {
|
||||||
|
possibleModes = config.possibleModes
|
||||||
|
|
||||||
|
for ((side, v) in config.pieces) {
|
||||||
|
pieces[side]!!.configure(v, config)
|
||||||
|
pieces[side]!!.default = config.defaults[side]!!
|
||||||
|
}
|
||||||
|
|
||||||
|
pull.withSupplier { pieces.values.all { it.pull.value } }
|
||||||
|
push.withSupplier { pieces.values.all { it.push.value } }
|
||||||
|
|
||||||
|
pull.withConsumer { v -> pieces.values.forEach { it.pull.input.invoke(v) } }
|
||||||
|
push.withConsumer { v -> pieces.values.forEach { it.push.input.invoke(v) } }
|
||||||
|
}
|
||||||
|
}
|
@ -50,7 +50,7 @@ class ItemHandlerPlayerInput(val menu: MatteryMenu, val allowPull: Boolean = tru
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun configure(config: MatteryDeviceBlockEntity.ConfigurableItemHandler) {
|
fun configure(config: MatteryDeviceBlockEntity.ConfigurableItemHandler) {
|
||||||
for ((side, v) in config.sides) {
|
for ((side, v) in config.pieces) {
|
||||||
pieces[side]!!.configure(v)
|
pieces[side]!!.configure(v)
|
||||||
pieces[side]!!.default = config.defaults[side]!!
|
pieces[side]!!.default = config.defaults[side]!!
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import ru.dbotthepony.mc.otm.block.entity.tech.ChemicalGeneratorBlockEntity
|
|||||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||||
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.MatterySlot
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.EnergyPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemHandlerPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemHandlerPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
|
||||||
@ -21,11 +22,13 @@ class ChemicalGeneratorMenu @JvmOverloads constructor(id: Int, inv: Inventory, t
|
|||||||
|
|
||||||
val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java)
|
val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java)
|
||||||
val itemConfig = ItemHandlerPlayerInput(this, allowPull = false, allowPush = true)
|
val itemConfig = ItemHandlerPlayerInput(this, allowPull = false, allowPush = true)
|
||||||
|
val energyConfig = EnergyPlayerInput(this, allowPull = false, allowPush = true)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
redstone.with(tile.redstoneControl::redstoneSetting)
|
redstone.with(tile.redstoneControl::redstoneSetting)
|
||||||
itemConfig.configure(tile.itemConfig)
|
itemConfig.configure(tile.itemConfig)
|
||||||
|
energyConfig.configure(tile.energyConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Loading…
Reference in New Issue
Block a user