Configurable Fluid Handler
This commit is contained in:
parent
e373512a61
commit
068e6ba3f9
@ -659,6 +659,7 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
|
|
||||||
gui("sides.item_config", "Item Configuration")
|
gui("sides.item_config", "Item Configuration")
|
||||||
gui("sides.energy_config", "Energy Configuration")
|
gui("sides.energy_config", "Energy Configuration")
|
||||||
|
gui("sides.fluid_config", "Fluid Configuration")
|
||||||
|
|
||||||
gui("sides.top", "Top")
|
gui("sides.top", "Top")
|
||||||
gui("sides.bottom", "Bottom")
|
gui("sides.bottom", "Bottom")
|
||||||
|
@ -664,6 +664,7 @@ private fun gui(provider: MatteryLanguageProvider) {
|
|||||||
|
|
||||||
gui("sides.item_config", "Настройка предметов")
|
gui("sides.item_config", "Настройка предметов")
|
||||||
gui("sides.energy_config", "Настройка энергии")
|
gui("sides.energy_config", "Настройка энергии")
|
||||||
|
gui("sides.fluid_config", "Настройка жидкости")
|
||||||
|
|
||||||
gui("sides.top", "Верхняя сторона")
|
gui("sides.top", "Верхняя сторона")
|
||||||
gui("sides.bottom", "Нижняя сторона")
|
gui("sides.bottom", "Нижняя сторона")
|
||||||
|
@ -13,6 +13,8 @@ import net.minecraft.network.chat.Component
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||||
|
import net.minecraftforge.fluids.FluidStack
|
||||||
|
import net.minecraftforge.fluids.capability.IFluidHandler
|
||||||
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
|
||||||
@ -21,6 +23,7 @@ import ru.dbotthepony.mc.otm.capability.UnmodifiableItemHandler
|
|||||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
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.capability.moveEnergy
|
||||||
|
import ru.dbotthepony.mc.otm.capability.moveFluid
|
||||||
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
|
||||||
@ -84,6 +87,153 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class ConfigurableFluidHandler<T : IFluidHandler>(
|
||||||
|
val capability: T,
|
||||||
|
|
||||||
|
val possibleModes: FlowDirection = FlowDirection.BI_DIRECTIONAL,
|
||||||
|
|
||||||
|
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 {
|
||||||
|
exposeSideless(ForgeCapabilities.FLUID_HANDLER, capability)
|
||||||
|
}
|
||||||
|
|
||||||
|
val front = Piece(RelativeSide.FRONT).also { it.flow = frontDefault }
|
||||||
|
val back = Piece(RelativeSide.BACK).also { it.flow = backDefault }
|
||||||
|
val left = Piece(RelativeSide.LEFT).also { it.flow = leftDefault }
|
||||||
|
val right = Piece(RelativeSide.RIGHT).also { it.flow = rightDefault }
|
||||||
|
val top = Piece(RelativeSide.TOP).also { it.flow = topDefault }
|
||||||
|
val bottom = Piece(RelativeSide.BOTTOM).also { it.flow = 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) : IFluidHandler, ITickable {
|
||||||
|
init {
|
||||||
|
tickList.always(this)
|
||||||
|
|
||||||
|
// https://tenor.com/view/simp-metal-gear-liquid-snake-running-gif-16717852
|
||||||
|
savetables.enum(::flow, "fluid_${side}_flow", FlowDirection::valueOf)
|
||||||
|
savetables.bool(::automatePull, "fluid_${side}_pull")
|
||||||
|
savetables.bool(::automatePush, "fluid_${side}_push")
|
||||||
|
}
|
||||||
|
|
||||||
|
private val controller = sides[side]!!.Cap(ForgeCapabilities.FLUID_HANDLER, this)
|
||||||
|
private val neighbour by sides[side]!!.track(ForgeCapabilities.FLUID_HANDLER)
|
||||||
|
|
||||||
|
var flow 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) {
|
||||||
|
controller.close()
|
||||||
|
} else {
|
||||||
|
controller.close()
|
||||||
|
controller.expose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// var automatePull by synchronizer.bool().property
|
||||||
|
var automatePull = false
|
||||||
|
// var automatePush by synchronizer.bool().property
|
||||||
|
var automatePush = false
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
if (flow == FlowDirection.NONE || !automatePull && !automatePush || redstoneControl.isBlockedByRedstone)
|
||||||
|
return
|
||||||
|
|
||||||
|
neighbour.ifPresentK {
|
||||||
|
if (flow.input && automatePull) {
|
||||||
|
moveFluid(source = it, destination = capability)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flow.output && automatePush) {
|
||||||
|
moveFluid(source = capability, destination = it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTanks(): Int {
|
||||||
|
if (flow == FlowDirection.NONE) {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
return capability.getTanks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFluidInTank(tank: Int): FluidStack {
|
||||||
|
if (flow == FlowDirection.NONE) {
|
||||||
|
return FluidStack.EMPTY
|
||||||
|
} else {
|
||||||
|
return capability.getFluidInTank(tank)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTankCapacity(tank: Int): Int {
|
||||||
|
if (flow == FlowDirection.NONE) {
|
||||||
|
return 0
|
||||||
|
} else {
|
||||||
|
return capability.getTankCapacity(tank)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isFluidValid(tank: Int, stack: FluidStack): Boolean {
|
||||||
|
if (flow.input) {
|
||||||
|
return capability.isFluidValid(tank, stack)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fill(resource: FluidStack, action: IFluidHandler.FluidAction): Int {
|
||||||
|
if (flow.input) {
|
||||||
|
return capability.fill(resource, action)
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drain(resource: FluidStack, action: IFluidHandler.FluidAction): FluidStack {
|
||||||
|
if (flow.output) {
|
||||||
|
return capability.drain(resource, action)
|
||||||
|
} else {
|
||||||
|
return FluidStack.EMPTY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drain(maxDrain: Int, action: IFluidHandler.FluidAction): FluidStack {
|
||||||
|
if (flow.output) {
|
||||||
|
return capability.drain(maxDrain, action)
|
||||||
|
} else {
|
||||||
|
return FluidStack.EMPTY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inner class ConfigurableEnergy<T : IMatteryEnergyStorage>(
|
inner class ConfigurableEnergy<T : IMatteryEnergyStorage>(
|
||||||
val capability: T,
|
val capability: T,
|
||||||
|
|
||||||
@ -129,6 +279,25 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
private val capControllers = exposeEnergy(side, this@Piece)
|
private val capControllers = exposeEnergy(side, this@Piece)
|
||||||
private val neighbour by sides[side]!!.track(ForgeCapabilities.ENERGY)
|
private val neighbour by sides[side]!!.track(ForgeCapabilities.ENERGY)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// var automatePull by synchronizer.bool().property
|
||||||
|
var automatePull = false
|
||||||
|
// var automatePush by synchronizer.bool().property
|
||||||
|
var automatePush = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
tickList.always(this)
|
||||||
|
|
||||||
|
savetables.enum(::energyFlow, "energy_${side}_flow", FlowDirection::valueOf)
|
||||||
|
savetables.bool(::automatePull, "energy_${side}_pull")
|
||||||
|
savetables.bool(::automatePush, "energy_${side}_push")
|
||||||
|
}
|
||||||
|
|
||||||
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
return capability.extractEnergy(howMuch, simulate)
|
return capability.extractEnergy(howMuch, simulate)
|
||||||
}
|
}
|
||||||
@ -151,12 +320,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
return Decimal.ZERO
|
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 {
|
override fun drainBattery(): Boolean {
|
||||||
return capability.drainBattery()
|
return capability.drainBattery()
|
||||||
}
|
}
|
||||||
@ -180,10 +343,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
tickList.always(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override var energyFlow by synchronizer.enum(possibleModes, setter = { value, access, setByRemote ->
|
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})" }
|
require(possibleModes.isSupertype(value)) { "Energy mode $value is not allowed (allowed modes: ${possibleModes.family})" }
|
||||||
|
|
||||||
@ -201,15 +360,6 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var automatePull by synchronizer.bool().property
|
|
||||||
var automatePush by synchronizer.bool().property
|
|
||||||
|
|
||||||
init {
|
|
||||||
savetables.enum(::energyFlow, "energy_${side}_flow", FlowDirection::valueOf)
|
|
||||||
savetables.bool(::automatePull, "energy_${side}_pull")
|
|
||||||
savetables.bool(::automatePush, "energy_${side}_push")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,9 +461,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
put(RelativeSide.BOTTOM, bottomDefault)
|
put(RelativeSide.BOTTOM, bottomDefault)
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class Piece(
|
inner class Piece(val side: RelativeSide) : IItemHandler, ITickable {
|
||||||
val side: RelativeSide,
|
|
||||||
) : IItemHandler, ITickable {
|
|
||||||
private var currentHandler: IItemHandler = EmptyItemHandler
|
private var currentHandler: IItemHandler = EmptyItemHandler
|
||||||
private val capController = sides[side]!!.Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
private val capController = sides[side]!!.Cap(ForgeCapabilities.ITEM_HANDLER, this)
|
||||||
private val neighbour by sides[side]!!.track(ForgeCapabilities.ITEM_HANDLER)
|
private val neighbour by sides[side]!!.track(ForgeCapabilities.ITEM_HANDLER)
|
||||||
@ -346,7 +494,7 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var automatePull by synchronizer.bool(setter = { value, access, _ ->
|
/*var automatePull by synchronizer.bool(setter = { value, access, _ ->
|
||||||
if (access.readBoolean() != value) {
|
if (access.readBoolean() != value) {
|
||||||
access.write(value)
|
access.write(value)
|
||||||
|
|
||||||
@ -366,7 +514,31 @@ abstract class MatteryDeviceBlockEntity(blockEntityType: BlockEntityType<*>, blo
|
|||||||
outerSlotPush = 0
|
outerSlotPush = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).property
|
}).property*/
|
||||||
|
|
||||||
|
var automatePull = false
|
||||||
|
set(value) {
|
||||||
|
if (field != value) {
|
||||||
|
field = value
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
innerSlotPush = 0
|
||||||
|
outerSlotPush = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var automatePush = false
|
||||||
|
set(value) {
|
||||||
|
if (field != value) {
|
||||||
|
field = value
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
innerSlotPush = 0
|
||||||
|
outerSlotPush = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
savetables.bool(::automatePull, "itemhandler_${side}_automatePull")
|
savetables.bool(::automatePull, "itemhandler_${side}_automatePull")
|
||||||
|
@ -62,8 +62,9 @@ class FluidTankBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
|||||||
bottomDefault = ItemHandlerMode.INPUT_OUTPUT,
|
bottomDefault = ItemHandlerMode.INPUT_OUTPUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val fluidConfig = ConfigurableFluidHandler(fluid)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
exposeGlobally(ForgeCapabilities.FLUID_HANDLER, fluid)
|
|
||||||
savetables.stateful(::fluid, FLUID_KEY)
|
savetables.stateful(::fluid, FLUID_KEY)
|
||||||
savetables.stateful(::fillInput)
|
savetables.stateful(::fillInput)
|
||||||
savetables.stateful(::drainInput)
|
savetables.stateful(::drainInput)
|
||||||
|
@ -106,6 +106,7 @@ object Widgets18 {
|
|||||||
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()
|
val ENERGY_CONFIGURATION = controlsGrid.next()
|
||||||
|
val FLUID_CONFIGURATION = controlsGrid.next()
|
||||||
|
|
||||||
val LEFT_CONTROLS_ITEMS = controls2(LEFT_CONTROLS)
|
val LEFT_CONTROLS_ITEMS = controls2(LEFT_CONTROLS)
|
||||||
val RIGHT_CONTROLS_ITEMS = controls2(RIGHT_CONTROLS)
|
val RIGHT_CONTROLS_ITEMS = controls2(RIGHT_CONTROLS)
|
||||||
|
@ -30,7 +30,7 @@ class FluidTankScreen(menu: FluidTankMenu, inventory: Inventory, title: Componen
|
|||||||
|
|
||||||
SlotPanel(this, frame, menu.output, x = 30f + s.width + 4f + 20f, y = 53f)
|
SlotPanel(this, frame, menu.output, x = 30f + s.width + 4f + 20f, y = 53f)
|
||||||
|
|
||||||
makeDeviceControls(this, frame, itemConfig = menu.itemConfig, redstoneConfig = menu.redstoneConfig)
|
makeDeviceControls(this, frame, itemConfig = menu.itemConfig, redstoneConfig = menu.redstoneConfig, fluidConfig = menu.fluidConfig)
|
||||||
makeCuriosPanel(this, frame, menu.equipment.curiosSlots, autoAlign = true)
|
makeCuriosPanel(this, frame, menu.equipment.curiosSlots, autoAlign = true)
|
||||||
|
|
||||||
PlayerEquipmentPanel(this, frame, armorSlots = menu.equipment.armorSlots).also {
|
PlayerEquipmentPanel(this, frame, armorSlots = menu.equipment.armorSlots).also {
|
||||||
|
@ -13,6 +13,7 @@ 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.BooleanInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.FluidConfigPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.IPlayerInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
@ -66,6 +67,18 @@ private fun <S : MatteryScreen<*>> makeEnergyModeButton(screen: S, parent: Frame
|
|||||||
return button
|
return button
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <S : MatteryScreen<*>> makeFluidModeButton(screen: S, parent: FramePanel<S>, input: FluidConfigPlayerInput.Piece, side: RelativeSide): LargeEnumRectangleButtonPanel<S, FlowDirection> {
|
||||||
|
val button = LargeEnumRectangleButtonPanel(screen, parent, enum = FlowDirection::class.java, prop = input.input, defaultValue = input.default)
|
||||||
|
|
||||||
|
for (v in FlowDirection.values()) {
|
||||||
|
button.add(v, skinElement = Widgets18.CONTROLS[side]!![v]!!, tooltip = TranslatableComponent(v.translationKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
button.finish()
|
||||||
|
|
||||||
|
return button
|
||||||
|
}
|
||||||
|
|
||||||
private fun moveButtons(
|
private fun moveButtons(
|
||||||
front: EditablePanel<*>,
|
front: EditablePanel<*>,
|
||||||
back: EditablePanel<*>,
|
back: EditablePanel<*>,
|
||||||
@ -191,6 +204,35 @@ private fun <S : MatteryScreen<*>> makeEnergyConfigPanel(
|
|||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <S : MatteryScreen<*>> makeFluidConfigPanel(
|
||||||
|
screen: S,
|
||||||
|
inputs: FluidConfigPlayerInput
|
||||||
|
): FramePanel<S> {
|
||||||
|
val frame = object : FramePanel<S>(screen, 78f, 80f, TranslatableComponent("otm.gui.sides.fluid_config")) {
|
||||||
|
override fun tickInner() {
|
||||||
|
super.tickInner()
|
||||||
|
|
||||||
|
if (!isEverFocused()) {
|
||||||
|
remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val front = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.FRONT]!!, RelativeSide.FRONT).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val back = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.BACK]!!, RelativeSide.BACK).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val left = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.LEFT]!!, RelativeSide.LEFT).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val right = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.RIGHT]!!, RelativeSide.RIGHT).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val top = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.TOP]!!, RelativeSide.TOP).also { it.predicate = Predicate { inputs.possibleModes.isSupertype(it) } }
|
||||||
|
val bottom = makeFluidModeButton(screen, frame, inputs.pieces[RelativeSide.BOTTOM]!!, 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()
|
||||||
|
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
|
||||||
class DeviceControls<out S : MatteryScreen<*>>(
|
class DeviceControls<out S : MatteryScreen<*>>(
|
||||||
screen: S,
|
screen: S,
|
||||||
parent: FramePanel<S>,
|
parent: FramePanel<S>,
|
||||||
@ -198,9 +240,11 @@ class DeviceControls<out S : MatteryScreen<*>>(
|
|||||||
val redstoneConfig: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
val redstoneConfig: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
||||||
val itemConfig: ItemConfigPlayerInput? = null,
|
val itemConfig: ItemConfigPlayerInput? = null,
|
||||||
val energyConfig: EnergyConfigPlayerInput? = null,
|
val energyConfig: EnergyConfigPlayerInput? = null,
|
||||||
|
val fluidConfig: FluidConfigPlayerInput? = null,
|
||||||
) : EditablePanel<S>(screen, parent, x = parent.width + 3f, height = 0f, width = 0f) {
|
) : EditablePanel<S>(screen, parent, x = parent.width + 3f, height = 0f, width = 0f) {
|
||||||
val itemConfigButton: LargeRectangleButtonPanel<S>?
|
val itemConfigButton: LargeRectangleButtonPanel<S>?
|
||||||
val energyConfigButton: LargeRectangleButtonPanel<S>?
|
val energyConfigButton: LargeRectangleButtonPanel<S>?
|
||||||
|
val fluidConfigButton: LargeRectangleButtonPanel<S>?
|
||||||
val redstoneControlsButton: LargeEnumRectangleButtonPanel<S, RedstoneSetting>?
|
val redstoneControlsButton: LargeEnumRectangleButtonPanel<S, RedstoneSetting>?
|
||||||
private var nextY = 0f
|
private var nextY = 0f
|
||||||
|
|
||||||
@ -262,6 +306,25 @@ class DeviceControls<out S : MatteryScreen<*>>(
|
|||||||
} else {
|
} else {
|
||||||
energyConfigButton = null
|
energyConfigButton = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fluidConfig != null) {
|
||||||
|
fluidConfigButton = addButton(object : LargeRectangleButtonPanel<S>(screen, this@DeviceControls, y = nextY, skinElement = Widgets18.FLUID_CONFIGURATION) {
|
||||||
|
init {
|
||||||
|
tooltip = TranslatableComponent("otm.gui.sides.fluid_config")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(mouseButton: Int) {
|
||||||
|
if (mouseButton == InputConstants.MOUSE_BUTTON_LEFT) {
|
||||||
|
val frame = makeFluidConfigPanel(screen, fluidConfig)
|
||||||
|
|
||||||
|
frame.x = absoluteX + width / 2f - frame.width / 2f
|
||||||
|
frame.y = absoluteY + height + 8f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
fluidConfigButton = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tickInner() {
|
override fun tickInner() {
|
||||||
@ -278,6 +341,7 @@ fun <S : MatteryScreen<*>> makeDeviceControls(
|
|||||||
redstoneConfig: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
redstoneConfig: IPlayerInputWithFeedback<RedstoneSetting>? = null,
|
||||||
itemConfig: ItemConfigPlayerInput? = null,
|
itemConfig: ItemConfigPlayerInput? = null,
|
||||||
energyConfig: EnergyConfigPlayerInput? = null,
|
energyConfig: EnergyConfigPlayerInput? = null,
|
||||||
|
fluidConfig: FluidConfigPlayerInput? = null,
|
||||||
): DeviceControls<S> {
|
): DeviceControls<S> {
|
||||||
return DeviceControls(screen, parent, extra = extra, redstoneConfig = redstoneConfig, itemConfig = itemConfig, energyConfig = energyConfig)
|
return DeviceControls(screen, parent, extra = extra, redstoneConfig = redstoneConfig, itemConfig = itemConfig, energyConfig = energyConfig, fluidConfig = fluidConfig)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import kotlin.reflect.KProperty0
|
|||||||
class Savetables : INBTSerializable<CompoundTag?> {
|
class Savetables : INBTSerializable<CompoundTag?> {
|
||||||
private val entries = ArrayList<Entry<*, *>>()
|
private val entries = ArrayList<Entry<*, *>>()
|
||||||
|
|
||||||
interface Entry<V : Any?, T : Tag?> : INBTSerializable<T?> {
|
sealed interface Entry<V : Any?, T : Tag?> : INBTSerializable<T?> {
|
||||||
val name: String
|
val name: String
|
||||||
val type: Class<T>
|
val type: Class<T>
|
||||||
fun validate()
|
fun validate()
|
||||||
|
@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.menu.MachineOutputSlot
|
|||||||
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.EnumInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||||
|
import ru.dbotthepony.mc.otm.menu.input.FluidConfigPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||||
import ru.dbotthepony.mc.otm.menu.widget.FluidGaugeWidget
|
import ru.dbotthepony.mc.otm.menu.widget.FluidGaugeWidget
|
||||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||||
@ -22,6 +23,7 @@ class FluidTankMenu(containerId: Int, inventory: Inventory, tile: FluidTankBlock
|
|||||||
val equipment = makeEquipmentSlots(true)
|
val equipment = makeEquipmentSlots(true)
|
||||||
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig)
|
val itemConfig = ItemConfigPlayerInput(this, tile?.itemConfig)
|
||||||
val redstoneConfig = EnumInputWithFeedback<RedstoneSetting>(this)
|
val redstoneConfig = EnumInputWithFeedback<RedstoneSetting>(this)
|
||||||
|
val fluidConfig = FluidConfigPlayerInput(this, tile?.fluidConfig)
|
||||||
|
|
||||||
val drainInput = object : MatterySlot(tile?.drainInput ?: SimpleContainer(1), 0) {
|
val drainInput = object : MatterySlot(tile?.drainInput ?: SimpleContainer(1), 0) {
|
||||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
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 FluidConfigPlayerInput(val menu: MatteryMenu, config: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>? = null, val allowPull: Boolean = false, val allowPush: Boolean = false) {
|
||||||
|
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 with(config: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>.Piece, parent: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>) {
|
||||||
|
pull.with(config::automatePull)
|
||||||
|
push.with(config::automatePush)
|
||||||
|
input.withSupplier { config.flow }.withConsumer { if (parent.possibleModes.isSupertype(it)) config.flow = 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 with(config: MatteryDeviceBlockEntity.ConfigurableFluidHandler<*>) {
|
||||||
|
possibleModes = config.possibleModes
|
||||||
|
|
||||||
|
for ((side, v) in config.pieces) {
|
||||||
|
pieces[side]!!.with(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) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (config != null) {
|
||||||
|
with(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
Loading…
Reference in New Issue
Block a user