blob: 1cac5f955485afdf9cda51c4f815eb78bb18449f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
package io.dico.parcels2.blockvisitor
import io.dico.parcels2.util.Region
import io.dico.parcels2.util.Vec3i
import kotlin.coroutines.experimental.SequenceBuilder
import kotlin.coroutines.experimental.buildIterator
abstract class RegionTraverser {
fun traverseRegion(region: Region): Iterable<Vec3i> = Iterable { buildIterator { build(region) } }
protected abstract suspend fun SequenceBuilder<Vec3i>.build(region: Region)
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 SequenceBuilder<Vec3i>.(Region) -> Unit) = object : RegionTraverser() {
override suspend fun SequenceBuilder<Vec3i>.build(region: Region) {
builder(region)
}
}
private suspend fun SequenceBuilder<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))
}
}
}
}
private suspend fun SequenceBuilder<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))
}
}
}
}
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))
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) }
}
}
}
|