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> { implementation(fg.deobf(create("mcjty.theoneprobe:theoneprobe:${mc_version_weak}-${the_one_probe_version}", closureOf<Any> {
(this as ExternalModuleDependency).isTransitive = false (this as ExternalModuleDependency).isTransitive = false
} as Closure<Any>))) } 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 { configurations {
@ -177,9 +180,9 @@ repositories {
} }
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so: // If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
//flatDir { flatDir {
// dir "libs" dir("libs")
//} }
} }
// Example configuration to allow publishing using the maven-publish plugin // 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=1.18.1
mc_version_weak=1.18 mc_version_weak=1.18
forge_gradle_version=5.1.27 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 jupiter_version=5.8.2
the_one_probe_version=5.0.1-5 the_one_probe_version=5.0.1-5

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability; package ru.dbotthepony.mc.otm.capability;
import mekanism.api.energy.IStrictEnergyHandler;
import net.minecraftforge.common.capabilities.*; import net.minecraftforge.common.capabilities.*;
import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability; import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; 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<IMatteryDrive> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<IStorageGraphNode> STORAGE_NODE = 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") @SuppressWarnings("unused")
public static void register(final RegisterCapabilitiesEvent event) { public static void register(final RegisterCapabilitiesEvent event) {
event.register(IMatteryEnergyStorage.class); 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.001"), // "otm.suffix.milli": "m%s",
new ImpreciseFraction("0.000001"), // "otm.suffix.micro": "μ%s", new ImpreciseFraction("0.000001"), // "otm.suffix.micro": "μ%s",
new ImpreciseFraction("0.000000001"), // "otm.suffix.nano": "n%s", new ImpreciseFraction("0.000000001"), // "otm.suffix.nano": "n%s",
new ImpreciseFraction("0.000000000001"), // "otm.suffix.pico": "p%s", //new ImpreciseFraction("0.000000000001"), // "otm.suffix.pico": "p%s",
new ImpreciseFraction("0.000000000000001"), // "otm.suffix.femto": "f%s", //new ImpreciseFraction("0.000000000000001"), // "otm.suffix.femto": "f%s",
new ImpreciseFraction("0.000000000000000001"), // "otm.suffix.atto": "a%s", //new ImpreciseFraction("0.000000000000000001"), // "otm.suffix.atto": "a%s",
new ImpreciseFraction("0.000000000000000000001"), // "otm.suffix.zepto": "z%s", //new ImpreciseFraction("0.000000000000000000001"), // "otm.suffix.zepto": "z%s",
new ImpreciseFraction("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s", //new ImpreciseFraction("0.000000000000000000000001"), // "otm.suffix.yocto": "y%s",
}; };
public static String formatDecimal(BigDecimal value, int decimals) { 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) 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 net.minecraftforge.items.CapabilityItemHandler
import ru.dbotthepony.mc.otm.block.BatteryBankBlock import ru.dbotthepony.mc.otm.block.BatteryBankBlock
import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage import ru.dbotthepony.mc.otm.capability.*
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.container.MatteryContainer import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ImpreciseFraction 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.menu.BatteryBankMenu
import ru.dbotthepony.mc.otm.orNull
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.set
import ru.dbotthepony.mc.otm.unaryMinus import ru.dbotthepony.mc.otm.unaryMinus
@ -86,30 +85,17 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i) val stack = container.getItem(i)
if (!stack.isEmpty) { if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent { stack.energy?.let {
if (it is IMatteryEnergyStorage) { val diff: ImpreciseFraction
val diff: ImpreciseFraction
if (mode) { if (mode) {
diff = it.receiveEnergyOuter(ImpreciseFraction.LONG_MAX_VALUE, true) diff = it.receiveEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
} else {
diff = it.extractEnergyOuter(ImpreciseFraction.LONG_MAX_VALUE, true)
}
distribution[i] = diff
summ += diff
} else { } else {
val diff: Int diff = it.extractEnergy(ImpreciseFraction.LONG_MAX_VALUE, true)
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]
} }
distribution[i] = diff
summ += distribution[i]
} }
} }
} }
@ -137,28 +123,16 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i) val stack = container.getItem(i)
if (!stack.isEmpty) { if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent { stack.energy?.let {
if (it is IMatteryEnergyStorage) { val diff: ImpreciseFraction
val diff: ImpreciseFraction
if (mode) { if (mode) {
diff = it.receiveEnergyOuter(howMuch * distList[i], simulate) diff = it.receiveEnergy(howMuch * distList[i], simulate)
} else {
diff = it.extractEnergyOuter(howMuch * distList[i], simulate)
}
summ += diff
} else { } else {
val diff: Int diff = it.extractEnergy(howMuch * distList[i], simulate)
if (mode) {
diff = it.receiveEnergy(howMuch * distList[i], simulate)
} else {
diff = it.extractEnergy(howMuch * distList[i], simulate)
}
summ += ImpreciseFraction(diff)
} }
summ += diff
} }
} }
} }
@ -193,12 +167,8 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i) val stack = container.getItem(i)
if (!stack.isEmpty) { if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent { stack.energy?.let {
if (it is IMatteryEnergyStorage) { result += it.energyStoredMattery
result += it.batteryLevel
} else {
result += it.energyStored
}
} }
} }
} }
@ -213,12 +183,8 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
val stack = container.getItem(i) val stack = container.getItem(i)
if (!stack.isEmpty) { if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent { stack.energy?.let {
if (it is IMatteryEnergyStorage) { result += it.maxEnergyStoredMattery
result += it.maxBatteryLevel
} else {
result += it.maxEnergyStored
}
} }
} }
} }
@ -315,6 +281,7 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
CapabilityEnergy.ENERGY, CapabilityEnergy.ENERGY,
-blockState.getValue(BlockMatteryRotatable.FACING) -blockState.getValue(BlockMatteryRotatable.FACING)
) { ) {
@Suppress("name_shadowing")
val level = this.level val level = this.level
if (level is ServerLevel) if (level is ServerLevel)
@ -326,24 +293,16 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
if (isBlockedByRedstone) if (isBlockedByRedstone)
return return
outputCapability.ifPresent { outputCapability.ifPresentK {
val (_, maxThroughput) = energy.getDistribution(false) val (_, maxThroughput) = energy.getDistribution(false)
if (maxThroughput.isZero) if (maxThroughput.isZero)
return@ifPresent return@ifPresentK
if (it is IMatteryEnergyStorage) { val diff = it.receiveEnergy(maxThroughput, false)
val diff = it.receiveEnergyOuter(maxThroughput, false)
if (!diff.isZero) { if (!diff.isZero) {
energy.extractEnergyInner(diff, false) energy.extractEnergyInner(diff, false)
}
} else {
val diff = it.receiveEnergy(maxThroughput, false)
if (diff != 0) {
energy.extractEnergyInner(diff, false)
}
} }
} }
} }

View File

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

View File

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

View File

@ -1,45 +1,119 @@
package ru.dbotthepony.mc.otm.capability 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 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.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.orNull
fun IEnergyStorage.receiveEnergy(amount: Fraction, simulate: Boolean): Int { fun IEnergyStorage.receiveEnergy(amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (amount.isZero()) if (this is IMatteryEnergyStorage)
return 0 return receiveEnergyOuter(amount, simulate)
if (amount > Fraction.INT_MAX_VALUE) if (!amount.isPositive)
return receiveEnergy(Int.MAX_VALUE, simulate) return ImpreciseFraction.ZERO
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 > ImpreciseFraction.INT_MAX_VALUE) 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 { fun IEnergyStorage.extractEnergy(amount: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (amount.isZero) if (this is IMatteryEnergyStorage)
return 0 return extractEnergyOuter(amount, simulate)
if (!amount.isPositive)
return ImpreciseFraction.ZERO
if (amount > ImpreciseFraction.INT_MAX_VALUE) 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 // IEnergyStorage for direct compat with Forge Energy
interface IMatteryEnergyStorage : IEnergyStorage { 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 fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
/** /**
* All or nothing * All or nothing
*
* @return energy extracted
*/ */
fun extractEnergyOuterExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { fun extractEnergyOuterExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val extracted = extractEnergyOuter(howMuch, true) val extracted = extractEnergyOuter(howMuch, true)
@ -32,11 +36,15 @@ interface IMatteryEnergyStorage : IEnergyStorage {
* for internal needs, e.g. for work * for internal needs, e.g. for work
* CAN also be used by something that does evil * CAN also be used by something that does evil
* e.g. sucking out energy anomaly should use this * e.g. sucking out energy anomaly should use this
*
* @return energy extracted
*/ */
fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
/** /**
* All or nothing * All or nothing
*
* @return energy extracted
*/ */
fun extractEnergyInnerExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { fun extractEnergyInnerExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val extracted = extractEnergyInner(howMuch, true) val extracted = extractEnergyInner(howMuch, true)
@ -54,6 +62,8 @@ interface IMatteryEnergyStorage : IEnergyStorage {
/** /**
* For energy receiving from outside, e.g. cables * For energy receiving from outside, e.g. cables
*
* @return energy accepted
*/ */
fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
@ -73,11 +83,15 @@ interface IMatteryEnergyStorage : IEnergyStorage {
/** /**
* For energy receiving from inside, e.g. generator generates power * For energy receiving from inside, e.g. generator generates power
*
* @return energy accepted
*/ */
fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction
/** /**
* All or nothing * All or nothing
*
* @return energy accepted
*/ */
fun receiveEnergyInnerExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { fun receiveEnergyInnerExact(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
val extracted = receiveEnergyInner(howMuch, true) 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_MAX_VALUE = ImpreciseFraction(BI_DOUBLE_MAX)
@JvmField val DOUBLE_MIN_VALUE = ImpreciseFraction(BI_DOUBLE_MIN) @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) @JvmField val NaN = ImpreciseFraction(0, Double.NaN)
@JvmStatic @JvmStatic

View File

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