Merge branch '1.21' into worldgen-placement-providers
This commit is contained in:
commit
07e6369454
@ -358,6 +358,9 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
|
||||
}
|
||||
|
||||
override fun get(): T? {
|
||||
if (isRemoved)
|
||||
return null
|
||||
|
||||
return cache?.capability
|
||||
}
|
||||
|
||||
@ -371,13 +374,13 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
|
||||
if (!SERVER_IS_LIVE) return
|
||||
val level = level as? ServerLevel
|
||||
|
||||
val creationVersion = ++currentVersion
|
||||
|
||||
if (level == null) {
|
||||
cache = null
|
||||
return
|
||||
}
|
||||
|
||||
val creationVersion = ++currentVersion
|
||||
|
||||
val direction = blockRotation.side2Dir(side)
|
||||
|
||||
cache = BlockCapabilityCache.create(
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.cable
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.level.Level
|
||||
@ -114,6 +115,8 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
|
||||
|
||||
val sides get() = energySides
|
||||
|
||||
val currentlyTransferringTo = ObjectArraySet<Pair<Node, RelativeSide>>()
|
||||
|
||||
override fun onNeighbour(link: Link) {
|
||||
if (link is DirectionLink) {
|
||||
updateBlockState(link.direction, true)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity.cable
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntRBTreeSet
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceArraySet
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet
|
||||
@ -19,6 +20,7 @@ import ru.dbotthepony.mc.otm.core.shuffle
|
||||
import ru.dbotthepony.mc.otm.graph.GraphNodeList
|
||||
import ru.dbotthepony.mc.otm.onceServer
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashSet
|
||||
import kotlin.collections.LinkedHashSet
|
||||
@ -626,108 +628,138 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
||||
notifyThroughputsChanged()
|
||||
}
|
||||
|
||||
fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal {
|
||||
livelyNodesList.shuffle(fromNode.blockEntity.level!!.otmRandom)
|
||||
private val indicesToRemove = IntRBTreeSet()
|
||||
private var recursionLevel = 0
|
||||
|
||||
fun receiveEnergy(howMuch: Decimal, simulate: Boolean, fromNode: EnergyCableBlockEntity.Node, fromSide: RelativeSide): Decimal {
|
||||
val thisLevel = ++recursionLevel
|
||||
val isMaster = thisLevel == 1
|
||||
|
||||
if (isMaster)
|
||||
livelyNodesList.shuffle(fromNode.blockEntity.level!!.otmRandom)
|
||||
|
||||
var i = -1
|
||||
val itr = livelyNodesList.iterator()
|
||||
var received = Decimal.ZERO
|
||||
var residue = howMuch.coerceAtMost(fromNode.energyThroughput)
|
||||
val snapshot = Reference2ObjectOpenHashMap<Segment, Decimal>()
|
||||
|
||||
for (pair in itr) {
|
||||
val (node, relSide) = pair
|
||||
val side = node.sides[relSide]!!
|
||||
i++
|
||||
|
||||
if (!side.isEnabled) {
|
||||
itr.remove()
|
||||
check(livelyNodes.remove(pair)) { "Lively nodes Set does not contain $pair" }
|
||||
// recursion prevention
|
||||
if (!fromNode.currentlyTransferringTo.add(pair))
|
||||
continue
|
||||
} else if (fromNode === node && side.side === fromSide) {
|
||||
continue
|
||||
}
|
||||
|
||||
val it = side.neighbour.get()
|
||||
try {
|
||||
val (node, relSide) = pair
|
||||
val side = node.sides[relSide]!!
|
||||
|
||||
if (it == null || it is EnergyCableBlockEntity.CableSide) {
|
||||
itr.remove()
|
||||
check(livelyNodes.remove(pair)) { "Lively nodes Set does not contain $pair" }
|
||||
continue
|
||||
}
|
||||
|
||||
val paths = getPath(fromNode, node, it.receiveEnergy(residue, true), !simulate)
|
||||
|
||||
if (paths.size == 1) {
|
||||
// Single path, fast scenario
|
||||
val path = paths[0]
|
||||
val pathTransferred = path.transfer(residue, simulate, snapshot)
|
||||
if (pathTransferred <= Decimal.ZERO) continue
|
||||
val thisReceived = it.receiveEnergy(pathTransferred, simulate)
|
||||
|
||||
// If cable transferred more than machine accepted, then "refund" energy
|
||||
// so cables record actual value transferred through them
|
||||
if (thisReceived != pathTransferred) {
|
||||
path.refund(pathTransferred - thisReceived, simulate, snapshot)
|
||||
|
||||
if (!simulate && thisReceived != Decimal.ZERO) {
|
||||
path.triggerBlockstateUpdates()
|
||||
}
|
||||
} else if (!simulate) {
|
||||
path.triggerBlockstateUpdates()
|
||||
}
|
||||
|
||||
received += thisReceived
|
||||
residue -= thisReceived
|
||||
if (!residue.isPositive) return received
|
||||
} else if (paths.size >= 2) {
|
||||
// Multiple paths, a bit more complicated
|
||||
// Determine how much machine is likely to accept
|
||||
val potentiallyAccepted = it.receiveEnergy(residue, true)
|
||||
|
||||
// Won't accept anything
|
||||
if (potentiallyAccepted <= Decimal.ZERO) continue
|
||||
|
||||
// Now determine combined available throughput
|
||||
// Make a copy of snapshot, so we can freely write into it
|
||||
val copy = snapshot.clone()
|
||||
var calcResidue = potentiallyAccepted
|
||||
|
||||
// TODO: Currently, all transfers cause Braess's paradox, because of greedy selection of "fastest" cable
|
||||
// Need to implement heuristics to better distribute load across different paths/segments
|
||||
for (path in paths) {
|
||||
val passed = path.transfer(calcResidue, true, copy)
|
||||
calcResidue -= passed
|
||||
if (calcResidue <= Decimal.ZERO) break
|
||||
}
|
||||
|
||||
if (calcResidue == potentiallyAccepted) {
|
||||
// мда
|
||||
if (!side.isEnabled) {
|
||||
indicesToRemove.add(i)
|
||||
livelyNodes.remove(pair)
|
||||
continue
|
||||
} else if (fromNode === node && side.side === fromSide) {
|
||||
continue
|
||||
}
|
||||
|
||||
var thisReceived = it.receiveEnergy(potentiallyAccepted - calcResidue, simulate)
|
||||
received += thisReceived
|
||||
residue -= thisReceived
|
||||
val it = side.neighbour.get()
|
||||
|
||||
for (path in paths) {
|
||||
val passed = path.transfer(thisReceived, simulate, snapshot)
|
||||
if (it == null || it is EnergyCableBlockEntity.CableSide) {
|
||||
indicesToRemove.add(i)
|
||||
livelyNodes.remove(pair)
|
||||
continue
|
||||
}
|
||||
|
||||
if (!simulate)
|
||||
val paths = getPath(fromNode, node, it.receiveEnergy(residue, true), !simulate)
|
||||
|
||||
if (paths.size == 1) {
|
||||
// Single path, fast scenario
|
||||
val path = paths[0]
|
||||
val pathTransferred = path.transfer(residue, simulate, snapshot)
|
||||
if (pathTransferred <= Decimal.ZERO) continue
|
||||
val thisReceived = it.receiveEnergy(pathTransferred, simulate)
|
||||
|
||||
// If cable transferred more than machine accepted, then "refund" energy
|
||||
// so cables record actual value transferred through them
|
||||
if (thisReceived != pathTransferred) {
|
||||
path.refund(pathTransferred - thisReceived, simulate, snapshot)
|
||||
|
||||
if (!simulate && thisReceived != Decimal.ZERO) {
|
||||
path.triggerBlockstateUpdates()
|
||||
}
|
||||
} else if (!simulate) {
|
||||
path.triggerBlockstateUpdates()
|
||||
}
|
||||
|
||||
thisReceived -= passed
|
||||
if (thisReceived <= Decimal.ZERO) break
|
||||
}
|
||||
|
||||
if (!residue.isPositive) return received
|
||||
//check(thisReceived <= Decimal.ZERO) { "Путом, алло, Путом, какого чёрта Путом? Путом почему ты заблокировал логику, а Путом?" }
|
||||
|
||||
if (thisReceived > Decimal.ZERO) {
|
||||
LOGGER.warn("Cable path from $fromNode to $node doesn't follow common sense, disabling.")
|
||||
paths.forEach { it.shortCircuit = true }
|
||||
received += thisReceived
|
||||
residue -= thisReceived
|
||||
if (!residue.isPositive) return received
|
||||
} else if (paths.size >= 2) {
|
||||
// Multiple paths, a bit more complicated
|
||||
// Determine how much machine is likely to accept
|
||||
val potentiallyAccepted = it.receiveEnergy(residue, true)
|
||||
|
||||
// Won't accept anything
|
||||
if (potentiallyAccepted <= Decimal.ZERO) continue
|
||||
|
||||
// Now determine combined available throughput
|
||||
// Make a copy of snapshot, so we can freely write into it
|
||||
val copy = snapshot.clone()
|
||||
var calcResidue = potentiallyAccepted
|
||||
|
||||
// TODO: Currently, all transfers cause Braess's paradox, because of greedy selection of "fastest" cable
|
||||
// Need to implement heuristics to better distribute load across different paths/segments
|
||||
for (path in paths) {
|
||||
val passed = path.transfer(calcResidue, true, copy)
|
||||
calcResidue -= passed
|
||||
if (calcResidue <= Decimal.ZERO) break
|
||||
}
|
||||
|
||||
if (calcResidue == potentiallyAccepted) {
|
||||
// мда
|
||||
continue
|
||||
}
|
||||
|
||||
var thisReceived = it.receiveEnergy(potentiallyAccepted - calcResidue, simulate)
|
||||
received += thisReceived
|
||||
residue -= thisReceived
|
||||
|
||||
for (path in paths) {
|
||||
val passed = path.transfer(thisReceived, simulate, snapshot)
|
||||
|
||||
if (!simulate)
|
||||
path.triggerBlockstateUpdates()
|
||||
|
||||
thisReceived -= passed
|
||||
if (thisReceived <= Decimal.ZERO) break
|
||||
}
|
||||
|
||||
if (!residue.isPositive) return received
|
||||
//check(thisReceived <= Decimal.ZERO) { "Путом, алло, Путом, какого чёрта Путом? Путом почему ты заблокировал логику, а Путом?" }
|
||||
|
||||
if (thisReceived > Decimal.ZERO) {
|
||||
LOGGER.warn("Cable path from $fromNode to $node doesn't follow common sense, disabling.")
|
||||
paths.forEach { it.shortCircuit = true }
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
fromNode.currentlyTransferringTo.remove(pair)
|
||||
}
|
||||
}
|
||||
|
||||
recursionLevel--
|
||||
|
||||
if (isMaster && indicesToRemove.isNotEmpty()) {
|
||||
val indices = indicesToRemove.iterator(indicesToRemove.lastInt())
|
||||
|
||||
while (indices.hasPrevious()) {
|
||||
livelyNodesList.removeAt(indices.previousInt())
|
||||
}
|
||||
|
||||
indicesToRemove.clear()
|
||||
}
|
||||
|
||||
return received
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ open class MatteryMenuSlot(container: Container, index: Int, x: Int = 0, y: Int
|
||||
}
|
||||
|
||||
open fun canTakeItemForPickAll(): Boolean {
|
||||
return (container.containerSlotOrNull(slotIndex) as? IFilteredContainerSlot)?.filter == null
|
||||
return (container.containerSlotOrNull(slotIndex) as? IFilteredContainerSlot)?.filter?.allowAll != false
|
||||
}
|
||||
|
||||
override fun getMaxStackSize(): Int {
|
||||
|
Loading…
Reference in New Issue
Block a user