Remove Mekanism compat since it will not be updated to newer versions

This commit is contained in:
DBotThePony 2023-10-26 18:44:03 +07:00
parent 15023b6599
commit 171e16a7c4
Signed by: DBot
GPG Key ID: DCC23B5715498507
13 changed files with 2 additions and 856 deletions

View File

@ -171,8 +171,6 @@ dependencies {
// runtimeOnly(fg.deobf("curse.maven:worldedit-225608:${worldedit_fileid}"))
// runtimeOnly(fg.deobf("at.ridgo8.moreoverlays:MoreOverlays-updated:${more_overlays_version}"))
compileOnly(fg.deobf("mekanism:Mekanism:1.20.1-10.3.9.homebaked:all"))
// runtimeOnly(fg.deobf("curse.maven:cyclops-core-232758:4392602"))
// runtimeOnly(fg.deobf("curse.maven:integrated-dynamics-236307:4391535"))
// runtimeOnly(fg.deobf("curse.maven:integrated-crafting-287357:4391487"))

View File

@ -38,8 +38,6 @@ import ru.dbotthepony.mc.otm.client.render.blockentity.BatteryBankRenderer;
import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer;
import ru.dbotthepony.mc.otm.compat.adastra.AdAstraCompatKt;
import ru.dbotthepony.mc.otm.compat.curios.CuriosCompatKt;
import ru.dbotthepony.mc.otm.compat.mekanism.MekanismHooks;
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
import ru.dbotthepony.mc.otm.config.AndroidConfig;
import ru.dbotthepony.mc.otm.config.ClientConfig;
import ru.dbotthepony.mc.otm.config.ExopackConfig;
@ -208,10 +206,6 @@ public final class OverdriveThatMatters {
WeaponNetworkChannel.INSTANCE.register();
GenericNetworkChannel.INSTANCE.register();
if (ModList.get().isLoaded("mekanism")) {
EVENT_BUS.addGenericListener(BlockEntity.class, EventPriority.NORMAL, QIOKt::attachCapabilities);
}
if (ModList.get().isLoaded(CuriosApi.MODID)) {
EVENT_BUS.addListener(EventPriority.NORMAL, CuriosCompatKt::onCuriosSlotModifiersUpdated);
}
@ -249,10 +243,6 @@ public final class OverdriveThatMatters {
EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::clientDisconnect);
if (ModList.get().isLoaded("mekanism")) {
EVENT_BUS.addListener(EventPriority.NORMAL, MekanismHooks::tooltipEvent);
}
EVENT_BUS.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::onRenderGuiEvent);
EVENT_BUS.addListener(EventPriority.NORMAL, AndroidMenuKeyMapping.INSTANCE::onMouseClick);

View File

@ -1,6 +1,5 @@
package ru.dbotthepony.mc.otm.capability;
import mekanism.api.energy.IStrictEnergyHandler;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityToken;
@ -51,10 +50,6 @@ public class MatteryCapability {
@NotNull
public static final Capability<StorageNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<IStrictEnergyHandler> MEKANISM_ENERGY = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
public static final Capability<ICuriosItemHandler> CURIOS_INVENTORY = CapabilityManager.get(new CapabilityToken<>() {});

View File

@ -7,7 +7,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
import mekanism.api.energy.IStrictEnergyHandler
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.SectionPos
@ -41,13 +40,9 @@ import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
import ru.dbotthepony.mc.otm.compat.mekanism.Mekanism2MatteryEnergyWrapper
import ru.dbotthepony.mc.otm.core.ISubscriptable
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.BlockRotation
import ru.dbotthepony.mc.otm.core.math.RelativeSide
@ -67,7 +62,6 @@ import java.util.function.Consumer
import java.util.function.Predicate
import java.util.function.Supplier
import java.util.stream.Stream
import kotlin.NoSuchElementException
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
@ -148,19 +142,11 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
protected fun exposeEnergyGlobally(value: IMatteryEnergyStorage, predicate: Predicate<RelativeSide> = Predicate { true }) {
exposeGlobally(ForgeCapabilities.ENERGY, value, predicate)
exposeGlobally(MatteryCapability.ENERGY, value, predicate)
if (isMekanismLoaded) {
exposeGlobally(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value), predicate)
}
}
protected fun exposeEnergySideless(value: IMatteryEnergyStorage) {
exposeSideless(ForgeCapabilities.ENERGY, value)
exposeSideless(MatteryCapability.ENERGY, value)
if (isMekanismLoaded) {
exposeSideless(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value))
}
}
protected fun exposeEnergy(side: RelativeSide, value: IMatteryEnergyStorage): ImmutableList<Side.Cap<*>> {
@ -169,10 +155,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
accept(thisSide.Cap(ForgeCapabilities.ENERGY, value))
accept(thisSide.Cap(MatteryCapability.ENERGY, value))
if (isMekanismLoaded) {
accept(thisSide.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(value)))
}
}
}
@ -227,47 +209,7 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
}
fun trackEnergy(): SideListener<IEnergyStorage> {
return object : SideListener<IEnergyStorage> {
private val regular = track(ForgeCapabilities.ENERGY)
private val mekanism: SubRef<IStrictEnergyHandler>?
private var actualMekanism: LazyOptional<IEnergyStorage>? = null
private val listeners = ISubscriptable.Impl<LazyOptional<IEnergyStorage>>()
override fun addListener(listener: Consumer<LazyOptional<IEnergyStorage>>): ISubscriptable.L {
val l = listeners.addListener(listener)
listener.accept(get())
return l
}
init {
regular.addListener { listeners.accept(it) }
if (isMekanismLoaded) {
mekanism = track(MatteryCapability.MEKANISM_ENERGY) as SubRef<IStrictEnergyHandler>
mekanism.addListener {
actualMekanism?.invalidate()
if (it.isPresent) {
actualMekanism = LazyOptional.of { Mekanism2MatteryEnergyWrapper(it.orElseThrow { NoSuchElementException("No mekanism energy was present, and tracker did not call back in time") }) }
} else {
actualMekanism = null
}
listeners.accept(get())
}
} else {
mekanism = null
}
}
override fun get(): LazyOptional<IEnergyStorage> {
val get = regular.get()
get.ifPresentK { if (it is IMatteryEnergyStorage) return get }
return actualMekanism ?: get
}
}
return track(ForgeCapabilities.ENERGY)
}
fun updateTracked() {

View File

@ -14,7 +14,6 @@ import ru.dbotthepony.mc.otm.block.tech.EnergyCounterBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.core.math.BlockRotation
import ru.dbotthepony.mc.otm.core.math.Decimal
@ -280,11 +279,6 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
back.Cap(ForgeCapabilities.ENERGY, energyOutput)
back.Cap(MatteryCapability.ENERGY, energyOutput)
if (isMekanismLoaded) {
front.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(energyInput))
back.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(energyOutput))
}
}
override fun tick() {

View File

@ -2,17 +2,14 @@ package ru.dbotthepony.mc.otm.capability
import com.google.common.collect.Streams
import net.minecraft.ChatFormatting
import net.minecraft.core.Direction
import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.IEnergyStorage
import net.minecraftforge.fluids.FluidStack
import net.minecraftforge.fluids.capability.IFluidHandler
import net.minecraftforge.fml.ModList
import net.minecraftforge.items.IItemHandler
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
@ -23,8 +20,6 @@ import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded
import ru.dbotthepony.mc.otm.compat.curios.curiosAwareStream
import ru.dbotthepony.mc.otm.compat.curios.curiosStream
import ru.dbotthepony.mc.otm.compat.curios.isCuriosLoaded
import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided
import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy
import ru.dbotthepony.mc.otm.container.util.awareStream
import ru.dbotthepony.mc.otm.container.util.iterator
import ru.dbotthepony.mc.otm.core.collect.AwareItemStack
@ -130,8 +125,6 @@ val IEnergyStorage.chargeRatio: Float get() {
return energyStored.toFloat() / maxEnergyStored.toFloat()
}
val isMekanismLoaded by lazy { ModList.get().isLoaded("mekanism") }
/**
* Shortcut for getting [IEnergyStorage], including wrappers for it
*/
@ -142,14 +135,6 @@ val ICapabilityProvider.energy: IEnergyStorage? get() {
return mattery.orNull()
}
if (isMekanismLoaded) {
val mekanismEnergy = mekanismEnergy
if (mekanismEnergy != null) {
return mekanismEnergy
}
}
return getCapability(ForgeCapabilities.ENERGY).orNull()
}
@ -157,63 +142,7 @@ val ICapabilityProvider.energy: IEnergyStorage? get() {
* Shortcut for getting sideless [IMatteryEnergyStorage], including wrappers for it
*/
val ICapabilityProvider.matteryEnergy: IMatteryEnergyStorage? get() {
val mattery = getCapability(MatteryCapability.ENERGY)
if (mattery.isPresent) {
return mattery.orNull()
}
if (isMekanismLoaded) {
val mekanismEnergy = mekanismEnergy
if (mekanismEnergy != null) {
return mekanismEnergy
}
}
return null
}
/**
* Shortcut for getting [LazyOptional] with [IEnergyStorage], including wrappers for it
*/
fun ICapabilityProvider.getEnergySided(side: Direction? = null): LazyOptional<out IEnergyStorage> {
val mattery = getCapability(MatteryCapability.ENERGY, side)
if (mattery.isPresent) {
return mattery
}
if (isMekanismLoaded) {
val mekanismEnergy = getMekanismEnergySided(side)
if (mekanismEnergy.isPresent) {
return mekanismEnergy
}
}
return getCapability(ForgeCapabilities.ENERGY, side)
}
/**
* Shortcut for getting [LazyOptional] with [IMatteryEnergyStorage], including wrappers for it
*/
fun ICapabilityProvider.getMatteryEnergySided(side: Direction? = null): LazyOptional<out IMatteryEnergyStorage> {
val mattery = getCapability(MatteryCapability.ENERGY, side)
if (mattery.isPresent) {
return mattery
}
if (isMekanismLoaded) {
val mekanismEnergy = getMekanismEnergySided(side)
if (mekanismEnergy.isPresent) {
return mekanismEnergy
}
}
return LazyOptional.empty()
return getCapability(MatteryCapability.ENERGY).orNull()
}
fun Player.items(includeCosmetics: Boolean = true): Iterator<ItemStack> {

View File

@ -12,8 +12,6 @@ import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set
@ -21,13 +19,10 @@ import ru.dbotthepony.mc.otm.core.tagNotNull
abstract class ItemEnergyStorageImpl(val itemStack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider, IEnergyStorageImpl {
private val resolver = LazyOptional.of { this }
private val resolverMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(this) } else null
override fun <T : Any> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap === ForgeCapabilities.ENERGY || cap === MatteryCapability.ENERGY) {
return resolver.cast()
} else if (cap === MatteryCapability.MEKANISM_ENERGY) {
return resolverMekanism?.cast() ?: LazyOptional.empty()
}
return LazyOptional.empty()

View File

@ -1,32 +0,0 @@
package ru.dbotthepony.mc.otm.compat.mekanism
import mekanism.api.math.FloatingLong
import ru.dbotthepony.mc.otm.core.math.Decimal
import java.math.BigInteger
private val LONG_OVERFLOW = (BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.TWO) * Decimal.PRECISION_POW_BI
private val LONG_OVERFLOW1 = BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.valueOf(Long.MAX_VALUE) + BigInteger.ONE
fun Decimal.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(), (fractionalFloat * 10_000.0).toInt().toShort())
}
fun FloatingLong.toDecimal(): Decimal {
var conv = BigInteger.valueOf(value) * Decimal.PRECISION_POW_BI + BigInteger.valueOf((decimal.toDouble() / 10_000.0 * Decimal.PRECISION_DOUBLE).toLong())
// Overflow
if (value < 0L) {
conv += LONG_OVERFLOW
}
return Decimal.raw(conv)
}

View File

@ -1,49 +0,0 @@
package ru.dbotthepony.mc.otm.compat.mekanism
import mekanism.api.Action
import mekanism.api.AutomationType
import mekanism.common.capabilities.energy.MachineEnergyContainer
import mekanism.common.registries.MekanismItems
import mekanism.common.tile.TileEntityChargepad
import net.minecraft.ChatFormatting
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraftforge.event.entity.player.ItemTooltipEvent
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
object MekanismHooks {
@JvmStatic
fun chargeAndroidFromPadHook(container: MachineEnergyContainer<TileEntityChargepad>, entity: LivingEntity) {
if (entity !is Player) return
if (entity.matteryPlayer?.isAndroid == true) {
val androidEnergy = entity.matteryPlayer!!.androidEnergy
val expectedAmount = container.energyPerTick
val remaining = (androidEnergy.receiveEnergy(expectedAmount.toDecimal() * Mekanism2MatteryEnergyWrapper.mekanism2MtJ, true) * Mattery2MekanismEnergyWrapper.mtj2Mekanism).toFloatingLong()
if (remaining.smallerThan(expectedAmount)) {
val extracted = container.extract(expectedAmount.subtract(remaining), Action.EXECUTE, AutomationType.INTERNAL)
if (!extracted.isZero) {
androidEnergy.receiveEnergy(extracted.toDecimal() * Mekanism2MatteryEnergyWrapper.mekanism2MtJ, false)
}
}
}
}
private val BLACKHOLE_IMMUNITY = TranslatableComponent("otm.item.blackhole_immunity").withStyle(ChatFormatting.DARK_GRAY)
@JvmStatic
fun tooltipEvent(event: ItemTooltipEvent) {
if (!isMekanismLoaded) {
throw IllegalStateException("Mekanism is not loaded!")
}
if (event.itemStack.`is`(MekanismItems.MODULE_GRAVITATIONAL_MODULATING.get())) {
event.toolTip.add(BLACKHOLE_IMMUNITY)
}
}
}

View File

@ -1,236 +0,0 @@
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.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.IEnergyStorage
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.orNull
import java.lang.ref.WeakReference
import java.util.WeakHashMap
private val LOGGER = LogManager.getLogger()
private class LazyCache<O, T>(private val provider: () -> O, private val computer: (O) -> T) : Lazy<T> {
private var cache: T? = null
private var observed: O? = null
override fun isInitialized(): Boolean {
return cache != null
}
override val value: T get() {
if (cache == null || observed == null || observed != provider.invoke()) {
observed = provider.invoke()
cache = computer.invoke(observed ?: throw ConcurrentModificationException())
}
return cache ?: throw ConcurrentModificationException()
}
}
private class DoubleLazy<T>(onion: () -> Lazy<T>) : Lazy<T> {
private val onion = lazy(onion)
override val value: T
get() = onion.value.value
override fun isInitialized(): Boolean {
return onion.isInitialized() && onion.value.isInitialized()
}
}
class Mekanism2MatteryEnergyWrapper(private val power: IStrictEnergyHandler, private val forgePower: IEnergyStorage? = null) : IMatteryEnergyStorage {
companion object {
val mekanism2MtJ by DoubleLazy lazy@{
try {
val conf = MekanismConfig.general
return@lazy LazyCache(conf.forgeConversionRate::get) { Decimal.ONE / it.toDecimal() }
} catch(err: Throwable) {
LOGGER.error("Unable to get Forge Energy to Mekanism Joules's conversion rate! Expect issues", err)
}
return@lazy lazyOf(Decimal.ONE)
}
}
override fun extractEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
return extractEnergy(howMuch, simulate)
}
override fun receiveEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
return receiveEnergy(howMuch, simulate)
}
override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
val action = when (simulate) {
true -> Action.SIMULATE
false -> Action.EXECUTE
}
return power.extractEnergy((howMuch * Mattery2MekanismEnergyWrapper.mtj2Mekanism).toFloatingLong(), action).toDecimal() * mekanism2MtJ
}
override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
val action = when (simulate) {
true -> Action.SIMULATE
false -> Action.EXECUTE
}
return howMuch - power.insertEnergy((howMuch * Mattery2MekanismEnergyWrapper.mtj2Mekanism).toFloatingLong(), action).toDecimal() * mekanism2MtJ
}
override val canSetBatteryLevel: Boolean
get() = power.energyContainerCount == 1
override var batteryLevel: Decimal
get() {
var sum = Decimal.ZERO
for (i in 0 until power.energyContainerCount) {
sum += power.getEnergy(i).toDecimal()
}
return sum * mekanism2MtJ
}
set(value) {
if (power.energyContainerCount != 1)
throw UnsupportedOperationException("Can set power only when we have 1 energy container, ${power.energyContainerCount} present")
power.setEnergy(0, (value * Mattery2MekanismEnergyWrapper.mtj2Mekanism).toFloatingLong())
}
override val maxBatteryLevel: Decimal
get() {
var sum = Decimal.ZERO
for (i in 0 until power.energyContainerCount) {
sum += power.getMaxEnergy(i).toDecimal()
}
return sum * mekanism2MtJ
}
override val energyFlow: FlowDirection
get() = FlowDirection.of(output = forgePower?.canExtract() ?: power.extractEnergy(FloatingLong.MAX_VALUE, Action.SIMULATE).greaterThan(FloatingLong.ZERO), input = forgePower?.canReceive() ?: power.insertEnergy(FloatingLong.MAX_VALUE, Action.SIMULATE).greaterThan(FloatingLong.ZERO))
}
class Mattery2MekanismEnergyWrapper(private val power: IMatteryEnergyStorage) : IStrictEnergyHandler {
companion object {
val mtj2Mekanism by DoubleLazy lazy@{
try {
val conf = MekanismConfig.general
return@lazy LazyCache(conf.forgeConversionRate::get) { it.toDecimal() }
} catch(err: Throwable) {
LOGGER.error("Unable to get Mekanism Joules's to Forge Energy conversion rate! Expect issues", err)
}
return@lazy lazyOf(Decimal.ONE)
}
}
override fun getEnergyContainerCount(): Int = 1
override fun getEnergy(container: Int): FloatingLong {
if (container != 0) {
return FloatingLong.ZERO
}
return (power.batteryLevel * mtj2Mekanism).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 * mtj2Mekanism).toFloatingLong()
}
override fun getNeededEnergy(container: Int): FloatingLong {
if (container != 0) {
return FloatingLong.ZERO
}
return (power.missingPower * mtj2Mekanism).toFloatingLong()
}
override fun insertEnergy(container: Int, howMuch: FloatingLong, action: Action): FloatingLong {
val copy = howMuch.copy()
return copy.minusEqual((power.receiveEnergyChecked(howMuch.toDecimal() * Mekanism2MatteryEnergyWrapper.mekanism2MtJ, action.simulate()) * mtj2Mekanism).toFloatingLong())
}
override fun extractEnergy(container: Int, howMuch: FloatingLong, action: Action): FloatingLong {
return (power.extractEnergyChecked(howMuch.toDecimal() * Mekanism2MatteryEnergyWrapper.mekanism2MtJ, action.simulate()) * mtj2Mekanism).toFloatingLong()
}
}
val ICapabilityProvider.mekanismEnergy: IMatteryEnergyStorage? get() {
if (!isMekanismLoaded) {
return null
}
val capability = getCapability(MatteryCapability.MEKANISM_ENERGY)
if (!capability.isPresent) {
return null
}
return Mekanism2MatteryEnergyWrapper(capability.orElseThrow(::IllegalStateException), getCapability(ForgeCapabilities.ENERGY).orNull())
}
private val lazyCache by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<Mekanism2MatteryEnergyWrapper>>>() }
private val lazyCacheDown by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<Mekanism2MatteryEnergyWrapper>>>() }
private val lazyCacheUp by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<Mekanism2MatteryEnergyWrapper>>>() }
private val lazyCacheSouth by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<Mekanism2MatteryEnergyWrapper>>>() }
private val lazyCacheNorth by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<Mekanism2MatteryEnergyWrapper>>>() }
private val lazyCacheEast by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<Mekanism2MatteryEnergyWrapper>>>() }
private val lazyCacheWest by lazy { WeakHashMap<LazyOptional<IStrictEnergyHandler>, WeakReference<LazyOptional<Mekanism2MatteryEnergyWrapper>>>() }
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 forgeEnergy = getCapability(ForgeCapabilities.ENERGY, side)
val resolver = LazyOptional.of {
Mekanism2MatteryEnergyWrapper(lazyOptional.orElseThrow(::IllegalStateException), forgeEnergy.orNull())
}
val ref = WeakReference(resolver)
cache[lazyOptional] = ref
lazyOptional.addListener {
ref.get()?.invalidate()
}
return resolver.cast()
}

View File

@ -1,301 +0,0 @@
package ru.dbotthepony.mc.otm.compat.mekanism
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import mekanism.common.content.qio.QIOFrequency
import mekanism.common.content.qio.QIOFrequency.QIOItemTypeData
import mekanism.common.lib.frequency.Frequency
import mekanism.common.lib.inventory.HashedItem
import mekanism.common.tile.qio.TileEntityQIODriveArray
import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.event.AttachCapabilitiesEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import ru.dbotthepony.mc.otm.core.util.ITickable
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.onceServer
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.core.math.isPositive
import ru.dbotthepony.mc.otm.core.util.LOHolder
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
import ru.dbotthepony.mc.otm.storage.*
import java.math.BigInteger
import java.util.UUID
import java.util.stream.Stream
private val QIO_LOCATION = ResourceLocation(OverdriveThatMatters.MOD_ID, "item_storage")
private class QIOTuple(
val mekanismItem: HashedItem,
override var stack: ItemStorageStack,
override val id: UUID,
var mark: Long
) : IStorageTuple.IMutable<ItemStorageStack>
private class QIOFrequencyAccess(val parent: QIOFrequency) : IStorageComponent<ItemStorageStack> {
private var mark = 0L
override val storageType: StorageStack.Type<ItemStorageStack>
get() = StorageStack.ITEMS
private val index = HashMap<UUID, QIOTuple>()
private val tracked = HashMap<HashedItem, QIOTuple>()
private val listeners = ArrayList<IStorageEventConsumer<ItemStorageStack>>()
override fun get(id: UUID): ItemStorageStack {
return index[id]?.stack ?: ItemStorageStack.EMPTY
}
override val stacks: Stream<IStorageTuple<ItemStorageStack>> get() {
return ArrayList<IStorageTuple<ItemStorageStack>>(index.size).also { it.addAll(index.values) }.stream()
}
override fun insertStack(stack: ItemStorageStack, simulate: Boolean): ItemStorageStack {
// Because there is no simulate method on QIO array, we have to simulate it by ourselves.
val hash = HashedItem.create(stack.toItemStack())
if (!simulate) {
//val used = TransporterManager.getToUse(stack.stack, parent.addItem(stack.stack))
val used = parent.addItem(stack.toItemStack())
if (used.count == stack.count.toInt()) {
return stack
}
scan(hash)
return ItemStorageStack(used)
}
if (parent.totalItemCount >= parent.totalItemCountCapacity) {
return stack
}
if (!parent.itemDataMap.containsKey(hash) && parent.totalItemTypeCapacity <= parent.itemDataMap.size) {
return stack
}
return stack.copy((parent.totalItemCountCapacity - parent.totalItemCount).toBigInteger().coerceAtMost(stack.count))
}
override fun extractStack(id: UUID, amount: BigInteger, simulate: Boolean): ItemStorageStack {
// Because there is no simulate method on QIO array, we have to simulate it by ourselves.
// ASSUMPTION: We can ALWAYS remove items from QIO grid.
if (!amount.isPositive)
return ItemStorageStack.EMPTY
var local = index[id] ?: return ItemStorageStack.EMPTY
scan(local.mekanismItem)
local = index[id] ?: return ItemStorageStack.EMPTY // unexpected...
if (simulate) {
return local.stack.copy(local.stack.count.coerceAtMost(amount))
}
val removed = parent.removeByType(local.mekanismItem, amount.toInt())
if (removed.isEmpty) {
return ItemStorageStack.EMPTY
}
val copy = ItemStorageStack(removed)
if (local.stack.count > copy.count) {
// expecting stack to be still present in QIO storage grid
scan(local.mekanismItem)
} else {
// expecting stack to be removed from QIO storage grid
check(parent.itemDataMap[local.mekanismItem] == null) {
"${local.mekanismItem} is expected to be empty in $parent, got ${parent.itemDataMap[local.mekanismItem]}"
}
for (listener in listeners) {
listener.onStackRemoved(local)
}
index.remove(local.id)
tracked.remove(local.mekanismItem)
}
return copy
}
override fun addListener(listener: IStorageEventConsumer<ItemStorageStack>): Boolean {
if (!listeners.contains(listener)) {
listeners.add(listener)
return true
}
return false
}
override fun removeListener(listener: IStorageEventConsumer<ItemStorageStack>): Boolean {
return listeners.remove(listener)
}
private fun scan(at: HashedItem, value: QIOItemTypeData = parent.itemDataMap[at] ?: throw IllegalArgumentException("$parent does not have item $at (${at.internalStack})")) {
val local = tracked[at]
if (local != null) {
local.mark = mark
if (local.stack.count.toLong() != value.count) {
local.stack = local.stack.copy(value.count.toBigInteger())
for (listener in listeners) {
listener.onStackChanged(local)
}
}
} else {
val tuple = QIOTuple(at, ItemStorageStack(at.internalStack, value.count.toBigInteger()), UUID.randomUUID(), mark)
index[tuple.id] = tuple
for (listener in listeners) {
listener.onStackAdded(tuple, this)
}
tracked[at] = tuple
}
}
fun scan() {
mark++
for ((key, value) in parent.itemDataMap) {
scan(key, value)
}
var changed: ArrayList<HashedItem>? = null
for ((key, value) in tracked) {
if (value.mark != mark) {
if (changed == null) {
changed = ArrayList()
}
changed.add(key)
}
}
// sweep
if (changed != null) {
for (key in changed) {
val tuple = tracked.remove(key)!!
for (listener in listeners) {
listener.onStackRemoved(tuple)
}
index.remove(tuple.id)
tracked.remove(tuple.mekanismItem)
}
}
}
}
private class QIOStorage(private val tile: TileEntityQIODriveArray) : ICapabilityProvider {
private var lastFrequency: QIOFrequency? = null
private var frequencyAccess: QIOFrequencyAccess? = null
private var wasAttached = false
val cell: StorageNode = object : StorageNode(), ITickable {
init {
manualAttaching = true
}
override fun tick() {
if (tile.isRemoved) {
isValid = false
return
}
val frequency = tile.qioFrequency
if (frequency != lastFrequency) {
if (wasAttached) {
wasAttached = false
val lastFrequency = lastFrequency ?: throw IllegalStateException("lastFrequency is null")
graph.userData.remove(key(lastFrequency))
}
frequencyAccess?.let(this::removeStorageComponent)
lastFrequency = frequency
if (frequency != null) {
frequencyAccess = QIOFrequencyAccess(frequency).also(this::addStorageComponent)
}
}
val frequencyAccess = frequencyAccess ?: return
frequencyAccess.scan()
val key = key(frequencyAccess.parent)
if (!graph.userData.containsKey(key)) {
graph.userData[key] = true
wasAttached = true
graph.add(frequencyAccess)
}
}
override fun removeComponents(from: StorageGraph) {
super.removeComponents(from)
if (wasAttached) {
val lastFrequency = lastFrequency ?: throw IllegalStateException("lastFrequency is null")
from.userData.remove(key(lastFrequency))
wasAttached = false
}
}
override fun invalidate() {
super.invalidate()
holder.invalidate()
}
override fun revive() {
super.revive()
holder.revive()
}
}
private val holder = LOHolder(cell)
override fun <T : Any> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap === MatteryCapability.STORAGE_NODE)
return holder.get()
return LazyOptional.empty()
}
companion object {
private fun key(frequency: Frequency) = keyMap.computeIfAbsent(frequency.name to frequency.owner, Object2ObjectFunction { UUID.randomUUID() })
private val keyMap = Object2ObjectArrayMap<Pair<String, UUID?>, UUID>()
}
}
@SubscribeEvent
@Suppress("unused")
fun attachCapabilities(event: AttachCapabilitiesEvent<BlockEntity>) {
if (!isMekanismLoaded) {
throw IllegalStateException("This event should never be called if Mekanism is not loaded.")
}
if (event.`object` is TileEntityQIODriveArray) {
val capability = QIOStorage(event.`object` as TileEntityQIODriveArray)
event.addCapability(QIO_LOCATION, capability)
onceServer {
if (!event.`object`.isRemoved) {
capability.cell.discover(event.`object`, MatteryCapability.STORAGE_NODE)
}
}
}
}

View File

@ -29,9 +29,7 @@ import ru.dbotthepony.mc.otm.capability.trackedItems
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.getBarColor
import ru.dbotthepony.mc.otm.capability.energy.getBarWidth
import ru.dbotthepony.mc.otm.capability.isMekanismLoaded
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
import ru.dbotthepony.mc.otm.config.EnergyBalanceValues
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.collect.filter
@ -160,7 +158,6 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
private inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
private val resolver = LazyOptional.of { this }
private val resolverMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(this) } else null
override val energyFlow: FlowDirection
get() = FlowDirection.BI_DIRECTIONAL
@ -181,8 +178,6 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
override fun <T : Any?> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (cap == ForgeCapabilities.ENERGY || cap == MatteryCapability.ENERGY) {
return resolver.cast()
} else if (cap == MatteryCapability.MEKANISM_ENERGY) {
return resolverMekanism?.cast() ?: LazyOptional.empty()
}
return LazyOptional.empty()

View File

@ -728,80 +728,6 @@ function initializeCoreMod() {
}
}
return node
}
},
'Mekanism Chargepad Android Charge': {
'target': {
'type': 'METHOD',
'class': 'mekanism.common.tile.TileEntityChargepad',
'methodName': 'onUpdateServer',
'methodDesc': '()V'
},
'transformer': function(node) {
var skipLabel = new Label()
var skipLabelNode = new LabelNode(skipLabel)
var labelIteratorEndNode
for (i = 0; i < node.instructions.size(); i++) {
var insn = node.instructions.get(i)
if (insn && insn.getOpcode() == opcodesRemapped.getfield && insn.name == 'CuriosLoaded') {
var nextInsn = node.instructions.get(i + 1) // IFEQ
labelIteratorEndNode = nextInsn.label
break
}
}
if (!labelIteratorEndNode) return node
for (i = 0; i < node.instructions.size(); i++) {
var insn = node.instructions.get(i)
if (insn && insn.getType() == AbstractInsnNode.LABEL) {
if (insn == labelIteratorEndNode) {
putInstructions(node, insn, [
new VarInsnNode(opcodesRemapped.aload, 0),
new FieldInsnNode(
opcodesRemapped.getfield,
'mekanism/common/tile/TileEntityChargepad',
'energyContainer',
'Lmekanism/common/capabilities/energy/MachineEnergyContainer;'
),
new VarInsnNode(opcodesRemapped.aload, 4),
new MethodInsnNode(
opcodesRemapped.invokestatic,
'ru/dbotthepony/mc/otm/compat/mekanism/MekanismHooks',
'chargeAndroidFromPadHook',
'(Lmekanism/common/capabilities/energy/MachineEnergyContainer;Lnet/minecraft/world/entity/LivingEntity;)V'
),
skipLabelNode
])
break
}
}
}
for (i = 0; i < node.instructions.size(); i++) {
var insn = node.instructions.get(i)
if (insn && insn.getOpcode() == opcodesRemapped.invokevirtual && insn.name == 'chargeHandler' && insn.desc == '(Ljava/util/Optional;)Z') {
var nextInsn = node.instructions.get(i + 1) // curios call is POP, pre-curios check call is IFNE; both need to redirect to loop skip label
if (nextInsn && (nextInsn.getOpcode() == opcodesRemapped.pop || nextInsn.getOpcode() == opcodesRemapped.ifne && nextInsn.label == labelIteratorEndNode)) {
node.instructions.set(nextInsn, new JumpInsnNode(opcodesRemapped.ifne, skipLabelNode))
continue
}
}
}
return node
}
}