Streamlined energy implementations with transparent mekanism wrappers

This commit is contained in:
DBotThePony 2022-02-27 14:24:37 +07:00
parent 98c91b01b0
commit 203b50dcb0
Signed by: DBot
GPG Key ID: DCC23B5715498507
6 changed files with 312 additions and 284 deletions

View File

@ -86,3 +86,5 @@ inline fun <T> LazyOptional<T>.ifPresentK(lambda: (T) -> Unit) {
lambda.invoke(value)
}
}
val ItemStack.tagNotNull get() = orCreateTag

View File

@ -15,7 +15,7 @@ import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
abstract class MatteryPoweredBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(p_155228_, p_155229_, p_155230_) {
abstract val energy: EnergyStorageImpl
abstract val energy: BlockEnergyStorageImpl
private var valid = true
val batteryContainer = MatteryContainer(this::setChangedLight, 1)

View File

@ -0,0 +1,299 @@
@file:Suppress("unused")
package ru.dbotthepony.mc.otm.capability
import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.tagNotNull
private enum class EnergyFlow {
INPUT, OUTPUT, BI_DIRECTIONAL
}
sealed class ItemEnergyStorageImpl(
private val type: EnergyFlow,
protected val itemStack: ItemStack,
maxBatteryLevel: ImpreciseFraction,
protected var maxInput: ImpreciseFraction?,
protected var maxOutput: ImpreciseFraction?
) : IMatteryEnergyStorage, ICapabilityProvider {
private val resolver = LazyOptional.of { this }
private val resolverMekanism = if (isMekanismLoaded) LazyOptional.of { MatteryToMekanismEnergyWrapper(this) } else null
override fun <T : Any> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap === CapabilityEnergy.ENERGY || cap === MatteryCapability.ENERGY) {
return resolver.cast()
} else if (cap === MatteryCapability.MEKANISM_ENERGY) {
return resolverMekanism?.cast() ?: LazyOptional.empty()
}
return LazyOptional.empty()
}
override var maxBatteryLevel: ImpreciseFraction = maxBatteryLevel
protected set
override var batteryLevel: ImpreciseFraction
get() = itemStack.tag?.get("energy")?.let { ImpreciseFraction.deserializeNBT(it) } ?: ImpreciseFraction.ZERO
protected set(value) {
itemStack.tagNotNull.put("energy", value.serializeNBT())
}
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == EnergyFlow.INPUT)
return ImpreciseFraction.ZERO
return extractEnergyInner(howMuch, simulate)
}
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == EnergyFlow.OUTPUT)
return ImpreciseFraction.ZERO
return receiveEnergyInner(howMuch, simulate)
}
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (!howMuch.isPositive)
return ImpreciseFraction.ZERO
@Suppress("NAME_SHADOWING")
var howMuch = howMuch
val maxOutput = maxOutput
if (maxOutput != null) {
howMuch = howMuch.min(maxOutput)
}
val batteryLevel = batteryLevel
if (!batteryLevel.isPositive)
return ImpreciseFraction.ZERO
val newLevel = (batteryLevel - howMuch).moreThanZero()
val diff = (batteryLevel - newLevel)
if (!simulate && batteryLevel != newLevel) {
this.batteryLevel = newLevel
}
return diff
}
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (!howMuch.isPositive)
return ImpreciseFraction.ZERO
@Suppress("NAME_SHADOWING")
var howMuch = howMuch
val maxInput = maxInput
if (maxInput != null) {
howMuch = howMuch.min(maxInput)
}
val batteryLevel = batteryLevel
if (batteryLevel >= maxBatteryLevel)
return ImpreciseFraction.ZERO
val newLevel = (batteryLevel + howMuch).min(maxBatteryLevel)
val diff = (newLevel - batteryLevel)
if (!simulate && batteryLevel != newLevel) {
this.batteryLevel = newLevel
}
return diff
}
override fun canExtract(): Boolean {
return type != EnergyFlow.INPUT
}
override fun canReceive(): Boolean {
return type != EnergyFlow.OUTPUT
}
}
open class EnergyConsumerItem(stack: ItemStack, maxBatteryLevel: ImpreciseFraction, maxInput: ImpreciseFraction? = null, maxOutput: ImpreciseFraction? = maxInput)
: ItemEnergyStorageImpl(EnergyFlow.INPUT, stack, maxBatteryLevel, maxInput, maxOutput)
open class EnergyProducerItem(stack: ItemStack, maxBatteryLevel: ImpreciseFraction, maxInput: ImpreciseFraction? = null, maxOutput: ImpreciseFraction? = maxInput)
: ItemEnergyStorageImpl(EnergyFlow.OUTPUT, stack, maxBatteryLevel, maxInput, maxOutput)
open class EnergyCapacitorItem(stack: ItemStack, maxBatteryLevel: ImpreciseFraction, maxInput: ImpreciseFraction? = null, maxOutput: ImpreciseFraction? = maxInput)
: ItemEnergyStorageImpl(EnergyFlow.BI_DIRECTIONAL, stack, maxBatteryLevel, maxInput, maxOutput)
sealed class BlockEnergyStorageImpl constructor(
protected val listener: () -> Unit,
private val type: EnergyFlow,
maxBatteryLevel: ImpreciseFraction,
protected var maxInput: ImpreciseFraction?,
protected var maxOutput: ImpreciseFraction?
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag> {
override var maxBatteryLevel: ImpreciseFraction = maxBatteryLevel
protected set
override var batteryLevel = ImpreciseFraction.ZERO
protected set
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == EnergyFlow.INPUT)
return ImpreciseFraction.ZERO
return extractEnergyInner(howMuch, simulate)
}
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == EnergyFlow.OUTPUT)
return ImpreciseFraction.ZERO
return receiveEnergyInner(howMuch, simulate)
}
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (!howMuch.isPositive)
return ImpreciseFraction.ZERO
@Suppress("NAME_SHADOWING")
var howMuch = howMuch
val maxOutput = maxOutput
if (maxOutput != null) {
howMuch = howMuch.min(maxOutput)
}
if (!batteryLevel.isPositive)
return ImpreciseFraction.ZERO
val newLevel = (batteryLevel - howMuch).moreThanZero()
val diff = (batteryLevel - newLevel)
if (!simulate && batteryLevel != newLevel) {
batteryLevel = newLevel
listener.invoke()
}
return diff
}
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (!howMuch.isPositive)
return ImpreciseFraction.ZERO
@Suppress("NAME_SHADOWING")
var howMuch = howMuch
val maxInput = maxInput
if (maxInput != null) {
howMuch = howMuch.min(maxInput)
}
if (batteryLevel >= maxBatteryLevel)
return ImpreciseFraction.ZERO
val newLevel = (batteryLevel + howMuch).min(maxBatteryLevel)
val diff = (newLevel - batteryLevel)
if (!simulate && batteryLevel != newLevel) {
batteryLevel = newLevel
listener.invoke()
}
return diff
}
override fun canExtract(): Boolean {
return type != EnergyFlow.INPUT
}
override fun canReceive(): Boolean {
return type != EnergyFlow.OUTPUT
}
override fun serializeNBT(): CompoundTag {
val tag = CompoundTag()
tag["energy_stored"] = batteryLevel.serializeNBT()
tag["energy_stored_max"] = maxBatteryLevel.serializeNBT()
maxInput?.let { tag["max_input"] = it.serializeNBT() }
maxOutput?.let { tag["max_output"] = it.serializeNBT() }
return tag
}
override fun deserializeNBT(nbt: CompoundTag) {
nbt.ifHas("energy_stored") { batteryLevel = ImpreciseFraction.deserializeNBT(it) }
nbt.ifHas("energy_stored_max") { maxBatteryLevel = ImpreciseFraction.deserializeNBT(it) }
nbt.ifHas("max_input") { maxInput = ImpreciseFraction.deserializeNBT(it) }
nbt.ifHas("max_output") { maxOutput = ImpreciseFraction.deserializeNBT(it) }
}
var resolver: LazyOptional<IMatteryEnergyStorage> = LazyOptional.of { this }
private set
fun invalidate() {
resolver.invalidate()
}
fun revive() {
resolver = LazyOptional.of { this }
}
companion object {
val DEFAULT_MAX_IO = ImpreciseFraction(200)
val DEFAULT_MAX_CAPACITY = ImpreciseFraction(60_000)
}
}
open class WorkerEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput
) : BlockEnergyStorageImpl(listener, EnergyFlow.INPUT, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
}
open class GeneratorEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput
) : BlockEnergyStorageImpl(listener, EnergyFlow.OUTPUT, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
}
open class CapacitorEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput
) : BlockEnergyStorageImpl(listener, EnergyFlow.BI_DIRECTIONAL, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
}

View File

@ -1,144 +0,0 @@
package ru.dbotthepony.mc.otm.capability
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
private enum class MachineType {
WORKER, GENERATOR, CAPACITOR
}
sealed class EnergyStorageImpl constructor(
protected val listener: () -> Unit,
private val type: MachineType,
override var maxBatteryLevel: ImpreciseFraction,
protected var maxInput: ImpreciseFraction,
protected var maxOutput: ImpreciseFraction
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag> {
override var batteryLevel = ImpreciseFraction.ZERO
protected set
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == MachineType.WORKER)
return ImpreciseFraction.ZERO
return extractEnergyInner(howMuch, simulate)
}
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val new = batteryLevel.minus(howMuch.min(maxOutput)).moreThanZero()
val diff = batteryLevel.minus(new)
if (!simulate && batteryLevel != new) {
batteryLevel = new
listener()
}
return diff
}
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (type == MachineType.GENERATOR)
return ImpreciseFraction.ZERO
return receiveEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val new = batteryLevel.plus(howMuch.min(maxInput)).min(maxBatteryLevel)
val diff = new.minus(batteryLevel)
if (!simulate && batteryLevel != new) {
batteryLevel = new
listener()
}
return diff
}
override fun canExtract(): Boolean {
return type != MachineType.WORKER
}
override fun canReceive(): Boolean {
return type != MachineType.GENERATOR
}
override fun serializeNBT(): CompoundTag {
val tag = CompoundTag()
// TODO: А это вообще надо?
tag["energy_stored"] = batteryLevel.serializeNBT()
// tag["energy_stored_max"] = maxBatteryLevel.serializeNBT()
// tag["max_input"] = maxInput.serializeNBT()
// tag["max_output"] = maxOutput.serializeNBT()
return tag
}
override fun deserializeNBT(nbt: CompoundTag) {
nbt.ifHas("energy_stored") { batteryLevel = ImpreciseFraction.deserializeNBT(it) }
// nbt.ifHas("energy_stored_max") { maxBatteryLevel = deserializeNBT(it) }
// nbt.ifHas("max_input") { maxInput = deserializeNBT(it) }
// nbt.ifHas("max_output") { maxOutput = deserializeNBT(it) }
}
var resolver: LazyOptional<IMatteryEnergyStorage> = LazyOptional.of { this }
private set
fun invalidate() {
resolver.invalidate()
}
fun revive() {
resolver = LazyOptional.of { this }
}
companion object {
val DEFAULT_MAX_IO = ImpreciseFraction(200)
val DEFAULT_MAX_CAPACITY = ImpreciseFraction(60_000)
}
}
open class WorkerEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction = maxInput
) : EnergyStorageImpl(listener, MachineType.WORKER, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
}
open class GeneratorEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction = maxInput
) : EnergyStorageImpl(listener, MachineType.GENERATOR, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
}
open class CapacitorEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction = maxInput
) : EnergyStorageImpl(listener, MachineType.CAPACITOR, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
}

View File

@ -18,80 +18,30 @@ import net.minecraft.world.item.Rarity
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.capability.EnergyCapacitorItem
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifPresentK
class BatteryItem : Item {
private inner class BatteryMatteryCapability(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
private fun energy(): ImpreciseFraction {
val tag = stack.orCreateTag
return if (tag.contains("otm_energy")) {
ImpreciseFraction.deserializeNBT(tag["otm_energy"])
} else ImpreciseFraction.ZERO
}
private fun energy(value: ImpreciseFraction) {
@Suppress("UsePropertyAccessSyntax")
stack.getOrCreateTag().put("otm_energy", value.serializeNBT())
}
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return extractEnergyInner(howMuch, simulate)
}
private inner class BatteryMatteryCapability(stack: ItemStack)
: EnergyCapacitorItem(stack, this@BatteryItem.storage, this@BatteryItem.receive, this@BatteryItem.extract) {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
val new = energy().minus(howMuch.min(extract)).moreThanZero()
val diff = energy().minus(new)
if (!simulate) {
energy(new)
}
return diff
}
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveEnergyInner(howMuch, simulate)
return super.extractEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
val new = energy().plus(howMuch.min(receive)).min(storage)
val diff = new.minus(energy())
if (!simulate) {
energy(new)
}
return diff
return super.receiveEnergyInner(howMuch, simulate)
}
override val missingPower: ImpreciseFraction get() {
return if (isCreative) ImpreciseFraction.LONG_MAX_VALUE else super.missingPower
}
override val batteryLevel: ImpreciseFraction get() {
return if (isCreative) ImpreciseFraction.LONG_MAX_VALUE else energy()
}
override val maxBatteryLevel: ImpreciseFraction get() {
return storage
}
private val resolver = LazyOptional.of<IMatteryEnergyStorage> { this }
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
return if (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY) resolver.cast() else LazyOptional.empty()
}
override fun canExtract(): Boolean {
return true
}
override fun canReceive(): Boolean {
return true
}
override var batteryLevel: ImpreciseFraction
get() { return if (isCreative) ImpreciseFraction.LONG_MAX_VALUE else super.batteryLevel }
set(value) { super.batteryLevel = value }
}
private val isCreative: Boolean
@ -129,6 +79,7 @@ class BatteryItem : Item {
p_41424_: TooltipFlag
) {
super.appendHoverText(stack, p_41422_, p_41423_, p_41424_)
if (isCreative) {
p_41423_.add(INFINITE_STORAGE)
p_41423_.add(throughputText)

View File

@ -32,86 +32,6 @@ import ru.dbotthepony.mc.otm.menu.FormattingHelper
import ru.dbotthepony.mc.otm.registry.EMPDamageSource
class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
private inner class Energy(private val itemStack: ItemStack) : ICapabilityProvider, IMatteryEnergyStorage {
private val resolver = LazyOptional.of { this }
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap == CapabilityEnergy.ENERGY || cap == MatteryCapability.ENERGY) {
return resolver.cast()
}
return LazyOptional.empty()
}
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return ImpreciseFraction.ZERO
}
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (!howMuch.isPositive) {
return ImpreciseFraction.ZERO
}
val batteryLevel = batteryLevel
val newValue = (batteryLevel - howMuch).moreThanZero()
if (newValue == batteryLevel) {
return ImpreciseFraction.ZERO
}
val diff = batteryLevel - newValue
if (!simulate) {
energy(newValue)
}
return diff
}
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveEnergyInner(howMuch, simulate)
}
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (!howMuch.isPositive) {
return ImpreciseFraction.ZERO
}
val batteryLevel = batteryLevel
val newValue = (batteryLevel + howMuch).min(maxBatteryLevel)
if (newValue == batteryLevel) {
return ImpreciseFraction.ZERO
}
val diff = newValue - batteryLevel
if (!simulate) {
energy(newValue)
}
return diff
}
private fun energy(value: ImpreciseFraction) {
@Suppress("UsePropertyAccessSyntax")
itemStack.getOrCreateTag().put("energy", value.serializeNBT())
}
override val batteryLevel: ImpreciseFraction
get() = itemStack.tag?.get("energy")?.let { ImpreciseFraction.deserializeNBT(it) } ?: ImpreciseFraction.ZERO
override val maxBatteryLevel: ImpreciseFraction
get() = MAX_ENERGY
override fun canExtract(): Boolean {
return false
}
override fun canReceive(): Boolean {
return true
}
}
val chargedAttributes: Multimap<Attribute, AttributeModifier>
val dischargedAttributes: Multimap<Attribute, AttributeModifier>
@ -208,7 +128,7 @@ class EnergySwordItem : Item(Properties().stacksTo(1).rarity(Rarity.RARE).tab(Ov
}
override fun initCapabilities(stack: ItemStack, nbt: CompoundTag?): ICapabilityProvider {
return Energy(stack)
return EnergyConsumerItem(stack, MAX_ENERGY)
}
override fun getAttributeModifiers(