Load font from pak files, bootstrap window
This commit is contained in:
parent
2793154bbb
commit
b79161cca2
@ -65,16 +65,12 @@ fun main() {
|
|||||||
|
|
||||||
Starbound.initializeGame(client.loadingLog)
|
Starbound.initializeGame(client.loadingLog)
|
||||||
|
|
||||||
client.onTermination {
|
|
||||||
Starbound.terminateLoading = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var ply: PlayerEntity? = null
|
var ply: PlayerEntity? = null
|
||||||
|
|
||||||
Starbound.onInitialize {
|
Starbound.mailboxInitialized.submit {
|
||||||
ply = PlayerEntity(client.world!!)
|
ply = PlayerEntity(client.world!!)
|
||||||
|
|
||||||
ply!!.position = Vector2d(225.0, 745.0)
|
ply!!.position = Vector2d(225.0, 680.0)
|
||||||
ply!!.spawn()
|
ply!!.spawn()
|
||||||
|
|
||||||
//for (chunkX in 17 .. 18) {
|
//for (chunkX in 17 .. 18) {
|
||||||
|
@ -62,6 +62,7 @@ import ru.dbotthepony.kstarbound.world.physics.Poly
|
|||||||
import java.io.*
|
import java.io.*
|
||||||
import java.lang.ref.Cleaner
|
import java.lang.ref.Cleaner
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
import java.util.concurrent.ForkJoinPool
|
import java.util.concurrent.ForkJoinPool
|
||||||
import java.util.concurrent.ForkJoinTask
|
import java.util.concurrent.ForkJoinTask
|
||||||
import java.util.concurrent.locks.LockSupport
|
import java.util.concurrent.locks.LockSupport
|
||||||
@ -80,6 +81,8 @@ object Starbound : ISBFileLocator {
|
|||||||
|
|
||||||
val thread = Thread(::universeThread, "Starbound Universe")
|
val thread = Thread(::universeThread, "Starbound Universe")
|
||||||
val mailbox = MailboxExecutorService(thread)
|
val mailbox = MailboxExecutorService(thread)
|
||||||
|
val mailboxBootstrapped = MailboxExecutorService(thread)
|
||||||
|
val mailboxInitialized = MailboxExecutorService(thread)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
thread.isDaemon = true
|
thread.isDaemon = true
|
||||||
@ -274,11 +277,14 @@ object Starbound : ISBFileLocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Volatile
|
|
||||||
var initializing = false
|
var initializing = false
|
||||||
private set
|
private set
|
||||||
var initialized = false
|
var initialized = false
|
||||||
private set
|
private set
|
||||||
|
var bootstrapping = false
|
||||||
|
private set
|
||||||
|
var bootstrapped = false
|
||||||
|
private set
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var terminateLoading = false
|
var terminateLoading = false
|
||||||
@ -370,29 +376,33 @@ object Starbound : ISBFileLocator {
|
|||||||
archivePaths.add(pak)
|
archivePaths.add(pak)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val initCallbacks = ArrayList<() -> Unit>()
|
private fun doBootstrap() {
|
||||||
|
if (!bootstrapped && !bootstrapping) {
|
||||||
var playerDefinition: PlayerDefinition by WriteOnce()
|
bootstrapping = true
|
||||||
private set
|
} else {
|
||||||
|
return
|
||||||
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")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.line("Finished reading pak archives in ${System.currentTimeMillis() - time}ms".also(LOGGER::info))
|
for (path in archivePaths) {
|
||||||
time = System.currentTimeMillis()
|
addPak(StarboundPak(path))
|
||||||
log.line("Building file index...".also(LOGGER::info))
|
}
|
||||||
|
|
||||||
|
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()
|
val ext2files = fileSystems.parallelStream()
|
||||||
.flatMap { it.explore() }
|
.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 tasks = ArrayList<ForkJoinTask<*>>()
|
||||||
val pool = if (parallel) ForkJoinPool.commonPool() else ForkJoinPool(1)
|
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(RecipeRegistry.load(log, ext2files, pool))
|
||||||
tasks.addAll(GlobalDefaults.load(log, pool))
|
tasks.addAll(GlobalDefaults.load(log, pool))
|
||||||
|
|
||||||
AssetPathStack.block("/") {
|
|
||||||
//playerDefinition = gson.fromJson(locate("/player.config").reader(), PlayerDefinition::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.forEach { it.join() }
|
tasks.forEach { it.join() }
|
||||||
|
|
||||||
if (!parallel)
|
if (!parallel)
|
||||||
@ -450,45 +456,64 @@ object Starbound : ISBFileLocator {
|
|||||||
|
|
||||||
initializing = false
|
initializing = false
|
||||||
initialized = true
|
initialized = true
|
||||||
|
checkMailbox()
|
||||||
log.line("Finished loading in ${System.currentTimeMillis() - time}ms")
|
log.line("Finished loading in ${System.currentTimeMillis() - time}ms")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializeGame(log: ILoadingLog, parallel: Boolean = true) {
|
fun initializeGame(log: ILoadingLog, parallel: Boolean = true) {
|
||||||
if (initializing) {
|
|
||||||
throw IllegalStateException("Already initializing!")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initialized) {
|
|
||||||
throw IllegalStateException("Already initialized!")
|
|
||||||
}
|
|
||||||
|
|
||||||
initializing = true
|
|
||||||
|
|
||||||
mailbox.submit {
|
mailbox.submit {
|
||||||
doInitialize(log, parallel)
|
doInitialize(log, parallel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onInitialize(callback: () -> Unit) {
|
fun bootstrapGame() {
|
||||||
if (initialized) {
|
mailbox.submit {
|
||||||
callback()
|
doBootstrap()
|
||||||
} else {
|
|
||||||
initCallbacks.add(callback)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
private fun universeThread() {
|
||||||
while (true) {
|
while (true) {
|
||||||
mailbox.executeQueuedTasks()
|
checkMailbox()
|
||||||
|
|
||||||
if (initialized && initCallbacks.isNotEmpty()) {
|
|
||||||
for (callback in initCallbacks) {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
|
|
||||||
initCallbacks.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
LockSupport.park()
|
LockSupport.park()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,11 +78,13 @@ import java.util.concurrent.ForkJoinWorkerThread
|
|||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import java.util.concurrent.locks.LockSupport
|
import java.util.concurrent.locks.LockSupport
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import java.util.function.Consumer
|
||||||
import java.util.function.IntConsumer
|
import java.util.function.IntConsumer
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
class StarboundClient : Closeable {
|
class StarboundClient : Closeable {
|
||||||
val window: Long
|
val window: Long
|
||||||
@ -383,7 +385,23 @@ class StarboundClient : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val freeType = FreeType()
|
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()
|
val programs = GLPrograms()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -739,6 +757,42 @@ class StarboundClient : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val layers = LayeredRenderer(this)
|
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 {
|
fun renderFrame(): Boolean {
|
||||||
ensureSameThread()
|
ensureSameThread()
|
||||||
@ -781,6 +835,71 @@ class StarboundClient : Closeable {
|
|||||||
return true
|
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()
|
layers.clear()
|
||||||
|
|
||||||
uberShaderPrograms.forEachValid {
|
uberShaderPrograms.forEachValid {
|
||||||
@ -875,36 +994,7 @@ class StarboundClient : Closeable {
|
|||||||
fontShaderPrograms.forEachValid { it.viewMatrix = viewportMatrixScreen }
|
fontShaderPrograms.forEachValid { it.viewMatrix = viewportMatrixScreen }
|
||||||
|
|
||||||
if (System.nanoTime() - loadingLog.lastActivity <= 4_000_000_000L) {
|
if (System.nanoTime() - loadingLog.lastActivity <= 4_000_000_000L) {
|
||||||
var alpha = 1f
|
//renderLoadingText()
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.clear(Matrix3f.identity())
|
stack.clear(Matrix3f.identity())
|
||||||
|
@ -10,10 +10,24 @@ import ru.dbotthepony.kstarbound.world.physics.Poly
|
|||||||
class PlayerEntity(world: World<*, *>) : Entity(world) {
|
class PlayerEntity(world: World<*, *>) : Entity(world) {
|
||||||
override val movementParameters: PlayerMovementParameters = GlobalDefaults.playerMovementParameters
|
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 {
|
init {
|
||||||
GlobalDefaults.playerMovementParameters.standingPoly?.let {
|
GlobalDefaults.playerMovementParameters.standingPoly?.let {
|
||||||
//hitboxes.add(it)
|
//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))
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user