mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-14 01:48:04 -04:00
rendering, data: fix bugs with saving chunks in memory
This commit is contained in:
parent
7be7124013
commit
ffc34ed1e5
@ -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?) {
|
||||
|
@ -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) {
|
||||
|
@ -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++
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user