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.ObjectArraySet
|
||||
import it.unimi.dsi.fastutil.objects.ObjectIterators
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.chat.Component
|
||||
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.level.block.state.BlockState
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import ru.dbotthepony.kommons.collect.toList
|
||||
import ru.dbotthepony.kommons.util.DelegateSetter
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
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.config.MachinesConfig
|
||||
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.collect.map
|
||||
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.multiblock.BlockEntityTag
|
||||
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.registry.game.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockTags
|
||||
@ -44,6 +44,7 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
MBlockEntities.BLACK_HOLE_GENERATOR, blockPos, blockState) {
|
||||
var multiblock: ShapedMultiblock? = null
|
||||
private set
|
||||
|
||||
private var multiblockSyncher: Closeable? = null
|
||||
|
||||
var lastRange by syncher.int(-1, setter = DelegateSetter { field, value ->
|
||||
@ -51,13 +52,23 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
multiblockSyncher?.close()
|
||||
multiblockSyncher = null
|
||||
multiblock?.close()
|
||||
energyTarget.invalidate()
|
||||
matterTarget.invalidate()
|
||||
multiblock = null
|
||||
field.accept(value)
|
||||
} else if (value != field.value) {
|
||||
multiblockSyncher?.close()
|
||||
multiblock?.close()
|
||||
multiblock = CONFIGURATIONS[value - 5].value.create(blockPos)
|
||||
|
||||
multiblock!!.onGenerationChanges(Runnable {
|
||||
energyTarget.invalidate()
|
||||
matterTarget.invalidate()
|
||||
})
|
||||
|
||||
multiblockSyncher = syncher.add0(multiblock!!)
|
||||
energyTarget.invalidate()
|
||||
matterTarget.invalidate()
|
||||
field.accept(value)
|
||||
}
|
||||
})
|
||||
@ -65,17 +76,16 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
||||
|
||||
var drawBuildingGuide by syncher.boolean()
|
||||
|
||||
val energy = CombinedProfiledEnergyStorage(
|
||||
FlowDirection.NONE,
|
||||
{ multiblock?.blockEntities(EnergyHatchBlockEntity.OUTPUT_TAG)?.iterator()?.map { it.energy } ?: ObjectIterators.emptyIterator() },
|
||||
{ level?.random }
|
||||
)
|
||||
private val energyTarget = InvalidableLazy.Impl {
|
||||
multiblock?.blockEntities(EnergyHatchBlockEntity.OUTPUT_TAG)?.iterator()?.map { it.energy }?.toList() ?: listOf()
|
||||
}
|
||||
|
||||
val matter = CombinedProfiledMatterStorage(
|
||||
FlowDirection.NONE,
|
||||
{ multiblock?.blockEntities(MatterHatchBlockEntity.INPUT_TAG)?.iterator()?.map { it.matter } ?: ObjectIterators.emptyIterator() },
|
||||
{ level?.random }
|
||||
)
|
||||
private val matterTarget = InvalidableLazy.Impl {
|
||||
multiblock?.blockEntities(MatterHatchBlockEntity.INPUT_TAG)?.iterator()?.map { it.matter }?.toList() ?: listOf()
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
|
||||
if (multiblock != null) {
|
||||
if (!multiblock.update(level, blockRotation.front)) {
|
||||
if (!multiblock.update(level, blockRotation.back)) {
|
||||
this.lastRange = findBlackHoleRange()
|
||||
} else {
|
||||
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 ru.dbotthepony.kommons.collect.flatMap
|
||||
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.capability.FlowDirection
|
||||
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.IMultiblockAccess
|
||||
import ru.dbotthepony.mc.otm.core.multiblock.IMultiblockListener
|
||||
import ru.dbotthepony.mc.otm.core.util.InvalidableLazy
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||
|
||||
class EnergyInterfaceBlockEntity(
|
||||
@ -34,20 +37,22 @@ class EnergyInterfaceBlockEntity(
|
||||
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(
|
||||
FlowDirection.input(isInput),
|
||||
{ multiblocks.iterator().flatMap { it.blockEntities(TARGET).iterator() }.map { it.energyInterfaceTarget } },
|
||||
{ level?.random }
|
||||
)
|
||||
val energy = CombinedProfiledEnergyStorage(FlowDirection.input(isInput), targets::value, { level?.random })
|
||||
|
||||
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) {
|
||||
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) {
|
||||
@ -59,6 +64,11 @@ class EnergyInterfaceBlockEntity(
|
||||
val itemHandler = container.handler(if (isInput) HandlerFilter.Dischargeable else HandlerFilter.Chargeable)
|
||||
private val neighbours = ArrayList<CapabilityCache<IEnergyStorage>>()
|
||||
|
||||
override fun setRemoved() {
|
||||
super.setRemoved()
|
||||
multiblocks.values.forEach { it.remove() }
|
||||
}
|
||||
|
||||
init {
|
||||
savetables.stateful(::container, BATTERY_KEY)
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import com.google.common.collect.Streams
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
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.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.shuffle
|
||||
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
|
||||
import java.util.function.Supplier
|
||||
import java.util.random.RandomGenerator
|
||||
import java.util.stream.Stream
|
||||
|
||||
private val LOGGER = LogManager.getLogger()
|
||||
@ -46,37 +41,6 @@ private val LOGGER = LogManager.getLogger()
|
||||
val Player.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
|
||||
*/
|
||||
|
@ -2,33 +2,37 @@ package ru.dbotthepony.mc.otm.capability.energy
|
||||
|
||||
import net.minecraft.util.RandomSource
|
||||
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.reduce
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.util.CapabilityListIterator
|
||||
import java.util.function.Supplier
|
||||
import java.util.random.RandomGenerator
|
||||
|
||||
open class CombinedEnergyStorage(
|
||||
final override val energyFlow: FlowDirection,
|
||||
val provider: Supplier<out Iterator<IMatteryEnergyStorage>>,
|
||||
val random: Supplier<RandomSource?> = Supplier { null }
|
||||
provider: Supplier<out List<IMatteryEnergyStorage>>,
|
||||
random: Supplier<RandomSource?> = Supplier { null }
|
||||
) : 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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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(
|
||||
energyFlow: FlowDirection,
|
||||
provider: Supplier<out Iterator<ProfiledEnergyStorage<*>>>,
|
||||
provider: Supplier<out List<ProfiledEnergyStorage<*>>>,
|
||||
random: Supplier<RandomSource?> = Supplier { null }
|
||||
) : 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 transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledEnergyStorage<*>).transferred } }, 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().iterator().map { (it as ProfiledEnergyStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
||||
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
|
||||
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() {
|
||||
received.tick()
|
||||
|
@ -2,32 +2,36 @@ package ru.dbotthepony.mc.otm.capability.matter
|
||||
|
||||
import net.minecraft.util.RandomSource
|
||||
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.reduce
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.util.CapabilityListIterator
|
||||
import java.util.function.Supplier
|
||||
import java.util.random.RandomGenerator
|
||||
|
||||
open class CombinedMatterStorage(
|
||||
final override val matterFlow: FlowDirection,
|
||||
val provider: Supplier<out Iterator<IMatterStorage>>,
|
||||
val random: Supplier<RandomSource?> = Supplier { null }
|
||||
provider: Supplier<out List<IMatterStorage>>,
|
||||
random: Supplier<RandomSource?> = Supplier { null }
|
||||
) : IMatterStorage {
|
||||
val iterator = CapabilityListIterator(provider, random)
|
||||
|
||||
val provider get() = iterator.provider
|
||||
val random get() = iterator.random
|
||||
|
||||
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) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
return provider.iterateProviders(random.get(), howMuch, simulate, IMatterStorage::extractMatter)
|
||||
return iterator.iterate(howMuch, simulate, IMatterStorage::extractMatter)
|
||||
}
|
||||
|
||||
final override val canSetMatterLevel: Boolean
|
||||
|
@ -14,15 +14,15 @@ import java.util.random.RandomGenerator
|
||||
|
||||
class CombinedProfiledMatterStorage(
|
||||
matterFlow: FlowDirection,
|
||||
provider: Supplier<out Iterator<ProfiledMatterStorage<*>>>,
|
||||
provider: Supplier<out List<ProfiledMatterStorage<*>>>,
|
||||
random: Supplier<RandomSource?> = Supplier { null }
|
||||
) : 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 transferred = CombinedDecimalHistoryChart(Supplier { this.provider.get().map { (it as ProfiledMatterStorage<*>).transferred } }, 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().iterator().map { (it as ProfiledMatterStorage<*>).transferred } }, ticks = AbstractProfiledStorage.HISTORY_SIZE)
|
||||
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
|
||||
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() {
|
||||
received.tick()
|
||||
|
@ -3,13 +3,10 @@ package ru.dbotthepony.mc.otm.core.multiblock
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
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.minecraft.world.phys.AABB
|
||||
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
|
||||
import java.util.*
|
||||
import ru.dbotthepony.kommons.util.Listenable
|
||||
|
||||
interface IMultiblockAccess {
|
||||
/**
|
||||
@ -19,6 +16,19 @@ interface IMultiblockAccess {
|
||||
val currentDirection: Direction?
|
||||
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?
|
||||
|
||||
/**
|
||||
|
@ -2,8 +2,6 @@ package ru.dbotthepony.mc.otm.core.multiblock
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
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.Reference2IntMaps
|
||||
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.state.BlockState
|
||||
import net.minecraft.world.phys.AABB
|
||||
import ru.dbotthepony.mc.otm.core.AABB
|
||||
import ru.dbotthepony.mc.otm.core.addAll
|
||||
import ru.dbotthepony.kommons.util.Listenable
|
||||
import ru.dbotthepony.mc.otm.core.collect.collect
|
||||
import ru.dbotthepony.mc.otm.core.collect.map
|
||||
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.util.LinkedList
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.function.BooleanSupplier
|
||||
import kotlin.collections.ArrayDeque
|
||||
import kotlin.collections.ArrayList
|
||||
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 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
|
||||
get() = remotes.isNotEmpty()
|
||||
|
||||
@ -147,6 +162,8 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
val be2 = blockEntity
|
||||
|
||||
if (be1 != be2) {
|
||||
generation++
|
||||
|
||||
if (be1 != null) {
|
||||
if (be1 is IMultiblockListener)
|
||||
referencedListeners.dereference(be1)
|
||||
@ -170,6 +187,8 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
val old = this.blockState
|
||||
|
||||
if (state != old) {
|
||||
generation++
|
||||
|
||||
if (old != null) {
|
||||
assignedBlockStateLists.forEach {
|
||||
it[old] = it.getInt(old) - 1
|
||||
@ -216,6 +235,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
}
|
||||
|
||||
private fun clearFull() {
|
||||
generation++
|
||||
val blockEntity = blockEntity
|
||||
|
||||
if (blockEntity != null) {
|
||||
@ -251,6 +271,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
generation++
|
||||
val blockEntity = blockEntity
|
||||
|
||||
if (blockEntity != null) {
|
||||
@ -269,6 +290,14 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
|
||||
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) {
|
||||
Direction.NORTH -> 0
|
||||
Direction.SOUTH -> 1
|
||||
@ -349,6 +378,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
generation++
|
||||
referencedListeners.clear()
|
||||
tag2BlockEntity.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
|
||||
private set
|
||||
private set(value) {
|
||||
if (value != field) {
|
||||
field = value
|
||||
generation++
|
||||
}
|
||||
}
|
||||
|
||||
private var iterator = this.parts.values.iterator()
|
||||
private var validParts = 0
|
||||
@ -565,6 +600,12 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
}
|
||||
|
||||
private var activeConfig: Config = north
|
||||
set(value) {
|
||||
if (field !== value) {
|
||||
field = value
|
||||
generation++
|
||||
}
|
||||
}
|
||||
|
||||
override val currentDirection: Direction?
|
||||
get() = if (isValid) activeConfig.currentDirection else null
|
||||
@ -606,6 +647,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
|
||||
fun update(levelAccessor: LevelAccessor): Boolean {
|
||||
isUpdating = true
|
||||
val thisGeneration = generation
|
||||
|
||||
try {
|
||||
val configurations = LinkedList<Config>()
|
||||
@ -627,6 +669,11 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
activeConfig = config
|
||||
isValid = true
|
||||
remotes.forEach { it.listener.run() }
|
||||
|
||||
if (thisGeneration != generation) {
|
||||
changeListeners.forEach { it.runnable.run() }
|
||||
}
|
||||
|
||||
return true
|
||||
} else {
|
||||
config.clear()
|
||||
@ -634,6 +681,10 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
}
|
||||
}
|
||||
|
||||
if (thisGeneration != generation) {
|
||||
changeListeners.forEach { it.runnable.run() }
|
||||
}
|
||||
|
||||
return false
|
||||
} finally {
|
||||
isUpdating = false
|
||||
@ -642,6 +693,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
|
||||
fun update(levelAccessor: LevelAccessor, direction: Direction): Boolean {
|
||||
isUpdating = true
|
||||
val thisGeneration = generation
|
||||
|
||||
try {
|
||||
var changes = false
|
||||
@ -673,6 +725,10 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
remotes.forEach { it.listener.run() }
|
||||
}
|
||||
|
||||
if (thisGeneration != generation) {
|
||||
changeListeners.forEach { it.runnable.run() }
|
||||
}
|
||||
|
||||
return isValid
|
||||
} finally {
|
||||
isUpdating = false
|
||||
@ -680,6 +736,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
changeListeners.clear()
|
||||
remotes.forEach { it.close() }
|
||||
configurations.forEach { it.clear() }
|
||||
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