From d8648d7088377f07c428878d0be64f229f8c3322 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sat, 18 Feb 2023 09:59:09 +0700 Subject: [PATCH] Capability subscriptions embedded into MatteryBlockEntity.Side --- .../dbotthepony/mc/otm/block/MatteryBlock.kt | 7 + .../mc/otm/block/entity/MatteryBlockEntity.kt | 159 ++++++++- .../entity/blackhole/BlackHoleBlockEntity.kt | 4 +- .../entity/matter/MatterBottlerBlockEntity.kt | 6 +- .../matter/MatterCapacitorBankBlockEntity.kt | 15 +- .../matter/MatterDecomposerBlockEntity.kt | 6 +- .../entity/matter/MatterPanelBlockEntity.kt | 9 +- .../matter/MatterRecyclerBlockEntity.kt | 6 +- .../matter/MatterReplicatorBlockEntity.kt | 7 +- .../entity/matter/MatterScannerBlockEntity.kt | 6 +- .../matter/PatternStorageBlockEntity.kt | 14 +- .../entity/storage/DriveRackBlockEntity.kt | 15 +- .../entity/storage/ItemMonitorBlockEntity.kt | 11 +- .../entity/storage/StorageBusBlockEntity.kt | 11 +- .../block/entity/storage/StorageInterfaces.kt | 56 +--- .../StoragePowerSupplierBlockEntity.kt | 17 +- .../entity/tech/BatteryBankBlockEntity.kt | 35 +- .../tech/ChemicalGeneratorBlockEntity.kt | 39 +-- .../entity/tech/EnergyCounterBlockEntity.kt | 127 ++------ .../mc/otm/block/storage/StorageInterfaces.kt | 44 --- .../mc/otm/block/tech/BatteryBankBlock.kt | 13 - .../otm/block/tech/ChemicalGeneratorBlock.kt | 21 -- .../mc/otm/block/tech/EnergyCounterBlock.kt | 17 - .../dbotthepony/mc/otm/core/GetterSetter.kt | 8 + .../mc/otm/core/util/BESubscribeList.kt | 303 ------------------ 25 files changed, 262 insertions(+), 694 deletions(-) delete mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BESubscribeList.kt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt index 1c271cb0b..c86a94288 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/MatteryBlock.kt @@ -23,7 +23,9 @@ import net.minecraft.world.level.material.Material import net.minecraft.world.level.material.MaterialColor import net.minecraft.world.phys.BlockHitResult import net.minecraft.world.phys.shapes.VoxelShape +import ru.dbotthepony.mc.otm.SERVER_IS_LIVE import ru.dbotthepony.mc.otm.block.entity.IRedstoneControlled +import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.core.get @@ -97,6 +99,7 @@ abstract class MatteryBlock @JvmOverloads constructor( if (this is EntityBlock && level.isClientSide) return InteractionResult.SUCCESS + @Suppress("DEPRECATION") return super.use(blockState, level, blockPos, ply, hand, blockHitResult) } @@ -167,6 +170,7 @@ abstract class MatteryBlock @JvmOverloads constructor( neighbourPos: BlockPos, movedByPiston: Boolean ) { + @Suppress("DEPRECATION") super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) if (this is EntityBlock && !level.isClientSide) { @@ -174,6 +178,9 @@ abstract class MatteryBlock @JvmOverloads constructor( if (tile is IRedstoneControlled) tile.redstoneControl.redstoneSignal = level.getBestNeighborSignal(pos) + + if (tile is MatteryBlockEntity && SERVER_IS_LIVE) + tile.neighborChanged(neighbour, neighbourPos, movedByPiston) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt index 1da14f61f..b29a1a17e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.block.entity import com.google.common.collect.ImmutableSet +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.Long2ObjectFunction import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap @@ -9,10 +10,8 @@ import net.minecraft.client.multiplayer.ClientLevel import net.minecraft.core.BlockPos import net.minecraft.core.Direction import net.minecraft.core.SectionPos -import net.minecraft.nbt.ByteTag +import net.minecraft.core.Vec3i import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.DoubleTag -import net.minecraft.nbt.FloatTag import net.minecraft.nbt.StringTag import net.minecraft.nbt.Tag import net.minecraft.resources.ResourceLocation @@ -20,6 +19,7 @@ import net.minecraft.server.level.ServerLevel import net.minecraft.server.level.ServerPlayer import net.minecraft.world.level.ChunkPos import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity @@ -41,25 +41,30 @@ 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.core.collect.SupplierList +import ru.dbotthepony.mc.otm.core.collect.WeakHashSet import ru.dbotthepony.mc.otm.core.forValidRefs import ru.dbotthepony.mc.otm.core.forValidRefsBreak import ru.dbotthepony.mc.otm.core.get import ru.dbotthepony.mc.otm.core.math.BlockRotation import ru.dbotthepony.mc.otm.core.math.RelativeSide +import ru.dbotthepony.mc.otm.core.math.minus +import ru.dbotthepony.mc.otm.core.math.plus import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.util.EnumValueCodec import ru.dbotthepony.mc.otm.core.util.Savetables import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket import ru.dbotthepony.mc.otm.network.FieldSynchronizer import ru.dbotthepony.mc.otm.network.WorldNetworkChannel +import ru.dbotthepony.mc.otm.once import ru.dbotthepony.mc.otm.oncePre import ru.dbotthepony.mc.otm.onceServer import java.lang.ref.WeakReference import java.util.Collections import java.util.EnumMap import java.util.WeakHashMap +import java.util.function.Supplier import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KProperty import kotlin.reflect.KProperty0 @@ -155,6 +160,11 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc exposeGlobally(ForgeCapabilities.ITEM_HANDLER, value) } + @Suppress("SuspiciousCallableReferenceInLambda") + protected fun trackGlobally(capability: Capability): List> { + return SupplierList(_sides.values.map { it.track(capability)::get }) + } + enum class SideMode(val filter: FlowDirection, val automation: FlowDirection) { DISABLED (FlowDirection.NONE, FlowDirection.NONE), NONE (FlowDirection.BI_DIRECTIONAL, FlowDirection.NONE), @@ -197,6 +207,81 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc private val caps = Reference2ObjectArrayMap, Cap<*>>() private val modeStates = Object2ObjectArrayMap() private val data = Object2ObjectArrayMap>() + private val subscriptions = Reference2ObjectArrayMap, SubRef<*>>() + private val knownLOs = WeakHashSet>() + + private inner class SubRef(var value: LazyOptional) : Supplier> { + override fun get(): LazyOptional { + return value + } + + fun unset() { + value = LazyOptional.empty() + } + } + + fun track(capability: Capability): Supplier> { + var subref = subscriptions[capability] as Supplier>? + + if (subref == null) { + subref = SubRef(LazyOptional.empty()) as SubRef + subscriptions[capability] = subref + level?.once { updateTracked(capability) } + } + + return subref + } + + fun updateTracked() { + for (key in subscriptions.keys) { + // Concurrent Modification safety: + // we do not add nor remove keys from map, we only update values + updateTracked(key) + } + } + + private fun updateTracked(capability: Capability<*>) { + if (isRemoved) return + val dir = blockRotation.side2Dir(side) + + val chunk = level + ?.chunkSource + ?.getChunkNow(SectionPos.blockToSectionCoord(blockPos.x), SectionPos.blockToSectionCoord(blockPos.z)) + + if (chunk == null) { + subscriptions[capability]!!.unset() + level?.once { updateTracked(capability) } + return + } + + val entity = chunk.getBlockEntity(blockPos + dir.normal) + + if (entity == null) { + subscriptions[capability]!!.unset() + return + } + + val new = entity.getCapability(capability, dir.opposite) + + if (!new.isPresent) { + subscriptions[capability]!!.unset() + return + } + + val subref = subscriptions[capability] as SubRef + + if (subref.value !== new) { + if (knownLOs.add(new)) { + val ref = WeakReference(this) + + new.addListener { + ref.get()?.updateTracked(capability) + } + } + + subref.value = new as LazyOptional + } + } val isEmpty get() = caps.isEmpty() && modeStates.isEmpty() @@ -453,6 +538,30 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc savetables.deserializeNBT(nbt) } + @Suppress("OVERRIDE_DEPRECATION") + override fun setBlockState(pBlockState: BlockState) { + val old = blockRotation + @Suppress("DEPRECATION") + super.setBlockState(pBlockState) + val new = blockRotation + + if (old != new) { + for (side in _sides.values) { + side.updateTracked() + side.invalidate() + } + } + + for (side in _sides.values) { + side.revive() + } + } + + fun neighborChanged(neighbour: Block, neighbourPos: BlockPos, movedByPiston: Boolean) { + val dir = vec2Dir[vecKey(neighbourPos - blockPos)] ?: return + _sides[blockRotation.dir2Side(dir)]!!.updateTracked() + } + protected fun tickOnce(func: Runnable) { level?.oncePre { if (!isRemoved) func.run() } } @@ -511,13 +620,31 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc synchronizer.defaultEndpoint.markUnused() } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + val old = this.level + super.setLevel(level) unsubscribe() _subCache = null - if (!p_155231_.isClientSide) { + if (!level.isClientSide) { subscribe() + + if (old != null) { + for (side in _sides.values) { + side.updateTracked() + side.invalidate() + } + + for (side in _sides.values) { + side.revive() + } + } else { + level.once { + for (side in _sides.values) { + side.updateTracked() + } + } + } } } @@ -751,6 +878,24 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc private val playerMap = WeakHashMap>() private val tickingMap = WeakHashMap>>() + private val vec2Dir = Int2ObjectOpenHashMap() + + private fun vecKey(value: Vec3i): Int { + if (value.x !in -1 .. 1) return -1 + if (value.y !in -1 .. 1) return -1 + if (value.z !in -1 .. 1) return -1 + val x = if (value.x < 0) 2 else value.x + val y = if (value.y < 0) 2 else value.y + val z = if (value.z < 0) 2 else value.z + return x or (y shl 4) or (z shl 8) + } + + init { + for (dir in Direction.values()) { + vec2Dir[vecKey(dir.normal)] = dir + } + } + fun onLevelUnload(event: LevelEvent.Unload) { val level = event.level as? ServerLevel ?: return playerMap.remove(level) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt index eb7e64e18..9d1477b0e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt @@ -85,8 +85,8 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery private var sleepTicks = 4 - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) sleepTicks = 4 } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt index 7c73c414a..036077d4f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterBottlerBlockEntity.kt @@ -133,10 +133,10 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : return matter } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) MatterNetworkGraph.discoverFull(this, matterNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt index a195923ad..b21812692 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterCapacitorBankBlockEntity.kt @@ -1,20 +1,13 @@ package ru.dbotthepony.mc.otm.block.entity.matter import net.minecraft.core.BlockPos -import net.minecraft.core.Direction -import net.minecraft.nbt.CompoundTag -import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel -import net.minecraft.world.Container import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState -import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.common.util.LazyOptional -import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.IDroppableContainer import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.BatteryBankBlockEntity @@ -30,8 +23,6 @@ import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.menu.matter.MatterCapacitorBankMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.core.nbt.map -import ru.dbotthepony.mc.otm.core.nbt.set class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.MATTER_CAPACITOR_BANK, p_155229_, p_155230_), IMatterGraphNode, IMatterStorage, IDroppableContainer { var gaugeLevel by synchronizer.float() @@ -161,10 +152,10 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) matterNode.destroy(::MatterNetworkGraph) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) MatterNetworkGraph.discoverFull(this, matterNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt index a2a73b6e2..3fd64d919 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterDecomposerBlockEntity.kt @@ -204,10 +204,10 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState) matterNode.destroy(::MatterNetworkGraph) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) MatterNetworkGraph.discoverFull(this, matterNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt index 0c248d17c..86e34f8c2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterPanelBlockEntity.kt @@ -1,13 +1,11 @@ package ru.dbotthepony.mc.otm.block.entity.matter import net.minecraft.core.BlockPos -import net.minecraft.core.Direction import net.minecraft.world.level.block.state.BlockState import ru.dbotthepony.mc.otm.menu.matter.MatterPanelMenu import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu -import net.minecraftforge.common.util.LazyOptional import ru.dbotthepony.mc.otm.capability.MatteryCapability import java.util.HashMap import java.util.UUID @@ -17,7 +15,6 @@ import net.minecraft.nbt.Tag import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.Level -import net.minecraftforge.common.capabilities.Capability import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.matter.* @@ -54,10 +51,10 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : exposeGlobally(MatteryCapability.TASK, this) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) MatterNetworkGraph.discoverFull(this, matterNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt index f9ae8769a..0426dee94 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterRecyclerBlockEntity.kt @@ -106,10 +106,10 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState) matterNode.destroy(::MatterNetworkGraph) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) MatterNetworkGraph.discoverFull(this, matterNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt index ffc1434c5..ecc75250f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterReplicatorBlockEntity.kt @@ -19,7 +19,6 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.matter.* import ru.dbotthepony.mc.otm.container.MatteryContainer -import ru.dbotthepony.mc.otm.container.ContainerHandler import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode @@ -164,10 +163,10 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : matterNode.destroy(::MatterNetworkGraph) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) MatterNetworkGraph.discoverFull(this, matterNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt index 2ee0658d3..907d8d2e4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/MatterScannerBlockEntity.kt @@ -169,10 +169,10 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : return null to IdleReason.ITEM } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) { + if (level is ServerLevel) { MatterNetworkGraph.discoverFull(this, matterNode) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/PatternStorageBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/PatternStorageBlockEntity.kt index 93c3ff577..0e372ba60 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/PatternStorageBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/matter/PatternStorageBlockEntity.kt @@ -8,20 +8,14 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.block.matter.PatternStorageBlock -import net.minecraft.nbt.CompoundTag -import net.minecraftforge.common.util.LazyOptional import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import ru.dbotthepony.mc.otm.menu.matter.PatternStorageMenu import net.minecraft.MethodsReturnNonnullByDefault -import net.minecraft.core.Direction import net.minecraft.server.level.ServerLevel -import net.minecraft.world.Container import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block -import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.common.capabilities.ForgeCapabilities import ru.dbotthepony.mc.otm.block.IDroppableContainer import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.capability.matter.* @@ -29,9 +23,7 @@ import ru.dbotthepony.mc.otm.core.collect.iterator import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph -import ru.dbotthepony.mc.otm.core.nbt.map import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.core.nbt.set import java.util.ArrayList import java.util.stream.Stream @@ -90,10 +82,10 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : private val itemHandler = container.handler { slot: Int, stack: ItemStack -> stack.getCapability(MatteryCapability.PATTERN).isPresent } override val droppableContainer by ::container - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) MatterNetworkGraph.discoverFull(this, matterNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt index f56a58c2c..e36f1b0fc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/DriveRackBlockEntity.kt @@ -1,9 +1,6 @@ package ru.dbotthepony.mc.otm.block.entity.storage import net.minecraft.core.BlockPos -import net.minecraft.core.Direction -import net.minecraft.nbt.CompoundTag -import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player @@ -11,9 +8,6 @@ import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState -import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.common.util.LazyOptional -import ru.dbotthepony.mc.otm.config.ServerConfig import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.capability.MatteryCapability @@ -21,11 +15,8 @@ import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.menu.storage.DriveRackMenu -import ru.dbotthepony.mc.otm.core.nbt.map -import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.storage.* class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : @@ -59,10 +50,10 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : exposeGlobally(MatteryCapability.STORAGE_NODE, cell) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) StorageNetworkGraph.discoverFull(this, cell.storageNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt index 46df0363d..03a5be273 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/ItemMonitorBlockEntity.kt @@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block.entity.storage import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import net.minecraft.core.BlockPos -import net.minecraft.core.Direction import net.minecraft.core.NonNullList import net.minecraft.nbt.CompoundTag import net.minecraft.network.FriendlyByteBuf @@ -20,12 +19,9 @@ import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.ForgeHooks -import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.util.INBTSerializable -import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.network.NetworkEvent import org.apache.logging.log4j.LogManager -import ru.dbotthepony.mc.otm.config.ServerConfig import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability @@ -42,7 +38,6 @@ import ru.dbotthepony.mc.otm.container.set import ru.dbotthepony.mc.otm.core.nbt.getEnum import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.menu.storage.ItemMonitorMenu -import ru.dbotthepony.mc.otm.registry.MBlocks import ru.dbotthepony.mc.otm.storage.* import java.math.BigInteger import java.util.* @@ -501,10 +496,10 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : return ItemMonitorMenu(containerID, inventory, this) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) + if (level is ServerLevel) StorageNetworkGraph.discoverFull(this, cell.storageNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt index 12ed70922..de9319380 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageBusBlockEntity.kt @@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.IntAVLTreeSet import net.minecraft.core.BlockPos import net.minecraft.core.Direction -import net.minecraft.nbt.CompoundTag import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.player.Inventory @@ -14,7 +13,6 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.BlockState -import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.items.IItemHandler @@ -25,7 +23,6 @@ import ru.dbotthepony.mc.otm.block.entity.storage.AbstractStorageImportExport.Co import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.config.MachinesConfig -import ru.dbotthepony.mc.otm.config.ServerConfig import ru.dbotthepony.mc.otm.container.ItemFilter import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom @@ -34,8 +31,6 @@ import ru.dbotthepony.mc.otm.core.math.getCapability import ru.dbotthepony.mc.otm.core.math.isPositive import ru.dbotthepony.mc.otm.core.math.isZero import ru.dbotthepony.mc.otm.core.math.plus -import ru.dbotthepony.mc.otm.core.nbt.map -import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.GraphNodeListener import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode @@ -115,10 +110,10 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter savetable(::filter, FILTER_KEY) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) { + if (level is ServerLevel) { StorageNetworkGraph.discoverFull(this, cell.storageNode) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt index 20ca390ac..f4ac6cedc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StorageInterfaces.kt @@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block.entity.storage import net.minecraft.core.BlockPos import net.minecraft.core.Direction -import net.minecraft.nbt.CompoundTag import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.player.Inventory @@ -15,28 +14,22 @@ import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.ForgeCapabilities -import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.items.IItemHandler -import ru.dbotthepony.mc.otm.* +import ru.dbotthepony.mc.otm.OverdriveThatMatters +import ru.dbotthepony.mc.otm.SERVER_IS_LIVE import ru.dbotthepony.mc.otm.block.CableBlock import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity -import ru.dbotthepony.mc.otm.capability.* +import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact import ru.dbotthepony.mc.otm.config.ConciseBalanceValues import ru.dbotthepony.mc.otm.config.MachinesConfig -import ru.dbotthepony.mc.otm.config.ServerConfig import ru.dbotthepony.mc.otm.container.ItemFilter -import ru.dbotthepony.mc.otm.core.* -import ru.dbotthepony.mc.otm.core.math.BlockRotationFreedom +import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.RelativeSide -import ru.dbotthepony.mc.otm.core.math.rotationTwo import ru.dbotthepony.mc.otm.core.math.toIntSafe -import ru.dbotthepony.mc.otm.core.math.unaryMinus -import ru.dbotthepony.mc.otm.core.nbt.map -import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.core.util.BESubscribeList +import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.graph.Graph6Node import ru.dbotthepony.mc.otm.graph.GraphNodeListener import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode @@ -45,11 +38,15 @@ import ru.dbotthepony.mc.otm.menu.storage.StorageExporterMenu import ru.dbotthepony.mc.otm.menu.storage.StorageImporterMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MNames -import ru.dbotthepony.mc.otm.storage.* +import ru.dbotthepony.mc.otm.storage.IStorageEventConsumer +import ru.dbotthepony.mc.otm.storage.IStorageProvider +import ru.dbotthepony.mc.otm.storage.ITEM_STORAGE +import ru.dbotthepony.mc.otm.storage.ItemStackWrapper +import ru.dbotthepony.mc.otm.storage.StorageStackType +import ru.dbotthepony.mc.otm.storage.addStack import java.math.BigInteger import java.util.* import java.util.stream.Stream -import kotlin.collections.HashSet abstract class AbstractStorageImportExport( blockType: BlockEntityType<*>, @@ -85,42 +82,23 @@ abstract class AbstractStorageImportExport( exposeAllSidesExcept(RelativeSide.FRONT, MatteryCapability.STORAGE_NODE, cell) } - override fun invalidateCaps() { - super.invalidateCaps() - target.invalidate() - } - - override fun reviveCaps() { - super.reviveCaps() - target.revive() - } - override fun setRemoved() { super.setRemoved() cell.destroy(level) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) { + if (level is ServerLevel) { StorageNetworkGraph.discoverFull(this, cell.storageNode) - tickOnceServer(this::checkSurroundings) } } protected abstract val targetCapability: Capability protected val target by lazy { - object : BESubscribeList(this@AbstractStorageImportExport, targetCapability) { - override fun test(t: Direction): Boolean { - return t == -this@AbstractStorageImportExport.blockState.getValue(BlockRotationFreedom.TWO.property).front - } - } - } - - fun checkSurroundings() { - target.update() + front.track(targetCapability) } abstract val filter: ItemFilter @@ -206,7 +184,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) nextTick-- - val target = target.firstOrNull() + val target = target.get().orNull() if (nextTick <= 0 && target != null && enoughEnergy) { val graph = cell.storageGraph ?: return @@ -318,7 +296,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : nextTick-- - val target = target.firstOrNull() + val target = target.get().orNull() if (nextTick <= 0 && target != null && enoughEnergy) { val graph = cell.storageGraph ?: return diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt index 3e7f09dcd..458e8a257 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/storage/StoragePowerSupplierBlockEntity.kt @@ -1,20 +1,12 @@ package ru.dbotthepony.mc.otm.block.entity.storage import net.minecraft.core.BlockPos -import net.minecraft.core.Direction -import net.minecraft.nbt.CompoundTag -import net.minecraft.network.chat.Component import net.minecraft.server.level.ServerLevel import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState -import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.common.util.LazyOptional -import ru.dbotthepony.mc.otm.OverdriveThatMatters -import ru.dbotthepony.mc.otm.config.ServerConfig -import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage @@ -25,9 +17,6 @@ import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph import ru.dbotthepony.mc.otm.menu.storage.StoragePowerSupplierMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities -import ru.dbotthepony.mc.otm.registry.MNames -import ru.dbotthepony.mc.otm.core.math.getDecimal -import ru.dbotthepony.mc.otm.core.nbt.set class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_POWER_SUPPLIER, blockPos, blockState) { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { @@ -51,10 +40,10 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState savetables.decimal(::powerPassed, POWER_PASSED_KEY) } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) + override fun setLevel(level: Level) { + super.setLevel(level) - if (p_155231_ is ServerLevel) { + if (level is ServerLevel) { StorageNetworkGraph.discoverFull(this, cell.storageNode) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt index 3a40b75aa..24863d985 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/BatteryBankBlockEntity.kt @@ -1,26 +1,28 @@ package ru.dbotthepony.mc.otm.block.entity.tech import net.minecraft.core.BlockPos -import net.minecraft.core.Direction import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack -import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.capabilities.ForgeCapabilities -import net.minecraftforge.energy.IEnergyStorage import ru.dbotthepony.mc.otm.block.IDroppableContainer import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity -import ru.dbotthepony.mc.otm.capability.* +import ru.dbotthepony.mc.otm.capability.FlowDirection +import ru.dbotthepony.mc.otm.capability.energy import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage -import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.capability.energyStoredMattery +import ru.dbotthepony.mc.otm.capability.extractEnergy +import ru.dbotthepony.mc.otm.capability.maxEnergyStoredMattery +import ru.dbotthepony.mc.otm.capability.receiveEnergy import ru.dbotthepony.mc.otm.container.HandlerFilter -import ru.dbotthepony.mc.otm.core.* +import ru.dbotthepony.mc.otm.container.MatteryContainer +import ru.dbotthepony.mc.otm.core.ImmutableList +import ru.dbotthepony.mc.otm.core.getValue +import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.RelativeSide -import ru.dbotthepony.mc.otm.core.math.facingOne -import ru.dbotthepony.mc.otm.core.util.BESubscribeList import ru.dbotthepony.mc.otm.menu.tech.BatteryBankMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities @@ -202,28 +204,17 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte } } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) - checkSurroundings() - } - - private val consumers = object : BESubscribeList(this@BatteryBankBlockEntity, ForgeCapabilities.ENERGY) { - override fun test(t: Direction): Boolean { - return blockState.facingOne == t - } - } - - fun checkSurroundings() = consumers.update(blockState.facingOne::equals) + private val consumers by front.track(ForgeCapabilities.ENERGY) fun tick() { if (redstoneControl.isBlockedByRedstone) return - for (it in consumers) { + consumers.ifPresentK { val (_, maxThroughput) = energy.getDistribution(false) if (maxThroughput.isZero) - continue + return@ifPresentK val diff = it.receiveEnergy(maxThroughput, true) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt index 88343b292..8f131b122 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/ChemicalGeneratorBlockEntity.kt @@ -1,12 +1,10 @@ package ru.dbotthepony.mc.otm.block.entity.tech import net.minecraft.core.BlockPos -import net.minecraft.nbt.CompoundTag import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu import net.minecraft.world.item.ItemStack -import net.minecraft.world.level.Level import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.state.BlockState import net.minecraftforge.common.ForgeConfigSpec @@ -18,7 +16,6 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity import ru.dbotthepony.mc.otm.block.entity.WorkerState import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.capability.energy.GeneratorEnergyStorage -import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper import ru.dbotthepony.mc.otm.container.MatteryContainer import ru.dbotthepony.mc.otm.container.HandlerFilter import ru.dbotthepony.mc.otm.core.* @@ -29,9 +26,6 @@ import ru.dbotthepony.mc.otm.core.util.WriteOnce import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue import ru.dbotthepony.mc.otm.core.math.defineDecimal -import ru.dbotthepony.mc.otm.core.nbt.map -import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.core.util.BESubscribeList class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.CHEMICAL_GENERATOR, pos, state), IDroppableContainer { override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { @@ -66,41 +60,18 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe savetable(::container, INVENTORY_KEY) exposeEnergyGlobally(energy) exposeItemsGlobally(itemHandler) + + savetables.int(::workTicks, WORK_TICKS_KEY) + savetables.int(::workTicksTotal, WORK_TICKS_TOTAL_KEY) } - private val consumers = BESubscribeList(this, ForgeCapabilities.ENERGY) - - fun checkSurroundings() = consumers.update() + private val consumers = trackGlobally(ForgeCapabilities.ENERGY) override fun setChangedLight() { super.setChangedLight() checkFuelSlot = true } - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) - tickOnceServer(consumers::update) - } - - override fun saveAdditional(nbt: CompoundTag) { - super.saveAdditional(nbt) - - nbt[WORK_TICKS_KEY] = workTicks - nbt[WORK_TICKS_TOTAL_KEY] = workTicksTotal - } - - override fun load(nbt: CompoundTag) { - super.load(nbt) - - workTicks = nbt.getInt(WORK_TICKS_KEY) - workTicksTotal = nbt.getInt(WORK_TICKS_TOTAL_KEY) - } - - override fun setBlockState(p_155251_: BlockState) { - super.setBlockState(p_155251_) - tickOnceServer(consumers::update) - } - var workTicks = 0 private set @@ -171,7 +142,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryDe } for (consumer in consumers) { - workWithPower(consumer) + consumer.ifPresentK(::workWithPower) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt index 9919aebeb..32c0b6782 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/tech/EnergyCounterBlockEntity.kt @@ -1,7 +1,6 @@ package ru.dbotthepony.mc.otm.block.entity.tech import net.minecraft.core.BlockPos -import net.minecraft.core.Direction import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.IntTag import net.minecraft.nbt.ListTag @@ -9,26 +8,21 @@ import net.minecraft.network.chat.Component import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.AbstractContainerMenu -import net.minecraft.world.level.Level import net.minecraft.world.level.block.state.BlockState -import net.minecraftforge.common.capabilities.Capability import net.minecraftforge.common.capabilities.ForgeCapabilities -import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.energy.IEnergyStorage 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 import ru.dbotthepony.mc.otm.core.math.getDecimal -import ru.dbotthepony.mc.otm.core.math.unaryMinus import ru.dbotthepony.mc.otm.core.nbt.getByteArrayList import ru.dbotthepony.mc.otm.core.nbt.ifHas import ru.dbotthepony.mc.otm.core.nbt.map import ru.dbotthepony.mc.otm.core.nbt.set -import ru.dbotthepony.mc.otm.core.util.BESubscribeList import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu import ru.dbotthepony.mc.otm.registry.MBlockEntities import java.util.* @@ -36,6 +30,10 @@ import java.util.* class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.ENERGY_COUNTER, p_155229_, p_155230_) { var passed by synchronizer.fraction() + override val blockRotation: BlockRotation get() { + return BlockRotation.of(blockState[EnergyCounterBlock.INPUT_DIRECTION]) + } + private val history = Array(10 * 20) { Decimal.ZERO } internal var historyTick = 0 @@ -124,22 +122,8 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat private val energyInput = EnergyCounterCap(true) private val energyOutput = EnergyCounterCap(false) - private val inputCapability = object : BESubscribeList(this@EnergyCounterBlockEntity, ForgeCapabilities.ENERGY) { - override fun test(t: Direction): Boolean { - return t == blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION) - } - } - - private val outputCapability = object : BESubscribeList(this@EnergyCounterBlockEntity, ForgeCapabilities.ENERGY) { - override fun test(t: Direction): Boolean { - return t == -blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION) - } - } - - override fun setLevel(p_155231_: Level) { - super.setLevel(p_155231_) - tickOnceServer(this::checkSurroundings) - } + private val inputCapability by front.track(ForgeCapabilities.ENERGY) + private val outputCapability by back.track(ForgeCapabilities.ENERGY) private inner class EnergyCounterCap(isInput: Boolean) : IMatteryEnergyStorage { override val energyFlow = FlowDirection.input(isInput) @@ -148,7 +132,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat if (redstoneControl.isBlockedByRedstone) return Decimal.ZERO - val it = inputCapability.first + val it = inputCapability.orNull() if (it != null) { val diff: Decimal @@ -176,7 +160,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat if (redstoneControl.isBlockedByRedstone) return Decimal.ZERO - val it = outputCapability.first + val it = outputCapability.orNull() if (it != null) { val diff: Decimal @@ -206,7 +190,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat override var batteryLevel: Decimal get() { if (energyFlow.input) { - val it = outputCapability.first + val it = outputCapability.orNull() if (it != null) { if (it is IMatteryEnergyStorage) { @@ -216,7 +200,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat return Decimal(it.energyStored) } } else { - val it = inputCapability.first + val it = inputCapability.orNull() if (it != null) { if (it is IMatteryEnergyStorage) { @@ -236,7 +220,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat override val maxBatteryLevel: Decimal get() { if (energyFlow.input) { - val it = outputCapability.first + val it = outputCapability.orNull() if (it != null) { if (it is IMatteryEnergyStorage) { @@ -246,7 +230,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat return Decimal(it.maxEnergyStored) } } else { - val it = inputCapability.first + val it = inputCapability.orNull() if (it != null) { if (it is IMatteryEnergyStorage) { @@ -263,7 +247,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat override val missingPower: Decimal get() { if (energyFlow.input) { - val it = outputCapability.first + val it = outputCapability.orNull() if (it != null) { if (it is IMatteryEnergyStorage) { @@ -273,7 +257,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat return Decimal((it.maxEnergyStored - it.energyStored).coerceAtLeast(0)) } } else { - val it = inputCapability.first + val it = inputCapability.orNull() if (it != null) { if (it is IMatteryEnergyStorage) { @@ -288,86 +272,19 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat } } - private var resolverInput = LazyOptional.of { energyInput } - private var resolverOutput = LazyOptional.of { energyOutput } + init { + front.Cap(ForgeCapabilities.ENERGY, energyInput) + front.Cap(MatteryCapability.ENERGY, energyInput) - private var resolverInputMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) } else null - private var resolverOutputMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyOutput) } else null - - private var valid = true - - override fun invalidateCaps() { - super.invalidateCaps() - valid = false - resolverInput.invalidate() - resolverInputMekanism?.invalidate() - resolverOutput.invalidate() - resolverOutputMekanism?.invalidate() - } - - override fun reviveCaps() { - super.reviveCaps() - valid = true - resolverInput = LazyOptional.of { energyInput } - resolverOutput = LazyOptional.of { energyOutput } + back.Cap(ForgeCapabilities.ENERGY, energyOutput) + back.Cap(MatteryCapability.ENERGY, energyOutput) if (isMekanismLoaded) { - resolverInputMekanism = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) } - resolverOutputMekanism = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyOutput) } + front.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(energyInput)) + back.Cap(MatteryCapability.MEKANISM_ENERGY, Mattery2MekanismEnergyWrapper(energyOutput)) } } - @Suppress("deprecation", "OVERRIDE_DEPRECATION") - override fun setBlockState(new: BlockState) { - val old = blockState - super.setBlockState(new) - - 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 { Mattery2MekanismEnergyWrapper(energyInput) } - resolverOutputMekanism = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyOutput) } - } - - checkSurroundings() - } - } - - fun checkSurroundings() { - inputCapability.update((blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION))::equals) - outputCapability.update((-blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION))::equals) - } - - override fun getCapability(cap: Capability, side: Direction?): LazyOptional { - if (side == null || isRemoved) - return super.getCapability(cap, side) - - if (valid) { - if (side == blockState.getValue(EnergyCounterBlock.INPUT_DIRECTION)) { - if (cap == MatteryCapability.ENERGY || cap == ForgeCapabilities.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 == ForgeCapabilities.ENERGY) { - return resolverOutput.cast() - } else if (cap == MatteryCapability.MEKANISM_ENERGY) { - return resolverOutputMekanism!!.cast() - } - } - } - - return super.getCapability(cap, side) - } - fun tick() { lastTick = history[historyTick] historyTick = (historyTick + 1) % history.size diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt index b3c1bd366..6f7a3e0f2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/storage/StorageInterfaces.kt @@ -114,28 +114,6 @@ class StorageImporterBlock : RotatableMatteryBlock(), EntityBlock { ): VoxelShape { return shapes[p_60555_]!! } - - @Suppress("OVERRIDE_DEPRECATION") - override fun neighborChanged( - state: BlockState, - level: Level, - pos: BlockPos, - neighbour: Block, - neighbourPos: BlockPos, - movedByPiston: Boolean - ) { - super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) - - if (!level.isClientSide) { - val tile = level.getBlockEntity(pos) - - if (tile is StorageImporterBlockEntity) { - level.oncePre { - tile.checkSurroundings() - } - } - } - } } class StorageExporterBlock : RotatableMatteryBlock(), EntityBlock { @@ -218,26 +196,4 @@ class StorageExporterBlock : RotatableMatteryBlock(), EntityBlock { ): VoxelShape { return shapes[p_60555_]!! } - - @Suppress("OVERRIDE_DEPRECATION") - override fun neighborChanged( - state: BlockState, - level: Level, - pos: BlockPos, - neighbour: Block, - neighbourPos: BlockPos, - movedByPiston: Boolean - ) { - super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) - - if (!level.isClientSide) { - val tile = level.getBlockEntity(pos) - - if (tile is StorageExporterBlockEntity) { - level.oncePre { - tile.checkSurroundings() - } - } - } - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BatteryBankBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BatteryBankBlock.kt index f84edddf7..75a288228 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BatteryBankBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/BatteryBankBlock.kt @@ -58,17 +58,4 @@ class BatteryBankBlock : RotatableMatteryBlock(), EntityBlock { override fun faceToPlayer(context: BlockPlaceContext): Boolean { return false } - - override fun neighborChanged( - state: BlockState, - level: Level, - pos: BlockPos, - neighbour: Block, - neighbourPos: BlockPos, - movedByPiston: Boolean - ) { - super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) - val blockEntity = level.getBlockEntity(pos) as? BatteryBankBlockEntity ?: return - level.oncePre { blockEntity.checkSurroundings() } - } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt index 4728e76e2..cc57e14d7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/ChemicalGeneratorBlock.kt @@ -75,27 +75,6 @@ class ChemicalGeneratorBlock : RotatableMatteryBlock(), EntityBlock { } } - override fun neighborChanged( - state: BlockState, - level: Level, - pos: BlockPos, - neighbour: Block, - neighbourPos: BlockPos, - movedByPiston: Boolean - ) { - super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) - - if (!level.isClientSide) { - val tile = level.getBlockEntity(pos) - - if (tile is ChemicalGeneratorBlockEntity) { - level.oncePre { - tile.checkSurroundings() - } - } - } - } - private val shapes = getShapeForEachState(rotationProperty) { BlockShapes.CHEMICAL_GENERATOR.rotateFromNorth(it[rotationProperty]).computeShape() } @Suppress("override_deprecation") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt index e393d52f5..b6c4a565a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/tech/EnergyCounterBlock.kt @@ -63,23 +63,6 @@ class EnergyCounterBlock : MatteryBlock(), EntityBlock { p_49915_.add(INPUT_DIRECTION, IF_DIRECTION) } - override fun neighborChanged( - state: BlockState, - level: Level, - pos: BlockPos, - neighbour: Block, - neighbourPos: BlockPos, - movedByPiston: Boolean - ) { - super.neighborChanged(state, level, pos, neighbour, neighbourPos, movedByPiston) - - if (SERVER_IS_LIVE) { - level.once { - (level.getBlockEntity(pos) as? EnergyCounterBlockEntity)?.checkSurroundings() - } - } - } - private val SHAPES = HashMap() init { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt index db519b33e..b64cbd207 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/GetterSetter.kt @@ -66,6 +66,14 @@ interface GetterSetter : Supplier, Consumer, ReadWriteProperty } } +operator fun Supplier.getValue(thisRef: Any?, property: KProperty<*>): T { + return get() +} + +operator fun Consumer.setValue(thisRef: Any?, property: KProperty<*>, value: T) { + accept(value) +} + fun KMutableProperty0.asGetterSetter(watch: ((old: V, new: V) -> Unit)? = null): GetterSetter { return GetterSetter.of(this).let { if (watch != null) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BESubscribeList.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BESubscribeList.kt deleted file mode 100644 index 18d010c75..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/BESubscribeList.kt +++ /dev/null @@ -1,303 +0,0 @@ -package ru.dbotthepony.mc.otm.core.util - -import net.minecraft.core.Direction -import net.minecraft.core.SectionPos -import net.minecraft.server.level.ServerLevel -import net.minecraft.world.level.block.entity.BlockEntity -import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.common.util.LazyOptional -import ru.dbotthepony.mc.otm.SERVER_IS_LIVE -import ru.dbotthepony.mc.otm.core.collect.WeakHashSet -import ru.dbotthepony.mc.otm.core.math.plus -import ru.dbotthepony.mc.otm.core.math.unaryMinus -import ru.dbotthepony.mc.otm.core.orNull -import ru.dbotthepony.mc.otm.onceServer -import java.lang.ref.WeakReference -import java.util.EnumMap -import java.util.function.Predicate - -private inline val Direction.flag: Int get() = 1 shl (ordinal + 1) - -/** - * This class allows block entities to track [capability] per block side. - * - * Allowed sides are governed by [test] method, which is open for override. - * - * **IMPORTANT:** Once rules behind [test] are changed, you MUST call [validate] or [update] right away, or expect hard to debug bugs. - * If rule changes can't be tracked in practical way, then flip on [alwaysValidate], although it will come with performance - * penalty (this will cause [iterator] to invoke [validate] on each its invocation). - * - * Subclasses can also override [subscribe] and [unsubscribe] to more finely track changes in neighbours. - * - * **THIS CLASS IS COMPLETELY THREAD UNSAFE**, it is assumed you only ever invoke it on server thread, - * or, at very least, thread where [ServerLevel] resides. - */ -open class BESubscribeList( - val block: BlockEntity, - val capability: Capability, - val alwaysValidate: Boolean = false -) : Predicate, Iterable { - private val knownCaps = WeakHashSet>() - private val trackedCaps = EnumMap>>(Direction::class.java) - private var updateQueued = false - private var firstKey: Direction? = null - private var lastDirectionSet = 0 - private var isWaitingOnChunk = false - - /** - * First valid capability, this is faster than invoking [iterator] and getting first value from it. - */ - val first: T? get() { - return firstLO.orNull() - } - - /** - * First valid capability as [LazyOptional], this is faster than invoking [iterator] and getting first value from it. - * - * If required, calls [update] - */ - val firstLO: LazyOptional get() { - if (updateQueued) { - update() - } else if (alwaysValidate) { - validate() - } - - for (i in 0 .. 2) { - if (firstKey == null) { - return LazyOptional.empty() - } - - val get = trackedCaps[firstKey]?.get() - - if (get == null || !get.isPresent) { - update() - continue - } - - return get - } - - return LazyOptional.empty() - } - - var valid = true - set(value) { - if (value != field) { - field = value - - if (value) { - update() - } - } - } - - fun invalidate() { - valid = false - } - - fun revive() { - valid = true - } - - // override - protected open fun subscribe(direction: Direction, capability: LazyOptional) {} - // override - protected open fun unsubscribe(direction: Direction, capability: LazyOptional?) {} - - override fun test(t: Direction): Boolean { - return true - } - - final override fun iterator(): Iterator { - if (updateQueued) { - update() - } else if (alwaysValidate) { - validate() - } - - return object : Iterator { - val iterator = trackedCaps.iterator() - var value: T? = null - - private fun find() { - while (iterator.hasNext() && value == null) { - val (k, v) = iterator.next() - value = v.get()?.orNull() - - if (value == null) { - iterator.remove() - unsubscribe(k, null) - } else if (!test(k)) { - iterator.remove() - unsubscribe(k, null) - updateQueued = true - } - } - } - - override fun hasNext(): Boolean { - find() - return value != null - } - - override fun next(): T { - find() - val value = value - this.value = null - return value ?: throw NoSuchElementException() - } - } - } - - fun update(direction: Direction) { - return update(direction::equals) - } - - private fun calculateDirectionSet(): Int { - var set = 0 - - for (value in VALUES) - if (test(value)) - set = set or value.flag - - return set - } - - /** - * Checks for one of these conditions to be true: - * * If [test] was determined to be changed during last time [iterator] was invoked AND tracked capability was filtered out due to [test] returning false - * * Performs a fast bitflag intersection test, by calling [test] on all directions and seeking difference between built set and previous set checked during last [update] - * * Tracked capabilities are checked for validity (if references are still valid) - * - * Once *any* of conditions above end up true, [update] is called and nothing else down the list is checked further. - */ - fun validate() { - check(valid) { "Subscription list is marked as invalid" } - - if (updateQueued) { - update() - return - } - - val new = calculateDirectionSet() - - if (new != lastDirectionSet) { - val intersect = new and lastDirectionSet - val removed = lastDirectionSet and (intersect.inv()) - val added = new and (intersect.inv()) - - for (dir in VALUES) { - if (dir.flag and removed != 0) { - val value1 = trackedCaps.remove(dir) - val value = value1?.get() - - if (value1 != null) { - unsubscribe(dir, value) - } - } - } - - if (added != 0) { - update { it.flag and added != 0 } - } - - lastDirectionSet = new - return - } - - val iterator = trackedCaps.iterator() - var any = 0 - - for ((k, v) in iterator) { - if (v.get() == null) { - unsubscribe(k, null) - any = any or k.flag - } - } - - if (any != 0) { - update { it.flag and any != 0 } - } - } - - /** - * Updates subscription list, searching for new capabilities and "removing" outdated ones. - * - * [predicate] narrows sides-to-check list, not replaces the set generated by this class' [test] - */ - @JvmOverloads - fun update(predicate: Predicate? = null) { - if (!valid || block.isRemoved) - return - - val level = block.level as? ServerLevel ?: return // don't run on client - val sorse = level.chunkSource - var waitChunkLoad = false - - var stream = Direction.stream() - - if (predicate != null) { - stream = stream.filter(predicate) - } else { - updateQueued = false - lastDirectionSet = calculateDirectionSet() - } - - stream = stream.filter(this) - firstKey = null - - for (dir in stream) { - val pos = block.blockPos + dir - val getChunk = sorse.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z)) - - if (getChunk == null) { - waitChunkLoad = true - } else { - val cap = getChunk.getBlockEntity(pos)?.getCapability(capability, -dir) - val knownCap = trackedCaps[dir]?.get() - - if (cap != null && cap.isPresent) { - if (knownCap !== cap) { - if (knownCaps.add(cap)) { - val ref = WeakReference(this) - - cap.addListener { - val self = ref.get() - - if (self != null) { - val current = self.trackedCaps[dir] - - if (current?.get() === it) { - self.update() - } - } - } - } - - trackedCaps[dir] = WeakReference(cap) - subscribe(dir, cap) - } - - if (firstKey == null) { - firstKey = dir - } - } else { - trackedCaps.remove(dir) - unsubscribe(dir, knownCap) - } - } - } - - if (waitChunkLoad && SERVER_IS_LIVE) { - onceServer { if (isWaitingOnChunk) update() } - isWaitingOnChunk = true - } else if (predicate == null) { - isWaitingOnChunk = false - } - } - - companion object { - private val VALUES = Direction.values() - } -}