diff --git a/doc/rendering/world_renderer.md b/doc/rendering/world_renderer.md index b3785a04f..ea25adb3c 100644 --- a/doc/rendering/world_renderer.md +++ b/doc/rendering/world_renderer.md @@ -45,6 +45,5 @@ - ToDo: - Build biome cache only in render distance - Update neighbour chunks if needed - - Reduce memory usage - Unload on minimize - Biomes: Check if chunk is single biome diff --git a/src/main/java/de/bixilon/minosoft/data/world/World.kt b/src/main/java/de/bixilon/minosoft/data/world/World.kt index 89e58925f..2c66f7585 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -37,13 +37,14 @@ import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent import de.bixilon.minosoft.modding.event.events.ChunkUnloadEvent import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition -import de.bixilon.minosoft.util.KUtil.synchronizedMapOf +import de.bixilon.minosoft.util.KUtil.lockMapOf import de.bixilon.minosoft.util.KUtil.toSynchronizedMap import de.bixilon.minosoft.util.MMath +import de.bixilon.minosoft.util.ReadWriteLock import de.bixilon.minosoft.util.chunk.ChunkUtil.canBuildBiomeCache import de.bixilon.minosoft.util.chunk.ChunkUtil.getChunkNeighbourPositions import de.bixilon.minosoft.util.chunk.ChunkUtil.received -import de.bixilon.minosoft.util.collections.SynchronizedMap +import de.bixilon.minosoft.util.collections.LockMap import glm_.func.common.clamp import glm_.vec2.Vec2i import glm_.vec3.Vec3 @@ -59,8 +60,9 @@ import kotlin.random.Random class World( val connection: PlayConnection, ) : BiomeAccessor { + val lock = ReadWriteLock() var cacheBiomeAccessor: NoiseBiomeAccessor? = null - val chunks: SynchronizedMap = synchronizedMapOf() + val chunks: LockMap = lockMapOf() val entities = WorldEntities() var hardcore = false var dimension: DimensionProperties? = null diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/RegistrySectionDataProvider.kt b/src/main/java/de/bixilon/minosoft/data/world/container/RegistrySectionDataProvider.kt index abb8f29bd..58597a13e 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/RegistrySectionDataProvider.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/RegistrySectionDataProvider.kt @@ -23,7 +23,7 @@ class RegistrySectionDataProvider( ) : SectionDataProvider(data, checkSize = checkSize) { @Suppress("UNCHECKED_CAST") - fun setIdData(ids: Array) { + fun setIdData(ids: IntArray) { val data: Array = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION) for ((index, id) in ids.withIndex()) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt index c5c14e44c..1dc061441 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt @@ -83,8 +83,8 @@ class RenderWindow( private var lastFrame = 0.0 private val latch = CountUpAndDownLatch(1) - private var renderingState = RenderingStates.RUNNING - set(value) { + var renderingState = RenderingStates.RUNNING + private set(value) { if (field == value) { return } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt index d571c2fc4..09ea9558a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt @@ -13,6 +13,9 @@ package de.bixilon.minosoft.gui.rendering.block +import de.bixilon.minosoft.config.key.KeyAction +import de.bixilon.minosoft.config.key.KeyBinding +import de.bixilon.minosoft.config.key.KeyCodes import de.bixilon.minosoft.data.assets.AssetsUtil import de.bixilon.minosoft.data.assets.Resources import de.bixilon.minosoft.data.direction.Directions @@ -23,11 +26,13 @@ import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.Renderer import de.bixilon.minosoft.gui.rendering.RendererBuilder +import de.bixilon.minosoft.gui.rendering.RenderingStates import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes import de.bixilon.minosoft.gui.rendering.block.preparer.AbstractSectionPreparer import de.bixilon.minosoft.gui.rendering.block.preparer.CullSectionPreparer import de.bixilon.minosoft.gui.rendering.modding.events.FrustumChangeEvent +import de.bixilon.minosoft.gui.rendering.modding.events.RenderingStateChangeEvent import de.bixilon.minosoft.gui.rendering.models.ModelLoader import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem import de.bixilon.minosoft.gui.rendering.system.base.phases.OpaqueDrawable @@ -222,6 +227,31 @@ class WorldRenderer( connection.registerEvent(CallbackEventInvoker.of { unloadChunk(it.chunkPosition) }) connection.registerEvent(CallbackEventInvoker.of { if (it.state == PlayConnectionStates.DISCONNECTED) unloadWorld() }) + connection.registerEvent(CallbackEventInvoker.of { + if (it.state == RenderingStates.PAUSED) { + unloadWorld() + } else if (it.previousState == RenderingStates.PAUSED) { + prepareWorld() + } + }) + + renderWindow.inputHandler.registerKeyCallback("minosoft:clear_chunk_cache".toResourceLocation(), KeyBinding( + mutableMapOf( + KeyAction.MODIFIER to mutableSetOf(KeyCodes.KEY_F3), + KeyAction.PRESS to mutableSetOf(KeyCodes.KEY_A), + ), + )) { + unloadWorld() + prepareWorld() + } + } + + private fun prepareWorld() { + world.lock.acquire() + for ((chunkPosition, chunk) in world.chunks) { + queueChunk(chunkPosition, chunk) + } + world.lock.release() } private fun unloadWorld() { @@ -402,7 +432,7 @@ class WorldRenderer( } private fun queueSection(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk? = world.chunks[chunkPosition], section: ChunkSection? = chunk?.get(sectionHeight), ignoreFrustum: Boolean = false) { - if (chunk == null || section == null) { + if (chunk == null || section == null || renderWindow.renderingState == RenderingStates.PAUSED) { return } val queued = internalQueueSection(chunkPosition, sectionHeight, chunk, section, ignoreFrustum) @@ -414,7 +444,7 @@ class WorldRenderer( } private fun queueChunk(chunkPosition: Vec2i, chunk: Chunk = world.chunks[chunkPosition]!!) { - if (!chunk.isFullyLoaded) { + if (!chunk.isFullyLoaded || renderWindow.renderingState == RenderingStates.PAUSED) { return } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt index bea477367..fcc621714 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt @@ -99,10 +99,13 @@ data class UnbakedBlockStateModel( } var direction = face.direction + var cullFace = face.cullFace rotation?.let { val rad = it.rad direction = Directions.byDirection(Vec3(face.direction.vectorf).apply { rotateAssign(rad) }) + cullFace = face.cullFace?.vectorf?.let { cullFace -> Directions.byDirection(Vec3(cullFace).apply { rotateAssign(rad) }) } + for ((index, position) in positions.withIndex()) { positions[index] = Vec3(position).apply { rotateAssign(rad, true) } } @@ -147,7 +150,7 @@ data class UnbakedBlockStateModel( uv = texturePositions, shade = shade, tintIndex = face.tintIndex, - cullFace = face.cullFace, + cullFace = cullFace, texture = texture, touching = touching, ) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/TextureParticle.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/TextureParticle.kt index d11c449d1..1ca6ca278 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/TextureParticle.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/TextureParticle.kt @@ -25,10 +25,10 @@ abstract class TextureParticle(connection: PlayConnection, position: Vec3d, velo abstract val texture: AbstractTexture? - override fun addVertex(transparentMesh: ParticleMesh, translucentMesh: ParticleMesh, time:Long) { + override fun addVertex(transparentMesh: ParticleMesh, particleMesh: ParticleMesh, time: Long) { val texture = texture ?: return when { - texture.transparency == TextureTransparencies.TRANSLUCENT || color.alpha != 255 -> translucentMesh + texture.transparency == TextureTransparencies.TRANSLUCENT || color.alpha != 255 -> particleMesh else -> transparentMesh }.addVertex(getCameraPosition(time), scale, texture, color) } diff --git a/src/main/java/de/bixilon/minosoft/util/KUtil.kt b/src/main/java/de/bixilon/minosoft/util/KUtil.kt index 3779954e9..9c64d7f29 100644 --- a/src/main/java/de/bixilon/minosoft/util/KUtil.kt +++ b/src/main/java/de/bixilon/minosoft/util/KUtil.kt @@ -85,6 +85,10 @@ object KUtil { } } + fun lockMapOf(vararg pairs: Pair): LockMap { + return LockMap(mutableMapOf(*pairs)) + } + fun synchronizedMapOf(vararg pairs: Pair): SynchronizedMap { return SynchronizedMap(mutableMapOf(*pairs)) }