Loading log progress bars

This commit is contained in:
DBotThePony 2023-09-29 23:34:15 +07:00
parent e96d668f26
commit 302aa9b83a
Signed by: DBot
GPG Key ID: DCC23B5715498507
5 changed files with 78 additions and 34 deletions

View File

@ -3,9 +3,14 @@ package ru.dbotthepony.kstarbound
import it.unimi.dsi.fastutil.ints.IntIterators
import it.unimi.dsi.fastutil.objects.ObjectIterators
interface ILoadingLog : Iterable<String> {
interface ILoadingLog : Iterable<ILoadingLog.ILine> {
interface ILine {
var text: String
val progress: Float
get() = if (maxElements > 0) elements.toFloat() / maxElements.toFloat() else 0f
var elements: Int
var maxElements: Int
}
fun line(text: String): ILine
@ -15,11 +20,18 @@ interface ILoadingLog : Iterable<String> {
get() = ""
set(value) {}
override var elements: Int
get() = 0
set(value) {}
override var maxElements: Int
get() = 0
set(value) {}
override fun line(text: String): ILine {
return this
}
override fun iterator(): Iterator<String> {
override fun iterator(): Iterator<ILine> {
return ObjectIterators.emptyIterator()
}
}
@ -44,6 +56,10 @@ class LoadingLog : ILoadingLog {
lastActivity = System.nanoTime()
}
@Volatile
override var elements: Int = 0
override var maxElements: Int = 0
init {
lastActivity = System.nanoTime()
@ -54,8 +70,8 @@ class LoadingLog : ILoadingLog {
}
}
override fun iterator(): Iterator<String> {
return object : Iterator<String> {
override fun iterator(): Iterator<ILoadingLog.ILine> {
return object : Iterator<ILoadingLog.ILine> {
private val index = (this@LoadingLog.index - 1) and 127
private val parent = IntIterators.fromTo(0, size)
@ -63,8 +79,8 @@ class LoadingLog : ILoadingLog {
return parent.hasNext()
}
override fun next(): String {
return lines[(index - parent.nextInt()) and 127]!!.text
override fun next(): ILoadingLog.ILine {
return lines[(index - parent.nextInt()) and 127]!!
}
}
}

View File

@ -65,15 +65,18 @@ object RecipeRegistry {
return listOf(executor.submit(Runnable {
val line = log.line("Loading recipes...")
val time = System.nanoTime()
line.maxElements = files.size
for (listedFile in files) {
for ((i, listedFile) in files.withIndex()) {
try {
line.text = ("Loading $listedFile")
val json = Starbound.gson.fromJson(listedFile.reader(), JsonElement::class.java)
val value = Starbound.gson.fromJson<RecipeDefinition>(JsonTreeReader(json), RecipeDefinition::class.java)
add(RegistryObject(value, json, listedFile))
line.elements++
} catch (err: Throwable) {
LOGGER.error("Loading recipe definition file $listedFile", err)
line.elements++
}
if (Starbound.terminateLoading) {

View File

@ -63,7 +63,7 @@ object Registries {
private fun loadStage(
log: ILoadingLog,
loader: ((String) -> Unit) -> Unit,
loader: (ILoadingLog.ILine) -> Unit,
name: String,
) {
if (Starbound.terminateLoading)
@ -71,15 +71,7 @@ object Registries {
val time = System.currentTimeMillis()
val line = log.line("Loading $name...".also(LOGGER::info))
loader {
if (Starbound.terminateLoading) {
throw InterruptedException("Game is terminating")
}
line.text = it
}
loader(line)
line.text = ("Loaded $name in ${System.currentTimeMillis() - time}ms".also(LOGGER::info))
}
@ -89,12 +81,16 @@ object Registries {
files: List<IStarboundFile>,
) {
loadStage(log, loader = {
it.maxElements = files.size
for (listedFile in files) {
try {
it("Loading $listedFile")
it.text = "Loading $listedFile"
registry.add(listedFile)
it.elements++
} catch (err: Throwable) {
LOGGER.error("Loading ${registry.name} definition file $listedFile", err)
it.elements++
}
if (Starbound.terminateLoading) {
@ -153,6 +149,7 @@ object Registries {
tasks.add(executor.submit {
val line = log.line("Loading items '$ext'")
val time = System.nanoTime()
line.maxElements = fileList.size
for (listedFile in fileList) {
try {
@ -160,8 +157,10 @@ object Registries {
val json = Starbound.gson.fromJson(listedFile.reader(), JsonObject::class.java)
val def: IItemDefinition = AssetPathStack(listedFile.computeDirectory()) { Starbound.gson.fromJson(JsonTreeReader(json), clazz) }
items.add(def, json, listedFile)
line.elements++
} catch (err: Throwable) {
LOGGER.error("Loading item definition file $listedFile", err)
line.elements++
}
if (Starbound.terminateLoading) {
@ -176,17 +175,18 @@ object Registries {
return tasks
}
private fun loadJsonFunctions(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
private fun loadJsonFunctions(line: ILoadingLog.ILine, files: Collection<IStarboundFile>) {
for (listedFile in files) {
callback("Loading $listedFile")
line.text = ("Loading $listedFile")
try {
val json = Starbound.gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
for ((k, v) in json.entrySet()) {
try {
callback("Loading $k from $listedFile")
line.text = ("Loading $k from $listedFile")
val fn = Starbound.gson.fromJson<JsonFunction>(JsonTreeReader(v), JsonFunction::class.java)
Registries.jsonFunctions.add(fn, v, listedFile, k)
jsonFunctions.add(fn, v, listedFile, k)
} catch (err: Exception) {
LOGGER.error("Loading json function definition $k from file $listedFile", err)
}
@ -201,18 +201,18 @@ object Registries {
}
}
private fun loadJson2Functions(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
private fun loadJson2Functions(line: ILoadingLog.ILine, files: Collection<IStarboundFile>) {
for (listedFile in files) {
callback("Loading $listedFile")
line.text = ("Loading $listedFile")
try {
val json = Starbound.gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
for ((k, v) in json.entrySet()) {
try {
callback("Loading $k from $listedFile")
line.text = ("Loading $k from $listedFile")
val fn = Starbound.gson.fromJson<Json2Function>(JsonTreeReader(v), Json2Function::class.java)
Registries.json2Functions.add(fn, v, listedFile, k)
json2Functions.add(fn, v, listedFile, k)
} catch (err: Throwable) {
LOGGER.error("Loading json 2function definition $k from file $listedFile", err)
}
@ -227,19 +227,19 @@ object Registries {
}
}
private fun loadTreasurePools(callback: (String) -> Unit, files: Collection<IStarboundFile>) {
private fun loadTreasurePools(line: ILoadingLog.ILine, files: Collection<IStarboundFile>) {
for (listedFile in files) {
callback("Loading $listedFile")
line.text = ("Loading $listedFile")
try {
val json = Starbound.gson.getAdapter(JsonObject::class.java).read(JsonReader(listedFile.reader()).also { it.isLenient = true })
for ((k, v) in json.entrySet()) {
try {
callback("Loading $k from $listedFile")
line.text = ("Loading $k from $listedFile")
val result = Starbound.gson.fromJson<TreasurePoolDefinition>(JsonTreeReader(v), TreasurePoolDefinition::class.java)
result.name = k
Registries.treasurePools.add(result, v, listedFile)
treasurePools.add(result, v, listedFile)
} catch (err: Throwable) {
LOGGER.error("Loading treasure pool definition $k from file $listedFile", err)
}

View File

@ -842,7 +842,7 @@ object Starbound : ISBFileLocator {
var playerDefinition: PlayerDefinition by WriteOnce()
private set
private fun doInitialize(log: ILoadingLog, parallel: Boolean = true) {
private fun doInitialize(log: ILoadingLog, parallel: Boolean) {
var time = System.currentTimeMillis()
if (archivePaths.isNotEmpty()) {
@ -918,7 +918,7 @@ object Starbound : ISBFileLocator {
log.line("Finished loading in ${System.currentTimeMillis() - time}ms")
}
fun initializeGame(log: ILoadingLog) {
fun initializeGame(log: ILoadingLog, parallel: Boolean = true) {
if (initializing) {
throw IllegalStateException("Already initializing!")
}
@ -928,7 +928,7 @@ object Starbound : ISBFileLocator {
}
initializing = true
Thread({ doInitialize(log) }, "Asset Loader").also {
Thread({ doInitialize(log, parallel) }, "Asset Loader").also {
it.isDaemon = true
it.start()
}

View File

@ -73,6 +73,7 @@ import java.time.Duration
import java.util.*
import java.util.concurrent.locks.LockSupport
import java.util.concurrent.locks.ReentrantLock
import java.util.stream.StreamSupport
import kotlin.collections.ArrayList
import kotlin.math.absoluteValue
import kotlin.math.roundToInt
@ -521,6 +522,20 @@ class StarboundClient : Closeable {
builder.draw(GL_LINES)
}
inline fun quadColor(color: RGBAColor = RGBAColor.WHITE, lambda: (VertexBuilder) -> Unit) {
val builder = programs.position.builder
builder.builder.begin(GeometryType.QUADS)
lambda.invoke(builder.builder)
builder.upload()
programs.position.use()
programs.position.colorMultiplier = color
programs.position.modelMatrix = stack.last()
builder.draw(GL_TRIANGLES)
}
inline fun lines(color: RGBAColor = RGBAColor.WHITE, lambda: (VertexBuilder) -> Unit) {
val builder = programs.position.builder
@ -856,10 +871,20 @@ class StarboundClient : Closeable {
stack.push()
stack.last().translate(y = viewportHeight.toFloat())
var shade = 255
for (line in loadingLog) {
val size = font.render(line, alignY = TextAlignY.BOTTOM, scale = 0.4f, color = RGBAColor(shade / 255f, shade / 255f, shade / 255f, alpha))
if (line.progress in 0.01f ..< 1f) {
quadColor(RGBAColor(0f, shade / 400f * line.progress, 0f, alpha * 0.8f)) {
it.vertex(0f, font.lineHeight * -0.4f)
it.vertex(viewportWidth * line.progress, font.lineHeight * -0.4f)
it.vertex(viewportWidth * line.progress, 0f)
it.vertex(0f, 0f)
}
}
val size = font.render(line.text, alignY = TextAlignY.BOTTOM, scale = 0.4f, color = RGBAColor(shade / 255f, shade / 255f, shade / 255f, alpha))
stack.last().translate(y = -size.height * 1.2f)
if (shade > 120) {