Initial direct Mekanism energy support

This commit is contained in:
DBotThePony 2022-02-27 11:50:52 +07:00
parent ddf2c178e6
commit 98c91b01b0
Signed by: DBot
GPG Key ID: DCC23B5715498507
14 changed files with 455 additions and 159 deletions

View File

@ -96,6 +96,9 @@ dependencies {
implementation(fg.deobf(create("mcjty.theoneprobe:theoneprobe:${mc_version_weak}-${the_one_probe_version}", closureOf<Any> {
(this as ExternalModuleDependency).isTransitive = false
} as Closure<Any>)))
//compileOnly(fg.deobf("blank:Mekanism-1.18.1:10.1.2.homebaked-api"))
implementation(fg.deobf("blank:Mekanism-1.18.1:10.1.2.homebaked-all"))
}
configurations {
@ -177,9 +180,9 @@ repositories {
}
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
//flatDir {
// dir "libs"
//}
flatDir {
dir("libs")
}
}
// Example configuration to allow publishing using the maven-publish plugin

View File

@ -10,9 +10,9 @@ mod_version=0.1
mc_version=1.18.1
mc_version_weak=1.18
forge_gradle_version=5.1.27
forge_version=39.0.64
forge_version=39.0.85
jei_version=9.1.1.48
jei_version=9.4.1.106
jupiter_version=5.8.2
the_one_probe_version=5.0.1-5

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability;
import mekanism.api.energy.IStrictEnergyHandler;
import net.minecraftforge.common.capabilities.*;
import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
@ -19,6 +20,8 @@ public class MatteryCapability {
public static final Capability<IMatteryDrive> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<IStorageGraphNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<IStrictEnergyHandler> MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {});
@SuppressWarnings("unused")
public static void register(final RegisterCapabilitiesEvent event) {
event.register(IMatteryEnergyStorage.class);

View File

@ -179,11 +179,11 @@ public class FormattingHelper {
new ImpreciseFraction("0.001"), // "otm.suffix.milli": "m%s",
new ImpreciseFraction("0.000001"), // "otm.suffix.micro": "μ%s",
new ImpreciseFraction("0.000000001"), // "otm.suffix.nano": "n%s",
new ImpreciseFraction("0.000000000001"), // "otm.suffix.pico": "p%s",
new ImpreciseFraction("0.000000000000001"), // "otm.suffix.femto": "f%s",
new ImpreciseFraction("0.000000000000000001"), // "otm.suffix.atto": "a%s",
new ImpreciseFraction("0.000000000000000000001"), // "otm.suffix.zepto": "z%s",
new ImpreciseFraction("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s",
//new ImpreciseFraction("0.000000000001"), // "otm.suffix.pico": "p%s",
//new ImpreciseFraction("0.000000000000001"), // "otm.suffix.femto": "f%s",
//new ImpreciseFraction("0.000000000000000001"), // "otm.suffix.atto": "a%s",
//new ImpreciseFraction("0.000000000000000000001"), // "otm.suffix.zepto": "z%s",
//new ImpreciseFraction("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s",
};
public static String formatDecimal(BigDecimal value, int decimals) {

View File

@ -86,7 +86,3 @@ inline fun <T> LazyOptional<T>.ifPresentK(lambda: (T) -> Unit) {
lambda.invoke(value)
}
}
val ItemStack.energy get() = getCapability(CapabilityEnergy.ENERGY).orNull()
val ItemStack.matteryEnergy get() = getCapability(MatteryCapability.ENERGY).orNull()
val LivingEntity.android get() = getCapability(MatteryCapability.ANDROID).orNull()

View File

@ -21,13 +21,12 @@ import net.minecraftforge.energy.IEnergyStorage
import net.minecraftforge.items.CapabilityItemHandler
import ru.dbotthepony.mc.otm.block.BatteryBankBlock
import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.ifPresentK
import ru.dbotthepony.mc.otm.menu.BatteryBankMenu
import ru.dbotthepony.mc.otm.orNull
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.unaryMinus
@ -86,30 +85,17 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
val diff: ImpreciseFraction
stack.energy?.let {
val diff: ImpreciseFraction
if (mode) {
diff = it.receiveEnergyOuter(ImpreciseFraction.LONG_MAX_VALUE, true)
} else {
diff = it.extractEnergyOuter(ImpreciseFraction.LONG_MAX_VALUE, true)
}
distribution[i] = diff
summ += diff
if (mode) {
diff = it.receiveEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
} else {
val diff: Int
if (mode) {
diff = it.receiveEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
} else {
diff = it.extractEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
}
distribution[i] = ImpreciseFraction(diff)
summ += distribution[i]
diff = it.extractEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
}
distribution[i] = diff
summ += distribution[i]
}
}
}
@ -137,28 +123,16 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
val diff: ImpreciseFraction
stack.energy?.let {
val diff: ImpreciseFraction
if (mode) {
diff = it.receiveEnergyOuter(howMuch * distList[i], simulate)
} else {
diff = it.extractEnergyOuter(howMuch * distList[i], simulate)
}
summ += diff
if (mode) {
diff = it.receiveEnergy(howMuch * distList[i], simulate)
} else {
val diff: Int
if (mode) {
diff = it.receiveEnergy(howMuch * distList[i], simulate)
} else {
diff = it.extractEnergy(howMuch * distList[i], simulate)
}
summ += ImpreciseFraction(diff)
diff = it.extractEnergy(howMuch * distList[i], simulate)
}
summ += diff
}
}
}
@ -193,12 +167,8 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
result += it.batteryLevel
} else {
result += it.energyStored
}
stack.energy?.let {
result += it.energyStoredMattery
}
}
}
@ -213,12 +183,8 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i)
if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
result += it.maxBatteryLevel
} else {
result += it.maxEnergyStored
}
stack.energy?.let {
result += it.maxEnergyStoredMattery
}
}
}
@ -315,6 +281,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
CapabilityEnergy.ENERGY,
-blockState.getValue(BlockMatteryRotatable.FACING)
) {
@Suppress("name_shadowing")
val level = this.level
if (level is ServerLevel)
@ -326,24 +293,16 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
if (isBlockedByRedstone)
return
outputCapability.ifPresent {
outputCapability.ifPresentK {
val (_, maxThroughput) = energy.getDistribution(false)
if (maxThroughput.isZero)
return@ifPresent
return@ifPresentK
if (it is IMatteryEnergyStorage) {
val diff = it.receiveEnergyOuter(maxThroughput, false)
val diff = it.receiveEnergy(maxThroughput, false)
if (!diff.isZero) {
energy.extractEnergyInner(diff, false)
}
} else {
val diff = it.receiveEnergy(maxThroughput, false)
if (diff != 0) {
energy.extractEnergyInner(diff, false)
}
if (!diff.isZero) {
energy.extractEnergyInner(diff, false)
}
}
}

View File

@ -119,9 +119,9 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
if (direction == blockState.getValue(BlockMatteryRotatable.FACING))
continue
val resolver = level.getBlockEntity(blockPos + direction)?.getCapability(CapabilityEnergy.ENERGY, -direction)
val resolver = level.getBlockEntity(blockPos + direction)?.getEnergySided(-direction)
resolver?.ifPresent {
resolver?.ifPresentK {
if (!known.contains(resolver)) {
val ref = WeakReference(this)
@ -168,22 +168,11 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
private var check = true
private fun workWithPower(it: IEnergyStorage) {
if (it is IMatteryEnergyStorage) {
val demand = it.missingPower
val extracted = energy.extractEnergyInner(demand, true)
val received = it.receiveEnergyOuter(extracted, false)
val extracted = energy.extractEnergyInner(THROUGHPUT, true)
val received = it.receiveEnergy(extracted, false)
if (!received.isZero) {
energy.extractEnergyInner(received, false)
}
} else {
val demand = it.receiveEnergy(THROUGHPUT_INT, true)
val extracted = energy.extractEnergyInner(demand, true)
val received = it.receiveEnergy(extracted, false)
if (received != 0) {
energy.extractEnergyInner(received, false)
}
if (!received.isZero) {
energy.extractEnergyInner(received, false)
}
}
@ -235,7 +224,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
val item = container[SLOT_BATTERY]
if (!item.isEmpty) {
item.getCapability(CapabilityEnergy.ENERGY).ifPresent(this::workWithPower)
item.energy?.let(this::workWithPower)
if (energy.batteryLevel.isZero) return
}

View File

@ -24,10 +24,8 @@ import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.block.EnergyCounterBlock
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.compat.mekanism.MatteryToMekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.EnergyCounterMenu
import ru.dbotthepony.mc.otm.network.MatteryNetworking
@ -138,6 +136,8 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
for (num in history)
list.add(num.serializeNBT())
ioLimit?.let { nbt["io_limit"] = it.serializeNBT() }
}
override fun load(nbt: CompoundTag) {
@ -147,6 +147,10 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
passed = ImpreciseFraction.deserializeNBT(it)
}
nbt.ifHas(("io_limit")) {
ioLimit = ImpreciseFraction.deserializeNBT(it)
}
nbt.ifHas(("history_tick"), IntTag::class.java) {
historyTick = it.asInt
}
@ -195,17 +199,9 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
val ioLimit = ioLimit
if (ioLimit != null) {
if (it is IMatteryEnergyStorage) {
diff = it.extractEnergyOuter(howMuch.min(ioLimit), simulate)
} else {
diff = ImpreciseFraction(it.extractEnergy(howMuch.min(ioLimit), simulate))
}
diff = it.extractEnergy(howMuch.min(ioLimit), simulate)
} else {
if (it is IMatteryEnergyStorage) {
diff = it.extractEnergyOuter(howMuch, simulate)
} else {
diff = ImpreciseFraction(it.extractEnergy(howMuch, simulate))
}
diff = it.extractEnergy(howMuch, simulate)
}
if (!simulate) {
@ -235,17 +231,9 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
val ioLimit = ioLimit
if (ioLimit != null) {
if (it is IMatteryEnergyStorage) {
diff = it.receiveEnergyOuter(howMuch.min(ioLimit), simulate)
} else {
diff = ImpreciseFraction(it.receiveEnergy(howMuch.min(ioLimit), simulate))
}
diff = it.receiveEnergy(howMuch.min(ioLimit), simulate)
} else {
if (it is IMatteryEnergyStorage) {
diff = it.receiveEnergyOuter(howMuch, simulate)
} else {
diff = ImpreciseFraction(it.receiveEnergy(howMuch, simulate))
}
diff = it.receiveEnergy(howMuch, simulate)
}
if (!simulate) {
@ -346,13 +334,19 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
private var resolverInput = LazyOptional.of<IMatteryEnergyStorage> { energyInput }
private var resolverOutput = LazyOptional.of<IMatteryEnergyStorage> { energyOutput }
private var resolverInputMekanism = if (isMekanismLoaded) LazyOptional.of { MatteryToMekanismEnergyWrapper(energyInput) } else null
private var resolverOutputMekanism = if (isMekanismLoaded) LazyOptional.of { MatteryToMekanismEnergyWrapper(energyInput) } else null
private var valid = true
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
resolverInput.invalidate()
resolverInputMekanism?.invalidate()
resolverOutput.invalidate()
resolverOutputMekanism?.invalidate()
}
override fun reviveCaps() {
@ -360,6 +354,11 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
valid = true
resolverInput = LazyOptional.of { energyInput }
resolverOutput = LazyOptional.of { energyOutput }
if (isMekanismLoaded) {
resolverInputMekanism = LazyOptional.of { MatteryToMekanismEnergyWrapper(energyInput) }
resolverOutputMekanism = LazyOptional.of { MatteryToMekanismEnergyWrapper(energyInput) }
}
}
@Suppress("deprecation")
@ -369,10 +368,18 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
if (new !== old && new.getValue(EnergyCounterBlock.INPUT_DIRECTION) != old.getValue(EnergyCounterBlock.INPUT_DIRECTION)) {
resolverInput.invalidate()
resolverInputMekanism?.invalidate()
resolverOutput.invalidate()
resolverOutputMekanism?.invalidate()
resolverInput = LazyOptional.of { energyInput }
resolverOutput = LazyOptional.of { energyOutput }
if (isMekanismLoaded) {
resolverInputMekanism = LazyOptional.of { MatteryToMekanismEnergyWrapper(energyInput) }
resolverOutputMekanism = LazyOptional.of { MatteryToMekanismEnergyWrapper(energyInput) }
}
if (level != null)
checkSurroundings(level)
}
@ -384,7 +391,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
side: Direction
): LazyOptional<IEnergyStorage> {
val ent = level.getBlockEntity(blockPos.offset(side.normal)) ?: return LazyOptional.empty()
val resolve = ent.getCapability(CapabilityEnergy.ENERGY, side.opposite)
val resolve = ent.getEnergySided(-side)
if (resolve !== old) {
val weak = WeakReference(this)
@ -427,10 +434,14 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
if (side == blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION)) {
if (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY) {
return resolverInput.cast()
} else if (cap === MatteryCapability.MEKANISM_ENERGY) {
return resolverInputMekanism!!.cast()
}
} else if (side == blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION).opposite) {
if (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY) {
return resolverOutput.cast()
} else if (cap === MatteryCapability.MEKANISM_ENERGY) {
return resolverOutputMekanism!!.cast()
}
}
}

View File

@ -1,45 +1,119 @@
package ru.dbotthepony.mc.otm.capability
import net.minecraft.core.Direction
import net.minecraft.world.entity.LivingEntity
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.core.Fraction
import net.minecraftforge.fml.ModList
import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided
import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.orNull
fun IEnergyStorage.receiveEnergy(amount: Fraction, simulate: Boolean): Int {
if (amount.isZero())
return 0
fun IEnergyStorage.receiveEnergy(amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (this is IMatteryEnergyStorage)
return receiveEnergyOuter(amount, simulate)
if (amount > Fraction.INT_MAX_VALUE)
return receiveEnergy(Int.MAX_VALUE, simulate)
return receiveEnergy(amount.wholePart().toInt(), simulate)
}
fun IEnergyStorage.extractEnergy(amount: Fraction, simulate: Boolean): Int {
if (amount.isZero())
return 0
if (amount > Fraction.INT_MAX_VALUE)
return extractEnergy(Int.MAX_VALUE, simulate)
return extractEnergy(amount.wholePart().toInt(), simulate)
}
fun IEnergyStorage.receiveEnergy(amount: ImpreciseFraction, simulate: Boolean): Int {
if (amount.isZero)
return 0
if (!amount.isPositive)
return ImpreciseFraction.ZERO
if (amount > ImpreciseFraction.INT_MAX_VALUE)
return receiveEnergy(Int.MAX_VALUE, simulate)
return ImpreciseFraction.valueOf(receiveEnergy(Int.MAX_VALUE, simulate))
return receiveEnergy(amount.toInt(), simulate)
return ImpreciseFraction.valueOf(receiveEnergy(amount.toInt(), simulate))
}
fun IEnergyStorage.extractEnergy(amount: ImpreciseFraction, simulate: Boolean): Int {
if (amount.isZero)
return 0
fun IEnergyStorage.extractEnergy(amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (this is IMatteryEnergyStorage)
return extractEnergyOuter(amount, simulate)
if (!amount.isPositive)
return ImpreciseFraction.ZERO
if (amount > ImpreciseFraction.INT_MAX_VALUE)
return extractEnergy(Int.MAX_VALUE, simulate)
return ImpreciseFraction.valueOf(extractEnergy(Int.MAX_VALUE, simulate))
return extractEnergy(amount.toInt(), simulate)
return ImpreciseFraction.valueOf(extractEnergy(amount.toInt(), simulate))
}
val IEnergyStorage.maxEnergyStoredMattery: ImpreciseFraction get() {
if (this is IMatteryEnergyStorage) {
return maxBatteryLevel
}
return ImpreciseFraction.valueOf(maxEnergyStored)
}
val IEnergyStorage.energyStoredMattery: ImpreciseFraction get() {
if (this is IMatteryEnergyStorage) {
return batteryLevel
}
return ImpreciseFraction.valueOf(energyStored)
}
val isMekanismLoaded by lazy { ModList.get().isLoaded("mekanism") }
/**
* Shortcut for getting [IEnergyStorage], including wrappers for it
*/
val ICapabilityProvider.energy: IEnergyStorage? get() {
if (isMekanismLoaded) {
val mekanismEnergy = mekanismEnergy
if (mekanismEnergy != null) {
return mekanismEnergy
}
}
return getCapability(CapabilityEnergy.ENERGY).orNull()
}
/**
* Shortcut for getting [IMatteryEnergyStorage], including wrappers for it
*/
val ICapabilityProvider.matteryEnergy: IMatteryEnergyStorage? get() {
if (isMekanismLoaded) {
val mekanismEnergy = mekanismEnergy
if (mekanismEnergy != null) {
return mekanismEnergy
}
}
return getCapability(MatteryCapability.ENERGY).orNull()
}
/**
* Shortcut for getting [LazyOptional] with [IEnergyStorage], including wrappers for it
*/
fun ICapabilityProvider.getEnergySided(side: Direction? = null): LazyOptional<IEnergyStorage> {
if (isMekanismLoaded) {
val mekanismEnergy = getMekanismEnergySided(side)
if (mekanismEnergy.isPresent) {
return mekanismEnergy.cast()
}
}
return getCapability(CapabilityEnergy.ENERGY, side)
}
/**
* Shortcut for getting [LazyOptional] with [IMatteryEnergyStorage], including wrappers for it
*/
fun ICapabilityProvider.getMatteryEnergySided(side: Direction? = null): LazyOptional<IMatteryEnergyStorage> {
if (isMekanismLoaded) {
val mekanismEnergy = getMekanismEnergySided(side)
if (mekanismEnergy.isPresent) {
return mekanismEnergy
}
}
return getCapability(MatteryCapability.ENERGY, side)
}
val LivingEntity.android get() = getCapability(MatteryCapability.ANDROID).orNull()

View File

@ -7,12 +7,16 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction
// IEnergyStorage for direct compat with Forge Energy
interface IMatteryEnergyStorage : IEnergyStorage {
/**
* such as cables. This is something that would work only with energy storage
* Such as cables. This is something that would work only with energy storage
*
* @return energy extracted
*/
fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
/**
* All or nothing
*
* @return energy extracted
*/
fun extractEnergyOuterExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val extracted = extractEnergyOuter(howMuch, true)
@ -32,11 +36,15 @@ interface IMatteryEnergyStorage : IEnergyStorage {
* for internal needs, e.g. for work
* CAN also be used by something that does evil
* e.g. sucking out energy anomaly should use this
*
* @return energy extracted
*/
fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
/**
* All or nothing
*
* @return energy extracted
*/
fun extractEnergyInnerExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val extracted = extractEnergyInner(howMuch, true)
@ -54,6 +62,8 @@ interface IMatteryEnergyStorage : IEnergyStorage {
/**
* For energy receiving from outside, e.g. cables
*
* @return energy accepted
*/
fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
@ -73,11 +83,15 @@ interface IMatteryEnergyStorage : IEnergyStorage {
/**
* For energy receiving from inside, e.g. generator generates power
*
* @return energy accepted
*/
fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
/**
* All or nothing
*
* @return energy accepted
*/
fun receiveEnergyInnerExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val extracted = receiveEnergyInner(howMuch, true)

View File

@ -0,0 +1,30 @@
package ru.dbotthepony.mc.otm.compat.mekanism
import mekanism.api.math.FloatingLong
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.math.BigInteger
private val LONG_OVERFLOW = BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.TWO
private val LONG_OVERFLOW1 = BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.ONE
fun ImpreciseFraction.toFloatingLong(): FloatingLong {
if (isNegative) {
// Floating long can't be negative
return FloatingLong.ZERO
}
if (whole >= LONG_OVERFLOW1) {
return FloatingLong.MAX_VALUE
}
return FloatingLong.create(whole.toLong(), (decimal * 10_000.0).toInt().toShort())
}
fun FloatingLong.toImpreciseFraction(): ImpreciseFraction {
// Overflow
if (value < 0L) {
return ImpreciseFraction(LONG_OVERFLOW + BigInteger.valueOf(value), decimal / 10_000.0)
}
return ImpreciseFraction(value, decimal / 10_000.0)
}

View File

@ -0,0 +1,194 @@
package ru.dbotthepony.mc.otm.compat.mekanism
import mekanism.api.Action
import mekanism.api.energy.IStrictEnergyHandler
import mekanism.api.math.FloatingLong
import mekanism.common.config.MekanismConfig
import net.minecraft.core.Direction
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.fml.ModList
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.lang.ref.WeakReference
import java.util.WeakHashMap
private val mekanismJoulesToFE by lazy {
try {
val conf = MekanismConfig.general
return@lazy conf.TO_FORGE.get().toImpreciseFraction()
} catch(_: Throwable) {
}
return@lazy ImpreciseFraction.ONE
}
private val mekanismJoulesFromFE by lazy {
try {
val conf = MekanismConfig.general
return@lazy conf.FROM_FORGE.get().toImpreciseFraction()
} catch(_: Throwable) {
}
return@lazy ImpreciseFraction.ONE
}
class MekanismEnergyWrapper(private val power: IStrictEnergyHandler) : IMatteryEnergyStorage {
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val action = when (simulate) {
true -> Action.SIMULATE
false -> Action.EXECUTE
}
return howMuch - power.extractEnergy((howMuch * mekanismJoulesFromFE).toFloatingLong(), action).toImpreciseFraction() * mekanismJoulesToFE
}
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return extractEnergyOuter(howMuch, simulate)
}
override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val action = when (simulate) {
true -> Action.SIMULATE
false -> Action.EXECUTE
}
return howMuch - power.insertEnergy((howMuch * mekanismJoulesFromFE).toFloatingLong(), action).toImpreciseFraction() * mekanismJoulesToFE
}
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return receiveEnergyOuter(howMuch, simulate)
}
override val batteryLevel: ImpreciseFraction
get() {
var sum = ImpreciseFraction.ZERO
for (i in 0 until power.energyContainerCount) {
sum += power.getEnergy(i).toImpreciseFraction()
}
return sum * mekanismJoulesToFE
}
override val maxBatteryLevel: ImpreciseFraction
get() {
var sum = ImpreciseFraction.ZERO
for (i in 0 until power.energyContainerCount) {
sum += power.getMaxEnergy(i).toImpreciseFraction()
}
return sum * mekanismJoulesToFE
}
}
class MatteryToMekanismEnergyWrapper(private val power: IMatteryEnergyStorage) : IStrictEnergyHandler {
override fun getEnergyContainerCount(): Int = 1
override fun getEnergy(container: Int): FloatingLong {
if (container != 0) {
return FloatingLong.ZERO
}
return (power.batteryLevel * mekanismJoulesFromFE).toFloatingLong()
}
override fun setEnergy(container: Int, value: FloatingLong) {
// no op
}
override fun getMaxEnergy(container: Int): FloatingLong {
if (container != 0) {
return FloatingLong.ZERO
}
return (power.maxBatteryLevel * mekanismJoulesFromFE).toFloatingLong()
}
override fun getNeededEnergy(container: Int): FloatingLong {
if (container != 0) {
return FloatingLong.ZERO
}
return (power.missingPower * mekanismJoulesFromFE).toFloatingLong()
}
override fun insertEnergy(container: Int, howMuch: FloatingLong, action: Action): FloatingLong {
val copy = howMuch.copy()
return copy.minusEqual((power.receiveEnergyOuter(howMuch.toImpreciseFraction() * mekanismJoulesToFE, action.simulate()) * mekanismJoulesFromFE).toFloatingLong())
}
override fun extractEnergy(container: Int, howMuch: FloatingLong, action: Action): FloatingLong {
val copy = howMuch.copy()
return copy.minusEqual((power.extractEnergyOuter(howMuch.toImpreciseFraction() * mekanismJoulesToFE, action.simulate()) * mekanismJoulesFromFE).toFloatingLong())
}
}
val ICapabilityProvider.mekanismEnergy: IMatteryEnergyStorage? get() {
if (!isMekanismLoaded) {
return null
}
val capability = getCapability(MatteryCapability.MEKANISM_ENERGY)
if (!capability.isPresent) {
return null
}
return MekanismEnergyWrapper(capability.orElseThrow(::IllegalStateException))
}
private val lazyCache by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<MekanismEnergyWrapper>>>() }
private val lazyCacheDown by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<MekanismEnergyWrapper>>>() }
private val lazyCacheUp by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<MekanismEnergyWrapper>>>() }
private val lazyCacheSouth by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<MekanismEnergyWrapper>>>() }
private val lazyCacheNorth by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<MekanismEnergyWrapper>>>() }
private val lazyCacheEast by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<MekanismEnergyWrapper>>>() }
private val lazyCacheWest by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<MekanismEnergyWrapper>>>() }
fun ICapabilityProvider.getMekanismEnergySided(side: Direction? = null): LazyOptional<IMatteryEnergyStorage> {
if (!isMekanismLoaded) {
return LazyOptional.empty()
}
val lazyOptional = getCapability(MatteryCapability.MEKANISM_ENERGY, side)
if (!lazyOptional.isPresent) {
return LazyOptional.empty()
}
val cache = when (side) {
Direction.DOWN -> lazyCacheDown
Direction.UP -> lazyCacheUp
Direction.NORTH -> lazyCacheNorth
Direction.SOUTH -> lazyCacheSouth
Direction.WEST -> lazyCacheWest
Direction.EAST -> lazyCacheEast
null -> lazyCache
}
val cached = cache[lazyOptional]?.get()
if (cached != null) {
return cached.cast()
}
val resolver = LazyOptional.of {
MekanismEnergyWrapper(lazyOptional.orElseThrow(::IllegalStateException))
}
val ref = WeakReference(resolver)
cache[lazyOptional] = ref
lazyOptional.addListener {
ref.get()?.invalidate()
}
return resolver.cast()
}

View File

@ -541,6 +541,30 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
@JvmField val DOUBLE_MAX_VALUE = ImpreciseFraction(BI_DOUBLE_MAX)
@JvmField val DOUBLE_MIN_VALUE = ImpreciseFraction(BI_DOUBLE_MIN)
private val cache = Array(256) { ImpreciseFraction(it - 128) }
/**
* Returns pooled value if present, otherwise constructs new object
*/
fun valueOf(value: Int): ImpreciseFraction {
if (value in -128 .. 127) {
return cache[value + 128]
}
return ImpreciseFraction(value)
}
/**
* Returns pooled value if present, otherwise constructs new object
*/
fun valueOf(value: Long): ImpreciseFraction {
if (value in -128 .. 127) {
return cache[value.toInt()]
}
return ImpreciseFraction(value)
}
@JvmField val NaN = ImpreciseFraction(0, Double.NaN)
@JvmStatic

View File

@ -26,8 +26,7 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import ru.dbotthepony.mc.otm.*
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.menu.FormattingHelper
import ru.dbotthepony.mc.otm.registry.EMPDamageSource