diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt index fe1218e2c..d3a08e6e9 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderLoader.kt @@ -51,6 +51,7 @@ object RenderLoader { } fun RenderContext.load(latch: AbstractLatch) { + val renderLatch = ParentLatch(1, latch) setThread() Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Creating window..." } val stopwatch = Stopwatch() @@ -73,7 +74,7 @@ object RenderLoader { renderSystem.reset() // Init stage - val initLatch = ParentLatch(1, latch) + val initLatch = ParentLatch(1, renderLatch) Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Generating font and gathering textures (after ${stopwatch.labTime()})..." } textureManager.dynamicTextures.load(initLatch) textureManager.initializeSkins(connection) @@ -95,16 +96,16 @@ object RenderLoader { // Post init stage Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Preloading textures (after ${stopwatch.labTime()})..." } - textureManager.staticTextures.preLoad(latch) + textureManager.staticTextures.preLoad(renderLatch) Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Loading textures (after ${stopwatch.labTime()})..." } - textureManager.staticTextures.load(latch) - font.postInit(latch) + textureManager.staticTextures.load(renderLatch) + font.postInit(renderLatch) Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Post loading renderer (after ${stopwatch.labTime()})..." } shaderManager.postInit() skeletalManager.postInit() - renderer.postInit(latch) + renderer.postInit(renderLatch) framebufferManager.postInit() @@ -134,8 +135,8 @@ object RenderLoader { textureManager.staticTextures.activate() - latch.dec() // initial count from rendering - latch.await() + renderLatch.dec() // initial count from rendering + renderLatch.await() Log.log(LogMessageType.RENDERING_LOADING) { "Rendering is fully prepared in ${stopwatch.totalTime()}" } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/Rendering.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/Rendering.kt index 56f9c0262..f968219f7 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/Rendering.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/Rendering.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2023 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -32,9 +32,10 @@ class Rendering(private val connection: PlayConnection) { fun start(latch: AbstractLatch, render: Boolean = true, audio: Boolean = true) { Log.log(LogMessageType.RENDERING_GENERAL, LogLevels.INFO) { "Hello LWJGL ${Version.getVersion()}!" } - latch.inc() - if (audio) startAudioPlayerThread(latch) - if (render) startRenderWindowThread(latch) + val loading = ParentLatch(2, latch) + if (audio) startAudioPlayerThread(loading) + if (render) startRenderWindowThread(loading) + latch.dec() } private fun startAudioPlayerThread(latch: AbstractLatch) { @@ -46,6 +47,7 @@ class Rendering(private val connection: PlayConnection) { try { Thread.currentThread().priority = Thread.MAX_PRIORITY audioPlayer.init(audioLatch) + latch.dec() // initial count audioPlayer.startLoop() audioPlayer.exit() } catch (exception: Throwable) { @@ -70,6 +72,7 @@ class Rendering(private val connection: PlayConnection) { Thread.currentThread().priority = Thread.MAX_PRIORITY CONTEXT_MAP[Thread.currentThread()] = context context.load(latch) + latch.dec() val loop = RenderLoop(context) context.awaitPlaying() loop.startLoop() diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt index e60189d1a..2a92e44c5 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/play/PlayConnection.kt @@ -20,6 +20,7 @@ import de.bixilon.kutil.concurrent.worker.task.TaskWorker import de.bixilon.kutil.concurrent.worker.task.WorkerTask import de.bixilon.kutil.latch.AbstractLatch import de.bixilon.kutil.latch.AbstractLatch.Companion.child +import de.bixilon.kutil.latch.CallbackLatch import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.kutil.observer.DataObserver.Companion.observed import de.bixilon.kutil.reflection.ReflectionUtil.forceSet @@ -67,6 +68,7 @@ import de.bixilon.minosoft.terminal.RunConfiguration import de.bixilon.minosoft.terminal.cli.CLI import de.bixilon.minosoft.util.KUtil import de.bixilon.minosoft.util.KUtil.startInit +import de.bixilon.minosoft.util.KUtil.waitIfLess import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogMessageType @@ -177,7 +179,6 @@ class PlayConnection( fun connect(latch: AbstractLatch? = null) { - val count = latch?.count ?: 0 check(!wasConnected) { "Connection was already connected!" } try { state = PlayConnectionStates.WAITING_MODS @@ -219,17 +220,12 @@ class PlayConnection( camera.init() - if (!RunConfiguration.DISABLE_RENDERING) { - val rendering = Rendering(this) - this.rendering = rendering - val renderLatch = latch.child(0) - rendering.start(renderLatch) - renderLatch.awaitWithChange() + + if (RunConfiguration.DISABLE_RENDERING) { + establish(latch) + } else { + establishRendering(latch) } - latch?.dec() // remove initial value - Log.log(LogMessageType.NETWORK_STATUS, level = LogLevels.INFO) { "Connecting to server: $address" } - network.connect(address, profiles.other.nativeNetwork) - state = PlayConnectionStates.ESTABLISHING } catch (exception: Throwable) { Log.log(LogMessageType.VERSION_LOADING, level = LogLevels.FATAL) { exception } if (this::assetsManager.isInitialized) { @@ -238,7 +234,25 @@ class PlayConnection( error = exception retry = false } - latch?.count = count + } + + private fun establish(latch: AbstractLatch?) { + latch?.dec() // remove initial value + Log.log(LogMessageType.NETWORK_STATUS, level = LogLevels.INFO) { "Connecting to server: $address" } + network.connect(address, profiles.other.nativeNetwork) + state = PlayConnectionStates.ESTABLISHING + } + + private fun establishRendering(latch: AbstractLatch?) { + val rendering = Rendering(this) + this.rendering = rendering + val renderLatch = CallbackLatch(1, latch) + rendering.start(renderLatch) + renderLatch.waitIfLess(2) + renderLatch += latch@{ + if (renderLatch.count > 0) return@latch + establish(latch) + } } override fun disconnect() { diff --git a/src/main/java/de/bixilon/minosoft/util/KUtil.kt b/src/main/java/de/bixilon/minosoft/util/KUtil.kt index b02e090c0..de8bbe67b 100644 --- a/src/main/java/de/bixilon/minosoft/util/KUtil.kt +++ b/src/main/java/de/bixilon/minosoft/util/KUtil.kt @@ -28,6 +28,7 @@ import de.bixilon.kutil.collections.CollectionUtil.synchronizedSetOf import de.bixilon.kutil.collections.CollectionUtil.toSynchronizedSet import de.bixilon.kutil.concurrent.pool.DefaultThreadPool import de.bixilon.kutil.concurrent.schedule.TaskScheduler +import de.bixilon.kutil.latch.AbstractLatch import de.bixilon.kutil.primitive.BooleanUtil.decide import de.bixilon.kutil.primitive.DoubleUtil import de.bixilon.kutil.primitive.DoubleUtil.matches @@ -342,4 +343,11 @@ object KUtil { return table } + + @Deprecated("kutil 1.24") + fun AbstractLatch.waitIfLess(value: Int, timeout: Long = 0L) = synchronized(notify) { + while (this.count < value) { + waitForChange(timeout) + } + } }