rendering, data: fix bugs with saving chunks in memory

This commit is contained in:
Bixilon 2021-04-27 17:57:28 +02:00
parent 7be7124013
commit ffc34ed1e5
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
6 changed files with 58 additions and 39 deletions

View File

@ -22,16 +22,15 @@ import de.bixilon.minosoft.data.world.biome.accessor.NullBiomeAccessor
import de.bixilon.minosoft.data.world.light.WorldLightAccessor
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkPosition
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import glm_.vec2.Vec2i
import glm_.vec3.Vec3i
import java.util.*
import java.util.concurrent.ConcurrentHashMap
/**
* Collection of chunks and more
*/
class World : BiomeAccessor {
val chunks: MutableMap<Vec2i, Chunk> = Collections.synchronizedMap(ConcurrentHashMap())
val chunks: MutableMap<Vec2i, Chunk> = synchronizedMapOf()
val entities = WorldEntities()
var isHardcore = false
var isRaining = false
@ -47,16 +46,14 @@ class World : BiomeAccessor {
return chunks[chunkLocation]?.getBlockState(blockPosition.inChunkPosition)
}
@Synchronized
fun getChunk(chunkPosition: Vec2i): Chunk? {
return chunks[chunkPosition]
}
@Synchronized
fun getOrCreateChunk(chunkPosition: Vec2i): Chunk {
return chunks[chunkPosition] ?: run {
val chunk = Chunk()
chunks[chunkPosition] = chunk
chunk
}
return chunks.getOrPut(chunkPosition) { Chunk() }
}
fun setBlock(blockPosition: Vec3i, blockState: BlockState?) {

View File

@ -14,14 +14,14 @@
package de.bixilon.minosoft.data.world
import de.bixilon.minosoft.data.entities.entities.Entity
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class WorldEntities : Iterable<Entity> {
private val idEntityMap: MutableMap<Int, Entity> = ConcurrentHashMap()
private val entityIdMap: MutableMap<Entity, Int> = ConcurrentHashMap()
private val entityUUIDMap: MutableMap<Entity, UUID> = ConcurrentHashMap()
private val uuidEntityMap: MutableMap<UUID, Entity> = ConcurrentHashMap()
private val idEntityMap: MutableMap<Int, Entity> = synchronizedMapOf()
private val entityIdMap: MutableMap<Entity, Int> = synchronizedMapOf()
private val entityUUIDMap: MutableMap<Entity, UUID> = synchronizedMapOf()
private val uuidEntityMap: MutableMap<UUID, Entity> = synchronizedMapOf()
fun add(entityId: Int?, entityUUID: UUID?, entity: Entity) {

View File

@ -37,6 +37,9 @@ import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.packets.s2c.play.PositionAndRotationS2CP
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.CountUpAndDownLatch
import de.bixilon.minosoft.util.KUtil.synchronizedListOf
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import de.bixilon.minosoft.util.KUtil.synchronizedSetOf
import de.bixilon.minosoft.util.Stopwatch
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogMessageType
@ -48,7 +51,6 @@ import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GL11.*
import org.lwjgl.system.MemoryStack
import org.lwjgl.system.MemoryUtil
import java.util.concurrent.ConcurrentLinkedQueue
class RenderWindow(
val connection: PlayConnection,
@ -73,16 +75,16 @@ class RenderWindow(
private val screenshotTaker = ScreenshotTaker(this)
val tintColorCalculator = TintColorCalculator(connection.world)
val font = Font()
val textures = TextureArray(mutableListOf())
val textures = TextureArray(synchronizedListOf())
val rendererMap: MutableMap<ResourceLocation, Renderer> = mutableMapOf()
val rendererMap: MutableMap<ResourceLocation, Renderer> = synchronizedMapOf()
val renderQueue = ConcurrentLinkedQueue<Runnable>()
val renderQueue: MutableList<Runnable> = synchronizedListOf()
lateinit var WHITE_TEXTURE: TextureLike
val screenResizeCallbacks: MutableSet<ScreenResizeCallback> = mutableSetOf(inputHandler.camera)
val screenResizeCallbacks: MutableSet<ScreenResizeCallback> = synchronizedSetOf(inputHandler.camera)
var tickCount = 0L
var lastTickTimer = System.currentTimeMillis()
@ -331,12 +333,13 @@ class RenderWindow(
// handle opengl context tasks, but limit it per frame
var actionsDone = 0
val renderQueue = renderQueue.toList()
for (renderQueueElement in renderQueue) {
if (actionsDone == RenderConstants.MAXIMUM_CALLS_PER_FRAME) {
break
}
renderQueueElement.run()
renderQueue.remove(renderQueueElement)
this.renderQueue.remove(renderQueueElement)
actionsDone++
}

View File

@ -40,13 +40,13 @@ import de.bixilon.minosoft.modding.event.events.*
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil.nullCast
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import de.bixilon.minosoft.util.KUtil.synchronizedSetOf
import de.bixilon.minosoft.util.MMath
import de.bixilon.minosoft.util.logging.Log
import glm_.vec2.Vec2i
import glm_.vec3.Vec3i
import org.lwjgl.opengl.GL11.glDepthMask
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class WorldRenderer(
private val connection: PlayConnection,
@ -56,9 +56,9 @@ class WorldRenderer(
private val waterBlock = connection.mapping.blockRegistry.get(ResourceLocation("minecraft:water"))?.nullCast<FluidBlock>()
override lateinit var shader: Shader
val allChunkSections: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = Collections.synchronizedMap(ConcurrentHashMap())
val visibleChunks: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = Collections.synchronizedMap(ConcurrentHashMap())
val queuedChunks: MutableSet<Vec2i> = Collections.synchronizedSet(mutableSetOf())
val allChunkSections: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = synchronizedMapOf()
val visibleChunks: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = synchronizedMapOf()
val queuedChunks: MutableSet<Vec2i> = synchronizedSetOf()
private var allBlocks: Collection<BlockState>? = null
@ -145,7 +145,7 @@ class WorldRenderer(
})
connection.registerEvent(CallbackEventInvoker.of<MultiBlockChangeEvent> {
val sectionHeights: MutableSet<Int> = mutableSetOf()
val sectionHeights: MutableSet<Int> = synchronizedSetOf()
for ((key) in it.blocks) {
sectionHeights.add(key.sectionHeight)
}
@ -201,7 +201,7 @@ class WorldRenderer(
private fun resolveBlockTextureIds(blocks: Collection<BlockState>): List<Texture> {
val textures: MutableList<Texture> = mutableListOf()
val textureMap: MutableMap<String, Texture> = ConcurrentHashMap()
val textureMap: MutableMap<String, Texture> = synchronizedMapOf()
for (block in blocks) {
for (model in block.renderers) {
@ -242,14 +242,14 @@ class WorldRenderer(
}
}
queuedChunks.remove(chunkPosition)
allChunkSections[chunkPosition] = Collections.synchronizedMap(ConcurrentHashMap())
allChunkSections[chunkPosition] = synchronizedMapOf()
var currentChunks: MutableMap<Int, ChunkSection> = Collections.synchronizedMap(ConcurrentHashMap())
var currentChunks: MutableMap<Int, ChunkSection> = synchronizedMapOf()
var currentIndex = 0
for ((sectionHeight, section) in chunk.sections!!) {
if (getSectionIndex(sectionHeight) != currentIndex) {
prepareChunkSections(chunkPosition, currentChunks)
currentChunks = Collections.synchronizedMap(ConcurrentHashMap())
currentChunks = synchronizedMapOf()
currentIndex = getSectionIndex(sectionHeight)
}
currentChunks[sectionHeight] = section
@ -300,7 +300,7 @@ class WorldRenderer(
renderWindow.renderQueue.add {
val sectionMap = allChunkSections.getOrPut(chunkPosition, { ConcurrentHashMap() })
val sectionMap = allChunkSections.getOrPut(chunkPosition) { synchronizedMapOf() }
sectionMap[index]?.let {
it.opaqueSectionArrayMesh.unload()
@ -329,7 +329,7 @@ class WorldRenderer(
sectionMap[index] = meshCollection
if (renderWindow.inputHandler.camera.frustum.containsChunk(chunkPosition, lowestBlockHeight, highestBlockHeight)) {
visibleChunks.getOrPut(chunkPosition, { ConcurrentHashMap() })[index] = meshCollection
visibleChunks.getOrPut(chunkPosition) { synchronizedMapOf() }[index] = meshCollection
} else {
visibleChunks[chunkPosition]?.remove(index)
}
@ -338,7 +338,7 @@ class WorldRenderer(
}
fun prepareChunkSection(chunkPosition: Vec2i, sectionHeight: Int) {
val sections: MutableMap<Int, ChunkSection> = Collections.synchronizedMap(ConcurrentHashMap())
val sections: MutableMap<Int, ChunkSection> = synchronizedMapOf()
val chunk = world.getChunk(chunkPosition)!!
val lowestSectionHeight = getSectionIndex(sectionHeight) * RenderConstants.CHUNK_SECTIONS_PER_MESH
for (i in lowestSectionHeight until lowestSectionHeight + RenderConstants.CHUNK_SECTIONS_PER_MESH) {
@ -381,7 +381,8 @@ class WorldRenderer(
}
private fun prepareWorld(world: World) {
for ((chunkLocation, chunk) in world.chunks) {
val chunkMap = world.chunks.toMap()
for ((chunkLocation, chunk) in chunkMap) {
prepareChunk(chunkLocation, chunk)
}
}
@ -393,8 +394,13 @@ class WorldRenderer(
override fun onFrustumChange() {
visibleChunks.clear()
for ((chunkLocation, indexMap) in allChunkSections) {
val visibleIndexMap: MutableMap<Int, ChunkMeshCollection> = Collections.synchronizedMap(ConcurrentHashMap())
val allChunkSections: Map<Vec2i, MutableMap<Int, ChunkMeshCollection>>
synchronized(this.allChunkSections) {
allChunkSections = this.allChunkSections.toMap()
}
for ((chunkLocation, rawIndexMap) in allChunkSections) {
val visibleIndexMap: MutableMap<Int, ChunkMeshCollection> = synchronizedMapOf()
val indexMap = rawIndexMap.toMap()
for ((index, mesh) in indexMap) {
if (renderWindow.inputHandler.camera.frustum.containsChunk(chunkLocation, mesh.lowestBlockHeight, mesh.highestBlockHeight)) {
visibleIndexMap[index] = mesh

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.util
import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.util.enum.AliasableEnum
import java.util.*
import kotlin.Pair
object KUtil {
@ -53,4 +54,16 @@ object KUtil {
fun String.asResourceLocation(): ResourceLocation {
return ResourceLocation(this)
}
fun <K, V> synchronizedMapOf(vararg pairs: Pair<K, V>): MutableMap<K, V> {
return Collections.synchronizedMap(mutableMapOf(*pairs))
}
fun <V> synchronizedSetOf(vararg values: V): MutableSet<V> {
return Collections.synchronizedSet(mutableSetOf(*values))
}
fun <V> synchronizedListOf(vararg values: V): MutableList<V> {
return Collections.synchronizedList(mutableListOf(*values))
}
}

View File

@ -24,8 +24,8 @@ import de.bixilon.minosoft.data.world.palette.Palette.Companion.choosePalette
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import java.util.*
import java.util.concurrent.ConcurrentHashMap
object ChunkUtil {
@ -59,7 +59,7 @@ object ChunkUtil {
// parse data
var arrayPosition = 0
val sectionMap: MutableMap<Int, ChunkSection> = Collections.synchronizedMap(ConcurrentHashMap())
val sectionMap: MutableMap<Int, ChunkSection> = synchronizedMapOf()
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) {
if (!sectionBitMask[sectionIndex]) {
continue
@ -125,7 +125,7 @@ object ChunkUtil {
}
var arrayPos = 0
val sectionMap: MutableMap<Int, ChunkSection> = Collections.synchronizedMap(ConcurrentHashMap())
val sectionMap: MutableMap<Int, ChunkSection> = synchronizedMapOf()
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until dimension.highestSection).withIndex()) { // max sections per chunks in chunk column
if (!sectionBitMask[sectionIndex]) {
continue
@ -144,7 +144,7 @@ object ChunkUtil {
fun readPaletteChunk(buffer: PlayInByteBuffer, dimension: Dimension, sectionBitMask: BitSet, isFullChunk: Boolean, containsSkyLight: Boolean = false): ChunkData {
val chunkData = ChunkData()
val sectionMap: MutableMap<Int, ChunkSection> = Collections.synchronizedMap(ConcurrentHashMap())
val sectionMap: MutableMap<Int, ChunkSection> = synchronizedMapOf()
for ((sectionIndex, sectionHeight) in (dimension.lowestSection until sectionBitMask.length()).withIndex()) { // max sections per chunks in chunk column
if (!sectionBitMask[sectionIndex]) {