@@ -25,10 +25,8 @@ import io.github.rothes.esu.core.util.UnsafeUtils.usBooleanAccessor
2525import io.github.rothes.esu.core.util.extension.math.floorI
2626import io.github.rothes.esu.core.util.extension.math.frac
2727import io.github.rothes.esu.core.util.extension.math.square
28- import it.unimi.dsi.fastutil.Hash
2928import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap
3029import it.unimi.dsi.fastutil.ints.IntArrayList
31- import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap
3230import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap
3331import kotlinx.coroutines.*
3432import net.minecraft.server.level.ServerLevel
@@ -61,7 +59,6 @@ import kotlin.time.Duration.Companion.seconds
6159object RaytraceHandlerImpl: RaytraceHandler<RaytraceHandlerImpl.RaytraceConfig, EmptyConfiguration>() {
6260
6361 private const val COLLISION_EPSILON = 1E- 7
64- private const val GRID_SIZE = 5
6562 private val INIT_SECTION : Array <LevelChunkSection > = arrayOf()
6663 private val ENTITY_TYPES : Int
6764
@@ -197,7 +194,7 @@ object RaytraceHandlerImpl: RaytraceHandler<RaytraceHandlerImpl.RaytraceConfig,
197194 }
198195 val entities = entityMap.int2ReferenceEntrySet().map {
199196 val squaredRange = (it.intKey + 8 ).square() // Add extra 8 blocks
200- SlicedEntities (squaredRange, it.value)
197+ SortedEntities (squaredRange, it.value)
201198 }
202199 /* Sort entities by tracking range */
203200
@@ -271,80 +268,67 @@ object RaytraceHandlerImpl: RaytraceHandler<RaytraceHandlerImpl.RaytraceConfig,
271268
272269 }
273270
274- fun tickPlayer (player : ServerPlayer , bukkit : Player , userCullData : UserCullData , level : ServerLevel , collected : List <SlicedEntities >) {
271+ fun tickPlayer (player : ServerPlayer , bukkit : Player , userCullData : UserCullData , level : ServerLevel , entities : List <SortedEntities >) {
275272 val viewDistanceSquared = (bukkit.viewDistance + 1 ).square() shl 8
276273
277- val shouldCull = userCullData.shouldCull
278- fun predicatePlayerPos (): Vec3 ? {
279- if (shouldCull && config.predicatePlayerPositon) {
280- val velocity = playerVelocityGetter.getPlayerMoveVelocity(player)
281- if (velocity.lengthSqr() >= 0.06 ) { // Threshold for sprinting
282- var x = player.x
283- var y = player.eyeY
284- var z = player.z
285-
286- var vx = velocity.x
287- var vy = velocity.y
288- var vz = velocity.z
289-
290- for (i in 0 until 3 ) {
291- x + = vx
292- y + = vy
293- z + = vz
294-
295- vx * = 0.91f
296- vy * = 0.98f
297- vz * = 0.91f
298- }
299- return Vec3 (x, y, z)
300- }
301- }
302- return null
303- }
304- val predicatedPlayerPos = predicatePlayerPos()
305-
306- var tickedEntities = 0
307-
308274 val playerX = player.x
309275 val playerY = player.y
310276 val playerZ = player.z
311277
312- for (sorted in collected) {
313- val range = min(sorted.trackRangeSquared, viewDistanceSquared)
314- val sqrt = sqrt(range.toDouble())
315- for (x in (playerX - sqrt).gridIndex().toLong() .. (playerX + sqrt).gridIndex()) {
316- for (z in (playerZ - sqrt).gridIndex().toLong() .. (playerZ + sqrt).gridIndex()) {
317- val index = x and (z shl Int .SIZE_BITS )
318- val entities = sorted.slices.get(index) ? : continue
319- for (entity in entities) {
320- val dist = (playerX - entity.x).square() + (playerZ - entity.z).square()
321- if (dist > range) continue
322-
323- tickedEntities++
324-
325- if (
326- ! shouldCull
327- || entity.isCurrentlyGlowing
328- || config.visibleEntityTypes.contains(entity.type)
329- || dist + (playerY - entity.y).square() <= forceVisibleDistanceSquared
330- ) {
331- userCullData.setCulled(entity.bukkitEntity, entity.id, false )
332- continue
333- }
278+ val shouldCull = userCullData.shouldCull
279+ val predicatedPlayerPos = if (shouldCull && config.predicatePlayerPositon) {
280+ val velocity = playerVelocityGetter.getPlayerMoveVelocity(player)
281+ if (velocity.lengthSqr() >= 0.06 ) { // Threshold for sprinting
282+ var x = playerX
283+ var y = player.eyeY
284+ var z = playerZ
285+
286+ var vx = velocity.x
287+ var vy = velocity.y
288+ var vz = velocity.z
289+
290+ for (i in 0 until 3 ) {
291+ x + = vx
292+ y + = vy
293+ z + = vz
294+
295+ vx * = 0.91f
296+ vy * = 0.98f
297+ vz * = 0.91f
298+ }
299+ Vec3 (x, y, z)
300+ } else null
301+ } else null
334302
335- userCullData.setCulled(entity.bukkitEntity, entity.id, raytrace(player, predicatedPlayerPos, entity, level))
336- }
303+ var tickedEntities = 0
304+
305+ for ((trackRange, entities) in entities) {
306+ val maxRange = min(trackRange, viewDistanceSquared)
307+ for (entity in entities) {
308+ if (entity == = player) continue
309+ val pos = entity.position()
310+ val dist = (playerX - pos.x).square() + (playerZ - pos.z).square()
311+ if (dist > maxRange) continue
312+
313+ tickedEntities++
314+
315+ if (
316+ ! shouldCull
317+ || entity.isCurrentlyGlowing
318+ || config.visibleEntityTypes.contains(entity.type)
319+ || dist + (playerY - pos.y).square() <= forceVisibleDistanceSquared
320+ ) {
321+ userCullData.setCulled(entity.bukkitEntity, entity.id, false )
322+ continue
337323 }
324+
325+ userCullData.setCulled(entity.bukkitEntity, entity.id, raytrace(player, predicatedPlayerPos, entity, level))
338326 }
339327 }
340328 userCullData.shouldCull = tickedEntities >= config.cullThreshold
341329 userCullData.tick()
342330 }
343331
344- private fun Location.toVec3 (): Vec3 {
345- return Vec3 (x, y, z)
346- }
347-
348332 fun raytrace (player : ServerPlayer , predPlayer : Vec3 ? , entity : Entity , level : ServerLevel ): Boolean {
349333 val from = player.eyePosition
350334 val aabb = entity.boundingBox
@@ -622,23 +606,7 @@ object RaytraceHandlerImpl: RaytraceHandler<RaytraceHandlerImpl.RaytraceConfig,
622606 }
623607 }
624608
625- class SlicedEntities (val trackRangeSquared : Int , entities : List <Entity >) {
626-
627- val slices = Long2ReferenceOpenHashMap <MutableList <Entity >>(16 , Hash .VERY_FAST_LOAD_FACTOR )
628-
629- init {
630- for (entity in entities) {
631- val id = entity.x.gridIndex().toLong() and (entity.z.gridIndex().toLong() shl Int .SIZE_BITS )
632- val get = slices.get(id)
633- if (get != null )
634- get.add(entity)
635- else
636- slices.put(id, ArrayList <Entity >(16 ).also { it.add(entity) })
637- }
638- }
639- }
640-
641- private fun Double.gridIndex () = floorI() shr GRID_SIZE
609+ data class SortedEntities (val trackRangeSquared : Int , val entities : List <Entity >)
642610
643611 data class RaytraceConfig (
644612 @Comment(" Asynchronous threads used to calculate visibility. More to update faster." )
0 commit comments