From cc92897293c2494b019a4f8e19a4d11bb0289909 Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Mon, 13 Nov 2023 15:04:14 +0100 Subject: [PATCH] entity render distance --- .../profile/profiles/entity/EntityProfile.kt | 2 ++ .../profiles/entity/general/GeneralC.kt | 32 +++++++++++++++++ .../rendering/entities/EntitiesRenderer.kt | 6 ++-- .../entities/renderer/EntityRenderer.kt | 8 +++-- .../entities/visibility/VisibilityManager.kt | 34 +++++++++++++++---- 5 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/general/GeneralC.kt diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/EntityProfile.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/EntityProfile.kt index c9f67ccae..a24b5db90 100644 --- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/EntityProfile.kt +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/EntityProfile.kt @@ -19,6 +19,7 @@ import de.bixilon.minosoft.config.profile.delegate.types.StringDelegate import de.bixilon.minosoft.config.profile.profiles.Profile import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfileManager.latestVersion import de.bixilon.minosoft.config.profile.profiles.entity.features.FeaturesC +import de.bixilon.minosoft.config.profile.profiles.entity.general.GeneralC import java.util.concurrent.atomic.AtomicInteger /** @@ -37,6 +38,7 @@ class EntityProfile( override var description by StringDelegate(this, description ?: "") + val general = GeneralC(this) val features = FeaturesC(this) override fun toString(): String { diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/general/GeneralC.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/general/GeneralC.kt new file mode 100644 index 000000000..55f7ad5c0 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/entity/general/GeneralC.kt @@ -0,0 +1,32 @@ +/* + * Minosoft + * 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. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.config.profile.profiles.entity.general + +import de.bixilon.minosoft.config.profile.delegate.primitive.BooleanDelegate +import de.bixilon.minosoft.config.profile.delegate.primitive.IntDelegate +import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfile +import de.bixilon.minosoft.data.world.World + +class GeneralC(profile: EntityProfile) { + /** + * Enables entity rendering + */ + var enabled by BooleanDelegate(profile, true) + + /** + * Entity render distance (x,y,z direction) + * May be -1 to use the block render distance + */ + var renderDistance by IntDelegate(profile, -1, "", ranges = arrayOf(-1..-1, 0..World.MAX_RENDER_DISTANCE)) +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntitiesRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntitiesRenderer.kt index 6a2d0b137..503415899 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntitiesRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntitiesRenderer.kt @@ -60,7 +60,8 @@ class EntitiesRenderer( this.visibility.reset() renderers.iterate { if (reset) it.reset() - visibility.update(it) + visibility.update(it, millis) + if (!it.visible) return@iterate it.update(millis) visibility.collect(it) } @@ -91,7 +92,8 @@ class EntitiesRenderer( companion object : RendererBuilder { - override fun build(connection: PlayConnection, context: RenderContext): EntitiesRenderer { + override fun build(connection: PlayConnection, context: RenderContext): EntitiesRenderer? { + if (!connection.profiles.entity.general.enabled) return null return EntitiesRenderer(connection, context) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt index 93e84f486..afea29fc2 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt @@ -72,12 +72,16 @@ abstract class EntityRenderer( open fun update(millis: Long, delta: Float) { updateLight(delta) - entity.draw(millis) - this.distance = (entity.renderInfo.eyePosition - renderer.connection.camera.entity.renderInfo.eyePosition).length2() + updateRenderInfo(millis) updateMatrix(delta) features.update(millis, delta) } + open fun updateRenderInfo(millis: Long) { + entity.draw(millis) + this.distance = (entity.renderInfo.eyePosition - renderer.connection.camera.entity.renderInfo.eyePosition).length2() + } + private fun getCurrentLight(): Int { var light = entity.physics.positionInfo.chunk?.light?.get(entity.physics.positionInfo.inChunkPosition) ?: return 0xFF if (entity.isOnFire) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/VisibilityManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/VisibilityManager.kt index b7c1c7809..c1d77d528 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/VisibilityManager.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/VisibilityManager.kt @@ -14,37 +14,58 @@ package de.bixilon.minosoft.gui.rendering.entities.visibility import de.bixilon.kutil.concurrent.lock.simple.SimpleLock +import de.bixilon.kutil.observer.DataObserver.Companion.observe +import de.bixilon.minosoft.data.world.view.ViewDistanceChangeEvent import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer import de.bixilon.minosoft.gui.rendering.events.VisibilityGraphChangeEvent import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen -import java.util.concurrent.atomic.AtomicInteger +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition class VisibilityManager(val renderer: EntitiesRenderer) { private var update = false var size: Int = 0 private set - private val count = AtomicInteger() val opaque: ArrayList = ArrayList(1000) val translucent: ArrayList = ArrayList(1000) private val lock = SimpleLock() private val graph = renderer.context.camera.visibilityGraph private val frustum = renderer.context.camera.matrixHandler.frustum + private var renderDistance = 0 fun init() { renderer.connection.events.listen { update = true } + renderer.connection.events.listen { updateViewDistance(server = it.viewDistance) } + renderer.profile.general::renderDistance.observe(this, true) { updateViewDistance(entity = it) } } + private fun updateViewDistance(entity: Int = renderer.profile.general.renderDistance, server: Int = renderer.connection.world.view.serverViewDistance) { + var distance = if (entity < 0) (server - 1) else entity + distance *= ProtocolDefinition.SECTION_LENGTH + this.renderDistance = distance * distance // length^2 + } + + fun reset() { opaque.clear() translucent.clear() - count.set(0) + size = 0 } - fun update(renderer: EntityRenderer<*>) { - // TODO: check render distance (and maybe entity distance) + private fun EntityRenderer<*>.isInRenderDistance(): Boolean { + return renderDistance < 0 || distance <= renderDistance + } + + fun update(renderer: EntityRenderer<*>, millis: Long) { + if (!renderer.isInRenderDistance()) { + // distance is only updated if the renderer is visible, so force update + renderer.updateRenderInfo(millis) + } + if (!renderer.isInRenderDistance()) { + return renderer.updateVisibility(true, true) + } val aabb = renderer.entity.renderInfo.cameraAABB val visible = aabb in frustum if (!visible) { @@ -57,8 +78,8 @@ class VisibilityManager(val renderer: EntitiesRenderer) { fun collect(renderer: EntityRenderer<*>) { if (!renderer.visible) return - count.incrementAndGet() lock.lock() + size++ for (feature in renderer.features) { if (!feature.enabled || !feature.visible) continue feature.collect(this) @@ -71,7 +92,6 @@ class VisibilityManager(val renderer: EntitiesRenderer) { this.opaque.sort() this.translucent.sort() this.update = false - size = count.get() } operator fun get(layer: EntityLayer) = when (layer) {