diff --git a/build.gradle.kts b/build.gradle.kts index 39c93d46b..52840439b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -96,6 +96,9 @@ dependencies { implementation(fg.deobf(create("mcjty.theoneprobe:theoneprobe:${mc_version_weak}-${the_one_probe_version}", closureOf { (this as ExternalModuleDependency).isTransitive = false } as Closure))) + + //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 diff --git a/gradle.properties b/gradle.properties index a71299cfe..a3d90e029 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java index 4cd6361cc..8643c35f8 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java @@ -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 DRIVE = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {}); + @SuppressWarnings("unused") public static void register(final RegisterCapabilitiesEvent event) { event.register(IMatteryEnergyStorage.class); diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java b/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java index ccc543bd4..1a1c51d4b 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java @@ -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) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt index 979409d1b..1b8758d0d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt @@ -86,7 +86,3 @@ inline fun LazyOptional.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() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt index df21e24d6..88507ae7c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BatteryBankBlockEntity.kt @@ -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) } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt index 6b3cbfb90..fe4c3b907 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/ChemicalGeneratorBlockEntity.kt @@ -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 } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt index c3c4d8ac4..d38702d3d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/EnergyCounterBlockEntity.kt @@ -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 { energyInput } private var resolverOutput = LazyOptional.of { 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 { 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() } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt index 5301e7bc0..3e8f09d67 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt @@ -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 { + 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 { + if (isMekanismLoaded) { + val mekanismEnergy = getMekanismEnergySided(side) + + if (mekanismEnergy.isPresent) { + return mekanismEnergy + } + } + + return getCapability(MatteryCapability.ENERGY, side) +} + +val LivingEntity.android get() = getCapability(MatteryCapability.ANDROID).orNull() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.kt index fb6635750..a7e062541 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.kt @@ -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) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Conversions.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Conversions.kt new file mode 100644 index 000000000..8e7bc3d51 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Conversions.kt @@ -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) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Power.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Power.kt new file mode 100644 index 000000000..23efaa924 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/compat/mekanism/Power.kt @@ -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, WeakReference>>() } +private val lazyCacheDown by lazy { WeakHashMap, WeakReference>>() } +private val lazyCacheUp by lazy { WeakHashMap, WeakReference>>() } +private val lazyCacheSouth by lazy { WeakHashMap, WeakReference>>() } +private val lazyCacheNorth by lazy { WeakHashMap, WeakReference>>() } +private val lazyCacheEast by lazy { WeakHashMap, WeakReference>>() } +private val lazyCacheWest by lazy { WeakHashMap, WeakReference>>() } + +fun ICapabilityProvider.getMekanismEnergySided(side: Direction? = null): LazyOptional { + 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() +} + diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/ImpreciseFraction.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/ImpreciseFraction.kt index b5457904c..c5e27a97d 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/ImpreciseFraction.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/ImpreciseFraction.kt @@ -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 diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt index 9fb4c0b5c..5a6c767c4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/EnergySwordItem.kt @@ -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