Compare commits
No commits in common. "2bcc1965ce4b6e661b4dfad00999c9255ca57c8f" and "3ad085c1ae976ce78f1505df9104df11157d481a" have entirely different histories.
2bcc1965ce
...
3ad085c1ae
@ -6,7 +6,6 @@ import net.minecraft.world.level.block.Blocks
|
|||||||
import net.minecraft.world.level.block.entity.FurnaceBlockEntity
|
import net.minecraft.world.level.block.entity.FurnaceBlockEntity
|
||||||
import net.minecraft.world.level.block.entity.HopperBlockEntity
|
import net.minecraft.world.level.block.entity.HopperBlockEntity
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.MultiblockStatus
|
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.multiblockEntity
|
import ru.dbotthepony.mc.otm.core.multiblock.multiblockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.shapedMultiblock
|
import ru.dbotthepony.mc.otm.core.multiblock.shapedMultiblock
|
||||||
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
||||||
@ -18,7 +17,7 @@ class MultiblockTestBlockEntity(blockPos: BlockPos, blockState: BlockState) : Ma
|
|||||||
override fun tick() {
|
override fun tick() {
|
||||||
super.tick()
|
super.tick()
|
||||||
|
|
||||||
if (config.update(level!!) == MultiblockStatus.VALID) {
|
if (config.update(level!!)) {
|
||||||
println("It matches!")
|
println("It matches!")
|
||||||
println("hopper block entities: ${config.blockEntities(HOPPERS)}")
|
println("hopper block entities: ${config.blockEntities(HOPPERS)}")
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
|
|||||||
import ru.dbotthepony.mc.otm.core.math.plus
|
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.MultiblockStatus
|
|
||||||
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.core.util.InvalidableLazy
|
||||||
import ru.dbotthepony.mc.otm.menu.tech.BlackHoleGeneratorMenu
|
import ru.dbotthepony.mc.otm.menu.tech.BlackHoleGeneratorMenu
|
||||||
@ -170,11 +169,9 @@ class BlackHoleGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
val multiblock = multiblock
|
val multiblock = multiblock
|
||||||
|
|
||||||
if (multiblock != null) {
|
if (multiblock != null) {
|
||||||
val status = multiblock.update(level, blockRotation.back)
|
if (!multiblock.update(level, blockRotation.back)) {
|
||||||
|
|
||||||
if (status == MultiblockStatus.INVALID) {
|
|
||||||
this.lastRange = findBlackHoleRange()
|
this.lastRange = findBlackHoleRange()
|
||||||
} else if (status == MultiblockStatus.VALID) {
|
} else {
|
||||||
val blackHole = multiblock.blockEntities(BLACK_HOLE).firstOrNull() ?: return
|
val blackHole = multiblock.blockEntities(BLACK_HOLE).firstOrNull() ?: return
|
||||||
|
|
||||||
val matterExtracted = matter.extractMatter(if (mode == Mode.TARGET_MASS && blackHole.mass != targetMass) minOf(injectionRate, (blackHole.mass - targetMass).absoluteValue) else injectionRate, true)
|
val matterExtracted = matter.extractMatter(if (mode == Mode.TARGET_MASS && blackHole.mass != targetMass) minOf(injectionRate, (blackHole.mass - targetMass).absoluteValue) else injectionRate, true)
|
||||||
|
@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
|
|||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
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.SectionPos
|
|
||||||
import net.minecraft.core.Vec3i
|
import net.minecraft.core.Vec3i
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
@ -19,11 +18,9 @@ import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
|
|||||||
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
import ru.dbotthepony.mc.otm.config.MachinesConfig
|
||||||
import ru.dbotthepony.mc.otm.core.getBlockStateNow
|
import ru.dbotthepony.mc.otm.core.getBlockStateNow
|
||||||
import ru.dbotthepony.mc.otm.core.getChunkNow
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.core.math.plus
|
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.MultiblockStatus
|
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblock
|
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblock
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblockFactory
|
import ru.dbotthepony.mc.otm.core.multiblock.ShapedMultiblockFactory
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.Strategy
|
import ru.dbotthepony.mc.otm.core.multiblock.Strategy
|
||||||
@ -40,7 +37,7 @@ class FlywheelBatteryBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
|
|||||||
private var cachedChargeEfficiency = Decimal.ONE
|
private var cachedChargeEfficiency = Decimal.ONE
|
||||||
|
|
||||||
val formed: Boolean
|
val formed: Boolean
|
||||||
get() = multiblock?.isValid == MultiblockStatus.VALID
|
get() = multiblock?.isValid == true
|
||||||
|
|
||||||
// dangerous as Reference2IntMap.Entry reference live data, and its behavior is undefined once flywheel updates again
|
// dangerous as Reference2IntMap.Entry reference live data, and its behavior is undefined once flywheel updates again
|
||||||
val currentlyUsedCore: Reference2IntMap.Entry<Block>? get() {
|
val currentlyUsedCore: Reference2IntMap.Entry<Block>? get() {
|
||||||
@ -112,41 +109,36 @@ class FlywheelBatteryBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
|
|||||||
super.tick()
|
super.tick()
|
||||||
|
|
||||||
val level = level!!
|
val level = level!!
|
||||||
var isUnloaded = false
|
|
||||||
|
|
||||||
if (multiblock == null || multiblock!!.update(level, blockRotation.front) != MultiblockStatus.VALID) {
|
if (multiblock == null || !multiblock!!.update(level, blockRotation.front)) {
|
||||||
val chunk = level.chunkSource.getChunkNow(blockPos)
|
var height = 0
|
||||||
|
val base = blockPos + blockRotation.back.normal * 2
|
||||||
|
|
||||||
if (chunk == null) {
|
while (level.getBlockStateNow(base.atY(blockPos.y + height)).block == MBlocks.FLYWHEEL_SHAFT) {
|
||||||
isUnloaded = true
|
height++
|
||||||
} else {
|
}
|
||||||
var height = 0
|
|
||||||
val base = blockPos + blockRotation.back.normal * 2
|
|
||||||
|
|
||||||
while (chunk.getBlockState(base.atY(blockPos.y + height)).block == MBlocks.FLYWHEEL_SHAFT) {
|
if (height <= 1) {
|
||||||
height++
|
lastHeight = 0
|
||||||
}
|
multiblock?.close()
|
||||||
|
multiblock = null
|
||||||
if (height <= 1) {
|
} else if (multiblock == null || lastHeight != height) {
|
||||||
lastHeight = 0
|
lastHeight = height
|
||||||
multiblock?.close()
|
multiblock?.close()
|
||||||
multiblock = null
|
multiblock = getConfiguration(height).create(blockPos)
|
||||||
} else if (multiblock == null || lastHeight != height) {
|
|
||||||
lastHeight = height
|
|
||||||
multiblock?.close()
|
|
||||||
multiblock = getConfiguration(height).create(blockPos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (multiblock?.isValid == MultiblockStatus.VALID) {
|
if (multiblock?.isValid == true) {
|
||||||
|
// energy.parent.batteryLevel *= Decimal("0.99994")
|
||||||
|
// this way energy loss is recorded in graph
|
||||||
val entry = multiblock!!.blocks(FLYWHEEL_MATERIAL).reference2IntEntrySet().first()
|
val entry = multiblock!!.blocks(FLYWHEEL_MATERIAL).reference2IntEntrySet().first()
|
||||||
val material = FlywheelMaterials[entry.key]!!
|
val material = FlywheelMaterials[entry.key]!!
|
||||||
energy.parent.maxBatteryLevel = material.storage * entry.intValue
|
energy.parent.maxBatteryLevel = material.storage * entry.intValue
|
||||||
cachedChargeEfficiency = material.receiveEfficiency
|
cachedChargeEfficiency = material.receiveEfficiency
|
||||||
currentLossPerTick = energy.parent.batteryLevel * MachinesConfig.Flywheel.PASSIVE_LOSS * material.momentumLossSpeed
|
currentLossPerTick = energy.parent.batteryLevel * MachinesConfig.Flywheel.PASSIVE_LOSS * material.momentumLossSpeed
|
||||||
energy.extractEnergy(currentLossPerTick, false)
|
energy.extractEnergy(currentLossPerTick, false)
|
||||||
} else if (!isUnloaded && multiblock?.isValid != MultiblockStatus.NOT_LOADED) {
|
} else {
|
||||||
energy.parent.maxBatteryLevel = Decimal.ZERO
|
energy.parent.maxBatteryLevel = Decimal.ZERO
|
||||||
currentLossPerTick = energy.parent.batteryLevel * MachinesConfig.Flywheel.ACTIVE_LOSS
|
currentLossPerTick = energy.parent.batteryLevel * MachinesConfig.Flywheel.ACTIVE_LOSS
|
||||||
energy.extractEnergy(currentLossPerTick, false)
|
energy.extractEnergy(currentLossPerTick, false)
|
||||||
@ -249,13 +241,10 @@ class FlywheelBatteryBlockEntity(blockPos: BlockPos, blockState: BlockState) : M
|
|||||||
block(MBlocks.FLYWHEEL_HOUSING)
|
block(MBlocks.FLYWHEEL_HOUSING)
|
||||||
|
|
||||||
if (y == height - 1) {
|
if (y == height - 1) {
|
||||||
// wrap in subnode to narrow blockentity lookups
|
block(MBlocks.ENERGY_INPUT_INTERFACE)
|
||||||
or {
|
block(MBlocks.ENERGY_OUTPUT_INTERFACE)
|
||||||
block(MBlocks.ENERGY_INPUT_INTERFACE)
|
tag(EnergyInterfaceBlockEntity.INPUT_TAG)
|
||||||
block(MBlocks.ENERGY_OUTPUT_INTERFACE)
|
tag(EnergyInterfaceBlockEntity.OUTPUT_TAG)
|
||||||
tag(EnergyInterfaceBlockEntity.INPUT_TAG)
|
|
||||||
tag(EnergyInterfaceBlockEntity.OUTPUT_TAG)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,4 @@ open class DynamicLabel<out S : Screen>(
|
|||||||
super.tickInner()
|
super.tickInner()
|
||||||
text = textSupplier.get()
|
text = textSupplier.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
// reserve some extra space for text
|
|
||||||
override val textSizeDeterminationPadding: Float
|
|
||||||
get() = 14f
|
|
||||||
|
|
||||||
override fun sizeToContents() {
|
|
||||||
text = textSupplier.get()
|
|
||||||
super.sizeToContents()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -279,11 +279,6 @@ open class FramePanel<out S : Screen>(
|
|||||||
|
|
||||||
protected val tabs: ArrayList<FramePanel<*>.AbstractTab> = ArrayList()
|
protected val tabs: ArrayList<FramePanel<*>.AbstractTab> = ArrayList()
|
||||||
|
|
||||||
override fun sizeToContents() {
|
|
||||||
super.sizeToContents()
|
|
||||||
width = maxOf(width, dockPaddingLeft + dockPaddingRight + (helpButton?.width ?: 0f) + (closeButton?.width ?: 0f) + (title?.let { font.width(it).toFloat() } ?: 0f))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun performLayout() {
|
override fun performLayout() {
|
||||||
for ((i, tab) in tabs.withIndex()) {
|
for ((i, tab) in tabs.withIndex()) {
|
||||||
tab.setPos(i * 28f, -28f)
|
tab.setPos(i * 28f, -28f)
|
||||||
|
@ -60,14 +60,11 @@ open class Label<out S : Screen>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open val textSizeDeterminationPadding: Float
|
|
||||||
get() = 0f
|
|
||||||
|
|
||||||
override fun sizeToContents() {
|
override fun sizeToContents() {
|
||||||
val w = font.width(text) + textSizeDeterminationPadding
|
val w = font.width(text)
|
||||||
val h = font.lineHeight + 2
|
val h = font.lineHeight + 2
|
||||||
|
|
||||||
width = width.coerceAtLeast(w)
|
width = width.coerceAtLeast(w.toFloat())
|
||||||
height = height.coerceAtLeast(h.toFloat())
|
height = height.coerceAtLeast(h.toFloat())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,6 @@ class BlackHoleGeneratorScreen(menu: BlackHoleGeneratorMenu, inventory: Inventor
|
|||||||
}).also {
|
}).also {
|
||||||
it.dock = Dock.TOP
|
it.dock = Dock.TOP
|
||||||
it.dockTop = 4f
|
it.dockTop = 4f
|
||||||
it.dockBottom = 4f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val energy = ProfiledPowerGaugePanel(this, frame, menu.energy)
|
val energy = ProfiledPowerGaugePanel(this, frame, menu.energy)
|
||||||
|
@ -5,7 +5,6 @@ import net.minecraft.network.chat.Component
|
|||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.Items
|
import net.minecraft.world.item.Items
|
||||||
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
|
|
||||||
import ru.dbotthepony.mc.otm.client.render.RenderGravity
|
import ru.dbotthepony.mc.otm.client.render.RenderGravity
|
||||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
||||||
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
|
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
|
||||||
@ -47,7 +46,7 @@ class FlywheelBatteryScreen(menu: FlywheelBatteryMenu, inventory: Inventory, tit
|
|||||||
it.dock = Dock.TOP
|
it.dock = Dock.TOP
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicLabel(this, frame, textSupplier = Supplier { menu.currentLossPerTick.get().formatPower(decimalPlaces = 4, formatAsReadable = ShiftPressedCond) }).also {
|
DynamicLabel(this, frame, textSupplier = Supplier { menu.currentLossPerTick.get().formatPower(decimalPlaces = 6) }).also {
|
||||||
it.dock = Dock.TOP
|
it.dock = Dock.TOP
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ class FlywheelBatteryScreen(menu: FlywheelBatteryMenu, inventory: Inventory, tit
|
|||||||
it.dock = Dock.TOP
|
it.dock = Dock.TOP
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicLabel(this, frame, textSupplier = Supplier { (menu.currentLossPerTick.get() * 20).formatPower(formatAsReadable = ShiftPressedCond) }).also {
|
DynamicLabel(this, frame, textSupplier = Supplier { (menu.currentLossPerTick.get() * 20).formatPower() }).also {
|
||||||
it.dock = Dock.TOP
|
it.dock = Dock.TOP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ import net.minecraft.world.item.component.ItemAttributeModifiers
|
|||||||
import net.minecraft.world.item.crafting.CraftingInput
|
import net.minecraft.world.item.crafting.CraftingInput
|
||||||
import net.minecraft.world.item.crafting.RecipeInput
|
import net.minecraft.world.item.crafting.RecipeInput
|
||||||
import net.minecraft.world.level.BlockGetter
|
import net.minecraft.world.level.BlockGetter
|
||||||
import net.minecraft.world.level.ChunkPos
|
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.LevelAccessor
|
import net.minecraft.world.level.LevelAccessor
|
||||||
import net.minecraft.world.level.block.Block
|
import net.minecraft.world.level.block.Block
|
||||||
@ -45,8 +44,6 @@ 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.level.block.state.StateHolder
|
import net.minecraft.world.level.block.state.StateHolder
|
||||||
import net.minecraft.world.level.block.state.properties.Property
|
import net.minecraft.world.level.block.state.properties.Property
|
||||||
import net.minecraft.world.level.chunk.ChunkSource
|
|
||||||
import net.minecraft.world.level.chunk.LevelChunk
|
|
||||||
import net.minecraft.world.phys.Vec3
|
import net.minecraft.world.phys.Vec3
|
||||||
import net.neoforged.neoforge.fluids.FluidStack
|
import net.neoforged.neoforge.fluids.FluidStack
|
||||||
import net.neoforged.neoforge.items.IItemHandler
|
import net.neoforged.neoforge.items.IItemHandler
|
||||||
@ -130,25 +127,13 @@ operator fun JsonObject.set(s: String, value: Number) = add(s, JsonPrimitive(val
|
|||||||
operator fun JsonObject.set(s: String, value: Boolean) = add(s, JsonPrimitive(value))
|
operator fun JsonObject.set(s: String, value: Boolean) = add(s, JsonPrimitive(value))
|
||||||
|
|
||||||
fun LevelAccessor.getBlockStateNow(pos: BlockPos): BlockState {
|
fun LevelAccessor.getBlockStateNow(pos: BlockPos): BlockState {
|
||||||
return getBlockStateNowOrNull(pos) ?: Blocks.AIR.defaultBlockState()
|
return chunkSource.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z))?.getBlockState(pos) ?: Blocks.AIR.defaultBlockState()
|
||||||
}
|
|
||||||
|
|
||||||
fun LevelAccessor.getBlockStateNowOrNull(pos: BlockPos): BlockState? {
|
|
||||||
return chunkSource.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z))?.getBlockState(pos)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LevelAccessor.getBlockEntityNow(pos: BlockPos): BlockEntity? {
|
fun LevelAccessor.getBlockEntityNow(pos: BlockPos): BlockEntity? {
|
||||||
return chunkSource.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z))?.getBlockEntity(pos)
|
return chunkSource.getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z))?.getBlockEntity(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ChunkSource.getChunkNow(pos: BlockPos): LevelChunk? {
|
|
||||||
return getChunkNow(SectionPos.blockToSectionCoord(pos.x), SectionPos.blockToSectionCoord(pos.z))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ChunkSource.getChunkNow(pos: ChunkPos): LevelChunk? {
|
|
||||||
return getChunkNow(pos.x, pos.z)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline val FluidStack.isNotEmpty get() = !isEmpty
|
inline val FluidStack.isNotEmpty get() = !isEmpty
|
||||||
inline val ItemStack.isNotEmpty get() = !isEmpty
|
inline val ItemStack.isNotEmpty get() = !isEmpty
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
|
|||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.core.Vec3i
|
import net.minecraft.core.Vec3i
|
||||||
import net.minecraft.world.level.ChunkPos
|
|
||||||
import net.minecraft.world.phys.Vec3
|
import net.minecraft.world.phys.Vec3
|
||||||
import org.joml.AxisAngle4f
|
import org.joml.AxisAngle4f
|
||||||
import org.joml.Matrix3f
|
import org.joml.Matrix3f
|
||||||
@ -421,12 +420,6 @@ operator fun BlockPos.plus(direction: Direction): BlockPos = this.offset(directi
|
|||||||
operator fun BlockPos.minus(direction: Vec3i): BlockPos = this.subtract(direction)
|
operator fun BlockPos.minus(direction: Vec3i): BlockPos = this.subtract(direction)
|
||||||
operator fun BlockPos.minus(direction: Direction): BlockPos = this.subtract(direction.normal)
|
operator fun BlockPos.minus(direction: Direction): BlockPos = this.subtract(direction.normal)
|
||||||
|
|
||||||
operator fun ChunkPos.compareTo(other: ChunkPos): Int {
|
|
||||||
val cmp = x.compareTo(other.x)
|
|
||||||
if (cmp != 0) return cmp
|
|
||||||
return z.compareTo(other.z)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun Vec3i.plus(direction: Vec3i): Vec3i = this.offset(direction)
|
operator fun Vec3i.plus(direction: Vec3i): Vec3i = this.offset(direction)
|
||||||
operator fun Vec3i.plus(direction: Direction): Vec3i = this.offset(direction.normal)
|
operator fun Vec3i.plus(direction: Direction): Vec3i = this.offset(direction.normal)
|
||||||
operator fun Vec3i.minus(direction: Vec3i): Vec3i = this.subtract(direction)
|
operator fun Vec3i.minus(direction: Vec3i): Vec3i = this.subtract(direction)
|
||||||
|
@ -7,10 +7,11 @@ import net.minecraft.world.level.LevelAccessor
|
|||||||
import net.minecraft.world.level.block.Rotation
|
import net.minecraft.world.level.block.Rotation
|
||||||
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 ru.dbotthepony.mc.otm.core.getBlockStateNow
|
||||||
import ru.dbotthepony.mc.otm.core.math.plus
|
import ru.dbotthepony.mc.otm.core.math.plus
|
||||||
|
|
||||||
fun interface BlockPredicate {
|
fun interface BlockPredicate {
|
||||||
fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean
|
fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean
|
||||||
|
|
||||||
fun rotate(rotation: Rotation): BlockPredicate {
|
fun rotate(rotation: Rotation): BlockPredicate {
|
||||||
return this
|
return this
|
||||||
@ -41,7 +42,7 @@ fun interface BlockPredicate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class Positioned(val offset: BlockPos, val parent: BlockPredicate) : BlockPredicate {
|
data class Positioned(val offset: BlockPos, val parent: BlockPredicate) : BlockPredicate {
|
||||||
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
return parent.test(offset + pos, access, blockState, blockEntity)
|
return parent.test(offset + pos, access, blockState, blockEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ fun interface BlockPredicate {
|
|||||||
constructor(vararg nodes: BlockPredicate) : this(ImmutableSet.copyOf(nodes))
|
constructor(vararg nodes: BlockPredicate) : this(ImmutableSet.copyOf(nodes))
|
||||||
constructor(nodes: Set<BlockPredicate>) : this(ImmutableSet.copyOf(nodes))
|
constructor(nodes: Set<BlockPredicate>) : this(ImmutableSet.copyOf(nodes))
|
||||||
|
|
||||||
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
return nodes.all { it.test(pos, access, blockState, blockEntity) }
|
return nodes.all { it.test(pos, access, blockState, blockEntity) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,19 +64,19 @@ fun interface BlockPredicate {
|
|||||||
constructor(vararg nodes: BlockPredicate) : this(ImmutableSet.copyOf(nodes))
|
constructor(vararg nodes: BlockPredicate) : this(ImmutableSet.copyOf(nodes))
|
||||||
constructor(nodes: Set<BlockPredicate>) : this(ImmutableSet.copyOf(nodes))
|
constructor(nodes: Set<BlockPredicate>) : this(ImmutableSet.copyOf(nodes))
|
||||||
|
|
||||||
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
return nodes.any { it.test(pos, access, blockState, blockEntity) }
|
return nodes.any { it.test(pos, access, blockState, blockEntity) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Air : BlockPredicate {
|
object Air : BlockPredicate {
|
||||||
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
return blockState.isAir
|
return blockState.isAir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object NotAir : BlockPredicate {
|
object NotAir : BlockPredicate {
|
||||||
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
override fun test(pos: BlockPos, access: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
return !blockState.isAir
|
return !blockState.isAir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ interface IMultiblockAccess {
|
|||||||
/**
|
/**
|
||||||
* Whenever this multiblock is valid (all checks passed)
|
* Whenever this multiblock is valid (all checks passed)
|
||||||
*/
|
*/
|
||||||
val isValid: MultiblockStatus
|
val isValid: Boolean
|
||||||
val currentDirection: Direction?
|
val currentDirection: Direction?
|
||||||
val currentNodes: Map<BlockPos, IMultiblockNode>
|
val currentNodes: Map<BlockPos, IMultiblockNode>
|
||||||
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.core.multiblock
|
|
||||||
|
|
||||||
enum class MultiblockStatus {
|
|
||||||
/**
|
|
||||||
* Multiblock is functional, configuration is valid
|
|
||||||
*/
|
|
||||||
VALID,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multiblock status is unknown because it require to check
|
|
||||||
*/
|
|
||||||
NOT_LOADED,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multiblock is invalid
|
|
||||||
*/
|
|
||||||
INVALID;
|
|
||||||
|
|
||||||
fun or(other: MultiblockStatus): MultiblockStatus {
|
|
||||||
if (ordinal <= other.ordinal) {
|
|
||||||
return this
|
|
||||||
} else {
|
|
||||||
return other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun valid(status: Boolean): MultiblockStatus {
|
|
||||||
return if (status) VALID else INVALID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,21 +7,19 @@ import it.unimi.dsi.fastutil.objects.Reference2IntMaps
|
|||||||
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
|
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.Direction
|
import net.minecraft.core.Direction
|
||||||
|
import net.minecraft.core.SectionPos
|
||||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||||
import net.minecraft.world.level.ChunkPos
|
|
||||||
import net.minecraft.world.level.LevelAccessor
|
import net.minecraft.world.level.LevelAccessor
|
||||||
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.entity.BlockEntity
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.level.chunk.LevelChunk
|
|
||||||
import net.minecraft.world.phys.AABB
|
import net.minecraft.world.phys.AABB
|
||||||
import ru.dbotthepony.kommons.util.Listenable
|
import ru.dbotthepony.kommons.util.Listenable
|
||||||
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
|
||||||
import ru.dbotthepony.mc.otm.core.getBlockStateNowOrNull
|
import ru.dbotthepony.mc.otm.core.getBlockStateNow
|
||||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||||
import ru.dbotthepony.mc.otm.core.math.compareTo
|
|
||||||
import ru.dbotthepony.mc.otm.core.math.plus
|
import ru.dbotthepony.mc.otm.core.math.plus
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
import ru.dbotthepony.mc.otm.network.syncher.IRemoteState
|
import ru.dbotthepony.mc.otm.network.syncher.IRemoteState
|
||||||
@ -37,7 +35,7 @@ import kotlin.collections.HashMap
|
|||||||
* [close] MUST be called when multiblock goes out of scope
|
* [close] MUST be called when multiblock goes out of scope
|
||||||
*/
|
*/
|
||||||
class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMultiblockAccess, ISynchable, Closeable, GlobalBlockEntityRemovalListener {
|
class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMultiblockAccess, ISynchable, Closeable, GlobalBlockEntityRemovalListener {
|
||||||
override var isValid: MultiblockStatus = MultiblockStatus.INVALID
|
override var isValid: Boolean = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private val customChecks = factory.customChecks
|
private val customChecks = factory.customChecks
|
||||||
@ -70,9 +68,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
get() = remotes.isNotEmpty()
|
get() = remotes.isNotEmpty()
|
||||||
|
|
||||||
private inner class Config(override val currentDirection: Direction, val pos: BlockPos, parts: Collection<ShapedMultiblockFactory.Part>) : IMultiblockAccess, ISynchable, GlobalBlockEntityRemovalListener, Comparable<Config> {
|
private inner class Config(override val currentDirection: Direction, val pos: BlockPos, parts: Collection<ShapedMultiblockFactory.Part>) : IMultiblockAccess, ISynchable, GlobalBlockEntityRemovalListener, Comparable<Config> {
|
||||||
private inner class Part private constructor(override val pos: BlockPos, val prototype: ShapedMultiblockFactory.Part, val chunkPos: ChunkPos) : Comparable<Part>, IMultiblockNode {
|
private inner class Part(override val pos: BlockPos, val prototype: ShapedMultiblockFactory.Part) : Comparable<Part>, IMultiblockNode {
|
||||||
constructor(pos: BlockPos, prototype: ShapedMultiblockFactory.Part) : this(pos, prototype, ChunkPos(pos))
|
|
||||||
|
|
||||||
var index = -1
|
var index = -1
|
||||||
|
|
||||||
private var blockEntity: BlockEntity? = null
|
private var blockEntity: BlockEntity? = null
|
||||||
@ -80,10 +76,12 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
private val assignedBlockEntityLists = ArrayList<BlockEntitySet<*>>(prototype.blockEntityTags.size)
|
private val assignedBlockEntityLists = ArrayList<BlockEntitySet<*>>(prototype.blockEntityTags.size)
|
||||||
private val assignedBlockStateLists = ArrayList<Reference2IntMap<BlockState>>()
|
private val assignedBlockStateLists = ArrayList<Reference2IntMap<BlockState>>()
|
||||||
private val assignedBlockLists = ArrayList<Reference2IntMap<Block>>()
|
private val assignedBlockLists = ArrayList<Reference2IntMap<Block>>()
|
||||||
private val children: ImmutableList<Part> by lazy(LazyThreadSafetyMode.NONE) { prototype.children.iterator().map { Part(pos, it, chunkPos) }.collect(ImmutableList.toImmutableList()) }
|
private val children: ImmutableList<Part> by lazy(LazyThreadSafetyMode.NONE) { prototype.children.iterator().map { Part(pos, it) }.collect(ImmutableList.toImmutableList()) }
|
||||||
|
|
||||||
override fun compareTo(other: Part): Int {
|
override fun compareTo(other: Part): Int {
|
||||||
return chunkPos.compareTo(other.chunkPos)
|
val cmp = SectionPos.blockToSectionCoord(pos.x).compareTo(SectionPos.blockToSectionCoord(other.pos.x))
|
||||||
|
if (cmp != 0) return cmp
|
||||||
|
return SectionPos.blockToSectionCoord(pos.z).compareTo(SectionPos.blockToSectionCoord(other.pos.z))
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -116,7 +114,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
stream.writeByte(status.ordinal)
|
stream.writeByte(status.ordinal)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun orPredicates(levelAccessor: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
private fun orPredicates(levelAccessor: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
if (prototype.predicate.isNotEmpty()) {
|
if (prototype.predicate.isNotEmpty()) {
|
||||||
if (lastSuccessfulPathPredicate != -1 && !prototype.predicate[lastSuccessfulPathPredicate].test(pos, levelAccessor, blockState, blockEntity)) {
|
if (lastSuccessfulPathPredicate != -1 && !prototype.predicate[lastSuccessfulPathPredicate].test(pos, levelAccessor, blockState, blockEntity)) {
|
||||||
lastSuccessfulPathPredicate = -1
|
lastSuccessfulPathPredicate = -1
|
||||||
@ -131,7 +129,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun orChildren(levelAccessor: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
private fun orChildren(levelAccessor: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
if (children.isNotEmpty()) {
|
if (children.isNotEmpty()) {
|
||||||
if (lastSuccessfulPathChildren != -1 && !children[lastSuccessfulPathChildren].test0(levelAccessor, blockState, blockEntity)) {
|
if (lastSuccessfulPathChildren != -1 && !children[lastSuccessfulPathChildren].test0(levelAccessor, blockState, blockEntity)) {
|
||||||
lastSuccessfulPathChildren = -1
|
lastSuccessfulPathChildren = -1
|
||||||
@ -146,7 +144,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun test0(levelAccessor: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): Boolean {
|
private fun test0(levelAccessor: LevelAccessor, blockState: BlockState, blockEntity: BlockEntity?): Boolean {
|
||||||
val test = when (prototype.strategy) {
|
val test = when (prototype.strategy) {
|
||||||
Strategy.OR_BOTH -> orPredicates(levelAccessor, blockState, blockEntity) && orChildren(levelAccessor, blockState, blockEntity)
|
Strategy.OR_BOTH -> orPredicates(levelAccessor, blockState, blockEntity) && orChildren(levelAccessor, blockState, blockEntity)
|
||||||
|
|
||||||
@ -161,7 +159,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
if (test) {
|
if (test) {
|
||||||
if (assignedBlockEntityLists.isNotEmpty()) {
|
if (assignedBlockEntityLists.isNotEmpty()) {
|
||||||
val be1 = this.blockEntity
|
val be1 = this.blockEntity
|
||||||
val be2 = blockEntity.value
|
val be2 = blockEntity
|
||||||
|
|
||||||
if (be1 != be2) {
|
if (be1 != be2) {
|
||||||
generation++
|
generation++
|
||||||
@ -221,19 +219,9 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
return test
|
return test
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test(levelAccessor: LevelAccessor): MultiblockStatus {
|
fun test(levelAccessor: LevelAccessor): Boolean {
|
||||||
val blockEntity = lazy(LazyThreadSafetyMode.NONE) { levelAccessor.getBlockEntityNow(pos) }
|
val blockEntity = levelAccessor.getBlockEntityNow(pos)
|
||||||
val blockState = levelAccessor.getBlockStateNowOrNull(pos) ?: return MultiblockStatus.NOT_LOADED
|
val blockState = levelAccessor.getBlockStateNow(pos)
|
||||||
return test(levelAccessor, blockState, blockEntity)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test(levelAccessor: LevelAccessor, chunk: LevelChunk): MultiblockStatus {
|
|
||||||
val blockEntity = lazy(LazyThreadSafetyMode.NONE) { chunk.getBlockEntity(pos) }
|
|
||||||
val blockState = chunk.getBlockState(pos)
|
|
||||||
return test(levelAccessor, blockState, blockEntity)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test(levelAccessor: LevelAccessor, blockState: BlockState, blockEntity: Lazy<BlockEntity?>): MultiblockStatus {
|
|
||||||
val status = test0(levelAccessor, blockState, blockEntity)
|
val status = test0(levelAccessor, blockState, blockEntity)
|
||||||
|
|
||||||
val previous = this.status
|
val previous = this.status
|
||||||
@ -243,7 +231,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
pushNetworkPartUpdate(this)
|
pushNetworkPartUpdate(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (status) MultiblockStatus.VALID else MultiblockStatus.INVALID
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearFull() {
|
private fun clearFull() {
|
||||||
@ -383,20 +371,6 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
.sorted() // group/localize parts by in-world chunks to maximize getChunk() cache hit rate
|
.sorted() // group/localize parts by in-world chunks to maximize getChunk() cache hit rate
|
||||||
.collect(ImmutableMap.toImmutableMap({ it.pos }, { it }))
|
.collect(ImmutableMap.toImmutableMap({ it.pos }, { it }))
|
||||||
|
|
||||||
private val partsByChunk: ImmutableMap<ChunkPos, ImmutableList<Part>>
|
|
||||||
|
|
||||||
init {
|
|
||||||
val builder = HashMap<ChunkPos, ArrayList<Part>>()
|
|
||||||
|
|
||||||
for (part in this.parts.values) {
|
|
||||||
builder.computeIfAbsent(part.chunkPos) { ArrayList() }.add(part)
|
|
||||||
}
|
|
||||||
|
|
||||||
partsByChunk = builder.entries.stream()
|
|
||||||
.map { it.key to ImmutableList.copyOf(it.value) }
|
|
||||||
.collect(ImmutableMap.toImmutableMap({ it.first }, { it.second }))
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
for ((i, part) in this.parts.values.withIndex()) {
|
for ((i, part) in this.parts.values.withIndex()) {
|
||||||
part.index = i
|
part.index = i
|
||||||
@ -421,7 +395,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
while (networkChangelog.size > parts.size) networkChangelog.removeLast()
|
while (networkChangelog.size > parts.size) networkChangelog.removeLast()
|
||||||
}
|
}
|
||||||
|
|
||||||
override var isValid: MultiblockStatus = MultiblockStatus.INVALID
|
override var isValid: Boolean = false
|
||||||
private set(value) {
|
private set(value) {
|
||||||
if (value != field) {
|
if (value != field) {
|
||||||
field = value
|
field = value
|
||||||
@ -429,6 +403,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var iterator = this.parts.values.iterator()
|
||||||
private var validParts = 0
|
private var validParts = 0
|
||||||
|
|
||||||
override fun compareTo(other: Config): Int {
|
override fun compareTo(other: Config): Int {
|
||||||
@ -437,46 +412,42 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
return cmp
|
return cmp
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(levelAccessor: LevelAccessor, updateEverything: Boolean = remotes.isNotEmpty()): MultiblockStatus {
|
fun updateRemaining(levelAccessor: LevelAccessor) {
|
||||||
val networkVersion = networkVersion
|
val networkVersion = networkVersion
|
||||||
|
|
||||||
isValid = MultiblockStatus.VALID
|
if (!isValid) { // update rest
|
||||||
validParts = 0
|
for (part in iterator) {
|
||||||
|
if (part.test(levelAccessor)) {
|
||||||
for ((chunkPos, parts) in partsByChunk) {
|
validParts++
|
||||||
val chunk = levelAccessor.chunkSource.getChunkNow(chunkPos.x, chunkPos.z)
|
|
||||||
|
|
||||||
if (chunk == null) {
|
|
||||||
isValid = MultiblockStatus.NOT_LOADED
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updateEverything) {
|
|
||||||
for (part in parts) {
|
|
||||||
val status = part.test(levelAccessor, chunk)
|
|
||||||
if (status === MultiblockStatus.VALID) validParts++
|
|
||||||
isValid = isValid.or(status)
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
for (part in parts) {
|
} else {
|
||||||
val status = part.test(levelAccessor, chunk)
|
for (part in iterator) {
|
||||||
|
if (part.test(levelAccessor))
|
||||||
if (status === MultiblockStatus.VALID)
|
validParts++
|
||||||
validParts++
|
else {
|
||||||
else {
|
isValid = false
|
||||||
isValid = status
|
break
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValid != MultiblockStatus.VALID) clear()
|
|
||||||
|
|
||||||
if (this.networkVersion != networkVersion) {
|
if (this.networkVersion != networkVersion) {
|
||||||
remotes.forEach { it.listener.run() }
|
remotes.forEach { it.listener.run() }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun update(levelAccessor: LevelAccessor, updateEverything: Boolean = remotes.isNotEmpty()): Boolean {
|
||||||
|
isValid = true
|
||||||
|
iterator = this.parts.values.iterator()
|
||||||
|
validParts = 0
|
||||||
|
updateRemaining(levelAccessor)
|
||||||
|
|
||||||
|
if (updateEverything && iterator.hasNext()) {
|
||||||
|
updateRemaining(levelAccessor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValid) clear()
|
||||||
return isValid
|
return isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +565,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
|
|
||||||
override fun read(stream: RegistryFriendlyByteBuf) {
|
override fun read(stream: RegistryFriendlyByteBuf) {
|
||||||
isRemote = true
|
isRemote = true
|
||||||
isValid = MultiblockStatus.entries[stream.readByte().toInt()]
|
isValid = stream.readBoolean()
|
||||||
activeConfig = configurations[stream.readUnsignedByte().toInt()]
|
activeConfig = configurations[stream.readUnsignedByte().toInt()]
|
||||||
activeConfig.read(stream)
|
activeConfig.read(stream)
|
||||||
}
|
}
|
||||||
@ -609,7 +580,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun write(stream: RegistryFriendlyByteBuf) {
|
override fun write(stream: RegistryFriendlyByteBuf) {
|
||||||
stream.writeByte(isValid.ordinal)
|
stream.writeBoolean(isValid)
|
||||||
stream.writeByte(activeConfig.index)
|
stream.writeByte(activeConfig.index)
|
||||||
remotes[activeConfig.index].write(stream)
|
remotes[activeConfig.index].write(stream)
|
||||||
}
|
}
|
||||||
@ -637,36 +608,36 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val currentDirection: Direction?
|
override val currentDirection: Direction?
|
||||||
get() = if (isValid == MultiblockStatus.VALID) activeConfig.currentDirection else null
|
get() = if (isValid) activeConfig.currentDirection else null
|
||||||
|
|
||||||
override val boundingBox: AABB?
|
override val boundingBox: AABB?
|
||||||
get() = if (isValid == MultiblockStatus.VALID) activeConfig.boundingBox else null
|
get() = if (isValid) activeConfig.boundingBox else null
|
||||||
|
|
||||||
override val currentNodes: Map<BlockPos, IMultiblockNode>
|
override val currentNodes: Map<BlockPos, IMultiblockNode>
|
||||||
get() = activeConfig.parts
|
get() = activeConfig.parts
|
||||||
|
|
||||||
override fun <T : Any> blockEntities(tag: BlockEntityTag<T>): Set<T> {
|
override fun <T : Any> blockEntities(tag: BlockEntityTag<T>): Set<T> {
|
||||||
if (isValid != MultiblockStatus.VALID) return setOf()
|
if (!isValid) return setOf()
|
||||||
return activeConfig.blockEntities(tag)
|
return activeConfig.blockEntities(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun blocks(tag: Any): Reference2IntMap<Block> {
|
override fun blocks(tag: Any): Reference2IntMap<Block> {
|
||||||
if (isValid != MultiblockStatus.VALID) return Reference2IntMaps.emptyMap()
|
if (!isValid) return Reference2IntMaps.emptyMap()
|
||||||
return activeConfig.blocks(tag)
|
return activeConfig.blocks(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun blockStates(tag: Any): Reference2IntMap<BlockState> {
|
override fun blockStates(tag: Any): Reference2IntMap<BlockState> {
|
||||||
if (isValid != MultiblockStatus.VALID) return Reference2IntMaps.emptyMap()
|
if (!isValid) return Reference2IntMaps.emptyMap()
|
||||||
return activeConfig.blockStates(tag)
|
return activeConfig.blockStates(tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun blocks(): Reference2IntMap<Block> {
|
override fun blocks(): Reference2IntMap<Block> {
|
||||||
if (isValid != MultiblockStatus.VALID) return Reference2IntMaps.emptyMap()
|
if (!isValid) return Reference2IntMaps.emptyMap()
|
||||||
return activeConfig.blocks()
|
return activeConfig.blocks()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun blockStates(): Reference2IntMap<BlockState> {
|
override fun blockStates(): Reference2IntMap<BlockState> {
|
||||||
if (isValid != MultiblockStatus.VALID) return Reference2IntMaps.emptyMap()
|
if (!isValid) return Reference2IntMaps.emptyMap()
|
||||||
return activeConfig.blockStates()
|
return activeConfig.blockStates()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +645,7 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
return activeConfig.blockEntityRemoved(blockEntity)
|
return activeConfig.blockEntityRemoved(blockEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(levelAccessor: LevelAccessor): MultiblockStatus {
|
fun update(levelAccessor: LevelAccessor): Boolean {
|
||||||
isUpdating = true
|
isUpdating = true
|
||||||
val thisGeneration = generation
|
val thisGeneration = generation
|
||||||
|
|
||||||
@ -688,29 +659,25 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
configurations.add(max)
|
configurations.add(max)
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid = MultiblockStatus.INVALID
|
isValid = false
|
||||||
var hadUnloadedChunks = false
|
|
||||||
|
|
||||||
while (configurations.isNotEmpty()) {
|
while (configurations.isNotEmpty()) {
|
||||||
val config = configurations.removeFirst()
|
val config = configurations.removeFirst()
|
||||||
val status = config.update(levelAccessor)
|
|
||||||
|
|
||||||
if (status == MultiblockStatus.VALID) {
|
if (config.update(levelAccessor)) {
|
||||||
if (customChecks.all { it.test(config) }) {
|
if (customChecks.all { it.test(config) }) {
|
||||||
activeConfig = config
|
activeConfig = config
|
||||||
isValid = MultiblockStatus.VALID
|
isValid = true
|
||||||
remotes.forEach { it.listener.run() }
|
remotes.forEach { it.listener.run() }
|
||||||
|
|
||||||
if (thisGeneration != generation) {
|
if (thisGeneration != generation) {
|
||||||
changeListeners.forEach { it.runnable.run() }
|
changeListeners.forEach { it.runnable.run() }
|
||||||
}
|
}
|
||||||
|
|
||||||
return status
|
return true
|
||||||
} else {
|
} else {
|
||||||
config.clear()
|
config.clear()
|
||||||
}
|
}
|
||||||
} else if (status == MultiblockStatus.NOT_LOADED) {
|
|
||||||
hadUnloadedChunks = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,23 +685,22 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
changeListeners.forEach { it.runnable.run() }
|
changeListeners.forEach { it.runnable.run() }
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid = if (hadUnloadedChunks) MultiblockStatus.NOT_LOADED else MultiblockStatus.INVALID
|
return false
|
||||||
return isValid
|
|
||||||
} finally {
|
} finally {
|
||||||
isUpdating = false
|
isUpdating = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(levelAccessor: LevelAccessor, direction: Direction): MultiblockStatus {
|
fun update(levelAccessor: LevelAccessor, direction: Direction): Boolean {
|
||||||
isUpdating = true
|
isUpdating = true
|
||||||
val thisGeneration = generation
|
val thisGeneration = generation
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var changes = false
|
var changes = false
|
||||||
|
|
||||||
if (activeConfig.currentDirection != direction && isValid === MultiblockStatus.VALID) {
|
if (activeConfig.currentDirection != direction && isValid) {
|
||||||
activeConfig.clear()
|
activeConfig.clear()
|
||||||
isValid = MultiblockStatus.INVALID
|
isValid = false
|
||||||
changes = true
|
changes = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -750,9 +716,9 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
activeConfig = config
|
activeConfig = config
|
||||||
isValid = config.update(levelAccessor)
|
isValid = config.update(levelAccessor)
|
||||||
|
|
||||||
if (isValid === MultiblockStatus.VALID) {
|
if (isValid) {
|
||||||
isValid = MultiblockStatus.valid(customChecks.all { it.test(config) })
|
isValid = customChecks.all { it.test(config) }
|
||||||
if (isValid !== MultiblockStatus.VALID) config.clear()
|
if (!isValid) config.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changes) {
|
if (changes) {
|
||||||
@ -773,6 +739,6 @@ class ShapedMultiblock(pos: BlockPos, factory: ShapedMultiblockFactory) : IMulti
|
|||||||
changeListeners.clear()
|
changeListeners.clear()
|
||||||
remotes.forEach { it.close() }
|
remotes.forEach { it.close() }
|
||||||
configurations.forEach { it.clear() }
|
configurations.forEach { it.clear() }
|
||||||
isValid = MultiblockStatus.INVALID
|
isValid = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.menu.tech
|
|||||||
|
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleGeneratorBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleGeneratorBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.multiblock.MultiblockStatus
|
|
||||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||||
import ru.dbotthepony.mc.otm.menu.input.DecimalInputWithFeedback
|
import ru.dbotthepony.mc.otm.menu.input.DecimalInputWithFeedback
|
||||||
@ -16,7 +15,7 @@ class BlackHoleGeneratorMenu(
|
|||||||
inventory: Inventory,
|
inventory: Inventory,
|
||||||
tile: BlackHoleGeneratorBlockEntity? = null,
|
tile: BlackHoleGeneratorBlockEntity? = null,
|
||||||
) : MatteryMenu(MMenus.BLACK_HOLE_GENERATOR, p_38852_, inventory, tile) {
|
) : MatteryMenu(MMenus.BLACK_HOLE_GENERATOR, p_38852_, inventory, tile) {
|
||||||
val formed = mSynchronizer.computedBoolean(BooleanSupplier { tile?.multiblock?.isValid == MultiblockStatus.VALID })
|
val formed = mSynchronizer.computedBoolean(BooleanSupplier { tile?.multiblock?.isValid ?: false })
|
||||||
val drawBuildingGuide = BooleanInputWithFeedback(this, tile?.let { it::drawBuildingGuide })
|
val drawBuildingGuide = BooleanInputWithFeedback(this, tile?.let { it::drawBuildingGuide })
|
||||||
val energy = CombinedProfiledLevelGaugeWidget(this, tile?.energy)
|
val energy = CombinedProfiledLevelGaugeWidget(this, tile?.energy)
|
||||||
val matter = CombinedProfiledLevelGaugeWidget(this, tile?.matter)
|
val matter = CombinedProfiledLevelGaugeWidget(this, tile?.matter)
|
||||||
|
Loading…
Reference in New Issue
Block a user