From 1e45098f8f3aac52e948d60f0ee9ad03d78875ef Mon Sep 17 00:00:00 2001 From: Bixilon Date: Fri, 26 May 2023 04:15:53 +0200 Subject: [PATCH] reduce memory allocations even more They are less, but those are the major ones and performance should be a lot better than before. Hopefully no bugs sneaked in :) --- .../registries/shapes/aabb/AABBIterator.kt | 11 ++++++- .../de/bixilon/minosoft/data/world/World.kt | 29 ++++++++++++------- .../minosoft/data/world/chunk/chunk/Chunk.kt | 14 +++++---- .../physics/parts/CollisionMovementPhysics.kt | 12 ++++++-- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/data/registries/shapes/aabb/AABBIterator.kt b/src/main/java/de/bixilon/minosoft/data/registries/shapes/aabb/AABBIterator.kt index 338eb823b..0023f2fa9 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/shapes/aabb/AABBIterator.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/shapes/aabb/AABBIterator.kt @@ -17,6 +17,7 @@ import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.data.world.chunk.chunk.Chunk import de.bixilon.minosoft.data.world.iterator.WorldIterator +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY class AABBIterator(val range: Array) : Iterator { private var count = 0 @@ -24,6 +25,8 @@ class AABBIterator(val range: Array) : Iterator { private var y = range[1].first private var z = range[2].first + private val position = Vec3i.EMPTY + val size: Int = maxOf(0, range[0].last - range[0].first + 1) * maxOf(0, range[1].last - range[1].first + 1) * maxOf(0, range[2].last - range[2].first + 1) constructor(aabb: AABB) : this(AABB.getRange(aabb.min.x, aabb.max.x), AABB.getRange(aabb.min.y, aabb.max.y), AABB.getRange(aabb.min.z, aabb.max.z)) @@ -36,11 +39,17 @@ class AABBIterator(val range: Array) : Iterator { return count < size } + private fun updatePosition() { + position.x = x + position.y = y + position.z = z + } + override fun next(): Vec3i { if (count >= size) throw IllegalStateException("No positions available anymore!") - val position = Vec3i(x, y, z) + updatePosition() if (z < range[2].last) z++ else { z = range[2].first if (y < range[1].last) y++ else { 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 8e16a1231..67848cf43 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -47,6 +47,8 @@ import de.bixilon.minosoft.data.world.positions.ChunkPositionUtil.inChunkPositio import de.bixilon.minosoft.data.world.time.WorldTime import de.bixilon.minosoft.data.world.view.WorldView import de.bixilon.minosoft.data.world.weather.WorldWeather +import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.util.chunk.ChunkUtil.isInViewDistance import java.util.* @@ -174,24 +176,31 @@ class World( } fun randomTick() { - val blockPosition = connection.player.physics.positionInfo.blockPosition - val chunk = this.chunks[blockPosition.chunkPosition] ?: return + val origin = connection.player.physics.positionInfo.blockPosition + val chunk = this.chunks[origin.chunkPosition] ?: return + val offset = Vec3i.EMPTY + val chunkDelta = Vec2i.EMPTY - // ToDo: Split that up in multiple threads? for (i in 0 until 667) { - randomTick(16, blockPosition, chunk) - randomTick(32, blockPosition, chunk) + randomTick(16, origin, offset, chunkDelta, chunk) + randomTick(32, origin, offset, chunkDelta, chunk) } } - private fun randomTick(radius: Int, origin: BlockPosition, chunk: Chunk) { - val offset = Vec3i(random.nextInt(-radius, radius), random.nextInt(-radius, radius), random.nextInt(-radius, radius)) - val blockPosition = origin + offset + private fun randomTick(radius: Int, origin: BlockPosition, offset: BlockPosition, chunkDelta: Vec2i, chunk: Chunk) { + offset.x = random.nextInt(-radius, radius) + offset.y = random.nextInt(-radius, radius) + offset.z = random.nextInt(-radius, radius) - val blockState = chunk.traceBlock(offset, origin, blockPosition) ?: return + val position = origin + offset - blockState.block.randomTick(connection, blockState, blockPosition, random) + chunkDelta.x = (origin.x - position.x) shr 4 + chunkDelta.y = (origin.z - position.z) shr 4 + + val state = chunk.traceBlock(position.x and 0x0F, position.y, position.z and 0x0F, chunkDelta) ?: return + + state.block.randomTick(connection, state, position, random) } operator fun get(aabb: AABB): WorldIterator { diff --git a/src/main/java/de/bixilon/minosoft/data/world/chunk/chunk/Chunk.kt b/src/main/java/de/bixilon/minosoft/data/world/chunk/chunk/Chunk.kt index 9c8da57b4..adabaef40 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/chunk/chunk/Chunk.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/chunk/chunk/Chunk.kt @@ -31,11 +31,11 @@ import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours import de.bixilon.minosoft.data.world.chunk.update.block.ChunkLocalBlockUpdate import de.bixilon.minosoft.data.world.chunk.update.block.SingleBlockUpdate import de.bixilon.minosoft.data.world.positions.ChunkPosition +import de.bixilon.minosoft.data.world.positions.ChunkPositionUtil.chunkPosition import de.bixilon.minosoft.data.world.positions.InChunkPosition import de.bixilon.minosoft.data.world.positions.SectionHeight import de.bixilon.minosoft.gui.rendering.util.VecUtil.inSectionHeight import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.inChunkPosition import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition @@ -231,12 +231,9 @@ class Chunk( @Deprecated("neighbours") fun traceBlock(offset: Vec3i, origin: Vec3i, blockPosition: Vec3i = origin + offset): BlockState? { - val originChunkPosition = origin.chunkPosition - val targetChunkPosition = blockPosition.chunkPosition + val chunkDelta = (origin - blockPosition).chunkPosition - val deltaChunkPosition = targetChunkPosition - originChunkPosition - - return traceBlock(blockPosition.inChunkPosition, deltaChunkPosition) + return traceBlock(blockPosition.x and 0x0F, blockPosition.y, blockPosition.z and 0x0F, chunkDelta) } @Deprecated("neighbours") @@ -274,6 +271,11 @@ class Chunk( private fun traceBlock(inChunkPosition: Vec3i, chunkOffset: Vec2i): BlockState? { return traceChunk(chunkOffset)?.get(inChunkPosition) } + + @Deprecated("neighbours") + fun traceBlock(x: Int, y: Int, z: Int, chunkOffset: Vec2i): BlockState? { + return traceChunk(chunkOffset)?.get(x, y, z) + } } diff --git a/src/main/java/de/bixilon/minosoft/physics/parts/CollisionMovementPhysics.kt b/src/main/java/de/bixilon/minosoft/physics/parts/CollisionMovementPhysics.kt index e678ecf68..3bbcca73e 100644 --- a/src/main/java/de/bixilon/minosoft/physics/parts/CollisionMovementPhysics.kt +++ b/src/main/java/de/bixilon/minosoft/physics/parts/CollisionMovementPhysics.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.physics.parts import de.bixilon.kotlinglm.vec3.Vec3d +import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.kotlinglm.vec3.swizzle.xz import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.registries.blocks.shapes.collision.CollisionPredicate @@ -27,9 +28,9 @@ import de.bixilon.minosoft.data.registries.shapes.voxel.VoxelShape import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.data.world.chunk.chunk.Chunk import de.bixilon.minosoft.data.world.iterator.WorldIterator -import de.bixilon.minosoft.data.world.positions.ChunkPositionUtil.inChunkPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.set import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY import de.bixilon.minosoft.physics.entities.EntityPhysics import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlin.math.abs @@ -41,6 +42,8 @@ object CollisionMovementPhysics { // TODO: add entity collisions (boat, shulker) // TODO: add world border collision shape + val inChunk = Vec3i.EMPTY + for ((position, state, chunk) in WorldIterator(aabb.extend(movement).grow(1.0).positions(), this, chunk)) { if (state.block !is CollidableBlock) continue @@ -49,7 +52,12 @@ object CollisionMovementPhysics { var shape = when (state.block) { is FixedCollidable -> state.block.getCollisionShape(state) - else -> state.block.getCollisionShape(context, position, state, chunk.getBlockEntity(position.inChunkPosition)) + else -> { + inChunk.x = position.x and 0x0F + inChunk.z = position.z and 0x0F + + state.block.getCollisionShape(context, position, state, chunk.getBlockEntity(inChunk)) + } } ?: continue shape += position