diff options
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt')
-rw-r--r-- | src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt | 303 |
1 files changed, 265 insertions, 38 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt b/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt index 3899db9..563d7a1 100644 --- a/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt +++ b/src/main/kotlin/io/dico/parcels2/blockvisitor/RegionTraverser.kt @@ -2,64 +2,291 @@ package io.dico.parcels2.blockvisitor import io.dico.parcels2.util.Region import io.dico.parcels2.util.Vec3i +import io.dico.parcels2.util.ext.clampMax -abstract class RegionTraverser { - fun traverseRegion(region: Region): Iterable<Vec3i> = Iterable { iterator<Vec3i> { build(region) } } +private typealias Scope = SequenceScope<Vec3i> - protected abstract suspend fun SequenceScope<Vec3i>.build(region: Region) +sealed class RegionTraverser { + fun traverseRegion(region: Region, worldHeight: Int = 256): Iterable<Vec3i> = + Iterable { iterator<Vec3i> { build(validify(region, worldHeight)) } } - companion object { - val upward = create { traverseUpward(it) } - val downward = create { traverseDownward(it) } - val forClearing get() = downward - val forFilling get() = upward - - inline fun create(crossinline builder: suspend SequenceScope<Vec3i>.(Region) -> Unit) = object : RegionTraverser() { - override suspend fun SequenceScope<Vec3i>.build(region: Region) { - builder(region) - } + private fun validify(region: Region, worldHeight: Int): Region { + if (region.origin.y < 0) { + val origin = region.origin withY 0 + val size = region.size.withY((region.size.y + region.origin.y).clampMax(worldHeight)) + return Region(origin, size) } - private suspend fun SequenceScope<Vec3i>.traverseDownward(region: Region) { - val origin = region.origin - val size = region.size - repeat(size.y) { y -> - repeat(size.z) { z -> - repeat(size.x) { x -> - yield(origin.add(x, size.y - y - 1, z)) - } - } - } + if (region.origin.y + region.size.y > worldHeight) { + val size = region.size.withY(worldHeight - region.origin.y) + return Region(region.origin, size) } - private suspend fun SequenceScope<Vec3i>.traverseUpward(region: Region) { - val origin = region.origin - val size = region.size - repeat(size.y) { y -> - repeat(size.z) { z -> - repeat(size.x) { x -> - yield(origin.add(x, size.y - y - 1, z)) - } - } - } + return region + } + + protected abstract suspend fun Scope.build(region: Region) + + companion object { + val upward = Directional(TraverseDirection(1, 1, 1), TraverseOrder(Dimension.Y, Dimension.X)) + val downward = Directional(TraverseDirection(1, -1, 1), TraverseOrder(Dimension.Y, Dimension.X)) + val toClear get() = downward + val toFill get() = upward + + fun convergingTo(y: Int) = Slicing(y, upward, downward, true) + + fun separatingFrom(y: Int) = Slicing(y, downward, upward, false) + } + + class Directional( + val direction: TraverseDirection, + val order: TraverseOrder + ) : RegionTraverser() { + override suspend fun Scope.build(region: Region) { + //traverserLogic(region, order, direction) } + } + + class Slicing( + val bottomSectionMaxY: Int, + val bottomTraverser: RegionTraverser, + val topTraverser: RegionTraverser, + val bottomFirst: Boolean = true + ) : RegionTraverser() { + private fun slice(region: Region, atY: Int): Pair<Region, Region?> { if (atY < region.size.y + 1) { val first = Region(region.origin, region.size.withY(atY + 1)) - val second = Region(region.origin.withY(atY), region.size.addY(-atY-1)) + val second = Region(region.origin.withY(atY), region.size.addY(-atY - 1)) return first to second } return region to null } - fun upToAndDownUntil(y: Int) = create { region -> - val (bottom, top) = slice(region, y) - traverseUpward(bottom) - top?.let { traverseDownward(it) } + override suspend fun Scope.build(region: Region) { + val (bottom, top) = slice(region, bottomSectionMaxY) + + if (bottomFirst) { + with(bottomTraverser) { build(bottom) } + top?.let { with(topTraverser) { build(it) } } + } else { + top?.let { with(topTraverser) { build(it) } } + with(bottomTraverser) { build(bottom) } + } + } + } + +} + +enum class Dimension { + X, + Y, + Z; + + fun extract(block: Vec3i) = + when (this) { + X -> block.x + Y -> block.y + Z -> block.z } + companion object { + private val values = values() + operator fun get(ordinal: Int) = values[ordinal] } +} + +inline class TraverseOrder(val orderNum: Int) { + private constructor(first: Dimension, swap: Boolean) + : this(if (swap) first.ordinal + 3 else first.ordinal) + + @Suppress("NOTHING_TO_INLINE") + private inline fun element(index: Int) = Dimension[(orderNum + index) % 3] + + private val swap inline get() = orderNum >= 3 + + /** + * The slowest changing dimension + */ + val primary: Dimension get() = element(0) + + /** + * Second slowest changing dimension + */ + val secondary: Dimension get() = element(if (swap) 2 else 1) + + /** + * Dimension that changes every block + */ + val tertiary: Dimension get() = element(if (swap) 1 else 2) + + /** + * All 3 dimensions in this order + */ + fun toArray() = arrayOf(primary, secondary, tertiary) + companion object { + private fun isSwap(primary: Dimension, secondary: Dimension) = secondary.ordinal != (primary.ordinal + 1) % 3 + + operator fun invoke(primary: Dimension, secondary: Dimension): TraverseOrder { + // tertiary is implicit + if (primary == secondary) throw IllegalArgumentException() + return TraverseOrder(primary, isSwap(primary, secondary)) + } + } + fun add(vec: Vec3i, dp: Int, ds: Int, dt: Int): Vec3i = + // optimize this, will be called lots + when (orderNum) { + 0 -> vec.add(dp, ds, dt) // xyz + 1 -> vec.add(dt, dp, ds) // yzx + 2 -> vec.add(ds, dt, dp) // zxy + 3 -> vec.add(dp, dt, ds) // xzy + 4 -> vec.add(ds, dp, dt) // yxz + 5 -> vec.add(dt, ds, dp) // zyx + else -> error("Invalid orderNum $orderNum") + } } + +class AltTraverser(val size: Vec3i, + val order: TraverseOrder, + val direction: TraverseDirection) { + + + suspend fun Scope.build() { + doPrimary() + } + + private suspend fun Scope.doPrimary() { + val dimension = order.primary + direction.directionOf(dimension).traverse(dimension.extract(size)) { value -> + + } + } + + private fun Dimension.setValue(value: Int) { + + } + +} + +enum class Increment(val offset: Int) { + UP(1), + DOWN(-1); + + companion object { + fun convert(bool: Boolean) = if (bool) UP else DOWN + } + + inline fun traverse(size: Int, op: (Int) -> Unit) { + when (this) { + UP -> repeat(size, op) + DOWN -> repeat(size) { op(size - it - 1) } + } + } + +} + +inline class TraverseDirection(val bits: Int) { + + fun directionOf(dimension: Dimension) = Increment.convert((1 shl dimension.ordinal) and bits != 0) + + companion object { + operator fun invoke(x: Int, y: Int, z: Int) = invoke(Vec3i(x, y, z)) + + operator fun invoke(block: Vec3i): TraverseDirection { + if (block.x == 0 || block.y == 0 || block.z == 0) throw IllegalArgumentException() + var bits = 0 + if (block.x > 0) bits = bits or 1 + if (block.y > 0) bits = bits or 2 + if (block.z > 0) bits = bits or 3 + return TraverseDirection(bits) + } + } + +} + +/* +private typealias Scope = SequenceScope<Vec3i> +private typealias ScopeAction = suspend Scope.(Int, Int, Int) -> Unit + +@Suppress("NON_EXHAUSTIVE_WHEN") +suspend fun Scope.traverserLogic( + region: Region, + order: TraverseOrder, + direction: TraverseDirection +) = with(direction) { + val (primary, secondary, tertiary) = order.toArray() + val (origin, size) = region + + when (order.primary) { + Dimension.X -> + when (order.secondary) { + Dimension.Y -> { + directionOf(primary).traverse(primary.extract(size)) { p -> + directionOf(secondary).traverse(secondary.extract(size)) { s -> + directionOf(tertiary).traverse(tertiary.extract(size)) { t -> + yield(origin.add(p, s, t)) + } + } + } + } + Dimension.Z -> { + directionOf(primary).traverse(primary.extract(size)) { p -> + directionOf(secondary).traverse(secondary.extract(size)) { s -> + directionOf(tertiary).traverse(tertiary.extract(size)) { t -> + yield(origin.add(p, t, s)) + } + } + } + } + } + + Dimension.Y -> + when (order.secondary) { + Dimension.X -> { + directionOf(primary).traverse(primary.extract(size)) { p -> + directionOf(secondary).traverse(secondary.extract(size)) { s -> + directionOf(tertiary).traverse(tertiary.extract(size)) { t -> + yield(origin.add(s, p, t)) + } + } + } + } + Dimension.Z -> { + directionOf(primary).traverse(primary.extract(size)) { p -> + directionOf(secondary).traverse(secondary.extract(size)) { s -> + directionOf(tertiary).traverse(tertiary.extract(size)) { t -> + yield(origin.add(t, p, s)) + } + } + } + } + } + + Dimension.Z -> + when (order.secondary) { + Dimension.X -> { + directionOf(primary).traverse(primary.extract(size)) { p -> + directionOf(secondary).traverse(secondary.extract(size)) { s -> + directionOf(tertiary).traverse(tertiary.extract(size)) { t -> + yield(origin.add(s, t, p)) + } + } + } + } + Dimension.Y -> { + directionOf(primary).traverse(primary.extract(size)) { p -> + directionOf(secondary).traverse(secondary.extract(size)) { s -> + directionOf(tertiary).traverse(tertiary.extract(size)) { t -> + yield(origin.add(t, s, p)) + } + } + } + } + } + } +} + +*/
\ No newline at end of file |