Improve ticker, actually remove nodes from storage graph
This commit is contained in:
parent
d4aa8cd7ee
commit
7152108cc8
@ -1,89 +1,177 @@
|
||||
|
||||
@file:Suppress("unused", "UNUSED_PARAMETER")
|
||||
|
||||
package ru.dbotthepony.mc.otm
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.event.TickEvent
|
||||
import net.minecraftforge.event.TickEvent.ServerTickEvent
|
||||
import net.minecraftforge.event.TickEvent.WorldTickEvent
|
||||
import net.minecraftforge.event.server.ServerAboutToStartEvent
|
||||
import net.minecraftforge.event.server.ServerStoppingEvent
|
||||
import net.minecraftforge.eventbus.api.EventPriority
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import net.minecraftforge.fml.LogicalSide
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Supplier
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
private val tick_until = WeakHashMap<Level, ArrayList<Supplier<Boolean>>>()
|
||||
private val tick_once = WeakHashMap<Level, ArrayList<Runnable>>()
|
||||
private val preServerTick = ArrayList<IConditionalTickable>()
|
||||
private val postServerTick = ArrayList<IConditionalTickable>()
|
||||
private val preServerTickOnce = ArrayList<ITickable>()
|
||||
private val postServerTickOnce = ArrayList<ITickable>()
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
@Suppress("unused")
|
||||
fun onServerStarting(event: ServerAboutToStartEvent?) {
|
||||
tick_until.clear()
|
||||
private val preWorldTick = WeakHashMap<Level, ArrayList<IConditionalTickable>>()
|
||||
private val postWorldTick = WeakHashMap<Level, ArrayList<IConditionalTickable>>()
|
||||
private val preWorldTickOnce = WeakHashMap<Level, ArrayList<ITickable>>()
|
||||
private val postWorldTickOnce = WeakHashMap<Level, ArrayList<ITickable>>()
|
||||
|
||||
fun interface ITickable {
|
||||
fun tick()
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
@Suppress("unused")
|
||||
fun onServerStopping(event: ServerStoppingEvent?) {
|
||||
tick_until.clear()
|
||||
interface IConditionalTickable : ITickable {
|
||||
/**
|
||||
* Once this returns false, it should stay false.
|
||||
*
|
||||
* If it suddenly turns true after being false, result is undefined.
|
||||
*/
|
||||
val canTick: Boolean
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
@Suppress("unused")
|
||||
fun onPreTick(event: WorldTickEvent) {
|
||||
if (event.phase != TickEvent.Phase.START || event.side != LogicalSide.SERVER) return
|
||||
fun onServerTick(event: ServerTickEvent) {
|
||||
if (event.phase === TickEvent.Phase.START) {
|
||||
for (i in preServerTick.size - 1 downTo 0) {
|
||||
val ticker = preServerTick[i]
|
||||
|
||||
// удаляем список сразу что бы если кто-либо добавит туда элементы у нас была "копия"
|
||||
val until = tick_until.remove(event.world)
|
||||
|
||||
if (until != null) {
|
||||
for (i in until.indices.reversed()) {
|
||||
if (until[i].get()) {
|
||||
until.removeAt(i)
|
||||
if (!ticker.canTick) {
|
||||
preServerTick.removeAt(i)
|
||||
} else {
|
||||
ticker.tick()
|
||||
}
|
||||
}
|
||||
|
||||
if (until.size != 0) {
|
||||
val replaced = tick_until.put(event.world, until)
|
||||
for (i in preServerTickOnce.size - 1 downTo 0) {
|
||||
preServerTickOnce[i].tick()
|
||||
preServerTickOnce.removeAt(i)
|
||||
}
|
||||
} else {
|
||||
for (i in postServerTick.size - 1 downTo 0) {
|
||||
val ticker = postServerTick[i]
|
||||
|
||||
if (replaced != null) {
|
||||
until.addAll(replaced)
|
||||
if (!ticker.canTick) {
|
||||
postServerTick.removeAt(i)
|
||||
} else {
|
||||
ticker.tick()
|
||||
}
|
||||
}
|
||||
|
||||
for (i in postServerTickOnce.size - 1 downTo 0) {
|
||||
postServerTickOnce[i].tick()
|
||||
postServerTickOnce.removeAt(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addPreServerTicker(ticker: IConditionalTickable) {
|
||||
preServerTick.add(ticker)
|
||||
}
|
||||
|
||||
fun addPostServerTicker(ticker: IConditionalTickable) {
|
||||
postServerTick.add(ticker)
|
||||
}
|
||||
|
||||
fun addPreServerTickerOnce(ticker: ITickable) {
|
||||
preServerTickOnce.add(ticker)
|
||||
}
|
||||
|
||||
fun addPostServerTickerOnce(ticker: ITickable) {
|
||||
postServerTickOnce.add(ticker)
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
fun onWorldTick(event: WorldTickEvent) {
|
||||
if (event.phase === TickEvent.Phase.START) {
|
||||
val it = preWorldTick[event.world]
|
||||
|
||||
if (it != null) {
|
||||
for (i in it.size - 1 downTo 0) {
|
||||
val ticker = it[i]
|
||||
|
||||
if (!ticker.canTick) {
|
||||
it.removeAt(i)
|
||||
} else {
|
||||
ticker.tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val it2 = preWorldTickOnce.remove(event.world)
|
||||
|
||||
if (it2 != null) {
|
||||
for (i in it2.size - 1 downTo 0) {
|
||||
it2[i].tick()
|
||||
it2.removeAt(i)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val it = postWorldTick[event.world]
|
||||
|
||||
if (it != null) {
|
||||
for (i in it.size - 1 downTo 0) {
|
||||
val ticker = it[i]
|
||||
|
||||
if (!ticker.canTick) {
|
||||
it.removeAt(i)
|
||||
} else {
|
||||
ticker.tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val it2 = postWorldTickOnce.remove(event.world)
|
||||
|
||||
if (it2 != null) {
|
||||
for (i in it2.size - 1 downTo 0) {
|
||||
it2[i].tick()
|
||||
it2.removeAt(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val once = tick_once.remove(event.world)
|
||||
|
||||
if (once != null)
|
||||
for (ticker in once)
|
||||
ticker.run()
|
||||
}
|
||||
|
||||
fun tickUntil(level: Level, ticker: Supplier<Boolean>) {
|
||||
tick_until.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
fun addPreWorldTicker(level: Level, ticker: IConditionalTickable) {
|
||||
preWorldTick.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
}
|
||||
|
||||
fun tickUntilServer(level: Level, ticker: Supplier<Boolean>) {
|
||||
if (level is ServerLevel)
|
||||
tick_until.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
fun addPostWorldTicker(level: Level, ticker: IConditionalTickable) {
|
||||
postWorldTick.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
}
|
||||
|
||||
fun tickUntilClient(level: Level, ticker: Supplier<Boolean>) {
|
||||
if (level is ClientLevel)
|
||||
tick_until.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
fun addPreWorldTickerOnce(level: Level, ticker: ITickable) {
|
||||
preWorldTickOnce.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
}
|
||||
|
||||
fun tickOnce(level: Level, ticker: Runnable) {
|
||||
tick_once.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
fun addPostWorldTickerOnce(level: Level, ticker: ITickable) {
|
||||
postWorldTickOnce.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
}
|
||||
|
||||
fun tickOnceServer(level: Level, ticker: Runnable) {
|
||||
if (level is ServerLevel)
|
||||
tick_once.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
private fun clear() {
|
||||
preServerTick.clear()
|
||||
postServerTick.clear()
|
||||
preWorldTick.clear()
|
||||
postWorldTick.clear()
|
||||
preServerTickOnce.clear()
|
||||
postServerTickOnce.clear()
|
||||
preWorldTickOnce.clear()
|
||||
postWorldTickOnce.clear()
|
||||
}
|
||||
|
||||
fun tickOnceClient(level: Level, ticker: Runnable) {
|
||||
if (level is ClientLevel)
|
||||
tick_once.computeIfAbsent(level) { ArrayList() }.add(ticker)
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
fun onServerStarting(event: ServerAboutToStartEvent?) {
|
||||
clear()
|
||||
}
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.HIGHEST)
|
||||
fun onServerStopping(event: ServerStoppingEvent?) {
|
||||
clear()
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
@ -14,11 +13,11 @@ import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import ru.dbotthepony.mc.otm.addPreWorldTickerOnce
|
||||
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.shapes.BlockShapes
|
||||
import ru.dbotthepony.mc.otm.tickOnceServer
|
||||
|
||||
class ChemicalGeneratorBlock : RotatableMatteryBlock(), EntityBlock {
|
||||
override fun newBlockEntity(p_153215_: BlockPos, p_153216_: BlockState): BlockEntity {
|
||||
@ -55,7 +54,7 @@ class ChemicalGeneratorBlock : RotatableMatteryBlock(), EntityBlock {
|
||||
val tile = level.getBlockEntity(pos)
|
||||
|
||||
if (tile is ChemicalGeneratorBlockEntity) {
|
||||
tickOnceServer(level) {
|
||||
addPreWorldTickerOnce(level) {
|
||||
tile.checkSurroundings()
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import net.minecraft.world.level.material.MaterialColor
|
||||
import net.minecraft.world.level.material.PushReaction
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import ru.dbotthepony.mc.otm.addPreWorldTickerOnce
|
||||
import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
|
||||
@ -30,7 +31,6 @@ import ru.dbotthepony.mc.otm.core.times
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
import ru.dbotthepony.mc.otm.shapes.BlockShapes
|
||||
import ru.dbotthepony.mc.otm.tickOnceServer
|
||||
import kotlin.math.PI
|
||||
|
||||
private val props = BlockBehaviour.Properties.of(Material.STONE, MaterialColor.COLOR_BLUE).requiresCorrectToolForDrops().strength(3f, 600.0f)
|
||||
@ -120,8 +120,8 @@ class BlockGravitationStabilizer : RotatableMatteryBlock(props), EntityBlock {
|
||||
) {
|
||||
super.neighborChanged(state, level, pos, sender, sender_pos, flag)
|
||||
|
||||
tickOnceServer(level) {
|
||||
if (level.getBlockState(pos).block !is BlockGravitationStabilizer) return@tickOnceServer
|
||||
addPreWorldTickerOnce(level) {
|
||||
if (level.getBlockState(pos).block !is BlockGravitationStabilizer) return@addPreWorldTickerOnce
|
||||
|
||||
val bb = getBoundingBlock(level, state, pos)
|
||||
if (bb.block !is BlockGravitationStabilizerLens) {
|
||||
@ -181,8 +181,8 @@ class BlockGravitationStabilizerLens : RotatableMatteryBlock(props) {
|
||||
) {
|
||||
super.neighborChanged(state, level, pos, sender, sender_pos, flag)
|
||||
|
||||
tickOnceServer(level) {
|
||||
if (level.getBlockState(pos).block !is BlockGravitationStabilizerLens) return@tickOnceServer
|
||||
addPreWorldTickerOnce(level) {
|
||||
if (level.getBlockState(pos).block !is BlockGravitationStabilizerLens) return@addPreWorldTickerOnce
|
||||
|
||||
val bb = getBoundingBlock(level, state, pos)
|
||||
if (bb.block !is BlockGravitationStabilizer) {
|
||||
|
@ -9,10 +9,9 @@ import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
|
||||
import ru.dbotthepony.mc.otm.addPreWorldTickerOnce
|
||||
import ru.dbotthepony.mc.otm.block.entity.StorageBusBlockEntity
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.tickOnceServer
|
||||
import ru.dbotthepony.mc.otm.unaryMinus
|
||||
|
||||
class StorageBusBlock : RotatableMatteryBlock(), EntityBlock {
|
||||
@ -51,7 +50,7 @@ class StorageBusBlock : RotatableMatteryBlock(), EntityBlock {
|
||||
val tile = level.getBlockEntity(pos)
|
||||
|
||||
if (tile is StorageBusBlockEntity) {
|
||||
tickOnceServer(level) {
|
||||
addPreWorldTickerOnce(level) {
|
||||
tile.checkSurroundings()
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
override val defaultDisplayName: Component
|
||||
get() = MACHINE_NAME
|
||||
|
||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
|
||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||
return DriveRackMenu(containerID, inventory, this)
|
||||
}
|
||||
|
||||
@ -101,6 +101,11 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
cell.revive()
|
||||
}
|
||||
|
||||
override fun setRemoved() {
|
||||
super.setRemoved()
|
||||
cell.destroy(level)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.drive_rack")
|
||||
private val STORAGE = ImpreciseFraction(80_000)
|
||||
|
@ -59,6 +59,11 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
cell.revive()
|
||||
}
|
||||
|
||||
override fun setRemoved() {
|
||||
super.setRemoved()
|
||||
cell.destroy(level)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.item_monitor")
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import net.minecraft.nbt.ByteTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.common.capabilities.Capability
|
||||
import ru.dbotthepony.mc.otm.addPreWorldTickerOnce
|
||||
import ru.dbotthepony.mc.otm.ifHas
|
||||
import ru.dbotthepony.mc.otm.set
|
||||
|
||||
@ -70,32 +71,32 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
|
||||
protected fun tickOnce(func: Runnable) {
|
||||
val level = level
|
||||
if (level != null) ru.dbotthepony.mc.otm.tickOnce(level) { if (!isRemoved) func.run() }
|
||||
if (level != null) addPreWorldTickerOnce(level) { if (!isRemoved) func.run() }
|
||||
}
|
||||
|
||||
protected fun tickOnceServer(func: Runnable) {
|
||||
val level = level
|
||||
if (level is ServerLevel) ru.dbotthepony.mc.otm.tickOnce(level) { if (!isRemoved) func.run() }
|
||||
if (level is ServerLevel) addPreWorldTickerOnce(level) { if (!isRemoved) func.run() }
|
||||
}
|
||||
|
||||
protected fun tickOnceClient(func: Runnable) {
|
||||
val level = level
|
||||
if (level is ClientLevel) ru.dbotthepony.mc.otm.tickOnce(level) { if (!isRemoved) func.run() }
|
||||
if (level is ClientLevel) addPreWorldTickerOnce(level) { if (!isRemoved) func.run() }
|
||||
}
|
||||
|
||||
protected fun tickOnce(func: (Level) -> Unit) {
|
||||
val level = level
|
||||
if (level != null) ru.dbotthepony.mc.otm.tickOnce(level) { if (!isRemoved) func(level) }
|
||||
if (level != null) addPreWorldTickerOnce(level) { if (!isRemoved) func(level) }
|
||||
}
|
||||
|
||||
protected fun tickOnceServer(func: (ServerLevel) -> Unit) {
|
||||
val level = level
|
||||
if (level is ServerLevel) ru.dbotthepony.mc.otm.tickOnce(level) { if (!isRemoved) func(level) }
|
||||
if (level is ServerLevel) addPreWorldTickerOnce(level) { if (!isRemoved) func(level) }
|
||||
}
|
||||
|
||||
protected fun tickOnceClient(func: (ClientLevel) -> Unit) {
|
||||
val level = level
|
||||
if (level is ClientLevel) ru.dbotthepony.mc.otm.tickOnce(level) { if (!isRemoved) func(level) }
|
||||
if (level is ClientLevel) addPreWorldTickerOnce(level) { if (!isRemoved) func(level) }
|
||||
}
|
||||
|
||||
protected fun <T> getAndBind(
|
||||
|
@ -333,6 +333,11 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
|
||||
component?.scan()
|
||||
}
|
||||
|
||||
override fun setRemoved() {
|
||||
super.setRemoved()
|
||||
cell.destroy(level)
|
||||
}
|
||||
|
||||
fun checkSurroundings() {
|
||||
val front = blockPos + blockState.getValue(RotatableMatteryBlock.FACING_FULL)
|
||||
val storage = level?.getBlockEntity(front)?.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)?.let { if (it.isPresent) it else null }
|
||||
|
@ -1,27 +1,51 @@
|
||||
package ru.dbotthepony.mc.otm.graph
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap
|
||||
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.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.IConditionalTickable
|
||||
import ru.dbotthepony.mc.otm.addPreWorldTicker
|
||||
import ru.dbotthepony.mc.otm.core.plus
|
||||
import ru.dbotthepony.mc.otm.tickUntil
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
abstract class Abstract6Graph<T> {
|
||||
abstract class Abstract6Graph<T> : IConditionalTickable {
|
||||
@JvmField
|
||||
protected val _nodes = ArrayList<Graph6Node<T>>()
|
||||
fun size() = _nodes.size
|
||||
|
||||
private val tickable = ArrayList<Graph6Node<T>>()
|
||||
|
||||
@JvmField
|
||||
val nodes = Collections.unmodifiableCollection(_nodes)
|
||||
val nodes: Collection<Graph6Node<T>> = Collections.unmodifiableCollection(_nodes)
|
||||
|
||||
/**
|
||||
* Allows storing arbitrary data by external code
|
||||
*/
|
||||
@JvmField
|
||||
val userData = Object2ObjectAVLTreeMap<UUID, Any>()
|
||||
|
||||
abstract fun onNodeRemoved(node: Graph6Node<T>)
|
||||
abstract fun onNodeAdded(node: Graph6Node<T>)
|
||||
|
||||
override val canTick: Boolean
|
||||
get() = _nodes.size > 0
|
||||
|
||||
override fun tick() {
|
||||
for (i in tickable.size - 1 downTo 0) {
|
||||
val node = tickable[i]
|
||||
|
||||
if (node.canTick) {
|
||||
node.tick()
|
||||
} else {
|
||||
tickable.removeAt(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeNode(node: Graph6Node<T>) {
|
||||
if (!_nodes.contains(node))
|
||||
throw IllegalStateException("Not containing node $node")
|
||||
@ -29,6 +53,10 @@ abstract class Abstract6Graph<T> {
|
||||
_nodes.remove(node)
|
||||
node.graph = null
|
||||
onNodeRemoved(node)
|
||||
|
||||
if (node.canTick) {
|
||||
tickable.remove(node)
|
||||
}
|
||||
}
|
||||
|
||||
fun addNode(node: Graph6Node<T>) {
|
||||
@ -38,6 +66,10 @@ abstract class Abstract6Graph<T> {
|
||||
_nodes.add(node)
|
||||
node.graph = this
|
||||
onNodeAdded(node)
|
||||
|
||||
if (node.canTick) {
|
||||
tickable.add(node)
|
||||
}
|
||||
}
|
||||
|
||||
fun merge(other: Abstract6Graph<T>): Abstract6Graph<T> {
|
||||
@ -65,9 +97,16 @@ abstract class Abstract6Graph<T> {
|
||||
nodeGetter: (BlockEntity) -> Graph6Node<T>?,
|
||||
factory: () -> Abstract6Graph<T>
|
||||
) {
|
||||
tickUntil(level) {
|
||||
!node.valid || discover(level, blockPos, node, nodeGetter, factory)
|
||||
}
|
||||
addPreWorldTicker(level, object : IConditionalTickable {
|
||||
override fun tick() {
|
||||
discovered = discover(level, blockPos, node, nodeGetter, factory)
|
||||
}
|
||||
|
||||
private var discovered = false
|
||||
|
||||
override val canTick: Boolean
|
||||
get() = !discovered && node.valid
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
@ -1,6 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.graph
|
||||
|
||||
import net.minecraft.core.Direction
|
||||
import ru.dbotthepony.mc.otm.IConditionalTickable
|
||||
import ru.dbotthepony.mc.otm.ITickable
|
||||
|
||||
interface GraphNodeListener {
|
||||
fun onNeighbourTop(node: Graph6Node<*>) = onNeighbour(node, Direction.UP)
|
||||
@ -23,7 +25,7 @@ interface GraphNodeListener {
|
||||
}
|
||||
|
||||
// Вершина графа, содержит то, к какому графу принадлежит, соседей и своё "значение"
|
||||
class Graph6Node<T>(@JvmField val value: T, graph: Abstract6Graph<T>? = null) {
|
||||
class Graph6Node<T>(@JvmField val value: T, graph: Abstract6Graph<T>? = null) : IConditionalTickable {
|
||||
var graph: Abstract6Graph<T>? = null
|
||||
|
||||
init {
|
||||
@ -182,6 +184,23 @@ class Graph6Node<T>(@JvmField val value: T, graph: Abstract6Graph<T>? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
override val canTick: Boolean
|
||||
get() {
|
||||
return if (value is IConditionalTickable) {
|
||||
value.canTick
|
||||
} else {
|
||||
value is ITickable
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
if (value is ITickable) {
|
||||
value.tick()
|
||||
} else {
|
||||
throw ClassCastException("$value is not tickable")
|
||||
}
|
||||
}
|
||||
|
||||
var seen: Int = 0
|
||||
|
||||
private fun _flood(): List<GraphFlooder<T>> {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.graph.storage
|
||||
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.common.util.LazyOptional
|
||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||
import ru.dbotthepony.mc.otm.storage.IStorage
|
||||
@ -117,4 +118,12 @@ open class BasicStorageGraphNode : IStorageGraphNode {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -3,20 +3,19 @@ package ru.dbotthepony.mc.otm.graph.storage
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import ru.dbotthepony.mc.otm.addPreServerTicker
|
||||
import ru.dbotthepony.mc.otm.addPreWorldTicker
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.graph.Abstract6Graph
|
||||
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||
import ru.dbotthepony.mc.otm.orNull
|
||||
import ru.dbotthepony.mc.otm.storage.*
|
||||
|
||||
class StorageNetworkGraph : Abstract6Graph<IStorageGraphNode>() {
|
||||
class StorageNetworkGraph(private val level: Level) : Abstract6Graph<IStorageGraphNode>() {
|
||||
private val virtualComponents = Object2ObjectArrayMap<StorageStackType<*>, VirtualComponent<*>>()
|
||||
|
||||
fun <T : IStorageStack> insertStack(obj: T, simulate: Boolean): T {
|
||||
return (getVirtualComponent(StorageRegistry.get(obj::class.java)) as VirtualComponent<T>).insertStack(obj, simulate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [VirtualComponent] representing [type] storage
|
||||
*/
|
||||
@ -31,6 +30,8 @@ class StorageNetworkGraph : Abstract6Graph<IStorageGraphNode>() {
|
||||
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)
|
||||
}
|
||||
@ -43,6 +44,11 @@ class StorageNetworkGraph : Abstract6Graph<IStorageGraphNode>() {
|
||||
for (identity in node.value.fetchComponents()) {
|
||||
add(identity)
|
||||
}
|
||||
|
||||
if (!addedTicker) {
|
||||
addedTicker = true
|
||||
addPreWorldTicker(level, this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNodeRemoved(node: Graph6Node<IStorageGraphNode>) {
|
||||
@ -63,9 +69,8 @@ class StorageNetworkGraph : Abstract6Graph<IStorageGraphNode>() {
|
||||
node,
|
||||
fun(_tile): Graph6Node<IStorageGraphNode>? {
|
||||
return _tile.getCapability(MatteryCapability.STORAGE_NODE).orNull()?.storageNode
|
||||
},
|
||||
::StorageNetworkGraph
|
||||
)
|
||||
}
|
||||
) { StorageNetworkGraph(tile.level!!) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ -80,8 +85,7 @@ class StorageNetworkGraph : Abstract6Graph<IStorageGraphNode>() {
|
||||
fun(_tile): Graph6Node<IStorageGraphNode>? {
|
||||
return _tile.getCapability(MatteryCapability.STORAGE_NODE).orNull()?.storageNode
|
||||
},
|
||||
::StorageNetworkGraph
|
||||
)
|
||||
) { StorageNetworkGraph(tile.level!!) }
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user