KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/world/Universe.kt

80 lines
2.8 KiB
Kotlin

package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kommons.util.AABBi
import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.defs.world.CelestialBaseInformation
import ru.dbotthepony.kstarbound.defs.world.CelestialParameters
import java.util.concurrent.CompletableFuture
abstract class Universe {
abstract val region: AABBi
abstract val baseInformation: CelestialBaseInformation
abstract suspend fun parameters(pos: UniversePos): CelestialParameters?
suspend fun name(pos: UniversePos): String? {
return parameters(pos)?.name
}
/**
* Return all valid system coordinates in the given x/y range. All systems
* are guaranteed to have unique x/y coordinates, and are meant to be viewed
* from the top in 2d. The z-coordinate is there simpy as a validation
* parameter.
*
* [callback] determines when to stop scanning (returning non empty KOptional will stop scanning)
*/
abstract suspend fun <T> scanSystems(region: AABBi, callback: suspend (UniversePos) -> KOptional<T>): KOptional<T>
abstract suspend fun scanConstellationLines(region: AABBi, aggressive: Boolean = false): List<Pair<Vector2i, Vector2i>>
/**
* Similar to [scanSystems], but scans for ALL systems in given range, on multiple threads
*/
abstract suspend fun findSystems(region: AABBi, includedTypes: Set<String>? = null): List<UniversePos>
abstract suspend fun hasChildren(pos: UniversePos): Boolean
abstract suspend fun children(pos: UniversePos): List<UniversePos>
/**
* Returns false if part or all of the specified region is not loaded. This
* is only relevant for calls to scanSystems and scanConstellationLines, and
* does not imply that each individual system in the given region is fully
* loaded with all planets moons etc, only that scanSystem and
* scanConstellationLines are not waiting on missing data.
*/
abstract fun scanRegionFullyLoaded(region: AABBi): Boolean
fun chunkPositions(region: AABBi): List<Vector2i> {
if (region.mins == region.maxs)
return emptyList()
val result = ArrayList<Vector2i>()
val mins = world2chunk(region.mins)
val maxs = world2chunk(region.maxs - Vector2i.POSITIVE_XY)
for (x in mins.x .. maxs.x) {
for (y in mins.y .. maxs.y) {
result.add(Vector2i(x, y))
}
}
return result
}
fun world2chunk(pos: IStruct2i): Vector2i {
val (x, y) = pos
return Vector2i(
(x - positiveModulo(x, baseInformation.chunkSize)) / baseInformation.chunkSize,
(y - positiveModulo(y, baseInformation.chunkSize)) / baseInformation.chunkSize)
}
fun chunkRegion(chunkPos: IStruct2i): AABBi {
val mins = Vector2i(chunkPos) * baseInformation.chunkSize
return AABBi(mins, mins + Vector2i.POSITIVE_XY * baseInformation.chunkSize)
}
}