New graph implementation

This commit is contained in:
DBotThePony 2023-03-24 20:25:35 +07:00
parent ebc41b808a
commit 5f16804feb
Signed by: DBot
GPG Key ID: DCC23B5715498507
36 changed files with 808 additions and 1146 deletions

View File

@ -11,8 +11,8 @@ import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage;
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider;
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage;
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode;
import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode;
import ru.dbotthepony.mc.otm.graph.matter.MatterNode;
import ru.dbotthepony.mc.otm.graph.storage.StorageNode;
import top.theillusivec4.curios.api.type.capability.ICurio;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
@ -33,7 +33,7 @@ public class MatteryCapability {
@Nonnull
@NotNull
public static final Capability<IMatterGraphNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<MatterNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
@ -49,7 +49,7 @@ public class MatteryCapability {
@Nonnull
@NotNull
public static final Capability<IStorageGraphNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
public static final Capability<StorageNode> STORAGE_NODE = CapabilityManager.get(new CapabilityToken<>() {});
@Nonnull
@NotNull
@ -67,10 +67,10 @@ public class MatteryCapability {
event.register(IMatteryEnergyStorage.class);
event.register(MatteryPlayerCapability.class);
event.register(IMatterStorage.class);
event.register(IMatterGraphNode.class);
event.register(MatterNode.class);
event.register(IPatternStorage.class);
event.register(IReplicationTaskProvider.class);
event.register(IMatteryDrive.class);
event.register(IStorageGraphNode.class);
event.register(StorageNode.class);
}
}

View File

@ -19,6 +19,7 @@ import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
import ru.dbotthepony.mc.otm.core.util.ITickable
import ru.dbotthepony.mc.otm.core.util.TickList
import ru.dbotthepony.mc.otm.graph.Abstract6Graph
import java.util.*
private val preServerTick = TickList()
@ -145,6 +146,8 @@ fun onServerTick(event: ServerTickEvent) {
preServerTick.tick()
} else {
postServerTick.tick()
// чтоб не плодить кучу подписчиков, вызовем напрямую отсюда
Abstract6Graph.tick()
}
}

View File

@ -2,135 +2,81 @@ package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.server.level.ServerLevel
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.state.BlockState
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.block.CableBlock
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.GraphNodeListener
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class MatterCableBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
BlockEntity(MBlockEntities.MATTER_CABLE, p_155229_, p_155230_), IMatterGraphNode, GraphNodeListener {
class MatterCableBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(MBlockEntities.MATTER_CABLE, p_155229_, p_155230_) {
val matterNode = object : MatterNode() {
override fun onNeighbour(direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, true)
private var valid = true
override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this }
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap === MatteryCapability.MATTER_NODE)
return resolverNode.cast()
if (newState !== blockState && SERVER_IS_LIVE)
level?.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
}
return super.getCapability(cap, side)
override fun onUnNeighbour(direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, false)
if (newState !== blockState && SERVER_IS_LIVE)
level?.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
}
}
override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_)
if (p_155231_ is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
init {
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
}
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, true)
if (newState !== blockState && SERVER_IS_LIVE)
level?.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
}
override fun onUnNeighbour(node: Graph6Node<*>, direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, false)
if (newState !== blockState && SERVER_IS_LIVE)
level?.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
override fun setLevel(level: Level) {
super.setLevel(level)
matterNode.discover(this)
}
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
}
class StorageCableBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
BlockEntity(MBlockEntities.STORAGE_CABLE, p_155229_, p_155230_), IStorageGraphNode, GraphNodeListener {
class StorageCableBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryBlockEntity(MBlockEntities.STORAGE_CABLE, p_155229_, p_155230_) {
val storageNode = object : StorageNode() {
override fun attachComponents(to: StorageGraph) {}
override fun removeComponents(from: StorageGraph) {}
private var valid = true
private val resolverNode = LazyOptional.of { this }
override fun onNeighbour(direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, true)
override fun attachComponents(to: StorageNetworkGraph) {}
override fun removeComponents(from: StorageNetworkGraph) {}
override val storageNode = Graph6Node<IStorageGraphNode>(this)
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
}
override fun reviveCaps() {
super.reviveCaps()
valid = true
}
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid) {
if (cap === MatteryCapability.STORAGE_NODE)
return resolverNode.cast()
if (newState !== blockState && SERVER_IS_LIVE)
level!!.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
}
return super.getCapability(cap, side)
override fun onUnNeighbour(direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, false)
if (newState !== blockState && SERVER_IS_LIVE)
level!!.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
}
}
override fun setLevel(p_155231_: Level) {
super.setLevel(p_155231_)
if (p_155231_ is ServerLevel)
StorageNetworkGraph.discoverFull(this, storageNode)
init {
exposeGlobally(MatteryCapability.STORAGE_NODE, storageNode)
}
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, true)
if (newState !== blockState && SERVER_IS_LIVE)
level!!.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
}
override fun onUnNeighbour(node: Graph6Node<*>, direction: Direction) {
val newState = blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, false)
if (newState !== blockState && SERVER_IS_LIVE)
level!!.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
override fun setLevel(level: Level) {
super.setLevel(level)
storageNode.discover(this)
}
override fun setRemoved() {
super.setRemoved()
val level = level!!
storageNode.destroy {
StorageNetworkGraph(level)
}
storageNode.isValid = false
}
}

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.block.entity.matter
import net.minecraft.core.BlockPos
import net.minecraft.nbt.StringTag
import net.minecraft.resources.ResourceLocation
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
@ -29,16 +28,16 @@ import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
import ru.dbotthepony.mc.otm.core.math.defineDecimal
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.util.WriteOnce
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.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.matter.IMatterValue
import ru.dbotthepony.mc.otm.matter.MatterManager
import ru.dbotthepony.mc.otm.menu.matter.ItemRepairerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames
class ItemRepairerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.ITEM_REPAIRER, blockPos, blockState), IMatterGraphNode {
class ItemRepairerBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.ITEM_REPAIRER, blockPos, blockState) {
val repairContainer = MatteryContainer(::containerChanged, 1).also(::addDroppableContainer)
private var matterPerTick = Decimal.ZERO
@ -48,13 +47,13 @@ class ItemRepairerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matt
var canNotWork = false
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matter = MatterStorageImpl(::setChangedLight, FlowDirection.INPUT, ::CAPACITY)
val matterNode = SimpleMatterNode(matter = matter)
val energy = WorkerEnergyStorage(::setChangedLight, ENERGY_VALUES)
init {
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
savetables.stateful(::repairContainer)
savetables.stateful(::matter)
@ -83,10 +82,10 @@ class ItemRepairerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matt
}
}
return (matterNode.graph as MatterNetworkGraph?)
?.patterns
?.filter { stack.item.isValidRepairItem(stack, ItemStack(it.item, 1)) }
?.findFirst()?.orElse(null).let {
return matterNode.graph
.patterns
.filter { stack.item.isValidRepairItem(stack, ItemStack(it.item, 1)) }
.findFirst().orElse(null).let {
if (it == null) {
IMatterValue.ZERO
} else {
@ -105,20 +104,14 @@ class ItemRepairerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matt
return ItemRepairerMenu(containerID, inventory, this)
}
override fun getMatterHandler(): IMatterStorage {
return matter
}
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
matterNode.discover(this)
}
private fun containerChanged() {
@ -147,7 +140,7 @@ class ItemRepairerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matt
}
}
val found = (matterNode.graph as MatterNetworkGraph?)?.patterns?.filter { item.item.isValidRepairItem(item, ItemStack(it.item, 1)) }?.findFirst()?.orElse(null)
val found = matterNode.graph.patterns.filter { item.item.isValidRepairItem(item, ItemStack(it.item, 1)) }.findFirst().orElse(null)
if (found != null) {
@Suppress("name_shadowing")
@ -187,7 +180,7 @@ class ItemRepairerBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matt
}
if (matter.storedMatter < matterPerTick) {
val graph = matterNode.graph as MatterNetworkGraph?
val graph = matterNode.graph as MatterGraph?
if (graph != null) {
val toDrain = (matterPerTick * EXTRACT_TICKS.coerceAtMost(item.damageValue)).coerceAtLeast(Decimal.ZERO).coerceAtMost(matter.missingMatter)

View File

@ -22,9 +22,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.HandlerFilter
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.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.menu.matter.MatterBottlerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.core.*
@ -33,11 +31,12 @@ 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.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode {
MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_) {
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
var isBottling: Boolean = true
@ -110,9 +109,11 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
}
val matterNode = SimpleMatterNode(matter = matter)
init {
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
exposeItemsGlobally(itemHandler)
savetables.bool(::isBottling)
@ -126,15 +127,9 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
private var initialCapacity: Decimal? = null
private var lastWorkStack: ItemStack? = null
override fun getMatterHandler(): IMatterStorage {
return matter
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
matterNode.discover(this)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
@ -163,7 +158,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun tick() {
@ -212,7 +207,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
initialCapacity = capability!!.storedMatter
}
val graph = matterNode.graph as MatterNetworkGraph?
val graph = matterNode.graph as MatterGraph?
if (capability != null) {
if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) !== WorkerState.WORKING) {

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.block.entity.matter
import net.minecraft.core.BlockPos
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
@ -17,17 +16,15 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.ifPresentK
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.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.menu.matter.MatterCapacitorBankMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.MATTER_CAPACITOR_BANK, p_155229_, p_155230_), IMatterGraphNode, IMatterStorage {
class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.MATTER_CAPACITOR_BANK, p_155229_, p_155230_), IMatterStorage {
var gaugeLevel by synchronizer.float().property
private set
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matterNode = SimpleMatterNode(matter = this)
override val canSetMatterLevel: Boolean
get() = false
@ -137,7 +134,7 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
init {
savetable(::container, INVENTORY_KEY)
exposeGlobally(MatteryCapability.MATTER, this)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
@ -146,17 +143,11 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
}
override fun getMatterHandler(): IMatterStorage {
return this
matterNode.discover(this)
}
}

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block.entity.matter
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
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
@ -10,32 +9,30 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
import ru.dbotthepony.mc.otm.container.HandlerFilter
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.item.MatterDustItem
import ru.dbotthepony.mc.otm.menu.matter.MatterDecomposerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.container.MatteryContainer
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.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.set
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.item.MatterDustItem
import ru.dbotthepony.mc.otm.matter.MatterManager
import ru.dbotthepony.mc.otm.menu.matter.MatterDecomposerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MNames
fun moveMatterAsDustIntoContainer(_matterValue: Decimal, container: MatteryContainer, OUTPUT_DUST_MAIN: Int, OUTPUT_DUST_STACKING: Int): Decimal {
var matterValue = _matterValue
@ -91,7 +88,7 @@ fun moveMatterAsDustIntoContainer(_matterValue: Decimal, container: MatteryConta
}
class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
: MatteryWorkerBlockEntity<MatterDecomposerBlockEntity.DecomposerJob>(MBlockEntities.MATTER_DECOMPOSER, pos, state, ::DecomposerJob), IMatterGraphNode {
: MatteryWorkerBlockEntity<MatterDecomposerBlockEntity.DecomposerJob>(MBlockEntities.MATTER_DECOMPOSER, pos, state, ::DecomposerJob) {
class DecomposerJob : Job {
val toDust: Boolean
@ -127,13 +124,12 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
savetable(::energy, ENERGY_KEY)
}
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matter = MatterStorageImpl(::setChangedLight, FlowDirection.OUTPUT, ::CAPACITY)
val matterNode = SimpleMatterNode(matter = matter)
init {
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
savetable(::matter, MATTER_STORAGE_KEY)
}
@ -199,24 +195,18 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
}
override fun getMatterHandler(): IMatterStorage {
return matter
matterNode.discover(this)
}
override fun tick() {
super.tick()
val grid = matterNode.graph as MatterNetworkGraph? ?: return
val grid = matterNode.graph as MatterGraph? ?: return
if (!matter.storedMatter.isZero) {
val diff = matter.extractMatterInner(matter.storedMatter, true)

View File

@ -25,14 +25,15 @@ import ru.dbotthepony.mc.otm.core.nbt.mapString
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.ItemSorter
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.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.ArrayList
import java.util.stream.Stream
class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryDeviceBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IReplicationTaskProvider {
MatteryDeviceBlockEntity(MBlockEntities.MATTER_PANEL, p_155229_, p_155230_), IReplicationTaskProvider {
class PlayerSettings(var sorter: ItemSorter = ItemSorter.DEFAULT, var ascending: Boolean = true) : INBTSerializable<CompoundTag> {
override fun serializeNBT(): CompoundTag {
@ -55,7 +56,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
private val listeners = ArrayList<MatterPanelMenu>()
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matterNode = SimpleMatterNode(tasks = this)
fun attachMenu(menu: MatterPanelMenu) {
listeners.add(menu)
@ -70,24 +71,18 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
init {
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
exposeGlobally(MatteryCapability.TASK, this)
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
matterNode.discover(this)
}
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
}
override fun getTaskHandler(): IReplicationTaskProvider {
return this
matterNode.isValid = false
}
private val _tasks = HashMap<UUID, ReplicationTask>()
@ -101,7 +96,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
override fun allocateTask(simulate: Boolean): ReplicationTaskAllocation? {
val graph = matterNode.graph as MatterNetworkGraph? ?: return null
val graph = matterNode.graph as MatterGraph? ?: return null
for ((key, task) in _tasks) {
if (task.required > 0) {
@ -127,7 +122,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val oldTask = localTask
localTask = localTask.finish()
val graph = matterNode.graph as MatterNetworkGraph?
val graph = matterNode.graph as MatterGraph?
// Задача полностью выполнена
if (localTask.required <= 0 && localTask.inProgress <= 0) {
@ -196,7 +191,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val task = _tasks[id] ?: return
_tasks.remove(id)
(matterNode.graph as MatterNetworkGraph?)?.onMatterTaskRemoved(task)
(matterNode.graph as MatterGraph?)?.onMatterTaskRemoved(task)
listeners.forEach { it.taskRemoved(task) }
setChanged()
@ -206,7 +201,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val task = ReplicationTask(UUID.randomUUID(), state.id, state.item, 0, 0, count)
_tasks[task.id] = task
(matterNode.graph as MatterNetworkGraph?)?.onMatterTaskCreated(task)
(matterNode.graph as MatterGraph?)?.onMatterTaskCreated(task)
listeners.forEach { it.taskUpdated(task) }
setChanged()
@ -215,7 +210,7 @@ class MatterPanelBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
override fun dropAllTasks() {
val graph = matterNode.graph as MatterNetworkGraph?
val graph = matterNode.graph as MatterGraph?
for (task in _tasks.values) {
graph?.onMatterTaskRemoved(task)

View File

@ -23,8 +23,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.core.math.Decimal
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.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.item.MatterDustItem
import ru.dbotthepony.mc.otm.menu.matter.MatterRecyclerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
@ -34,9 +33,10 @@ import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.set
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
: MatteryWorkerBlockEntity<MatterRecyclerBlockEntity.RecyclerJob>(MBlockEntities.MATTER_RECYCLER, blockPos, blockState, ::RecyclerJob), IMatterGraphNode {
: MatteryWorkerBlockEntity<MatterRecyclerBlockEntity.RecyclerJob>(MBlockEntities.MATTER_RECYCLER, blockPos, blockState, ::RecyclerJob) {
class RecyclerJob : Job {
var totalMatter: Decimal
@ -72,13 +72,9 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
val container = MatteryContainer(this::itemContainerUpdated, 1).also(::addDroppableContainer)
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matterNode = SimpleMatterNode(matter = matter)
val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_CONFIG)
override fun getMatterHandler(): IMatterStorage {
return matter
}
private val itemHandler = container.handler(object : HandlerFilter {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
return stack.item is MatterDustItem
@ -93,7 +89,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
exposeItemsGlobally(itemHandler)
exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
savetable(::energy, ENERGY_KEY)
savetable(::container, INVENTORY_KEY)
savetable(::matter, MATTER_STORAGE_KEY)
@ -101,14 +97,12 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
matterNode.discover(this)
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
@ -155,7 +149,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
override fun tick() {
super.tick()
val graph = matterNode.graph as MatterNetworkGraph? ?: return
val graph = matterNode.graph as MatterGraph? ?: return
val received = graph.receiveMatter(matter.storedMatter, false)
if (!received.isZero) {

View File

@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block.entity.matter
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
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
@ -10,22 +9,20 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
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.capability.matter.IMatterStorage
import ru.dbotthepony.mc.otm.capability.matter.IPatternState
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTask
import ru.dbotthepony.mc.otm.capability.matter.MatterStorageImpl
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.capability.matter.ReplicationTask
import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
import ru.dbotthepony.mc.otm.container.HandlerFilter
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.menu.matter.MatterReplicatorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.DecimalConfigValue
import ru.dbotthepony.mc.otm.core.math.defineDecimal
@ -33,7 +30,12 @@ import ru.dbotthepony.mc.otm.core.math.getDecimal
import ru.dbotthepony.mc.otm.core.math.set
import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.matter.MatterManager
import ru.dbotthepony.mc.otm.menu.matter.MatterReplicatorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames
class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity<MatterReplicatorBlockEntity.ReplicatorJob>(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_, {
@ -42,7 +44,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
} catch(err: NoSuchElementException) {
null
}
}), IMatterGraphNode {
}) {
class ReplicatorJob : ItemJob {
val matterPerTick: Decimal
@ -98,16 +100,39 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matter = MatterStorageImpl(this::matterLevelUpdated, FlowDirection.INPUT, ::MATTER_CAPACITY)
val container = MatteryContainer(this::itemContainerUpdated, 5).also(::addDroppableContainer)
val itemHandler = container.handler(HandlerFilter.OnlyOut)
val matterNode = object : MatterNode() {
override fun getMatterHandler(): IMatterStorage {
return matter
}
override fun onMatterTaskCreated(task: IReplicationTask<*>) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun <T : IReplicationTask<*>> onMatterTaskUpdated(newState: T, oldState: T) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun onPatternAdded(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
}
init {
exposeEnergyGlobally(energy)
exposeItemsGlobally(itemHandler)
exposeGlobally(MatteryCapability.MATTER, matter)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
savetable(::energy, ENERGY_KEY)
savetable(::matter, MATTER_STORAGE_KEY)
@ -126,7 +151,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return Status.FAILURE_WAIT
}
(matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(job.task.id)
matterNode.graph.notifyTaskCompletion(job.task.id)
return Status.SUCCESS
}
@ -134,38 +159,18 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return Status.FAILURE_ITEM
}
(matterNode.graph as MatterNetworkGraph?)?.notifyTaskCompletion(job.task.id)
matterNode.graph.notifyTaskCompletion(job.task.id)
return Status.SUCCESS
}
override fun onMatterTaskCreated(task: IReplicationTask<*>) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun <T : IReplicationTask<*>> onMatterTaskUpdated(newState: T, oldState: T) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun onPatternAdded(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
matterNode.discover(this)
}
override fun jobUpdated(oldJob: ReplicatorJob?, newJob: ReplicatorJob?) {
@ -176,7 +181,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
var visualItemStack by synchronizer.item(observe = false)
private set
var visualProgress by synchronizer.float()
var visualProgress by synchronizer.float().property
private set
var renderRotation = 0f
@ -188,8 +193,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return null to IdleReason.POWER
}
val graph = matterNode.graph as MatterNetworkGraph? ?: return null to null
val allocation = graph.allocateTask(simulate = false) ?: return null to IdleReason.OBSERVING
val allocation = matterNode.graph.allocateTask(simulate = false) ?: return null to IdleReason.OBSERVING
val stack = allocation.task.stack(1)
val matter = MatterManager.get(stack)
@ -211,7 +215,6 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun onWorkTick(requiredPower: Decimal, extractedPower: Decimal, ticksAdvanced: Double, job: ReplicatorJob): Status {
val drainPerTick = job.matterPerTick * ticksAdvanced
val graph = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT_FAST
if (matter.extractMatterInner(drainPerTick, true) < drainPerTick) {
// в машине недостаточно материи
@ -219,7 +222,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
if (drainPerTick > matter.maxStoredMatter) {
// в тик требуется больше материи, чем её может хранить репликатор
val toExtract = drainPerTick - matter.extractMatterInner(drainPerTick, true)
val drain = graph.extractMatter(toExtract, true)
val drain = matterNode.graph.extractMatter(toExtract, true)
if (drain != toExtract) {
// недостаточно материи в сети
@ -228,12 +231,12 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
// достаточно материи в сети + внутри машины
matter.extractMatterInner(drainPerTick, false)
graph.extractMatter(drain, false)
matterNode.graph.extractMatter(drain, false)
return Status.SUCCESS
} else {
// в тик требуется меньше материи, чем её может хранить репликатор
// примем из сети недостающее количество бака материи, или 200 тиков репликации, что меньше
val drain = graph.extractMatter((drainPerTick * DRAIN_MULT)
val drain = matterNode.graph.extractMatter((drainPerTick * DRAIN_MULT)
.coerceAtMost(job.matterPerTick * (job.ticks - workTicks - ticksAdvanced))
.coerceAtLeast(Decimal.ONE)
.coerceAtMost(matter.missingMatter), false)

View File

@ -22,18 +22,18 @@ 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.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.menu.matter.MatterScannerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.core.util.WriteOnce
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
import ru.dbotthepony.mc.otm.matter.MatterManager
import java.util.*
import kotlin.math.pow
class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::ItemJob), IMatterGraphNode {
MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::ItemJob) {
val container = MatteryContainer(this::itemContainerUpdated, 1).also(::addDroppableContainer)
val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
@ -47,45 +47,43 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
})
val matterNode = object : MatterNode() {
override fun onPatternAdded(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun onPatternRemoved(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
}
init {
exposeItemsGlobally(itemHandler)
exposeEnergyGlobally(energy)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
savetable(::container, INVENTORY_KEY)
savetable(::energy, ENERGY_KEY)
}
// IMatterGraphNode
override fun onPatternAdded(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun onPatternRemoved(state: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) {
if (idleReason == IdleReason.OBSERVING) {
isIdling = false
}
}
// /IMatterGraphNode
override val matterNode: Graph6Node<IMatterGraphNode> = Graph6Node(this)
override fun invalidateCaps() {
super.invalidateCaps()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
@ -93,14 +91,12 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
override fun onJobFinish(job: ItemJob): Status {
val grid = matterNode.graph as MatterNetworkGraph? ?: return Status.FAILURE_WAIT
val stack = job.itemStack
if (stack.isEmpty || !MatterManager.hasMatterValue(stack)) return Status.SUCCESS
var findState: IPatternState? = null
for (state in grid.patterns.filter { it.item === stack.item }) {
for (state in matterNode.graph.patterns.filter { it.item === stack.item }) {
if (findState == null && state.researchPercent < 1.0) {
findState = state
} else if (findState != null && findState.researchPercent < state.researchPercent && state.researchPercent < 1.0) {
@ -117,7 +113,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
PatternState(UUID.randomUUID(), stack.item, researchAdvance)
}
if (!grid.insertPattern(new, onlyUpdate = false, simulate = false).isFailed) {
if (!matterNode.graph.insertPattern(new, onlyUpdate = false, simulate = false).isFailed) {
return Status.SUCCESS
} else {
return Status.FAILURE_WAIT
@ -129,14 +125,12 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
return null to IdleReason.POWER
}
val grid = matterNode.graph as MatterNetworkGraph? ?: return null to null
val stack = container.getItem(0)
if (stack.isEmpty || !MatterManager.canDecompose(stack)) return null to IdleReason.ITEM
var findState: IPatternState? = null
for (state in grid.patterns.filter { it.item === stack.item }) {
for (state in matterNode.graph.patterns.filter { it.item === stack.item }) {
if (state.researchPercent < 1.0) {
findState = state
} else if (state.researchPercent >= 1.0) {
@ -155,7 +149,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
PatternState(UUID.randomUUID(), stack.item, researchAdvance)
}
if (!grid.insertPattern(new, onlyUpdate = false, simulate = true).isFailed) {
if (!matterNode.graph.insertPattern(new, onlyUpdate = false, simulate = true).isFailed) {
val copy = stack.copy().also { it.count = 1 }
stack.shrink(1)
container.setChanged()
@ -168,10 +162,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel) {
MatterNetworkGraph.discoverFull(this, matterNode)
}
matterNode.discover(this)
}
companion object {

View File

@ -20,8 +20,8 @@ import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.capability.matter.*
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.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.ArrayList
import java.util.stream.Stream
@ -29,24 +29,22 @@ import java.util.stream.Stream
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryDeviceBlockEntity(MBlockEntities.PATTERN_STORAGE, p_155229_, p_155230_), IMatterGraphNode, IPatternStorage {
MatteryDeviceBlockEntity(MBlockEntities.PATTERN_STORAGE, p_155229_, p_155230_), IPatternStorage {
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matterNode = SimpleMatterNode(patterns = this)
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 8) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
val grid = matterNode.graph as MatterNetworkGraph?
if (grid != null && !ItemStack.isSameItemSameTags(new, old)) {
if (!ItemStack.isSameItemSameTags(new, old)) {
if (!old.isEmpty) {
old.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
cap.patterns.forEach { grid.onPatternRemoved(it) }
cap.patterns.forEach { matterNode.graph.onPatternRemoved(it) }
}
}
if (!new.isEmpty) {
new.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
cap.patterns.forEach { grid.onPatternAdded(it) }
cap.patterns.forEach { matterNode.graph.onPatternAdded(it) }
}
}
@ -82,23 +80,17 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
MatterNetworkGraph.discoverFull(this, matterNode)
}
override fun getPatternHandler(): IPatternStorage {
return this
matterNode.discover(this)
}
override fun invalidateCaps() {
super.invalidateCaps()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
init {
exposeGlobally(MatteryCapability.PATTERN, this)
exposeGlobally(MatteryCapability.MATTER_NODE, this)
exposeGlobally(MatteryCapability.MATTER_NODE, matterNode)
exposeItemsGlobally(itemHandler)
savetable(::container, INVENTORY_KEY)
@ -138,7 +130,7 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun setRemoved() {
super.setRemoved()
matterNode.destroy(::MatterNetworkGraph)
matterNode.isValid = false
}
override fun insertPattern(pattern: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
@ -149,14 +141,10 @@ class PatternStorageBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
if (!simulate) {
setChanged()
val graph = matterNode.graph as MatterNetworkGraph?
if (graph != null) {
if (status.isInserted) {
graph.onPatternAdded(status.newState!!)
} else {
graph.onPatternUpdated(status.newState!!, status.oldState!!)
}
if (status.isInserted) {
matterNode.graph.onPatternAdded(status.newState!!)
} else {
matterNode.graph.onPatternUpdated(status.newState!!, status.oldState!!)
}
}

View File

@ -9,13 +9,13 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
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.container.MatteryContainer
import ru.dbotthepony.mc.otm.menu.storage.DriveRackMenu
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.storage.*
@ -41,7 +41,7 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
}.also(::addDroppableContainer)
val cell = BasicStorageGraphNode(energy)
val cell = StorageNode(energy)
init {
savetable(::energy, ENERGY_KEY)
@ -52,9 +52,7 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
StorageNetworkGraph.discoverFull(this, cell.storageNode)
cell.discover(this)
}
override fun tick() {
@ -68,6 +66,6 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun setRemoved() {
super.setRemoved()
cell.destroy(level)
cell.isValid = false
}
}

View File

@ -30,8 +30,8 @@ import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.container.set
@ -188,13 +188,13 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
var poweredView: PoweredVirtualComponent<ItemStackWrapper>? = null
private set
val cell = object : BasicStorageGraphNode(energy) {
override fun attachComponents(to: StorageNetworkGraph) {
val cell = object : StorageNode(energy) {
override fun attachComponents(to: StorageGraph) {
super.attachComponents(to)
poweredView = PoweredVirtualComponent(to.getVirtualComponent(ITEM_STORAGE), energy)
}
override fun removeComponents(from: StorageNetworkGraph) {
override fun removeComponents(from: StorageGraph) {
super.removeComponents(from)
poweredView?.removeListeners()
poweredView = null
@ -499,13 +499,11 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel)
StorageNetworkGraph.discoverFull(this, cell.storageNode)
cell.discover(this)
}
override fun setRemoved() {
super.setRemoved()
cell.destroy(level)
cell.isValid = false
}
}

View File

@ -4,8 +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.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
@ -31,21 +29,14 @@ 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.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.GraphNodeListener
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.menu.storage.StorageBusMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.storage.*
import java.lang.ref.WeakReference
import java.math.BigInteger
import java.util.*
import java.util.stream.Stream
import kotlin.NoSuchElementException
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
private class SlotTuple(val slot: Int, val stack: ItemStack)
private class TrackedTuple(override val stack: ItemStackWrapper, override val id: UUID) : IStorageTuple<ItemStackWrapper> {
@ -77,15 +68,15 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
savetable(::energy, ENERGY_KEY)
}
val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener {
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
val cell: StorageNode = object : StorageNode(energy) {
override fun onNeighbour(direction: Direction) {
val newState = this@StorageBusBlockEntity.blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, true)
if (newState !== this@StorageBusBlockEntity.blockState && SERVER_IS_LIVE)
level?.setBlock(blockPos, newState, Block.UPDATE_CLIENTS)
}
override fun onUnNeighbour(node: Graph6Node<*>, direction: Direction) {
override fun onUnNeighbour(direction: Direction) {
val newState = this@StorageBusBlockEntity.blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, false)
if (newState !== this@StorageBusBlockEntity.blockState && SERVER_IS_LIVE)
@ -109,11 +100,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel) {
StorageNetworkGraph.discoverFull(this, cell.storageNode)
}
cell.discover(this)
tickList.once(this::checkSurroundings)
}
@ -128,7 +115,7 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
override fun setRemoved() {
super.setRemoved()
cell.destroy(level)
cell.isValid = false
}
fun checkSurroundings() {

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.block.entity.storage
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
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
@ -26,14 +25,10 @@ import ru.dbotthepony.mc.otm.config.ConciseBalanceValues
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.container.ItemFilter
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.toIntSafe
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
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.menu.storage.StorageExporterMenu
import ru.dbotthepony.mc.otm.menu.storage.StorageImporterMenu
import ru.dbotthepony.mc.otm.once
@ -62,8 +57,8 @@ abstract class AbstractStorageImportExport<T>(
savetable(::energy, ENERGY_KEY)
}
val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener {
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
val cell: StorageNode = object : StorageNode(energy) {
override fun onNeighbour(direction: Direction) {
level?.once {
if (!isRemoved) {
val newState = this@AbstractStorageImportExport.blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, true)
@ -74,7 +69,7 @@ abstract class AbstractStorageImportExport<T>(
}
}
override fun onUnNeighbour(node: Graph6Node<*>, direction: Direction) {
override fun onUnNeighbour(direction: Direction) {
level?.once {
if (!isRemoved) {
val newState = this@AbstractStorageImportExport.blockState.setValue(CableBlock.MAPPING_CONNECTION_PROP[direction]!!, false)
@ -93,15 +88,12 @@ abstract class AbstractStorageImportExport<T>(
override fun setRemoved() {
super.setRemoved()
cell.destroy(level)
cell.isValid = false
}
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel) {
StorageNetworkGraph.discoverFull(this, cell.storageNode)
}
cell.discover(this)
}
protected abstract val targetCapability: Capability<T>
@ -117,7 +109,6 @@ abstract class AbstractStorageImportExport<T>(
}
companion object {
val MAX_POWER = Decimal(10_000)
const val FILTER_KEY = "filter"
}
}
@ -155,7 +146,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : A
if (redstoneControl.isBlockedByRedstone || !filter.match(stack))
return stack
val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return stack
val view = cell.graph.getVirtualComponent(ITEM_STORAGE)
val maxMove = energy.extractEnergyExact(ITEM_STORAGE.energyPerOperation, stack.count.toBigInteger(), true)
if (maxMove == BigInteger.ZERO)
@ -195,8 +186,7 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : A
val target = target.get().orNull()
if (nextTick <= 0 && target != null && enoughEnergy) {
val graph = cell.storageGraph ?: return
val items = graph.getVirtualComponent(ITEM_STORAGE)
val items = cell.graph.getVirtualComponent(ITEM_STORAGE)
if (lastSlot >= target.slots) {
lastSlot = 0
@ -227,7 +217,6 @@ class StorageImporterBlockEntity(blockPos: BlockPos, blockState: BlockState) : A
companion object {
const val MAX_MOVE_PER_OPERATION = 4
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_IMPORTER}")
private const val INTERVAL = 5
const val MAX_FILTERS = 6 * 3
}
@ -271,7 +260,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
override val filter = ItemFilter(MAX_FILTERS) { _, _, _ ->
relevantTuples.clear()
val component = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return@ItemFilter
val component = cell.graph.getVirtualComponent(ITEM_STORAGE)
for (tuple in component.stacks) {
addStack(tuple, component)
@ -291,7 +280,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
private val exportStacks: Stream<Pair<UUID, ItemStackWrapper>>
get() {
val view = cell.storageGraph?.getVirtualComponent(ITEM_STORAGE) ?: return Stream.empty()
val view = cell.graph.getVirtualComponent(ITEM_STORAGE)
return relevantTuples.stream().map { it to view[it] }
}
@ -308,8 +297,7 @@ class StorageExporterBlockEntity(blockPos: BlockPos, blockState: BlockState) :
val target = target.get().orNull()
if (nextTick <= 0 && target != null && enoughEnergy) {
val graph = cell.storageGraph ?: return
val items = graph.getVirtualComponent(ITEM_STORAGE)
val items = cell.graph.getVirtualComponent(ITEM_STORAGE)
if (lastSlot >= target.slots) {
lastSlot = 0

View File

@ -13,8 +13,8 @@ import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.energy.transferChecked
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.graph.storage.StorageNode
import ru.dbotthepony.mc.otm.graph.storage.StorageGraph
import ru.dbotthepony.mc.otm.menu.storage.StoragePowerSupplierMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
@ -23,7 +23,7 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
return StoragePowerSupplierMenu(containerID, inventory, this)
}
val cell = BasicStorageGraphNode()
val cell = StorageNode()
val energy = WorkerEnergyStorage(this, MachinesConfig.STORAGE_POWER_SUPPLIER)
init {
@ -42,15 +42,12 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
override fun setLevel(level: Level) {
super.setLevel(level)
if (level is ServerLevel) {
StorageNetworkGraph.discoverFull(this, cell.storageNode)
}
cell.discover(this)
}
override fun setRemoved() {
super.setRemoved()
cell.destroy(level)
cell.isValid = false
}
override fun tick() {
@ -62,9 +59,7 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
if (energy.batteryLevel.isZero)
return
val graph = cell.storageGraph ?: return
if (graph.powerDemandingNodes.isEmpty())
if (cell.graph.powerDemandingNodes.isEmpty())
return
var demand = Decimal.ZERO
@ -72,7 +67,7 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
val available = energy.batteryLevel.coerceAtMost(MachinesConfig.STORAGE_POWER_SUPPLIER.throughput)
for (demanding in graph.powerDemandingNodes) {
for (demanding in cell.graph.powerDemandingNodes) {
val received = demanding.receiveEnergy(available, true)
if (received.isPositive) {
@ -84,13 +79,13 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
if (demand.isZero) {
return
} else if (demand < available) {
for (demanding in graph.powerDemandingNodes) {
for (demanding in cell.graph.powerDemandingNodes) {
powerPassed += energy.transferChecked(demanding, available, false)
}
} else {
val forEach = available / i
for (demanding in graph.powerDemandingNodes) {
for (demanding in cell.graph.powerDemandingNodes) {
powerPassed += energy.transferChecked(demanding, forEach, false)
}
}

View File

@ -21,8 +21,9 @@ 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.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
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
@ -206,14 +207,14 @@ private class QIOStorage(private val tile: TileEntityQIODriveArray) : ICapabilit
private var frequencyAccess: QIOFrequencyAccess? = null
private var wasAttached = false
val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(), ITickable {
val cell: StorageNode = object : StorageNode(), ITickable {
init {
manualAttaching = true
}
override fun tick() {
if (tile.isRemoved) {
destroy(tile.level)
isValid = false
return
}
@ -225,9 +226,7 @@ private class QIOStorage(private val tile: TileEntityQIODriveArray) : ICapabilit
val lastFrequency = lastFrequency ?: throw IllegalStateException("lastFrequency is null")
checkNotNull(storageGraph) {
"Unexpected internal state (expected storage graph to be present, something detached $this from storage grid, but did not call removeComponents())"
}.userData.remove(key(lastFrequency))
graph.userData.remove(key(lastFrequency))
}
frequencyAccess?.let(this::removeStorageComponent)
@ -240,17 +239,16 @@ private class QIOStorage(private val tile: TileEntityQIODriveArray) : ICapabilit
val frequencyAccess = frequencyAccess ?: return
frequencyAccess.scan()
val storageGraph = storageGraph ?: return
val key = key(frequencyAccess.parent)
if (!storageGraph.userData.containsKey(key)) {
storageGraph.userData[key] = true
if (!graph.userData.containsKey(key)) {
graph.userData[key] = true
wasAttached = true
storageGraph.add(frequencyAccess)
graph.add(frequencyAccess)
}
}
override fun removeComponents(from: StorageNetworkGraph) {
override fun removeComponents(from: StorageGraph) {
super.removeComponents(from)
if (wasAttached) {
@ -259,11 +257,23 @@ private class QIOStorage(private val tile: TileEntityQIODriveArray) : ICapabilit
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 cell.get().cast()
return holder.get()
return LazyOptional.empty()
}
@ -286,8 +296,8 @@ fun attachCapabilities(event: AttachCapabilitiesEvent<BlockEntity>) {
event.addCapability(QIO_LOCATION, capability)
onceServer {
if (!event.`object`.isRemoved && event.`object`.level?.isClientSide == false) {
StorageNetworkGraph.discoverFull(event.`object`, capability.cell.storageNode)
if (!event.`object`.isRemoved) {
capability.cell.discover(event.`object`, MatteryCapability.STORAGE_NODE)
}
}
}

View File

@ -0,0 +1,20 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraftforge.common.util.LazyOptional
class LOHolder<T : Any>(val value: T) {
private var lazyOptional: LazyOptional<T> = LazyOptional.of { value }
fun invalidate() {
lazyOptional.invalidate()
}
fun revive() {
lazyOptional.invalidate()
lazyOptional = LazyOptional.of { value }
}
fun <T> get(): LazyOptional<T> {
return lazyOptional.cast()
}
}

View File

@ -1,178 +1,172 @@
package ru.dbotthepony.mc.otm.graph
import net.minecraft.core.BlockPos
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 ru.dbotthepony.mc.otm.core.util.IConditionalTickable
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.addTicker
import ru.dbotthepony.mc.otm.core.util.ITickable
import java.lang.ref.WeakReference
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
abstract class Abstract6Graph<T> : IConditionalTickable {
protected val nodes = ArrayList<Graph6Node<T>>()
fun size() = nodes.size
private val tickable = ArrayList<Graph6Node<T>>()
val nodeList: Collection<Graph6Node<T>> = Collections.unmodifiableCollection(nodes)
open class Abstract6Graph<N : Graph6Node<N, G>, G : Abstract6Graph<N, G>> : IConditionalTickable {
private val nodesInternal = ArrayList<N>()
private val conditional = ArrayList<IConditionalTickable>()
private val always = ArrayList<ITickable>()
protected val nodes: List<N> = Collections.unmodifiableList(nodesInternal)
val size get() = nodesInternal.size
var isMerged = false
private set
private var isTicking = false
/**
* Allows storing arbitrary data by external code
*/
@JvmField
val userData = HashMap<UUID, Any>()
abstract fun onNodeRemoved(node: Graph6Node<T>)
abstract fun onNodeAdded(node: Graph6Node<T>)
open fun onNodeRemoved(node: N) {}
open fun onNodeAdded(node: N) {}
open fun onMergedInto(other: G) {}
override fun tick(): Boolean {
for (i in tickable.size - 1 downTo 0) {
val node = tickable[i]
protected open fun innerTick(): Boolean {
return false
}
final override fun tick(): Boolean {
if (isMerged)
return false
// позволяет вершинам изменять список тикающих вершин
for (i in conditional.size - 1 downTo 0) {
val node = conditional[i]
if (!node.tick()) {
tickable.removeAt(i)
conditional.removeAt(i)
}
}
return nodes.size > 0
// позволяет вершинам изменять список тикающих вершин
for (node in always.size - 1 downTo 0) {
always[node].tick()
}
return innerTick() || always.isNotEmpty() || conditional.isNotEmpty()
}
fun removeNode(node: Graph6Node<T>) {
if (!nodes.remove(node))
throw IllegalStateException("Not containing node $node")
fun addNode(node: N): Boolean {
if (node in nodesInternal)
return false
node.graph = null
onNodeRemoved(node)
tickable.remove(node)
}
nodesInternal.add(node)
fun addNode(node: Graph6Node<T>) {
if (nodes.contains(node))
throw IllegalStateException("Already containing node $node")
if (node is IConditionalTickable) {
conditional.add(node)
if (!isTicking) {
isTicking = true
next.add(WeakReference(this))
}
} else if (node is ITickable) {
always.add(node)
if (!isTicking) {
isTicking = true
next.add(WeakReference(this))
}
}
nodes.add(node)
node.graph = this
onNodeAdded(node)
tickable.add(node)
return true
}
fun merge(other: Abstract6Graph<T>): Abstract6Graph<T> {
fun removeNode(node: N): Boolean {
if (!nodesInternal.remove(node))
return false
nodesInternal.remove(node)
if (node is IConditionalTickable)
conditional.remove(node)
else if (node is ITickable)
always.remove(node)
onNodeRemoved(node)
return true
}
fun retain(nodes: Set<N>) {
for (i in this.nodesInternal.size - 1 downTo 0) {
if (this.nodesInternal[i] !in nodes) {
val node = this.nodesInternal[i]
this.nodesInternal.removeAt(i)
if (node is IConditionalTickable)
conditional.remove(node)
else if (node is ITickable)
always.remove(node)
onNodeRemoved(node)
}
}
}
fun merge(other: G, setter: (N, G) -> Unit): G {
if (other === this)
return this
if (size() >= other.size()) {
for (node in other.nodes) {
nodes.add(node)
node.graph = this
if (size >= other.size) {
for (node in other.nodesInternal) {
nodesInternal.add(node)
setter.invoke(node, this as G)
onNodeAdded(node)
if (node is IConditionalTickable) {
conditional.add(node)
if (!isTicking) {
isTicking = true
next.add(WeakReference(this))
}
} else if (node is ITickable) {
always.add(node)
if (!isTicking) {
isTicking = true
next.add(WeakReference(this))
}
}
}
other.isMerged = true
other.onMergedInto(this as G)
return this
} else {
return other.merge(this)
return other.merge(this as G, setter)
}
}
companion object {
fun <T> discoverFull(
level: ServerLevel,
blockPos: BlockPos,
node: Graph6Node<T>,
nodeGetter: (BlockEntity) -> Graph6Node<T>?,
factory: () -> Abstract6Graph<T>
) {
level.addTicker {
!discover(level, blockPos, node, nodeGetter, factory) && node.valid
}
}
private val graphs = ArrayList<WeakReference<Abstract6Graph<*, *>>>()
private val next = ArrayList<WeakReference<Abstract6Graph<*, *>>>()
@JvmStatic
fun <T> discover(
level: ServerLevel,
blockPos: BlockPos,
node: Graph6Node<T>,
nodeGetter: (BlockEntity) -> Graph6Node<T>?,
factory: () -> Abstract6Graph<T>
): Boolean {
var fullDiscovery = true
node.nullifyConnections()
var _graph = node.graph
// для начала найдем граф к которому будем принадлежать
if (_graph == null) {
for (dir in Direction.values()) {
val offset = blockPos + dir
val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(offset.x), SectionPos.blockToSectionCoord(offset.z))
if (chunk == null) {
fullDiscovery = false
continue
}
val entity = chunk.getBlockEntity(offset)
if (entity != null) {
val getNode = nodeGetter(entity)
if (getNode?.graph != null) {
_graph = getNode.graph
break
}
}
}
// мы нашли граф рядом
if (_graph != null) {
node.graph = _graph
_graph.addNode(node)
} else {
// графов рядом нет, создаем свой
_graph = factory()
node.graph = _graph
_graph.addNode(node)
}
fun tick() {
if (next.isNotEmpty()) {
graphs.addAll(next)
next.clear()
}
// теперь снова смотрим на соседей, если у них нет графа - присоединяем к своему
// если у них есть граф - слияем его со своим или свой с его
for (dir in Direction.values()) {
val offset = blockPos + dir
val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(offset.x), SectionPos.blockToSectionCoord(offset.z))
val iterator = graphs.iterator()
if (chunk == null) {
fullDiscovery = false
continue
}
for (value in iterator) {
val graph = value.get()
val entity = chunk.getBlockEntity(offset)
if (entity != null) {
val getNode = nodeGetter(entity)
if (getNode != null) {
// у вершины нет своего графа
// добавляем в свой граф
if (getNode.graph == null) {
getNode.graph = node.graph!!
node.graph!!.addNode(getNode)
} else if (getNode.graph != node.graph) {
// у вершины уже есть свой граф, и он не наш
// произведём слияние графов
val merged = getNode.graph!!.merge(node.graph!!)
getNode.graph = merged
node.graph = merged
}
node.setToNeightbour(getNode, dir)
}
if (graph == null || !graph.tick()) {
graph?.isTicking = false
iterator.remove()
}
}
return fullDiscovery
}
}
}

View File

@ -1,313 +1,268 @@
package ru.dbotthepony.mc.otm.graph
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
import ru.dbotthepony.mc.otm.core.util.ITickable
import ru.dbotthepony.mc.otm.SERVER_IS_LIVE
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 ru.dbotthepony.mc.otm.addTicker
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.core.math.unaryMinus
import ru.dbotthepony.mc.otm.core.orNull
import java.util.EnumMap
import java.util.concurrent.atomic.AtomicInteger
interface GraphNodeListener {
fun onNeighbourTop(node: Graph6Node<*>) = onNeighbour(node, Direction.UP)
fun onNeighbourBottom(node: Graph6Node<*>) = onNeighbour(node, Direction.DOWN)
fun onNeighbourLeft(node: Graph6Node<*>) = onNeighbour(node, Direction.WEST)
fun onNeighbourRight(node: Graph6Node<*>) = onNeighbour(node, Direction.EAST)
fun onNeighbourFront(node: Graph6Node<*>) = onNeighbour(node, Direction.SOUTH)
fun onNeighbourBack(node: Graph6Node<*>) = onNeighbour(node, Direction.NORTH)
open class Graph6Node<N : Graph6Node<N, G>, G : Abstract6Graph<N, G>>(val graphFactory: () -> G) {
private val neighbours = EnumMap<Direction, N>(Direction::class.java)
fun onNeighbour(node: Graph6Node<*>, direction: Direction)
fun onUnNeighbourTop(node: Graph6Node<*>) = onUnNeighbour(node, Direction.UP)
fun onUnNeighbourBottom(node: Graph6Node<*>) = onUnNeighbour(node, Direction.DOWN)
fun onUnNeighbourLeft(node: Graph6Node<*>) = onUnNeighbour(node, Direction.WEST)
fun onUnNeighbourRight(node: Graph6Node<*>) = onUnNeighbour(node, Direction.EAST)
fun onUnNeighbourFront(node: Graph6Node<*>) = onUnNeighbour(node, Direction.SOUTH)
fun onUnNeighbourBack(node: Graph6Node<*>) = onUnNeighbour(node, Direction.NORTH)
fun onUnNeighbour(node: Graph6Node<*>, direction: Direction)
}
// Вершина графа, содержит то, к какому графу принадлежит, соседей и своё "значение"
class Graph6Node<T>(@JvmField val value: T, graph: Abstract6Graph<T>? = null) : IConditionalTickable {
var graph: Abstract6Graph<T>? = null
init {
this.graph = graph
}
var top: Graph6Node<T>? = null
set(value) {
if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph")
if (field != value && this.value is GraphNodeListener) {
if (field != null) {
this.value.onUnNeighbourTop(field!!)
}
if (value != null) {
this.value.onNeighbourTop(value)
}
}
field = value
}
var bottom: Graph6Node<T>? = null
set(value) {
if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph")
if (field != value && this.value is GraphNodeListener) {
if (field != null) {
this.value.onUnNeighbourBottom(field!!)
}
if (value != null) {
this.value.onNeighbourBottom(value)
}
}
field = value
}
var left: Graph6Node<T>? = null
set(value) {
if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph")
if (field != value && this.value is GraphNodeListener) {
if (field != null) {
this.value.onUnNeighbourLeft(field!!)
}
if (value != null) {
this.value.onNeighbourLeft(value)
}
}
field = value
}
var right: Graph6Node<T>? = null
set(value) {
if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph")
if (field != value && this.value is GraphNodeListener) {
if (field != null) {
this.value.onUnNeighbourRight(field!!)
}
if (value != null) {
this.value.onNeighbourRight(value)
}
}
field = value
}
var front: Graph6Node<T>? = null
set(value) {
if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph")
if (field != value && this.value is GraphNodeListener) {
if (field != null) {
this.value.onUnNeighbourFront(field!!)
}
if (value != null) {
this.value.onNeighbourFront(value)
}
}
field = value
}
var back: Graph6Node<T>? = null
set(value) {
if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph")
if (field != value && this.value is GraphNodeListener) {
if (field != null) {
this.value.onUnNeighbourBack(field!!)
}
if (value != null) {
this.value.onNeighbourBack(value)
}
}
field = value
}
fun nullifyConnections() {
top?.bottom = null
bottom?.top = null
left?.right = null
right?.left = null
front?.back = null
back?.front = null
top = null
bottom = null
left = null
right = null
front = null
back = null
}
fun setToNeightbour(node: Graph6Node<T>, direction: Direction) {
when (direction) {
Direction.DOWN -> {
node.top = this
bottom = node
}
Direction.UP -> {
node.bottom = this
top = node
}
Direction.NORTH -> {
node.front = this
back = node
}
Direction.SOUTH -> {
node.back = this
front = node
}
Direction.WEST -> {
node.right = this
left = node
}
Direction.EAST -> {
node.left = this
right = node
}
}
}
override fun tick(): Boolean {
if (value is IConditionalTickable) {
return value.tick()
} else if (value is ITickable) {
value.tick()
return true
} else {
return false
}
}
var seen: Int = 0
private fun _flood(): List<GraphFlooder<T>> {
val list = ArrayList<GraphFlooder<T>>()
var seen = Int.MAX_VALUE
GraphFlooder.floodIf(top, seen) {
seen = it.seen
list.add(it)
}
GraphFlooder.floodIf(bottom, seen) {
seen = it.seen
list.add(it)
}
GraphFlooder.floodIf(left, seen) {
seen = it.seen
list.add(it)
}
GraphFlooder.floodIf(right, seen) {
seen = it.seen
list.add(it)
}
GraphFlooder.floodIf(front, seen) {
seen = it.seen
list.add(it)
}
GraphFlooder.floodIf(back, seen) {
seen = it.seen
list.add(it)
}
return list
}
fun flood(): List<GraphFlooder<T>> {
top?.bottom = null
bottom?.top = null
left?.right = null
right?.left = null
front?.back = null
back?.front = null
val list = _flood()
top?.bottom = this
bottom?.top = this
left?.right = this
right?.left = this
front?.back = this
back?.front = this
return list
}
var valid = true
var graph: G = graphFactory.invoke()
private set
fun destroy(factory: () -> Abstract6Graph<T>): List<GraphFlooder<T>> {
if (!valid || !SERVER_IS_LIVE) return emptyList()
init {
graph.addNode(this as N)
}
top?.bottom = null
bottom?.top = null
left?.right = null
right?.left = null
front?.back = null
back?.front = null
private var seen: Int = 0
graph?.removeNode(this)
operator fun get(direction: Direction): N? = neighbours[direction]
var num = 0
operator fun set(direction: Direction, node: N?) {
set(direction, node, false)
}
if (top != null) num++
if (bottom != null) num++
if (left != null) num++
if (right != null) num++
if (front != null) num++
if (back != null) num++
fun set(direction: Direction, node: N?, allowReplacement: Boolean) {
check(isValid) { "Can not neighbour any node while this node is invalid" }
if (num < 2) {
return emptyList()
val old = neighbours[direction]
if (old === node) return
if (old != null)
breakConnection(this as N, old, direction)
if (node != null) {
require(node.isValid) { "Can not neighbour invalid node" }
val opposite = -direction
if (allowReplacement) {
node.neighbours[opposite]?.let {
breakConnection(node, it, opposite)
}
check(node.neighbours[opposite] == null) { "$node didn't break connection at direction $opposite" }
} else {
check(node.neighbours[opposite] == null) { "Trying to form connection from $this to $node at direction $direction, but $node already has neighbour at $opposite (${node.neighbours[opposite]})!" }
}
node.neighbours[opposite] = this as N
neighbours[direction] = node
node.graph.merge(graph, setter)
node.onNeighbour(opposite)
onNeighbour(direction)
} else {
neighbours.remove(direction)
}
}
var top: N?
get() = neighbours[Direction.UP]
set(value) {
set(Direction.UP, value)
}
val paths = _flood()
if (paths.size < 2) {
return paths
var bottom: N?
get() = neighbours[Direction.DOWN]
set(value) {
set(Direction.DOWN, value)
}
var biggest = paths[0]
var south: N?
get() = neighbours[Direction.SOUTH]
set(value) {
set(Direction.SOUTH, value)
}
for (i in 1 until paths.size) {
if (biggest.size() < paths[i].size()) {
biggest = paths[i]
var north: N?
get() = neighbours[Direction.NORTH]
set(value) {
set(Direction.NORTH, value)
}
var west: N?
get() = neighbours[Direction.WEST]
set(value) {
set(Direction.WEST, value)
}
var east: N?
get() = neighbours[Direction.EAST]
set(value) {
set(Direction.EAST, value)
}
open fun onNeighbour(direction: Direction) {}
open fun onUnNeighbour(direction: Direction) {}
protected open fun invalidate() {}
protected open fun revive() {}
var isValid: Boolean = true
set(value) {
if (value == field) return
field = value
if (!value) {
val neighbours = ArrayList(neighbours.entries)
for ((dir, node) in neighbours) {
breakConnection(this as N, node, dir)
}
graph.removeNode(this as N)
invalidate()
} else {
revive()
}
}
for (flooder in paths) {
if (flooder == biggest) continue
fun discover(
level: ServerLevel,
blockPos: BlockPos,
nodeGetter: (BlockEntity) -> N?
) {
if (!isValid) return
val graph = factory()
level.addTicker {
isValid && !discoverStep(level, blockPos, nodeGetter)
}
}
for (node in flooder.nodes) {
node.graph?.removeNode(node)
graph.addNode(node)
fun discover(
level: ServerLevel,
blockPos: BlockPos,
capability: Capability<out N>
) {
if (!isValid) return
level.addTicker {
isValid && !discoverStep(level, blockPos) { it.getCapability(capability).orNull() }
}
}
fun discover(blockEntity: BlockEntity, nodeGetter: (BlockEntity) -> N?) {
discover(blockEntity.level as? ServerLevel ?: return, blockEntity.blockPos, nodeGetter)
}
fun discover(blockEntity: BlockEntity, capability: Capability<out N>) {
discover(blockEntity.level as? ServerLevel ?: return, blockEntity.blockPos, capability)
}
fun discoverStep(
level: ServerLevel,
blockPos: BlockPos,
nodeGetter: (BlockEntity) -> N?,
): Boolean {
if (!isValid) return false
var fullDiscovery = true
for (dir in directions) {
val offset = blockPos + dir
val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(offset.x), SectionPos.blockToSectionCoord(offset.z))
if (chunk == null) {
fullDiscovery = false
set(dir, null)
continue
}
val entity = chunk.getBlockEntity(offset)
if (entity != null) {
set(dir, nodeGetter(entity))
} else {
set(dir, null)
}
}
return paths
return fullDiscovery
}
companion object {
private val setter = Graph6Node<*, *>::graph::set
private val nextSeen = AtomicInteger()
private val directions = Direction.values()
private fun <N : Graph6Node<N, G>, G : Abstract6Graph<N, G>> breakConnection(a: N, b: N, direction: Direction) {
val opposite = -direction
require(a.neighbours[direction] === b) { "$a does not neighbour with $b at direction $direction (forward)" }
require(b.neighbours[opposite] === a) { "$b does not neighbour with $a at direction $opposite (backward)" }
require(a.graph === b.graph) { "$a and $b belong to different graphs (${a.graph} vs ${b.graph})" }
a.neighbours.remove(direction)
b.neighbours.remove(opposite)
val seen = nextSeen.incrementAndGet()
val flood1 = flood(a, seen)
if (b.seen != seen) {
val flood2 = flood(b, seen)
val big: ArrayList<N>
val small: ArrayList<N>
if (flood1.size >= flood2.size) {
big = flood1
small = flood2
} else {
big = flood2
small = flood1
}
a.graph.retain(ReferenceOpenHashSet(big))
val newGraph = a.graphFactory.invoke()
for (node in small) {
node.graph = newGraph
}
for (node in small) {
if (node.isValid) {
newGraph.addNode(node)
}
}
}
if (a.isValid)
a.onUnNeighbour(direction)
if (b.isValid)
b.onUnNeighbour(opposite)
}
private fun <N : Graph6Node<N, G>, G : Abstract6Graph<N, G>> flood(startingNode: N, seen: Int): ArrayList<N> {
val unopen = ArrayList<N>()
val result = ArrayList<N>()
unopen.add(startingNode)
while (unopen.isNotEmpty()) {
val last = unopen.removeLast()
if (last.seen < seen) {
result.add(last)
last.seen = seen
for (node in last.neighbours.values) {
if (node.seen < seen) {
unopen.add(node)
}
}
}
}
return result
}
}
}

View File

@ -1,64 +0,0 @@
package ru.dbotthepony.mc.otm.graph
import java.util.*
import kotlin.collections.ArrayList
class GraphFlooder<T>(val startNode: Graph6Node<T>, @JvmField val seen: Int = nextSeen++) {
var flooded = false
private set
private val _nodes = ArrayList<Graph6Node<T>>()
@JvmField
val nodes = Collections.unmodifiableCollection(_nodes)!!
fun size() = _nodes.size
private fun flood(node: Graph6Node<T>) {
if (node.seen >= seen) return
_nodes.add(node)
node.seen = seen
if (node.top != null) flood(node.top!!)
if (node.bottom != null) flood(node.bottom!!)
if (node.left != null) flood(node.left!!)
if (node.right != null) flood(node.right!!)
if (node.front != null) flood(node.front!!)
if (node.back != null) flood(node.back!!)
}
fun flood() {
if (flooded) throw IllegalStateException("Already flooded")
flooded = true
_nodes.add(startNode)
startNode.seen = seen
if (startNode.top != null) flood(startNode.top!!)
if (startNode.bottom != null) flood(startNode.bottom!!)
if (startNode.left != null) flood(startNode.left!!)
if (startNode.right != null) flood(startNode.right!!)
if (startNode.front != null) flood(startNode.front!!)
if (startNode.back != null) flood(startNode.back!!)
}
companion object {
private var nextSeen = 0
fun <T> floodIf(node: Graph6Node<T>?, seen: Int, runnable: (GraphFlooder<T>) -> Unit) {
if (node != null && node.seen < seen) {
if (seen == Int.MAX_VALUE) {
val flooder = GraphFlooder(node)
flooder.flood()
runnable(flooder)
} else {
val flooder = GraphFlooder(node, seen)
flooder.flood()
runnable(flooder)
}
}
}
}
}

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.graph.matter
import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.graph.Graph6Node
interface IMatterGraphListener {
fun onPatternAdded(state: IPatternState) {}
@ -13,12 +12,3 @@ interface IMatterGraphListener {
fun onMatterTaskFinished(state: IReplicationTask<*>) {}
fun onMatterTaskRemoved(state: IReplicationTask<*>) {}
}
interface IMatterGraphNode : IMatterGraphListener {
fun getMatterHandler(): IMatterStorage? = null
fun getPatternHandler(): IPatternStorage? = null
fun getTaskHandler(): IReplicationTaskProvider? = null
val matterNode: Graph6Node<IMatterGraphNode>
val matterGraph: MatterNetworkGraph? get() = matterNode.graph as MatterNetworkGraph?
}

View File

@ -1,30 +1,25 @@
package ru.dbotthepony.mc.otm.graph.matter
import com.google.common.collect.Streams
import net.minecraft.server.level.ServerLevel
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
import net.minecraft.world.item.Item
import net.minecraft.world.level.block.entity.BlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.core.filterNotNull
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.graph.Abstract6Graph
import ru.dbotthepony.mc.otm.graph.Graph6Node
import java.util.*
import java.util.function.Predicate
import java.util.stream.Stream
import kotlin.collections.HashSet
@Suppress("unused")
class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListener {
private val listeners = HashSet<IMatterGraphListener>()
class MatterGraph : Abstract6Graph<MatterNode, MatterGraph>(), IMatterGraphListener {
private val listeners = ObjectOpenHashSet<IMatterGraphListener>()
fun addListener(listener: IMatterGraphListener) = listeners.add(listener)
fun removeListener(listener: IMatterGraphListener) = listeners.remove(listener)
override fun onNodeRemoved(node: Graph6Node<IMatterGraphNode>) {
val patterns = node.value.getPatternHandler()
override fun onNodeRemoved(node: MatterNode) {
val patterns = node.getPatternHandler()
if (patterns != null) {
for (pattern in patterns.patterns) {
@ -32,7 +27,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
}
}
val tasks = node.value.getTaskHandler()
val tasks = node.getTaskHandler()
if (tasks != null) {
for (task in tasks.replicationTasks) {
@ -41,24 +36,24 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
}
for (pattern in this.patterns) {
node.value.onPatternRemoved(pattern)
node.onPatternRemoved(pattern)
}
for (task in this.tasks) {
node.value.onMatterTaskRemoved(task)
node.onMatterTaskRemoved(task)
}
}
override fun onNodeAdded(node: Graph6Node<IMatterGraphNode>) {
override fun onNodeAdded(node: MatterNode) {
for (pattern in this.patterns) {
node.value.onPatternAdded(pattern)
node.onPatternAdded(pattern)
}
for (task in this.tasks) {
node.value.onMatterTaskCreated(task)
node.onMatterTaskCreated(task)
}
val patterns = node.value.getPatternHandler()
val patterns = node.getPatternHandler()
if (patterns != null) {
for (pattern in patterns.patterns) {
@ -66,7 +61,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
}
}
val tasks = node.value.getTaskHandler()
val tasks = node.getTaskHandler()
if (tasks != null) {
for (task in tasks.replicationTasks) {
@ -79,7 +74,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
var level = Decimal.ZERO
for (node in nodes) {
val matter = node.value.getMatterHandler()
val matter = node.getMatterHandler()
if (matter != null && matter.matterFlow == FlowDirection.BI_DIRECTIONAL) {
level += matter.storedMatter
@ -93,7 +88,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
var level = Decimal.ZERO
for (node in nodes) {
val matter = node.value.getMatterHandler()
val matter = node.getMatterHandler()
if (matter != null && matter.matterFlow == FlowDirection.BI_DIRECTIONAL) {
level += matter.maxStoredMatter
@ -112,7 +107,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
var extracted = Decimal.ZERO
for (node in nodes) {
val matter = node.value.getMatterHandler()
val matter = node.getMatterHandler()
if (matter != null) {
val value = matter.extractMatter(howMuch, simulate)
@ -136,7 +131,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
var received = Decimal.ZERO
for (node in nodes) {
val matter = node.value.getMatterHandler()
val matter = node.getMatterHandler()
if (matter != null && matter.matterFlow == FlowDirection.BI_DIRECTIONAL) {
val value = matter.receiveMatter(howMuch, simulate)
@ -160,7 +155,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
var received = Decimal.ZERO
for (node in nodes) {
val matter = node.value.getMatterHandler()
val matter = node.getMatterHandler()
if (matter != null && matter.matterFlow != FlowDirection.OUTPUT) {
val value = matter.receiveMatter(howMuch, simulate)
@ -177,7 +172,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
private fun doInsertPattern(state: IPatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
for (node in nodes) {
val storage = node.value.getPatternHandler()
val storage = node.getPatternHandler()
if (storage != null) {
val status = storage.insertPattern(state, onlyUpdate, simulate)
@ -198,23 +193,23 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
return doInsertPattern(state, false, simulate)
}
val tasks: Stream<out IReplicationTask<*>> get() {
return Streams.concat(*nodes.mapNotNull { it.value.getTaskHandler()?.replicationTasks }.toTypedArray())
val tasks: Stream<IReplicationTask<*>> get() {
return nodes.stream().map { it.getTaskHandler()?.replicationTasks }.filterNotNull().flatMap { it }
}
val allTasks: Stream<out IReplicationTask<*>> get() {
return Streams.concat(*nodes.mapNotNull { it.value.getTaskHandler()?.allReplicationTasks }.toTypedArray())
val allTasks: Stream<IReplicationTask<*>> get() {
return nodes.stream().map { it.getTaskHandler()?.allReplicationTasks }.filterNotNull().flatMap { it }
}
val patterns: Stream<out IPatternState> get() {
return nodes.stream().map { it.value.getPatternHandler()?.patterns }.filterNotNull().flatMap { it }
val patterns: Stream<IPatternState> get() {
return nodes.stream().map { it.getPatternHandler()?.patterns }.filterNotNull().flatMap { it }
}
val patternCount: Long get() {
var value = 0L
for (node in nodes) {
val storage = node.value.getPatternHandler()
val storage = node.getPatternHandler()
if (storage != null) {
value += storage.storedPatterns
@ -228,7 +223,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
var value = 0L
for (node in nodes) {
val storage = node.value.getPatternHandler()
val storage = node.getPatternHandler()
if (storage != null) {
value += storage.patternCapacity
@ -240,7 +235,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
fun getPattern(id: UUID): IPatternState? {
for (node in nodes) {
val storage = node.value.getPatternHandler()
val storage = node.getPatternHandler()
if (storage != null) {
val get = storage.getPattern(id)
@ -260,7 +255,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
fun findPattern(predicate: Predicate<IPatternState>): IPatternState? {
for (node in nodes) {
val storage = node.value.getPatternHandler()
val storage = node.getPatternHandler()
if (storage != null) {
val find = storage.patterns.filter(predicate).findAny()
@ -284,7 +279,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
fun allocateTask(simulate: Boolean): ReplicationTaskAllocation? {
for (node in nodes) {
val tasks = node.value.getTaskHandler()
val tasks = node.getTaskHandler()
if (tasks != null) {
val allocated = tasks.allocateTask(simulate)
@ -299,87 +294,41 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
}
fun notifyTaskCompletion(taskId: UUID): Boolean {
return nodes.any { it.value.getTaskHandler()?.notifyTaskCompletion(taskId) == true }
return nodes.any { it.getTaskHandler()?.notifyTaskCompletion(taskId) == true }
}
override fun onPatternAdded(state: IPatternState) {
for (node in nodes) node.value.onPatternAdded(state)
for (node in nodes) node.onPatternAdded(state)
for (node in listeners) node.onPatternAdded(state)
}
override fun onPatternRemoved(state: IPatternState) {
for (node in nodes) node.value.onPatternRemoved(state)
for (node in nodes) node.onPatternRemoved(state)
for (node in listeners) node.onPatternRemoved(state)
}
override fun onPatternUpdated(newState: IPatternState, oldState: IPatternState) {
for (node in nodes) node.value.onPatternUpdated(newState, oldState)
for (node in nodes) node.onPatternUpdated(newState, oldState)
for (node in listeners) node.onPatternUpdated(newState, oldState)
}
override fun onMatterTaskCreated(task: IReplicationTask<*>) {
for (node in nodes) node.value.onMatterTaskCreated(task)
for (node in nodes) node.onMatterTaskCreated(task)
for (node in listeners) node.onMatterTaskCreated(task)
}
override fun <T : IReplicationTask<*>> onMatterTaskUpdated(newState: T, oldState: T) {
for (node in nodes) node.value.onMatterTaskUpdated(newState, oldState)
for (node in nodes) node.onMatterTaskUpdated(newState, oldState)
for (node in listeners) node.onMatterTaskUpdated(newState, oldState)
}
override fun onMatterTaskFinished(state: IReplicationTask<*>) {
for (node in nodes) node.value.onMatterTaskFinished(state)
for (node in nodes) node.onMatterTaskFinished(state)
for (node in listeners) node.onMatterTaskFinished(state)
}
override fun onMatterTaskRemoved(state: IReplicationTask<*>) {
for (node in nodes) node.value.onMatterTaskRemoved(state)
for (node in nodes) node.onMatterTaskRemoved(state)
for (node in listeners) node.onMatterTaskRemoved(state)
}
companion object {
@JvmStatic
fun discoverFull(tile: BlockEntity, node: Graph6Node<IMatterGraphNode>) {
if (tile.level !is ServerLevel)
return
return discoverFull(
tile.level!! as ServerLevel,
tile.blockPos,
node,
fun(_tile): Graph6Node<IMatterGraphNode>? {
val resolve = _tile.getCapability(MatteryCapability.MATTER_NODE)
return if (resolve.isPresent) {
resolve.resolve().get().matterNode
} else {
null
}
},
::MatterNetworkGraph
)
}
@JvmStatic
fun discover(tile: BlockEntity, node: Graph6Node<IMatterGraphNode>): Boolean {
if (tile.level !is ServerLevel)
return false
return discover(
tile.level!! as ServerLevel,
tile.blockPos,
node,
fun(_tile): Graph6Node<IMatterGraphNode>? {
val resolve = _tile.getCapability(MatteryCapability.MATTER_NODE)
return if (resolve.isPresent) {
resolve.resolve().get().matterNode
} else {
null
}
},
::MatterNetworkGraph
)
}
}
}

View File

@ -0,0 +1,18 @@
package ru.dbotthepony.mc.otm.graph.matter
import net.minecraft.world.level.block.entity.BlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider
import ru.dbotthepony.mc.otm.graph.Graph6Node
open class MatterNode : Graph6Node<MatterNode, MatterGraph>(::MatterGraph), IMatterGraphListener {
open fun getMatterHandler(): IMatterStorage? = null
open fun getPatternHandler(): IPatternStorage? = null
open fun getTaskHandler(): IReplicationTaskProvider? = null
fun discover(blockEntity: BlockEntity) {
discover(blockEntity, MatteryCapability.MATTER_NODE)
}
}

View File

@ -0,0 +1,23 @@
package ru.dbotthepony.mc.otm.graph.matter
import ru.dbotthepony.mc.otm.capability.matter.IMatterStorage
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
import ru.dbotthepony.mc.otm.capability.matter.IReplicationTaskProvider
open class SimpleMatterNode(
private val matter: IMatterStorage? = null,
private val patterns: IPatternStorage? = null,
private val tasks: IReplicationTaskProvider? = null,
) : MatterNode() {
override fun getMatterHandler(): IMatterStorage? {
return matter
}
override fun getPatternHandler(): IPatternStorage? {
return patterns
}
override fun getTaskHandler(): IReplicationTaskProvider? {
return tasks
}
}

View File

@ -1,22 +0,0 @@
package ru.dbotthepony.mc.otm.graph.storage
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.storage.IStorage
interface IStorageGraphNode {
/**
* Called by storage graph on node being attached to it
*/
fun attachComponents(to: StorageNetworkGraph)
/**
* Called by storage graph on node being detached from it
*
* This is NOT called when graph is being destroyed (e.g. even by merging
* with another graph).
*/
fun removeComponents(from: StorageNetworkGraph)
val storageNode: Graph6Node<IStorageGraphNode>
val storageGraph: StorageNetworkGraph? get() = storageNode.graph as StorageNetworkGraph?
}

View File

@ -14,8 +14,9 @@ import ru.dbotthepony.mc.otm.core.orNull
import ru.dbotthepony.mc.otm.storage.*
import java.util.LinkedList
class StorageNetworkGraph(private val level: Level) : Abstract6Graph<IStorageGraphNode>() {
class StorageGraph : Abstract6Graph<StorageNode, StorageGraph>() {
private val virtualComponents = Object2ObjectArrayMap<StorageStackType<*>, VirtualComponent<*>>()
val powerDemandingNodes = LinkedList<IMatteryEnergyStorage>()
/**
* Returns a [VirtualComponent] representing [type] storage
@ -31,8 +32,6 @@ class StorageNetworkGraph(private val level: Level) : Abstract6Graph<IStorageGra
return virtualComponents.computeIfAbsent(StorageRegistry.get(type), Object2ObjectFunction { VirtualComponent(type) }) as VirtualComponent<T>
}
private var addedTicker = false
fun <T : IStorageStack> add(storage: IStorage<T>) {
getVirtualComponent(storage.storageType).add(storage)
}
@ -46,50 +45,12 @@ class StorageNetworkGraph(private val level: Level) : Abstract6Graph<IStorageGra
return (virtual as VirtualComponent<T>).contains(storage)
}
override fun onNodeAdded(node: Graph6Node<IStorageGraphNode>) {
node.value.attachComponents(this)
if (!addedTicker) {
addedTicker = true
level.addTickerPre(this)
}
override fun onNodeAdded(node: StorageNode) {
node.attachComponents(this)
}
override fun onNodeRemoved(node: Graph6Node<IStorageGraphNode>) {
node.value.removeComponents(this)
override fun onNodeRemoved(node: StorageNode) {
node.removeComponents(this)
}
val powerDemandingNodes = LinkedList<IMatteryEnergyStorage>()
companion object {
@JvmStatic
fun discoverFull(tile: BlockEntity, node: Graph6Node<IStorageGraphNode>) {
if (tile.level !is ServerLevel)
return
return discoverFull(
tile.level as ServerLevel,
tile.blockPos,
node,
fun(_tile): Graph6Node<IStorageGraphNode>? {
return _tile.getCapability(MatteryCapability.STORAGE_NODE).orNull()?.storageNode
}
) { StorageNetworkGraph(tile.level!!) }
}
@JvmStatic
fun discover(tile: BlockEntity, node: Graph6Node<IStorageGraphNode>): Boolean {
if (tile.level !is ServerLevel)
return false
return discover(
tile.level as ServerLevel,
tile.blockPos,
node,
fun(_tile): Graph6Node<IStorageGraphNode>? {
return _tile.getCapability(MatteryCapability.STORAGE_NODE).orNull()?.storageNode
},
) { StorageNetworkGraph(tile.level!!) }
}
}
}

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.mc.otm.graph.storage
import net.minecraft.world.level.Level
import net.minecraftforge.common.util.LazyOptional
import net.minecraft.world.level.block.entity.BlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.storage.IStorage
@ -9,9 +9,7 @@ import ru.dbotthepony.mc.otm.storage.IStorageStack
import ru.dbotthepony.mc.otm.storage.StorageStackType
import java.util.*
open class BasicStorageGraphNode(private val energyDemander: IMatteryEnergyStorage? = null) : IStorageGraphNode {
private var resolver = LazyOptional.of<IStorageGraphNode> { this }
private var valid = true
open class StorageNode(private val energyDemander: IMatteryEnergyStorage? = null) : Graph6Node<StorageNode, StorageGraph>(::StorageGraph) {
protected val components = ArrayList<IStorage<*>>()
/**
@ -22,13 +20,12 @@ open class BasicStorageGraphNode(private val energyDemander: IMatteryEnergyStora
* [invalidate] and [removeComponents] still detach all components
*/
protected var manualAttaching = false
@Suppress("LeakingThis")
final override val storageNode = Graph6Node<IStorageGraphNode>(this)
private var demandingEnergy = false
override fun attachComponents(to: StorageNetworkGraph) {
/**
* Called by storage graph on node being attached to it
*/
open fun attachComponents(to: StorageGraph) {
if (energyDemander != null) {
if (energyDemander.missingPower.isPositive) {
demandingEnergy = true
@ -45,19 +42,13 @@ open class BasicStorageGraphNode(private val energyDemander: IMatteryEnergyStora
}
}
fun tickEnergyDemanding() {
energyDemander ?: throw IllegalStateException("No energy demander")
if (!demandingEnergy && storageGraph != null && energyDemander.missingPower.isPositive) {
demandingEnergy = true
storageGraph!!.powerDemandingNodes.add(energyDemander)
} else if (demandingEnergy && storageGraph != null && !energyDemander.missingPower.isPositive) {
demandingEnergy = false
storageGraph!!.powerDemandingNodes.remove(energyDemander)
}
}
override fun removeComponents(from: StorageNetworkGraph) {
/**
* Called by storage graph on node being detached from it
*
* This is NOT called when graph is being destroyed (e.g. even by merging
* with another graph).
*/
open fun removeComponents(from: StorageGraph) {
for (component in components) {
from.remove(component)
}
@ -68,6 +59,18 @@ open class BasicStorageGraphNode(private val energyDemander: IMatteryEnergyStora
}
}
fun tickEnergyDemanding() {
energyDemander ?: throw IllegalStateException("No energy demander")
if (!demandingEnergy && energyDemander.missingPower.isPositive) {
demandingEnergy = true
graph.powerDemandingNodes.add(energyDemander)
} else if (demandingEnergy && !energyDemander.missingPower.isPositive) {
demandingEnergy = false
graph.powerDemandingNodes.remove(energyDemander)
}
}
@Suppress("unchecked_cast")
fun <T : IStorageStack, U : IStorage<T>> computeIfAbsent(identity: StorageStackType<T>, provider: (StorageStackType<T>) -> U): U {
for (component in components) {
@ -90,8 +93,8 @@ open class BasicStorageGraphNode(private val energyDemander: IMatteryEnergyStora
components.add(component)
if (valid && !manualAttaching)
storageGraph?.add(component)
if (isValid && !manualAttaching)
graph.add(component)
}
fun removeStorageComponent(component: IStorage<*>) {
@ -111,8 +114,8 @@ open class BasicStorageGraphNode(private val energyDemander: IMatteryEnergyStora
val self = components[indexOf]
components.removeAt(indexOf)
if (valid)
storageGraph?.remove(self)
if (isValid)
graph.remove(self)
}
fun removeStorageComponent(component: StorageStackType<*>) {
@ -132,47 +135,25 @@ open class BasicStorageGraphNode(private val energyDemander: IMatteryEnergyStora
val self = components[indexOf]
components.removeAt(indexOf)
if (valid && !manualAttaching)
storageGraph?.remove(self)
if (isValid && !manualAttaching)
graph.remove(self)
}
open fun invalidate() {
if (!valid) return
valid = false
resolver.invalidate()
override fun invalidate() {
for (component in components) {
graph.remove(component)
}
}
val storageGraph = storageGraph
if (storageGraph != null) {
override fun revive() {
if (!manualAttaching) {
for (component in components) {
storageGraph.remove(component)
graph.add(component)
}
}
}
open fun revive() {
if (valid) return
valid = true
resolver = LazyOptional.of { this }
val storageGraph = storageGraph
if (storageGraph != null && !manualAttaching) {
for (component in components) {
storageGraph.add(component)
}
}
}
fun get(): LazyOptional<IStorageGraphNode> {
return if (valid) resolver else LazyOptional.empty()
}
fun destroy(level: Level?) {
if (level != null) {
storageNode.destroy { StorageNetworkGraph(level) }
} else {
storageGraph?.removeNode(storageNode)
}
fun discover(blockEntity: BlockEntity) {
discover(blockEntity, MatteryCapability.STORAGE_NODE)
}
}

View File

@ -45,8 +45,8 @@ class MatterBottlerMenu @JvmOverloads constructor(
storageSlots = immutableList(6) { index ->
object : MatterySlot(container, index) {
override fun mayPlace(p_40231_: ItemStack): Boolean {
val cap = p_40231_.getCapability(MatteryCapability.MATTER).orNull() ?: return false
override fun mayPlace(itemStack: ItemStack): Boolean {
val cap = itemStack.getCapability(MatteryCapability.MATTER).orNull() ?: return false
if (workFlow.value) {
return index < 3 && cap.canReceiveMatter

View File

@ -29,9 +29,9 @@ class MatterCapacitorBankMenu @JvmOverloads constructor(
} else {
matterGauge = LevelGaugeWidget(this, tile)
totalMatterGauge = LevelGaugeWidget(this, {
tile.matterGraph?.getMatterStorageLevel() ?: Decimal.ZERO
tile.matterNode.graph.getMatterStorageLevel()
}, {
tile.matterGraph?.getMatterStorageMaxLevel() ?: Decimal.ZERO
tile.matterNode.graph.getMatterStorageMaxLevel()
})
}

View File

@ -19,7 +19,7 @@ import ru.dbotthepony.mc.otm.core.util.DecimalValueCodec
import ru.dbotthepony.mc.otm.core.util.ItemSorter
import ru.dbotthepony.mc.otm.core.util.codec
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphListener
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.graph.matter.MatterGraph
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.network.*
import ru.dbotthepony.mc.otm.registry.MMenus
@ -176,7 +176,7 @@ class MatterPanelMenu @JvmOverloads constructor(
})
val totalMatterStored: Decimal by mSynchronizer.ComputedField(
getter = { tile?.matterGraph?.getMatterStorageLevel() ?: Decimal.ZERO },
getter = { tile?.matterNode?.graph?.getMatterStorageLevel() ?: Decimal.ZERO },
codec = DecimalValueCodec,
)
@ -278,8 +278,7 @@ class MatterPanelMenu @JvmOverloads constructor(
val tile = tile as MatterPanelBlockEntity? ?: return
val graph = tile.matterGraph ?: return
val state = graph.getPattern(id)
val state = tile.matterNode.graph.getPattern(id)
if (state == null) {
LOGGER.error("Received replication request from {} of {}, but it is not found in grid", ply, id)
@ -312,14 +311,13 @@ class MatterPanelMenu @JvmOverloads constructor(
}
private var initialSend = false
private var listeningGrid: MatterNetworkGraph? = null
private var listeningGrid: MatterGraph? = null
init {
if (tile != null) {
listeningGrid = tile.matterGraph
listeningGrid = tile.matterNode.graph
tile.attachMenu(this)
listeningGrid?.addListener(this)
listeningGrid!!.addListener(this)
}
}
@ -347,13 +345,9 @@ class MatterPanelMenu @JvmOverloads constructor(
val tile = tile as MatterPanelBlockEntity?
if (tile != null) {
val grid = tile.matterGraph
if (grid != null) {
initialSend = true
sendNetwork(PatternsChangePacket(true, grid.patterns.toList()))
}
val grid = tile.matterNode.graph
initialSend = true
sendNetwork(PatternsChangePacket(true, grid.patterns.toList()))
sendNetwork(TasksChangePacket(true, tile.allReplicationTasks.toList()))
}
}

View File

@ -1,9 +1,7 @@
package ru.dbotthepony.mc.otm.menu.matter
import com.google.common.collect.ImmutableList
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.block.entity.matter.MatterRecyclerBlockEntity
import ru.dbotthepony.mc.otm.item.MatterDustItem
@ -26,8 +24,8 @@ class MatterRecyclerMenu @JvmOverloads constructor(
val container = tile?.container ?: SimpleContainer(1)
input = object : MatterySlot(container, 0) {
override fun mayPlace(p_40231_: ItemStack): Boolean {
return p_40231_.item is MatterDustItem && (p_40231_.item as MatterDustItem).getMatterValue(p_40231_) != null
override fun mayPlace(itemStack: ItemStack): Boolean {
return itemStack.item is MatterDustItem && (itemStack.item as MatterDustItem).getMatterValue(itemStack) != null
}
}

View File

@ -36,8 +36,8 @@ class MatterScannerMenu @JvmOverloads constructor(
if (tile != null) {
progress = ProgressGaugeWidget(this, tile::workProgress, tile::isUnableToProcess)
patterns = LevelGaugeWidget(this,
{ Decimal(tile.matterGraph?.patternCount ?: 0L) },
{ Decimal(tile.matterGraph?.patternCapacity ?: 0L) })
{ Decimal(tile.matterNode.graph.patternCount) },
{ Decimal(tile.matterNode.graph.patternCapacity) })
} else {
progress = ProgressGaugeWidget(this)
patterns = LevelGaugeWidget(this)

View File

@ -29,9 +29,9 @@ class PatternStorageMenu @JvmOverloads constructor(
} else {
storedThis = LevelGaugeWidget(this, tile)
storedGrid = LevelGaugeWidget(this, {
Decimal(tile.matterGraph?.patternCount ?: 0)
Decimal(tile.matterNode.graph.patternCount)
}, {
Decimal(tile.matterGraph?.patternCapacity ?: 0)
Decimal(tile.matterNode.graph.patternCapacity)
})
}

View File

@ -22,7 +22,7 @@ class StoragePowerSupplierMenu @JvmOverloads constructor(
override fun broadcastChanges() {
if (tile is StoragePowerSupplierBlockEntity) {
totalTransferred = tile.powerPassed
activeNodes = tile.cell.storageGraph?.powerDemandingNodes?.size ?: 0
activeNodes = tile.cell.graph.powerDemandingNodes.size
}
super.broadcastChanges()