Load font from pak files, bootstrap window

This commit is contained in:
DBotThePony 2023-12-01 19:03:51 +07:00
parent 2793154bbb
commit b79161cca2
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 214 additions and 89 deletions

View File

@ -65,16 +65,12 @@ fun main() {
Starbound.initializeGame(client.loadingLog)
client.onTermination {
Starbound.terminateLoading = true
}
var ply: PlayerEntity? = null
Starbound.onInitialize {
Starbound.mailboxInitialized.submit {
ply = PlayerEntity(client.world!!)
ply!!.position = Vector2d(225.0, 745.0)
ply!!.position = Vector2d(225.0, 680.0)
ply!!.spawn()
//for (chunkX in 17 .. 18) {

View File

@ -62,6 +62,7 @@ import ru.dbotthepony.kstarbound.world.physics.Poly
import java.io.*
import java.lang.ref.Cleaner
import java.text.DateFormat
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ForkJoinPool
import java.util.concurrent.ForkJoinTask
import java.util.concurrent.locks.LockSupport
@ -80,6 +81,8 @@ object Starbound : ISBFileLocator {
val thread = Thread(::universeThread, "Starbound Universe")
val mailbox = MailboxExecutorService(thread)
val mailboxBootstrapped = MailboxExecutorService(thread)
val mailboxInitialized = MailboxExecutorService(thread)
init {
thread.isDaemon = true
@ -274,11 +277,14 @@ object Starbound : ISBFileLocator {
}
}
@Volatile
var initializing = false
private set
var initialized = false
private set
var bootstrapping = false
private set
var bootstrapped = false
private set
@Volatile
var terminateLoading = false
@ -370,29 +376,33 @@ object Starbound : ISBFileLocator {
archivePaths.add(pak)
}
private val initCallbacks = ArrayList<() -> Unit>()
var playerDefinition: PlayerDefinition by WriteOnce()
private set
private fun doInitialize(log: ILoadingLog, parallel: Boolean) {
var time = System.currentTimeMillis()
if (archivePaths.isNotEmpty()) {
log.line("Searching for pak archives...".also(LOGGER::info))
for (path in archivePaths) {
val line = log.line("Reading index of ${path}...".also(LOGGER::info))
addPak(StarboundPak(path) { _, status ->
line.text = ("${path.parent}/${path.name}: $status")
})
}
private fun doBootstrap() {
if (!bootstrapped && !bootstrapping) {
bootstrapping = true
} else {
return
}
log.line("Finished reading pak archives in ${System.currentTimeMillis() - time}ms".also(LOGGER::info))
time = System.currentTimeMillis()
log.line("Building file index...".also(LOGGER::info))
for (path in archivePaths) {
addPak(StarboundPak(path))
}
bootstrapped = true
bootstrapping = false
checkMailbox()
}
private fun doInitialize(log: ILoadingLog, parallel: Boolean) {
if (!initializing && !initialized) {
initializing = true
} else {
return
}
doBootstrap()
val time = System.currentTimeMillis()
val ext2files = fileSystems.parallelStream()
.flatMap { it.explore() }
@ -428,7 +438,7 @@ object Starbound : ISBFileLocator {
}
})
log.line("Finished building file index in ${System.currentTimeMillis() - time}ms".also(LOGGER::info))
checkMailbox()
val tasks = ArrayList<ForkJoinTask<*>>()
val pool = if (parallel) ForkJoinPool.commonPool() else ForkJoinPool(1)
@ -437,10 +447,6 @@ object Starbound : ISBFileLocator {
tasks.addAll(RecipeRegistry.load(log, ext2files, pool))
tasks.addAll(GlobalDefaults.load(log, pool))
AssetPathStack.block("/") {
//playerDefinition = gson.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
}
tasks.forEach { it.join() }
if (!parallel)
@ -450,45 +456,64 @@ object Starbound : ISBFileLocator {
initializing = false
initialized = true
checkMailbox()
log.line("Finished loading in ${System.currentTimeMillis() - time}ms")
}
fun initializeGame(log: ILoadingLog, parallel: Boolean = true) {
if (initializing) {
throw IllegalStateException("Already initializing!")
}
if (initialized) {
throw IllegalStateException("Already initialized!")
}
initializing = true
mailbox.submit {
doInitialize(log, parallel)
}
}
fun onInitialize(callback: () -> Unit) {
if (initialized) {
callback()
} else {
initCallbacks.add(callback)
fun bootstrapGame() {
mailbox.submit {
doBootstrap()
}
}
private fun checkMailbox() {
mailbox.executeQueuedTasks()
if (bootstrapped)
mailboxBootstrapped.executeQueuedTasks()
if (initialized)
mailboxInitialized.executeQueuedTasks()
}
private var fontPath: File? = null
fun loadFont(): CompletableFuture<File> {
val fontPath = fontPath
if (fontPath != null)
return CompletableFuture.completedFuture(fontPath)
return CompletableFuture.supplyAsync(Supplier {
val fontPath = Starbound.fontPath
if (fontPath != null)
return@Supplier fontPath
val file = locate("/hobo.ttf")
if (!file.exists)
throw FileNotFoundException("Unable to locate font file /hobo.ttf")
else if (!file.isFile)
throw FileNotFoundException("/hobo.ttf is not a file!")
else {
val tempPath = File(System.getProperty("java.io.tmpdir"), "sb-hobo.ttf")
tempPath.writeBytes(file.read().array())
Starbound.fontPath = tempPath
return@Supplier tempPath
}
}, mailboxBootstrapped)
}
private fun universeThread() {
while (true) {
mailbox.executeQueuedTasks()
if (initialized && initCallbacks.isNotEmpty()) {
for (callback in initCallbacks) {
callback()
}
initCallbacks.clear()
}
checkMailbox()
LockSupport.park()
}
}

View File

@ -78,11 +78,13 @@ import java.util.concurrent.ForkJoinWorkerThread
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.locks.LockSupport
import java.util.concurrent.locks.ReentrantLock
import java.util.function.Consumer
import java.util.function.IntConsumer
import kotlin.collections.ArrayList
import kotlin.concurrent.withLock
import kotlin.math.absoluteValue
import kotlin.math.roundToInt
import kotlin.properties.Delegates
class StarboundClient : Closeable {
val window: Long
@ -383,7 +385,23 @@ class StarboundClient : Closeable {
}
val freeType = FreeType()
val font = Font()
var font: Font by Delegates.notNull()
private set
private var fontInitialized = false
init {
Starbound.loadFont().thenAcceptAsync(Consumer {
try {
font = Font(it.canonicalPath)
fontInitialized = true
} catch (err: Throwable) {
LOGGER.fatal("Unable to load font", err)
}
}, mailbox)
}
val programs = GLPrograms()
init {
@ -739,6 +757,42 @@ class StarboundClient : Closeable {
}
private val layers = LayeredRenderer(this)
private var dotsIndex = 0
private val dotTime = 4
private var dotInc = 1
private fun renderLoadingText() {
var alpha = 1f
if (System.nanoTime() - loadingLog.lastActivity >= 3_000_000_000L) {
alpha = 1f - (System.nanoTime() - loadingLog.lastActivity - 3_000_000_000L) / 1_000_000_000f
}
stack.push()
stack.last().translate(y = viewportHeight.toFloat())
var shade = 255
for (line in loadingLog) {
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) {
shade -= 10
}
}
stack.pop()
}
fun renderFrame(): Boolean {
ensureSameThread()
@ -781,6 +835,71 @@ class StarboundClient : Closeable {
return true
}
if (!Starbound.initialized || !fontInitialized) {
executeQueuedTasks()
updateViewportParams()
clearColor = RGBAColor.BLACK
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
val min = viewportHeight.coerceAtMost(viewportWidth)
val size = min * 0.01f
val program = programs.positionColor
val builder = program.builder
uberShaderPrograms.forEachValid { it.viewMatrix = viewportMatrixScreen }
fontShaderPrograms.forEachValid { it.viewMatrix = viewportMatrixScreen }
stack.clear(Matrix3f.identity())
program.colorMultiplier = RGBAColor.WHITE
if (!fontInitialized) {
builder.builder.begin(GeometryType.QUADS)
dotsIndex += dotInc
if (dotsIndex < 0) {
dotsIndex = 1
dotInc = 1
} else if (dotsIndex > dotTime * 3) {
dotsIndex = dotTime * 3 - 1
dotInc = -1
}
val a = if (dotsIndex / dotTime == 0) RGBAColor.SLATE_GRAY else RGBAColor.WHITE
val b = if (dotsIndex / dotTime == 1) RGBAColor.SLATE_GRAY else RGBAColor.WHITE
val c = if (dotsIndex / dotTime == 2) RGBAColor.SLATE_GRAY else RGBAColor.WHITE
builder.builder.vertex(viewportWidth * 0.5f - size - size * 4f, viewportHeight * 0.5f - size).color(a)
builder.builder.vertex(viewportWidth * 0.5f + size - size * 4f, viewportHeight * 0.5f - size).color(a)
builder.builder.vertex(viewportWidth * 0.5f + size - size * 4f, viewportHeight * 0.5f + size).color(a)
builder.builder.vertex(viewportWidth * 0.5f - size - size * 4f, viewportHeight * 0.5f + size).color(a)
builder.builder.vertex(viewportWidth * 0.5f - size, viewportHeight * 0.5f - size).color(b)
builder.builder.vertex(viewportWidth * 0.5f + size, viewportHeight * 0.5f - size).color(b)
builder.builder.vertex(viewportWidth * 0.5f + size, viewportHeight * 0.5f + size).color(b)
builder.builder.vertex(viewportWidth * 0.5f - size, viewportHeight * 0.5f + size).color(b)
builder.builder.vertex(viewportWidth * 0.5f - size + size * 4f, viewportHeight * 0.5f - size).color(c)
builder.builder.vertex(viewportWidth * 0.5f + size + size * 4f, viewportHeight * 0.5f - size).color(c)
builder.builder.vertex(viewportWidth * 0.5f + size + size * 4f, viewportHeight * 0.5f + size).color(c)
builder.builder.vertex(viewportWidth * 0.5f - size + size * 4f, viewportHeight * 0.5f + size).color(c)
program.use()
builder.upload()
builder.draw()
} else {
renderLoadingText()
}
GLFW.glfwSwapBuffers(window)
GLFW.glfwPollEvents()
return true
}
layers.clear()
uberShaderPrograms.forEachValid {
@ -875,36 +994,7 @@ class StarboundClient : Closeable {
fontShaderPrograms.forEachValid { it.viewMatrix = viewportMatrixScreen }
if (System.nanoTime() - loadingLog.lastActivity <= 4_000_000_000L) {
var alpha = 1f
if (System.nanoTime() - loadingLog.lastActivity >= 3_000_000_000L) {
alpha = 1f - (System.nanoTime() - loadingLog.lastActivity - 3_000_000_000L) / 1_000_000_000f
}
stack.push()
stack.last().translate(y = viewportHeight.toFloat())
var shade = 255
for (line in loadingLog) {
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) {
shade -= 10
}
}
stack.pop()
//renderLoadingText()
}
stack.clear(Matrix3f.identity())

View File

@ -10,10 +10,24 @@ import ru.dbotthepony.kstarbound.world.physics.Poly
class PlayerEntity(world: World<*, *>) : Entity(world) {
override val movementParameters: PlayerMovementParameters = GlobalDefaults.playerMovementParameters
var isWalking = false
var isRunning = false
var isCrouching = false
var isFlying = false
var isFalling = false
var canJump = false
var isJumping = false
var isGroundMovement = false
var isLiquidMovement = false
init {
GlobalDefaults.playerMovementParameters.standingPoly?.let {
//hitboxes.add(it)
hitboxes.add(Starbound.gson.fromJson("""[ [-0.75, -2.0], [-0.35, -2.5], [0.35, -2.5], [0.75, -2.0], [0.75, 0.65], [0.35, 1.22], [-0.35, 1.22], [-0.75, 0.65] ]""", Poly::class.java))
}
}
override fun move() {
super.move()
}
}