Drive rack insert/extract controls, profiled energy, updated menu, make redstone control of drive rack actually do stuff
This commit is contained in:
parent
10de6eb864
commit
a6eb0ca7f1
@ -8,8 +8,10 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
@ -18,10 +20,12 @@ import ru.dbotthepony.mc.otm.menu.storage.DriveRackMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.storage.optics.priority
|
||||
import ru.dbotthepony.mc.otm.storage.optics.powered
|
||||
import ru.dbotthepony.mc.otm.storage.optics.flow
|
||||
|
||||
class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, blockPos, blockState) {
|
||||
val energy = WorkerEnergyStorage(this::setChangedLight, MachinesConfig.DRIVE_RACK)
|
||||
val energy = ProfiledEnergyStorage(WorkerEnergyStorage(this::setChangedLight, MachinesConfig.DRIVE_RACK))
|
||||
val cell = StorageNode(energy)
|
||||
val energyConfig = ConfigurableEnergy(energy)
|
||||
|
||||
var insertPriority = 0
|
||||
set(value) {
|
||||
@ -35,16 +39,22 @@ class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
setChangedLight()
|
||||
}
|
||||
|
||||
var mode = FlowDirection.BI_DIRECTIONAL
|
||||
set(value) {
|
||||
field = value
|
||||
setChangedLight()
|
||||
}
|
||||
|
||||
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 4) {
|
||||
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
|
||||
super.setChanged(slot, new, old)
|
||||
|
||||
old.getCapability(MatteryCapability.DRIVE).ifPresentK {
|
||||
cell.removeStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy))
|
||||
cell.removeStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy).flow(::mode))
|
||||
}
|
||||
|
||||
new.getCapability(MatteryCapability.DRIVE).ifPresentK {
|
||||
cell.addStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy))
|
||||
cell.addStorageComponent(it.priority(::insertPriority, ::extractPriority).powered(energy).flow(::mode))
|
||||
}
|
||||
}
|
||||
}.also(::addDroppableContainer)
|
||||
@ -52,10 +62,14 @@ class DriveRackBlockEntity(blockPos: BlockPos, blockState: BlockState) : Mattery
|
||||
init {
|
||||
savetable(::energy, ENERGY_KEY)
|
||||
savetable(::container, INVENTORY_KEY)
|
||||
exposeEnergyGlobally(energy)
|
||||
exposeGlobally(MatteryCapability.STORAGE_NODE, cell)
|
||||
savetables.int(::insertPriority)
|
||||
savetables.int(::extractPriority)
|
||||
savetables.enum(::mode, map = FlowDirection::valueOf)
|
||||
|
||||
redstoneControl.addListener {
|
||||
cell.isDetached = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun setLevel(level: Level) {
|
||||
|
@ -28,6 +28,7 @@ import ru.dbotthepony.mc.otm.config.ClientConfig
|
||||
import ru.dbotthepony.mc.otm.core.GetterSetter
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
||||
import ru.dbotthepony.mc.otm.core.util.ItemSorter
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
@ -342,6 +343,17 @@ class DeviceControls<out S : MatteryScreen<*>>(
|
||||
return button
|
||||
}
|
||||
|
||||
fun addStorageMode(prop: GetterSetter<FlowDirection>) {
|
||||
val mode = LargeEnumRectangleButtonPanel(screen, this, prop = prop, defaultValue = FlowDirection.BI_DIRECTIONAL, enum = FlowDirection::class.java)
|
||||
|
||||
mode.add(FlowDirection.INPUT, Widgets18.ONLY_STORE, FlowDirection.INPUT.title)
|
||||
mode.add(FlowDirection.OUTPUT, Widgets18.ONLY_EXTRACT, FlowDirection.OUTPUT.title)
|
||||
mode.add(FlowDirection.BI_DIRECTIONAL, Widgets18.STORE_EXTRACT, FlowDirection.BI_DIRECTIONAL.title)
|
||||
mode.finish()
|
||||
|
||||
addButton(mode)
|
||||
}
|
||||
|
||||
inline fun <reified T : Enum<T>> sortingButtons(ascending: GetterSetter<Boolean>, sorting: GetterSetter<T>, default: T, configurator: LargeEnumRectangleButtonPanel<S, T>.() -> Unit) {
|
||||
LargeBooleanRectangleButtonPanel(
|
||||
screen,
|
||||
@ -415,18 +427,19 @@ class DeviceControls<out S : MatteryScreen<*>>(
|
||||
upgradeWindow!!.toScreenCenter()
|
||||
upgradeWindow!!.popup()
|
||||
} else {
|
||||
val square = ceil(upgrades.slots.size.toDouble().pow(0.5)).toInt()
|
||||
val size = square * AbstractSlotPanel.SIZE
|
||||
val (columns, rows) = SPECIAL_UPGRADE_CASES.getOrElse(upgrades.slots.size - 1) {
|
||||
val square = ceil(it.toDouble().pow(0.5)).toInt()
|
||||
square to square
|
||||
}
|
||||
|
||||
upgradeWindow = FramePanel(screen, (size + 40f).coerceAtLeast(120f), 30f + size, TranslatableComponent("otm.gui.upgrades")).also { frame ->
|
||||
val grid = GridPanel(screen, frame, width = AbstractSlotPanel.SIZE * square, height = AbstractSlotPanel.SIZE * square, columns = square, rows = square)
|
||||
upgradeWindow = FramePanel(screen, (columns * AbstractSlotPanel.SIZE + 40f).coerceAtLeast(120f), 30f + rows * AbstractSlotPanel.SIZE, TranslatableComponent("otm.gui.upgrades")).also { frame ->
|
||||
val grid = GridPanel(screen, frame, columns = columns, rows = rows)
|
||||
|
||||
for (slot in upgrades.slots) {
|
||||
SlotPanel(screen, grid, slot)
|
||||
}
|
||||
|
||||
grid.dock = Dock.FILL
|
||||
grid.dockResize = DockResizeMode.NONE
|
||||
|
||||
screen.addPanel(frame)
|
||||
|
||||
@ -524,6 +537,15 @@ class DeviceControls<out S : MatteryScreen<*>>(
|
||||
x = (parent?.width ?: 0f) + 3f
|
||||
y = 0f
|
||||
}
|
||||
|
||||
companion object {
|
||||
val SPECIAL_UPGRADE_CASES = immutableList {
|
||||
accept(1 to 1)
|
||||
accept(2 to 1)
|
||||
accept(3 to 1)
|
||||
accept(2 to 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <S : MatteryScreen<*>> makeDeviceControls(
|
||||
|
@ -4,8 +4,8 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import ru.dbotthepony.mc.otm.client.render.RenderGravity
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
|
||||
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
|
||||
open class GridPanel<out S : Screen>(
|
||||
@ -80,4 +80,10 @@ open class GridPanel<out S : Screen>(
|
||||
totalHeight += maxHeight
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun <S : Screen> slots(screen: S, parent: EditablePanel<*>?, columns: Int, rows: Int): GridPanel<S> {
|
||||
return GridPanel(screen, parent, width = columns * AbstractSlotPanel.SIZE, height = rows * AbstractSlotPanel.SIZE, rows = rows, columns = columns)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,21 @@ package ru.dbotthepony.mc.otm.client.screen.storage
|
||||
import net.minecraft.network.chat.Component
|
||||
import ru.dbotthepony.mc.otm.menu.storage.DriveRackMenu
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.client.render.Widgets18
|
||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.slot.BatterySlotPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeEnumRectangleButtonPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.input.IntInputPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel
|
||||
import ru.dbotthepony.mc.otm.client.screen.widget.WidePowerGaugePanel
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
|
||||
class DriveRackScreen(menu: DriveRackMenu, inventory: Inventory, title: Component) :
|
||||
MatteryScreen<DriveRackMenu>(menu, inventory, title) {
|
||||
@ -15,14 +25,30 @@ class DriveRackScreen(menu: DriveRackMenu, inventory: Inventory, title: Componen
|
||||
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
||||
val frame = super.makeMainFrame()!!
|
||||
|
||||
WidePowerGaugePanel(this, frame, menu.energyWidget, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT)
|
||||
BatterySlotPanel(this, frame, menu.batterySlot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE)
|
||||
makeBars(frame, profiledEnergy = menu.profiledEnergy, batterySlot = menu.batterySlot)
|
||||
|
||||
SlotPanel(this, frame, menu.storageSlots[0], 71f, 32f)
|
||||
SlotPanel(this, frame, menu.storageSlots[1], 71f + 18f, 32f)
|
||||
val grid = GridPanel.slots(this, frame, 2, 2)
|
||||
grid.dock = Dock.FILL
|
||||
|
||||
SlotPanel(this, frame, menu.storageSlots[2], 71f, 32f + 18f)
|
||||
SlotPanel(this, frame, menu.storageSlots[3], 71f + 18f, 32f + 18f)
|
||||
for (slot in menu.storageSlots)
|
||||
SlotPanel(this, grid, slot)
|
||||
|
||||
IntInputPanel(this, frame, menu.insertPriority).also {
|
||||
it.dock = Dock.BOTTOM
|
||||
it.tooltips.add(TranslatableComponent("otm.gui.insert_priority"))
|
||||
it.childrenOrder = -1
|
||||
it.dockMargin = DockProperty(left = 20f, right = 10f, bottom = 2f)
|
||||
}
|
||||
|
||||
IntInputPanel(this, frame, menu.extractPriority).also {
|
||||
it.dock = Dock.BOTTOM
|
||||
it.tooltips.add(TranslatableComponent("otm.gui.extract_priority"))
|
||||
it.childrenOrder = -2
|
||||
it.dockMargin = DockProperty(left = 20f, right = 10f, bottom = 2f)
|
||||
}
|
||||
|
||||
val controls = DeviceControls(this, frame, energyConfig = menu.energyConfig, redstoneConfig = menu.redstoneConfig)
|
||||
controls.addStorageMode(menu.mode)
|
||||
|
||||
return frame
|
||||
}
|
||||
|
@ -52,14 +52,7 @@ class StorageBusScreen(menu: StorageBusMenu, inventory: Inventory, title: Compon
|
||||
}
|
||||
|
||||
val controls = DeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, energyConfig = menu.energyConfig)
|
||||
val mode = LargeEnumRectangleButtonPanel(this, frame, prop = menu.mode, defaultValue = FlowDirection.BI_DIRECTIONAL, enum = FlowDirection::class.java)
|
||||
|
||||
mode.add(FlowDirection.INPUT, Widgets18.ONLY_STORE, FlowDirection.INPUT.title)
|
||||
mode.add(FlowDirection.OUTPUT, Widgets18.ONLY_EXTRACT, FlowDirection.OUTPUT.title)
|
||||
mode.add(FlowDirection.BI_DIRECTIONAL, Widgets18.STORE_EXTRACT, FlowDirection.BI_DIRECTIONAL.title)
|
||||
mode.finish()
|
||||
|
||||
controls.addButton(mode)
|
||||
controls.addStorageMode(menu.mode)
|
||||
|
||||
return frame
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ open class StorageNode(private val energyDemander: IMatteryEnergyStorage? = null
|
||||
|
||||
fun addStorageComponent(component: IStorage<*>) {
|
||||
if (components.add(component))
|
||||
if (isValid && !manualAttaching)
|
||||
if (isValid && !manualAttaching && !isDetached)
|
||||
graph.add(component)
|
||||
}
|
||||
|
||||
@ -86,6 +86,23 @@ open class StorageNode(private val energyDemander: IMatteryEnergyStorage? = null
|
||||
graph.remove(component)
|
||||
}
|
||||
|
||||
var isDetached = false
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
field = value
|
||||
|
||||
if (value) {
|
||||
for (component in components) {
|
||||
graph.remove(component)
|
||||
}
|
||||
} else if (!manualAttaching) {
|
||||
for (component in components) {
|
||||
graph.add(component)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun invalidate() {
|
||||
for (component in components) {
|
||||
graph.remove(component)
|
||||
|
@ -485,6 +485,10 @@ abstract class MatteryMenu(
|
||||
return super.addSlot(pSlot)
|
||||
}
|
||||
|
||||
fun addSlot(slots: Iterable<Slot>) {
|
||||
slots.forEach(::addSlot)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds slot to "storage slots" list (utilized by quick move) and calls [addSlot]
|
||||
*
|
||||
|
@ -2,27 +2,31 @@ package ru.dbotthepony.mc.otm.menu.storage
|
||||
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.block.entity.storage.DriveRackBlockEntity
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.menu.DriveSlot
|
||||
import ru.dbotthepony.mc.otm.menu.MatteryPoweredMenu
|
||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||
import ru.dbotthepony.mc.otm.menu.input.EnergyConfigPlayerInput
|
||||
import ru.dbotthepony.mc.otm.menu.input.EnumInputWithFeedback
|
||||
import ru.dbotthepony.mc.otm.menu.input.IntInputWithFeedback
|
||||
import ru.dbotthepony.mc.otm.menu.makeSlots
|
||||
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
|
||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||
|
||||
class DriveRackMenu @JvmOverloads constructor(
|
||||
p_38852_: Int,
|
||||
containerId: Int,
|
||||
inventory: Inventory,
|
||||
tile: DriveRackBlockEntity? = null
|
||||
) : MatteryPoweredMenu(MMenus.DRIVE_RACK, p_38852_, inventory, tile) {
|
||||
val storageSlots: List<MatterySlot>
|
||||
) : MatteryPoweredMenu(MMenus.DRIVE_RACK, containerId, inventory, tile) {
|
||||
val storageSlots = makeSlots(tile?.container ?: SimpleContainer(4), ::DriveSlot)
|
||||
val energyConfig = EnergyConfigPlayerInput(this, tile?.energyConfig)
|
||||
val profiledEnergy = ProfiledLevelGaugeWidget(this, tile?.energy, energyWidget)
|
||||
val insertPriority = IntInputWithFeedback(this, tile?.let { it::insertPriority })
|
||||
val extractPriority = IntInputWithFeedback(this, tile?.let { it::extractPriority })
|
||||
val mode = EnumInputWithFeedback(this, tile?.let { it::mode }, FlowDirection.WITHOUT_NONE)
|
||||
|
||||
init {
|
||||
val container = tile?.container ?: SimpleContainer(4)
|
||||
|
||||
storageSlots = immutableList(4) {
|
||||
addStorageSlot(DriveSlot(container, it))
|
||||
}
|
||||
|
||||
addStorageSlot(storageSlots)
|
||||
addInventorySlots()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
package ru.dbotthepony.mc.otm.storage.optics
|
||||
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageComponent
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageEventConsumer
|
||||
import ru.dbotthepony.mc.otm.storage.StorageStack
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import java.util.function.Supplier
|
||||
|
||||
class FlowControlComponent<S : StorageStack<S>>(private val parent: IStorageComponent<S>, private val flow: Supplier<FlowDirection>) : IStorageComponent<S> by parent {
|
||||
override fun addListener(listener: IStorageEventConsumer<S>): Boolean {
|
||||
return parent.addListener(ListenerProxy(listener, this))
|
||||
}
|
||||
|
||||
override fun removeListener(listener: IStorageEventConsumer<S>): Boolean {
|
||||
return parent.removeListener(ListenerProxy(listener, this))
|
||||
}
|
||||
|
||||
override fun insertStack(stack: S, simulate: Boolean): S {
|
||||
if (!flow.get().input) {
|
||||
return storageType.empty
|
||||
}
|
||||
|
||||
return parent.insertStack(stack, simulate)
|
||||
}
|
||||
|
||||
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): S {
|
||||
if (!flow.get().output) {
|
||||
return storageType.empty
|
||||
}
|
||||
|
||||
return parent.extractStack(id, amount, simulate)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is FlowControlComponent<*> && parent == other.parent
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return parent.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "FlowControlComponent[flow=${flow.get()}, $parent]"
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.storage.optics
|
||||
|
||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageAcceptor
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageComponent
|
||||
@ -76,3 +77,11 @@ fun <S : StorageStack<S>> IVirtualStorageComponent<S>.powered(energy: Supplier<I
|
||||
fun <S : StorageStack<S>> IVirtualStorageComponent<S>.powered(energy: IMatteryEnergyStorage): IVirtualStorageComponent<S> {
|
||||
return PoweredVirtualComponent(this) { energy }
|
||||
}
|
||||
|
||||
fun <S : StorageStack<S>> IStorageComponent<S>.flow(flow: Supplier<FlowDirection>): IStorageComponent<S> {
|
||||
return FlowControlComponent(this, flow)
|
||||
}
|
||||
|
||||
fun <S : StorageStack<S>> IStorageComponent<S>.flow(flow: FlowDirection): IStorageComponent<S> {
|
||||
return FlowControlComponent(this) { flow }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user