Battery bank now have configurable item and energy sides

This commit is contained in:
DBotThePony 2023-03-12 17:57:39 +07:00
parent aeeabe90ee
commit f88163d1e5
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 109 additions and 135 deletions

View File

@ -25,7 +25,7 @@ import ru.dbotthepony.mc.otm.core.math.RelativeSide
import ru.dbotthepony.mc.otm.menu.tech.BatteryBankMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.BATTERY_BANK, p_155229_, p_155230_) {
class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.BATTERY_BANK, p_155229_, p_155230_), IMatteryEnergyStorage {
var gaugeLevel by synchronizer.float()
private set
@ -34,7 +34,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
batteryStatus[slot].value = new.getCapability(ForgeCapabilities.ENERGY).isPresent
gaugeLevel = (energy.batteryLevel / energy.maxBatteryLevel).toFloat()
gaugeLevel = (batteryLevel / maxBatteryLevel).toFloat()
}
}.also(::addDroppableContainer)
@ -42,35 +42,73 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
synchronizer.bool(false)
}
private val itemHandler = container.handler(
object : HandlerFilter {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return stack.getCapability(ForgeCapabilities.ENERGY).isPresent
}
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
return true
}
}
val itemConfig = ConfigurableItemHandler(
input = container.handler(HandlerFilter.Dischargeable.and(HandlerFilter.OnlyIn)),
output = container.handler(HandlerFilter.OnlyOut),
frontDefault = ItemHandlerMode.INPUT_OUTPUT,
backDefault = ItemHandlerMode.INPUT_OUTPUT,
leftDefault = ItemHandlerMode.INPUT_OUTPUT,
rightDefault = ItemHandlerMode.INPUT_OUTPUT,
topDefault = ItemHandlerMode.INPUT_OUTPUT,
bottomDefault = ItemHandlerMode.INPUT_OUTPUT,
)
init {
exposeItemsGlobally(itemHandler)
savetable(::container, INVENTORY_KEY)
}
private data class BatteryBankDistribution(val distribution: Array<Decimal>, val maxThroughput: Decimal)
private inner class BatteryBankEnergy(override val energyFlow: FlowDirection) : IMatteryEnergyStorage {
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
return distributeEnergy(isReceiving = false, howMuch, simulate)
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
return distributeEnergy(isReceiving = false, howMuch, simulate)
}
private fun getDistribution(isReceiving: Boolean): BatteryBankDistribution {
val distribution = Array(container.containerSize) { Decimal.ZERO }
var summ = Decimal.ZERO
for (i in 0 until container.containerSize) {
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.energy?.let {
val diff: Decimal
if (isReceiving) {
diff = it.receiveEnergy(it.maxEnergyStoredMattery, true)
} else {
diff = it.extractEnergy(it.energyStoredMattery, true)
}
distribution[i] = diff
summ += distribution[i]
}
}
}
fun getDistribution(isReceiving: Boolean): BatteryBankDistribution {
val distribution = Array(container.containerSize) { Decimal.ZERO }
var summ = Decimal.ZERO
if (!summ.isZero) {
for (i in 0 until container.containerSize) {
distribution[i] = distribution[i] / summ
}
}
return BatteryBankDistribution(distribution, summ)
}
private fun distributeEnergy(isReceiving: Boolean, howMuch: Decimal, simulate: Boolean, set: Boolean = false): Decimal {
if (!howMuch.isPositive)
return Decimal.ZERO
val distribution = getDistribution(isReceiving)
if (distribution.maxThroughput.isZero)
return Decimal.ZERO
val distList = distribution.distribution
var summ = Decimal.ZERO
for (i in 0 until container.containerSize) {
if (!distList[i].isZero) {
val stack = container.getItem(i)
if (!stack.isEmpty) {
@ -78,95 +116,57 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val diff: Decimal
if (isReceiving) {
diff = it.receiveEnergy(it.maxEnergyStoredMattery, true)
diff = it.receiveEnergy(howMuch * distList[i], simulate)
} else {
diff = it.extractEnergy(it.energyStoredMattery, true)
diff = it.extractEnergy(howMuch * distList[i], simulate)
}
distribution[i] = diff
summ += distribution[i]
summ += diff
}
}
}
if (!summ.isZero) {
for (i in 0 until container.containerSize) {
distribution[i] = distribution[i] / summ
}
}
return BatteryBankDistribution(distribution, summ)
}
private fun distributeEnergy(isReceiving: Boolean, howMuch: Decimal, simulate: Boolean, set: Boolean = false): Decimal {
if (!howMuch.isPositive)
return Decimal.ZERO
if (!simulate && !summ.isZero) {
setChangedLight()
gaugeLevel = (batteryLevel / maxBatteryLevel).toFloat()
}
val distribution = getDistribution(isReceiving)
return summ
}
if (distribution.maxThroughput.isZero)
return Decimal.ZERO
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
return distributeEnergy(isReceiving = true, howMuch, simulate)
}
val distList = distribution.distribution
var summ = Decimal.ZERO
override val canSetBatteryLevel: Boolean
get() = false
override val energyFlow: FlowDirection
get() = FlowDirection.BI_DIRECTIONAL
override var batteryLevel: Decimal
get() {
var result = Decimal.ZERO
for (i in 0 until container.containerSize) {
if (!distList[i].isZero) {
val stack = container.getItem(i)
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.energy?.let {
val diff: Decimal
if (isReceiving) {
diff = it.receiveEnergy(howMuch * distList[i], simulate)
} else {
diff = it.extractEnergy(howMuch * distList[i], simulate)
}
summ += diff
}
if (!stack.isEmpty) {
stack.energy?.let {
result += it.energyStoredMattery
}
}
}
if (!simulate && !summ.isZero) {
setChangedLight()
gaugeLevel = (batteryLevel / maxBatteryLevel).toFloat()
}
return summ
return result
}
set(value) {
throw UnsupportedOperationException("Can't set battery value for battery bank")
}
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
return distributeEnergy(isReceiving = true, howMuch, simulate)
}
override val canSetBatteryLevel: Boolean
get() = false
override var batteryLevel: Decimal
get() {
var result = Decimal.ZERO
for (i in 0 until container.containerSize) {
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.energy?.let {
result += it.energyStoredMattery
}
}
}
return result
}
set(value) {
throw UnsupportedOperationException("Can't set battery value for battery bank")
}
override val maxBatteryLevel: Decimal
get() {
override val maxBatteryLevel: Decimal
get() {
var result = Decimal.ZERO
for (i in 0 until container.containerSize) {
@ -181,57 +181,25 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
return result
}
}
private val energyReceiver = BatteryBankEnergy(FlowDirection.INPUT)
private val energyExtractor = BatteryBankEnergy(FlowDirection.OUTPUT)
private val energy = BatteryBankEnergy(FlowDirection.BI_DIRECTIONAL)
val energyConfig = ConfigurableEnergy(
this,
frontDefault = FlowDirection.OUTPUT,
backDefault = FlowDirection.INPUT,
leftDefault = FlowDirection.INPUT,
rightDefault = FlowDirection.INPUT,
topDefault = FlowDirection.INPUT,
bottomDefault = FlowDirection.INPUT
)
init {
energyConfig.front.automatePush = true
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return BatteryBankMenu(containerID, inventory, this)
}
init {
exposeEnergySideless(energy)
exposeEnergy(RelativeSide.FRONT, energyExtractor)
for (side in RelativeSide.values()) {
if (side != RelativeSide.FRONT) {
exposeEnergy(side, energyReceiver)
}
}
}
private val consumers by front.track(ForgeCapabilities.ENERGY)
override fun tick() {
super.tick()
if (redstoneControl.isBlockedByRedstone)
return
consumers.ifPresentK {
val (_, maxThroughput) = energy.getDistribution(false)
if (maxThroughput.isZero)
return@ifPresentK
val diff = it.receiveEnergy(maxThroughput, true)
if (!diff.isZero) {
val newExtract = energy.extractEnergy(diff, true)
val newReceive = it.receiveEnergy(newExtract, true)
val extracted = energy.extractEnergy(newReceive, false)
val received = it.receiveEnergy(extracted, false)
if (received < extracted) {
energy.receiveEnergy(extracted - received, false)
}
}
}
}
companion object {
const val CAPACITY = 6 * 2
}

View File

@ -23,7 +23,7 @@ class BatteryBankScreen(menu: BatteryBankMenu, p_97742_: Inventory, p_97743_: Co
for (i in 6 .. 11)
BatterySlotPanel(this, frame, menu.storageSlots[i], 44f + 18 * (i - 6), 32f + 18f)
makeDeviceControls(this, frame, redstone = menu.redstone)
makeDeviceControls(this, frame, redstone = menu.redstone, energyConfig = menu.energyConfig, itemConfig = menu.itemConfig)
return frame
}

View File

@ -13,7 +13,9 @@ import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.menu.BatterySlot
import ru.dbotthepony.mc.otm.menu.MatteryMenu
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.ItemHandlerPlayerInput
import ru.dbotthepony.mc.otm.registry.MMenus
class BatteryBankMenu @JvmOverloads constructor(
@ -24,10 +26,14 @@ class BatteryBankMenu @JvmOverloads constructor(
val powerLevel: LevelGaugeWidget
val storageSlots: List<MatterySlot>
val redstone = EnumInputWithFeedback(this, RedstoneSetting::class.java)
val energyConfig = EnergyPlayerInput(this, allowPull = false, allowPush = true)
val itemConfig = ItemHandlerPlayerInput(this, allowPull = false, allowPush = false)
init {
if (tile != null) {
redstone.with(tile.redstoneControl::redstoneSetting)
energyConfig.configure(tile.energyConfig)
itemConfig.configure(tile.itemConfig)
}
val container: Container = tile?.container ?: SimpleContainer(BatteryBankBlockEntity.CAPACITY)