Compare commits
2 Commits
480fa7cf7c
...
cbfd8001c7
Author | SHA1 | Date | |
---|---|---|---|
cbfd8001c7 | |||
d03991137e |
@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.block.entity.blackhole
|
|||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectIterators
|
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
@ -10,6 +9,7 @@ import net.minecraft.world.entity.player.Player
|
|||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.neoforged.neoforge.capabilities.Capabilities
|
import net.neoforged.neoforge.capabilities.Capabilities
|
||||||
|
import ru.dbotthepony.kommons.collect.toList
|
||||||
import ru.dbotthepony.kommons.util.DelegateSetter
|
import ru.dbotthepony.kommons.util.DelegateSetter
|
||||||
import ru.dbotthepony.kommons.util.getValue
|
import ru.dbotthepony.kommons.util.getValue
|
||||||
import ru.dbotthepony.kommons.util.setValue
|
import ru.dbotthepony.kommons.util.setValue
|
||||||
@ -23,7 +23,6 @@ import ru.dbotthepony.mc.otm.capability.energy.CombinedProfiledEnergyStorage
|
|||||||
import ru.dbotthepony.mc.otm.capability.matter.CombinedProfiledMatterStorage
|
import ru.dbotthepony.mc.otm.capability.matter.CombinedProfiledMatterStorage
|
||||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||||
import ru.dbotthepony.mc.otm.config.ServerConfig
|
import ru.dbotthepony.mc.otm.config.ServerConfig
|
||||||
import ru.dbotthepony.mc.otm.core.RandomSource2Generator
|
|
||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.collect.map
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblock
|
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblock
|
||||||
@ -34,6 +33,7 @@ import ru.dbotthepony.mc.otm.core.math.plus
|
|||||||
import ru.dbotthepony.mc.otm.core.math.times
|
import ru.dbotthepony.mc.otm.core.math.times
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
|
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.shapedMultiblock
|
import ru.dbotthepony.mc.otm.core.multiblock.shapedMultiblock
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.InvalidableLazy
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.BlackHoleGeneratorMenu
|
import ru.dbotthepony.mc.otm.menu.tech.BlackHoleGeneratorMenu
|
||||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||||
import ru.dbotthepony.mc.otm.registry.MBlockTags
|
import ru.dbotthepony.mc.otm.registry.MBlockTags
|
||||||
@ -44,6 +44,7 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
MBlockEntities.BLACK_HOLE_GENERATOR, blockPos, blockState) {
|
MBlockEntities.BLACK_HOLE_GENERATOR, blockPos, blockState) {
|
||||||
var multiblock: ShapedMultiblock? = null
|
var multiblock: ShapedMultiblock? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private var multiblockSyncher: Closeable? = null
|
private var multiblockSyncher: Closeable? = null
|
||||||
|
|
||||||
var lastRange by syncher.int(-1, setter = DelegateSetter { field, value ->
|
var lastRange by syncher.int(-1, setter = DelegateSetter { field, value ->
|
||||||
@ -51,13 +52,23 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
multiblockSyncher?.close()
|
multiblockSyncher?.close()
|
||||||
multiblockSyncher = null
|
multiblockSyncher = null
|
||||||
multiblock?.close()
|
multiblock?.close()
|
||||||
|
energyTarget.invalidate()
|
||||||
|
matterTarget.invalidate()
|
||||||
multiblock = null
|
multiblock = null
|
||||||
field.accept(value)
|
field.accept(value)
|
||||||
} else if (value != field.value) {
|
} else if (value != field.value) {
|
||||||
multiblockSyncher?.close()
|
multiblockSyncher?.close()
|
||||||
multiblock?.close()
|
multiblock?.close()
|
||||||
multiblock = CONFIGURATIONS[value - 5].value.create(blockPos)
|
multiblock = CONFIGURATIONS[value - 5].value.create(blockPos)
|
||||||
|
|
||||||
|
multiblock!!.onGenerationChanges(Runnable {
|
||||||
|
energyTarget.invalidate()
|
||||||
|
matterTarget.invalidate()
|
||||||
|
})
|
||||||
|
|
||||||
multiblockSyncher = syncher.add0(multiblock!!)
|
multiblockSyncher = syncher.add0(multiblock!!)
|
||||||
|
energyTarget.invalidate()
|
||||||
|
matterTarget.invalidate()
|
||||||
field.accept(value)
|
field.accept(value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -65,17 +76,16 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
|
|
||||||
var drawBuildingGuide by syncher.boolean()
|
var drawBuildingGuide by syncher.boolean()
|
||||||
|
|
||||||
val energy = CombinedProfiledEnergyStorage(
|
private val energyTarget = InvalidableLazy.Impl {
|
||||||
FlowDirection.NONE,
|
multiblock?.blockEntities(EnergyHatchBlockEntity.OUTPUT_TAG)?.iterator()?.map { it.energy }?.toList() ?: listOf()
|
||||||
{ multiblock?.blockEntities(EnergyHatchBlockEntity.OUTPUT_TAG)?.iterator()?.map { it.energy } ?: ObjectIterators.emptyIterator() },
|
}
|
||||||
{ level?.random }
|
|
||||||
)
|
|
||||||
|
|
||||||
val matter = CombinedProfiledMatterStorage(
|
private val matterTarget = InvalidableLazy.Impl {
|
||||||
FlowDirection.NONE,
|
multiblock?.blockEntities(MatterHatchBlockEntity.INPUT_TAG)?.iterator()?.map { it.matter }?.toList() ?: listOf()
|
||||||
{ multiblock?.blockEntities(MatterHatchBlockEntity.INPUT_TAG)?.iterator()?.map { it.matter } ?: ObjectIterators.emptyIterator() },
|
}
|
||||||
{ level?.random }
|
|
||||||
)
|
val energy = CombinedProfiledEnergyStorage(FlowDirection.NONE, energyTarget::value, { level?.random })
|
||||||
|
val matter = CombinedProfiledMatterStorage(FlowDirection.NONE, matterTarget::value, { level?.random })
|
||||||
|
|
||||||
enum class Mode(val label: Component, val tooltip: Component) {
|
enum class Mode(val label: Component, val tooltip: Component) {
|
||||||
TARGET_MASS(TranslatableComponent("otm.gui.black_hole_generator.sustain.mode"), TranslatableComponent("otm.gui.black_hole_generator.sustain.desc")),
|
TARGET_MASS(TranslatableComponent("otm.gui.black_hole_generator.sustain.mode"), TranslatableComponent("otm.gui.black_hole_generator.sustain.desc")),
|
||||||
@ -159,7 +169,7 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
val multiblock = multiblock
|
val multiblock = multiblock
|
||||||
|
|
||||||
if (multiblock != null) {
|
if (multiblock != null) {
|
||||||
if (!multiblock.update(level, blockRotation.front)) {
|
if (!multiblock.update(level, blockRotation.back)) {
|
||||||
this.lastRange = findBlackHoleRange()
|
this.lastRange = findBlackHoleRange()
|
||||||
} else {
|
} else {
|
||||||
val blackHole = multiblock.blockEntities(BLACK_HOLE).firstOrNull() ?: return
|
val blackHole = multiblock.blockEntities(BLACK_HOLE).firstOrNull() ?: return
|
||||||
|
@ -11,6 +11,8 @@ import net.neoforged.neoforge.capabilities.Capabilities
|
|||||||
import net.neoforged.neoforge.energy.IEnergyStorage
|
import net.neoforged.neoforge.energy.IEnergyStorage
|
||||||
import ru.dbotthepony.kommons.collect.flatMap
|
import ru.dbotthepony.kommons.collect.flatMap
|
||||||
import ru.dbotthepony.kommons.collect.map
|
import ru.dbotthepony.kommons.collect.map
|
||||||
|
import ru.dbotthepony.kommons.collect.toList
|
||||||
|
import ru.dbotthepony.kommons.util.Listenable
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.capability.energy.CombinedProfiledEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.CombinedProfiledEnergyStorage
|
||||||
@ -22,6 +24,7 @@ import ru.dbotthepony.mc.otm.core.math.RelativeSide
|
|||||||
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
|
import ru.dbotthepony.mc.otm.core.multiblock.BlockEntityTag
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockAccess
|
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockAccess
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockListener
|
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockListener
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.InvalidableLazy
|
||||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||||
|
|
||||||
class EnergyInterfaceBlockEntity(
|
class EnergyInterfaceBlockEntity(
|
||||||
@ -34,20 +37,22 @@ class EnergyInterfaceBlockEntity(
|
|||||||
val energyInterfaceTarget: ProfiledEnergyStorage<*>
|
val energyInterfaceTarget: ProfiledEnergyStorage<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
private val multiblocks = LinkedHashSet<IMultiblockAccess>()
|
private val multiblocks = LinkedHashMap<IMultiblockAccess, Listenable.L>()
|
||||||
|
private val targets = InvalidableLazy.Impl {
|
||||||
|
multiblocks.keys.iterator().flatMap { it.blockEntities(TARGET).iterator() }.map { it.energyInterfaceTarget }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
val energy = CombinedProfiledEnergyStorage(
|
val energy = CombinedProfiledEnergyStorage(FlowDirection.input(isInput), targets::value, { level?.random })
|
||||||
FlowDirection.input(isInput),
|
|
||||||
{ multiblocks.iterator().flatMap { it.blockEntities(TARGET).iterator() }.map { it.energyInterfaceTarget } },
|
|
||||||
{ level?.random }
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun onAddedToMultiblock(multiblock: IMultiblockAccess) {
|
override fun onAddedToMultiblock(multiblock: IMultiblockAccess) {
|
||||||
check(multiblocks.add(multiblock)) { "$this already tracks $multiblock" }
|
check(!isRemoved) { "Block was removed" }
|
||||||
|
check(multiblocks.put(multiblock, multiblock.onGenerationChanges(Runnable { targets.invalidate() })) == null) { "$this already tracks $multiblock" }
|
||||||
|
targets.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRemovedFromMultiblock(multiblock: IMultiblockAccess) {
|
override fun onRemovedFromMultiblock(multiblock: IMultiblockAccess) {
|
||||||
check(multiblocks.remove(multiblock)) { "$this does not track $multiblock" }
|
check(multiblocks.remove(multiblock)?.remove() != null || isRemoved) { "$this does not track $multiblock" }
|
||||||
|
targets.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
val container = object : MatteryContainer(::markDirtyFast, CAPACITY) {
|
val container = object : MatteryContainer(::markDirtyFast, CAPACITY) {
|
||||||
@ -59,6 +64,11 @@ class EnergyInterfaceBlockEntity(
|
|||||||
val itemHandler = container.handler(if (isInput) HandlerFilter.Dischargeable else HandlerFilter.Chargeable)
|
val itemHandler = container.handler(if (isInput) HandlerFilter.Dischargeable else HandlerFilter.Chargeable)
|
||||||
private val neighbours = ArrayList<CapabilityCache<IEnergyStorage>>()
|
private val neighbours = ArrayList<CapabilityCache<IEnergyStorage>>()
|
||||||
|
|
||||||
|
override fun setRemoved() {
|
||||||
|
super.setRemoved()
|
||||||
|
multiblocks.values.forEach { it.remove() }
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
savetables.stateful(::container, BATTERY_KEY)
|
savetables.stateful(::container, BATTERY_KEY)
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package ru.dbotthepony.mc.otm.capability
|
package ru.dbotthepony.mc.otm.capability
|
||||||
|
|
||||||
import com.google.common.collect.Streams
|
import com.google.common.collect.Streams
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
|
||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.util.RandomSource
|
|
||||||
import net.minecraft.world.entity.LivingEntity
|
import net.minecraft.world.entity.LivingEntity
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
@ -35,10 +33,7 @@ import ru.dbotthepony.mc.otm.core.collect.filter
|
|||||||
import ru.dbotthepony.mc.otm.core.collect.map
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.shuffle
|
|
||||||
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
|
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
|
||||||
import java.util.function.Supplier
|
|
||||||
import java.util.random.RandomGenerator
|
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
private val LOGGER = LogManager.getLogger()
|
private val LOGGER = LogManager.getLogger()
|
||||||
@ -46,37 +41,6 @@ private val LOGGER = LogManager.getLogger()
|
|||||||
val Player.matteryPlayer: MatteryPlayer get() = (this as IMatteryPlayer).otmPlayer
|
val Player.matteryPlayer: MatteryPlayer get() = (this as IMatteryPlayer).otmPlayer
|
||||||
val LivingEntity.matteryPlayer: MatteryPlayer? get() = (this as? IMatteryPlayer)?.otmPlayer
|
val LivingEntity.matteryPlayer: MatteryPlayer? get() = (this as? IMatteryPlayer)?.otmPlayer
|
||||||
|
|
||||||
fun <T> Supplier<out Iterator<T>>.iterateProviders(random: RandomSource?, value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal): Decimal {
|
|
||||||
val providers = get()
|
|
||||||
val iteratorProvider: () -> Iterator<T>
|
|
||||||
|
|
||||||
if (random == null) {
|
|
||||||
iteratorProvider = providers::iterator
|
|
||||||
} else {
|
|
||||||
val providerList = ObjectArrayList(providers)
|
|
||||||
providerList.shuffle(random)
|
|
||||||
iteratorProvider = providerList::iterator
|
|
||||||
}
|
|
||||||
|
|
||||||
var leftover = value
|
|
||||||
|
|
||||||
for (provider in iteratorProvider()) {
|
|
||||||
leftover -= walker(provider, leftover, true)
|
|
||||||
if (leftover.signum() <= 0) break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (simulate) return value - leftover
|
|
||||||
|
|
||||||
leftover = value
|
|
||||||
|
|
||||||
for (provider in iteratorProvider()) {
|
|
||||||
leftover -= walker(provider, leftover, false)
|
|
||||||
if (leftover.signum() <= 0) break
|
|
||||||
}
|
|
||||||
|
|
||||||
return value - leftover
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does a checked energy receive, calls [IMatteryEnergyStorage.receiveEnergyChecked] if possible
|
* Does a checked energy receive, calls [IMatteryEnergyStorage.receiveEnergyChecked] if possible
|
||||||
*/
|
*/
|
||||||
|
@ -2,33 +2,37 @@ package ru.dbotthepony.mc.otm.capability.energy
|
|||||||
|
|
||||||
import net.minecraft.util.RandomSource
|
import net.minecraft.util.RandomSource
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.capability.iterateProviders
|
|
||||||
import ru.dbotthepony.mc.otm.core.collect.map
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
import ru.dbotthepony.mc.otm.core.collect.reduce
|
import ru.dbotthepony.mc.otm.core.collect.reduce
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.CapabilityListIterator
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
import java.util.random.RandomGenerator
|
|
||||||
|
|
||||||
open class CombinedEnergyStorage(
|
open class CombinedEnergyStorage(
|
||||||
final override val energyFlow: FlowDirection,
|
final override val energyFlow: FlowDirection,
|
||||||
val provider: Supplier<out Iterator<IMatteryEnergyStorage>>,
|
provider: Supplier<out List<IMatteryEnergyStorage>>,
|
||||||
val random: Supplier<RandomSource?> = Supplier { null }
|
random: Supplier<RandomSource?> = Supplier { null }
|
||||||
) : IMatteryEnergyStorage {
|
) : IMatteryEnergyStorage {
|
||||||
|
val iterator = CapabilityListIterator(provider, random)
|
||||||
|
|
||||||
|
val provider get() = iterator.provider
|
||||||
|
val random get() = iterator.random
|
||||||
|
|
||||||
final override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
final override fun extractEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
return provider.iterateProviders(random.get(), howMuch, simulate, IMatteryEnergyStorage::extractEnergy)
|
return iterator.iterate(howMuch, simulate, IMatteryEnergyStorage::extractEnergy)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
final override fun receiveEnergy(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
return provider.iterateProviders(random.get(), howMuch, simulate, IMatteryEnergyStorage::receiveEnergy)
|
return iterator.iterate(howMuch, simulate, IMatteryEnergyStorage::receiveEnergy)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
final override fun extractEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
|
final override fun extractEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
return provider.iterateProviders(random.get(), howMuch, simulate, IMatteryEnergyStorage::extractEnergyChecked)
|
return iterator.iterate(howMuch, simulate, IMatteryEnergyStorage::extractEnergyChecked)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun receiveEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
|
final override fun receiveEnergyChecked(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
return provider.iterateProviders(random.get(), howMuch, simulate, IMatteryEnergyStorage::receiveEnergyChecked)
|
return iterator.iterate(howMuch, simulate, IMatteryEnergyStorage::receiveEnergyChecked)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -14,15 +14,15 @@ import java.util.random.RandomGenerator
|
|||||||
|
|
||||||
class CombinedProfiledEnergyStorage(
|
class CombinedProfiledEnergyStorage(
|
||||||
energyFlow: FlowDirection,
|
energyFlow: FlowDirection,
|
||||||
provider: Supplier<out Iterator<ProfiledEnergyStorage<*>>>,
|
provider: Supplier<out List<ProfiledEnergyStorage<*>>>,
|
||||||
random: Supplier<RandomSource?> = Supplier { null }
|
random: Supplier<RandomSource?> = Supplier { null }
|
||||||
) : CombinedEnergyStorage(energyFlow, provider, random), IProfiledMatteryEnergyStorage, IProfiledStorage.Combined, ITickable {
|
) : CombinedEnergyStorage(energyFlow, provider, random), IProfiledMatteryEnergyStorage, IProfiledStorage.Combined, ITickable {
|
||||||
override val received = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledEnergyStorage<*>).received } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
override val received = CombinedDecimalHistoryChart(Supplier { this.provider.get().iterator().map { (it as ProfiledEnergyStorage<*>).received } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
||||||
override val transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledEnergyStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
override val transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().iterator().map { (it as ProfiledEnergyStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
||||||
override val receivedThisTick: Decimal
|
override val receivedThisTick: Decimal
|
||||||
get() = provider.get().map { (it as ProfiledEnergyStorage<*>).receivedThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
get() = provider.get().iterator().map { (it as ProfiledEnergyStorage<*>).receivedThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
||||||
override val transferredThisTick: Decimal
|
override val transferredThisTick: Decimal
|
||||||
get() = provider.get().map { (it as ProfiledEnergyStorage<*>).transferredThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
get() = provider.get().iterator().map { (it as ProfiledEnergyStorage<*>).transferredThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
received.tick()
|
received.tick()
|
||||||
|
@ -2,32 +2,36 @@ package ru.dbotthepony.mc.otm.capability.matter
|
|||||||
|
|
||||||
import net.minecraft.util.RandomSource
|
import net.minecraft.util.RandomSource
|
||||||
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
import ru.dbotthepony.mc.otm.capability.FlowDirection
|
||||||
import ru.dbotthepony.mc.otm.capability.iterateProviders
|
|
||||||
import ru.dbotthepony.mc.otm.core.collect.map
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
import ru.dbotthepony.mc.otm.core.collect.reduce
|
import ru.dbotthepony.mc.otm.core.collect.reduce
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.util.CapabilityListIterator
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
import java.util.random.RandomGenerator
|
|
||||||
|
|
||||||
open class CombinedMatterStorage(
|
open class CombinedMatterStorage(
|
||||||
final override val matterFlow: FlowDirection,
|
final override val matterFlow: FlowDirection,
|
||||||
val provider: Supplier<out Iterator<IMatterStorage>>,
|
provider: Supplier<out List<IMatterStorage>>,
|
||||||
val random: Supplier<RandomSource?> = Supplier { null }
|
random: Supplier<RandomSource?> = Supplier { null }
|
||||||
) : IMatterStorage {
|
) : IMatterStorage {
|
||||||
|
val iterator = CapabilityListIterator(provider, random)
|
||||||
|
|
||||||
|
val provider get() = iterator.provider
|
||||||
|
val random get() = iterator.random
|
||||||
|
|
||||||
final override var storedMatter: Decimal
|
final override var storedMatter: Decimal
|
||||||
get() = provider.get().map { it.storedMatter }.reduce(Decimal.ZERO, Decimal::plus)
|
get() = provider.get().iterator().map { it.storedMatter }.reduce(Decimal.ZERO, Decimal::plus)
|
||||||
set(value) {
|
set(value) {
|
||||||
throw UnsupportedOperationException()
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
final override val maxStoredMatter: Decimal
|
final override val maxStoredMatter: Decimal
|
||||||
get() = provider.get().map { it.maxStoredMatter }.reduce(Decimal.ZERO, Decimal::plus)
|
get() = provider.get().iterator().map { it.maxStoredMatter }.reduce(Decimal.ZERO, Decimal::plus)
|
||||||
|
|
||||||
final override fun receiveMatter(howMuch: Decimal, simulate: Boolean): Decimal {
|
final override fun receiveMatter(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
return provider.iterateProviders(random.get(), howMuch, simulate, IMatterStorage::receiveMatter)
|
return iterator.iterate(howMuch, simulate, IMatterStorage::receiveMatter)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun extractMatter(howMuch: Decimal, simulate: Boolean): Decimal {
|
final override fun extractMatter(howMuch: Decimal, simulate: Boolean): Decimal {
|
||||||
return provider.iterateProviders(random.get(), howMuch, simulate, IMatterStorage::extractMatter)
|
return iterator.iterate(howMuch, simulate, IMatterStorage::extractMatter)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override val canSetMatterLevel: Boolean
|
final override val canSetMatterLevel: Boolean
|
||||||
|
@ -14,15 +14,15 @@ import java.util.random.RandomGenerator
|
|||||||
|
|
||||||
class CombinedProfiledMatterStorage(
|
class CombinedProfiledMatterStorage(
|
||||||
matterFlow: FlowDirection,
|
matterFlow: FlowDirection,
|
||||||
provider: Supplier<out Iterator<ProfiledMatterStorage<*>>>,
|
provider: Supplier<out List<ProfiledMatterStorage<*>>>,
|
||||||
random: Supplier<RandomSource?> = Supplier { null }
|
random: Supplier<RandomSource?> = Supplier { null }
|
||||||
) : CombinedMatterStorage(matterFlow, provider, random), IProfiledMatterStorage, IProfiledStorage.Combined, ITickable {
|
) : CombinedMatterStorage(matterFlow, provider, random), IProfiledMatterStorage, IProfiledStorage.Combined, ITickable {
|
||||||
override val received = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledMatterStorage<*>).received } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
override val received = CombinedDecimalHistoryChart(Supplier { this.provider.get().iterator().map { (it as ProfiledMatterStorage<*>).received } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
||||||
override val transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledMatterStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
override val transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().iterator().map { (it as ProfiledMatterStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
||||||
override val receivedThisTick: Decimal
|
override val receivedThisTick: Decimal
|
||||||
get() = provider.get().map { (it as ProfiledMatterStorage<*>).receivedThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
get() = provider.get().iterator().map { (it as ProfiledMatterStorage<*>).receivedThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
||||||
override val transferredThisTick: Decimal
|
override val transferredThisTick: Decimal
|
||||||
get() = provider.get().map { (it as ProfiledMatterStorage<*>).transferredThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
get() = provider.get().iterator().map { (it as ProfiledMatterStorage<*>).transferredThisTick }.reduce(Decimal.ZERO, Decimal::plus)
|
||||||
|
|
||||||
override fun tick() {
|
override fun tick() {
|
||||||
received.tick()
|
received.tick()
|
||||||
|
@ -3,13 +3,10 @@ package ru.dbotthepony.mc.otm.core.multiblock
|
|||||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap
|
import it.unimi.dsi.fastutil.objects.Reference2IntMap
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.world.level.Level
|
|
||||||
import net.minecraft.world.level.block.Block
|
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.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.phys.AABB
|
import net.minecraft.world.phys.AABB
|
||||||
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
|
import ru.dbotthepony.kommons.util.Listenable
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
interface IMultiblockAccess {
|
interface IMultiblockAccess {
|
||||||
/**
|
/**
|
||||||
@ -19,6 +16,19 @@ interface IMultiblockAccess {
|
|||||||
val currentDirection: Direction?
|
val currentDirection: Direction?
|
||||||
val currentNodes: Map<BlockPos, IMultiblockNode>
|
val currentNodes: Map<BlockPos, IMultiblockNode>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arbitrary number representing counter which increases when *something* has changed regarding multiblock configuraiton,
|
||||||
|
* probably something not even visible in public interface
|
||||||
|
*
|
||||||
|
* Useful for caching data structures which derive from current state of multiblock
|
||||||
|
*/
|
||||||
|
val generation: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [listener] will be executed whenever [generation] changes
|
||||||
|
*/
|
||||||
|
fun onGenerationChanges(listener: Runnable): Listenable.L
|
||||||
|
|
||||||
val boundingBox: AABB?
|
val boundingBox: AABB?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,8 +2,6 @@ package ru.dbotthepony.mc.otm.core.multiblock
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableMap
|
import com.google.common.collect.ImmutableMap
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
|
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap
|
import it.unimi.dsi.fastutil.objects.Reference2IntMap
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2IntMaps
|
import it.unimi.dsi.fastutil.objects.Reference2IntMaps
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
|
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
|
||||||
@ -16,8 +14,7 @@ import net.minecraft.world.level.block.Block
|
|||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.phys.AABB
|
import net.minecraft.world.phys.AABB
|
||||||
import ru.dbotthepony.mc.otm.core.AABB
|
import ru.dbotthepony.kommons.util.Listenable
|
||||||
import ru.dbotthepony.mc.otm.core.addAll
|
|
||||||
import ru.dbotthepony.mc.otm.core.collect.collect
|
import ru.dbotthepony.mc.otm.core.collect.collect
|
||||||
import ru.dbotthepony.mc.otm.core.collect.map
|
import ru.dbotthepony.mc.otm.core.collect.map
|
||||||
import ru.dbotthepony.mc.otm.core.getBlockEntityNow
|
import ru.dbotthepony.mc.otm.core.getBlockEntityNow
|
||||||
@ -30,7 +27,6 @@ import ru.dbotthepony.mc.otm.network.syncher.ISynchable
|
|||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
import java.util.function.BooleanSupplier
|
|
||||||
import kotlin.collections.ArrayDeque
|
import kotlin.collections.ArrayDeque
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.collections.HashMap
|
import kotlin.collections.HashMap
|
||||||
@ -49,6 +45,25 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
private val east = Config(Direction.EAST, pos, factory.east)
|
private val east = Config(Direction.EAST, pos, factory.east)
|
||||||
private val configurations = ImmutableList.of(north, south, west, east)
|
private val configurations = ImmutableList.of(north, south, west, east)
|
||||||
|
|
||||||
|
override var generation: Int = 0
|
||||||
|
private set
|
||||||
|
|
||||||
|
private val changeListeners = CopyOnWriteArrayList<ChangeListener>()
|
||||||
|
|
||||||
|
private inner class ChangeListener(val runnable: Runnable) : Listenable.L {
|
||||||
|
init {
|
||||||
|
changeListeners.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove() {
|
||||||
|
changeListeners.remove(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onGenerationChanges(listener: Runnable): Listenable.L {
|
||||||
|
return ChangeListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
override val hasRemotes: Boolean
|
override val hasRemotes: Boolean
|
||||||
get() = remotes.isNotEmpty()
|
get() = remotes.isNotEmpty()
|
||||||
|
|
||||||
@ -147,6 +162,8 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
val be2 = blockEntity
|
val be2 = blockEntity
|
||||||
|
|
||||||
if (be1 != be2) {
|
if (be1 != be2) {
|
||||||
|
generation++
|
||||||
|
|
||||||
if (be1 != null) {
|
if (be1 != null) {
|
||||||
if (be1 is IMultiblockListener)
|
if (be1 is IMultiblockListener)
|
||||||
referencedListeners.dereference(be1)
|
referencedListeners.dereference(be1)
|
||||||
@ -170,6 +187,8 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
val old = this.blockState
|
val old = this.blockState
|
||||||
|
|
||||||
if (state != old) {
|
if (state != old) {
|
||||||
|
generation++
|
||||||
|
|
||||||
if (old != null) {
|
if (old != null) {
|
||||||
assignedBlockStateLists.forEach {
|
assignedBlockStateLists.forEach {
|
||||||
it[old] = it.getInt(old) - 1
|
it[old] = it.getInt(old) - 1
|
||||||
@ -216,6 +235,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun clearFull() {
|
private fun clearFull() {
|
||||||
|
generation++
|
||||||
val blockEntity = blockEntity
|
val blockEntity = blockEntity
|
||||||
|
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
@ -251,6 +271,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
|
generation++
|
||||||
val blockEntity = blockEntity
|
val blockEntity = blockEntity
|
||||||
|
|
||||||
if (blockEntity != null) {
|
if (blockEntity != null) {
|
||||||
@ -269,6 +290,14 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
|
|
||||||
private val referencedListeners = MultiblockListenerSet(this)
|
private val referencedListeners = MultiblockListenerSet(this)
|
||||||
|
|
||||||
|
override var generation: Int
|
||||||
|
get() = this@ShapedMultiblock.generation
|
||||||
|
private set(value) { this@ShapedMultiblock.generation = value }
|
||||||
|
|
||||||
|
override fun onGenerationChanges(listener: Runnable): Listenable.L {
|
||||||
|
return this@ShapedMultiblock.onGenerationChanges(listener)
|
||||||
|
}
|
||||||
|
|
||||||
val index = when (currentDirection) {
|
val index = when (currentDirection) {
|
||||||
Direction.NORTH -> 0
|
Direction.NORTH -> 0
|
||||||
Direction.SOUTH -> 1
|
Direction.SOUTH -> 1
|
||||||
@ -349,6 +378,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
|
generation++
|
||||||
referencedListeners.clear()
|
referencedListeners.clear()
|
||||||
tag2BlockEntity.values.forEach { it.clear() }
|
tag2BlockEntity.values.forEach { it.clear() }
|
||||||
tag2BlockState.values.forEach { it.clear() }
|
tag2BlockState.values.forEach { it.clear() }
|
||||||
@ -366,7 +396,12 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
override var isValid: Boolean = false
|
override var isValid: Boolean = false
|
||||||
private set
|
private set(value) {
|
||||||
|
if (value != field) {
|
||||||
|
field = value
|
||||||
|
generation++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var iterator = this.parts.values.iterator()
|
private var iterator = this.parts.values.iterator()
|
||||||
private var validParts = 0
|
private var validParts = 0
|
||||||
@ -565,6 +600,12 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var activeConfig: Config = north
|
private var activeConfig: Config = north
|
||||||
|
set(value) {
|
||||||
|
if (field !== value) {
|
||||||
|
field = value
|
||||||
|
generation++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override val currentDirection: Direction?
|
override val currentDirection: Direction?
|
||||||
get() = if (isValid) activeConfig.currentDirection else null
|
get() = if (isValid) activeConfig.currentDirection else null
|
||||||
@ -606,6 +647,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
|
|
||||||
fun update(levelAccessor: LevelAccessor): Boolean {
|
fun update(levelAccessor: LevelAccessor): Boolean {
|
||||||
isUpdating = true
|
isUpdating = true
|
||||||
|
val thisGeneration = generation
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val configurations = LinkedList<Config>()
|
val configurations = LinkedList<Config>()
|
||||||
@ -627,6 +669,11 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
activeConfig = config
|
activeConfig = config
|
||||||
isValid = true
|
isValid = true
|
||||||
remotes.forEach { it.listener.run() }
|
remotes.forEach { it.listener.run() }
|
||||||
|
|
||||||
|
if (thisGeneration != generation) {
|
||||||
|
changeListeners.forEach { it.runnable.run() }
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
config.clear()
|
config.clear()
|
||||||
@ -634,6 +681,10 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thisGeneration != generation) {
|
||||||
|
changeListeners.forEach { it.runnable.run() }
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
} finally {
|
} finally {
|
||||||
isUpdating = false
|
isUpdating = false
|
||||||
@ -642,6 +693,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
|
|
||||||
fun update(levelAccessor: LevelAccessor, direction: Direction): Boolean {
|
fun update(levelAccessor: LevelAccessor, direction: Direction): Boolean {
|
||||||
isUpdating = true
|
isUpdating = true
|
||||||
|
val thisGeneration = generation
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var changes = false
|
var changes = false
|
||||||
@ -673,6 +725,10 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
remotes.forEach { it.listener.run() }
|
remotes.forEach { it.listener.run() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thisGeneration != generation) {
|
||||||
|
changeListeners.forEach { it.runnable.run() }
|
||||||
|
}
|
||||||
|
|
||||||
return isValid
|
return isValid
|
||||||
} finally {
|
} finally {
|
||||||
isUpdating = false
|
isUpdating = false
|
||||||
@ -680,6 +736,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
changeListeners.clear()
|
||||||
remotes.forEach { it.close() }
|
remotes.forEach { it.close() }
|
||||||
configurations.forEach { it.clear() }
|
configurations.forEach { it.clear() }
|
||||||
isValid = false
|
isValid = false
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.core.util
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||||
|
import net.minecraft.util.RandomSource
|
||||||
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
|
import ru.dbotthepony.mc.otm.core.shuffle
|
||||||
|
import java.util.function.Supplier
|
||||||
|
|
||||||
|
class CapabilityListIterator<T>(
|
||||||
|
val provider: Supplier<out List<T>>,
|
||||||
|
val random: Supplier<RandomSource?>,
|
||||||
|
) {
|
||||||
|
private var shuffleCache = IntArray(0)
|
||||||
|
|
||||||
|
private fun doIterate(values: List<T>, value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal, indexProvider: () -> IntIterator): Decimal {
|
||||||
|
var leftover = value
|
||||||
|
|
||||||
|
for (index in indexProvider()) {
|
||||||
|
val provider = values[index]
|
||||||
|
leftover -= walker(provider, leftover, true)
|
||||||
|
if (leftover.signum() <= 0) break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simulate) return value - leftover
|
||||||
|
|
||||||
|
leftover = value
|
||||||
|
|
||||||
|
for (index in indexProvider()) {
|
||||||
|
val provider = values[index]
|
||||||
|
leftover -= walker(provider, leftover, false)
|
||||||
|
if (leftover.signum() <= 0) break
|
||||||
|
}
|
||||||
|
|
||||||
|
return value - leftover
|
||||||
|
}
|
||||||
|
|
||||||
|
fun iterate(value: Decimal, simulate: Boolean, walker: T.(Decimal, Boolean) -> Decimal): Decimal {
|
||||||
|
val providers = provider.get()
|
||||||
|
if (providers.isEmpty()) return Decimal.ZERO
|
||||||
|
val random = random.get()
|
||||||
|
|
||||||
|
if (random == null || providers.size == 1) {
|
||||||
|
return doIterate(providers, value, simulate, walker, providers.indices::iterator)
|
||||||
|
} else {
|
||||||
|
if (shuffleCache.size != providers.size) {
|
||||||
|
shuffleCache = IntArray(providers.size) { it }
|
||||||
|
}
|
||||||
|
|
||||||
|
shuffleCache.shuffle(random)
|
||||||
|
return doIterate(providers, value, simulate, walker, shuffleCache::iterator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user