Make EntityIndex#walk significantly faster when querying large regions

This commit is contained in:
DBotThePony 2024-05-01 11:59:04 +07:00
parent afd93fea99
commit 884a432676
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.kstarbound.world
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
import it.unimi.dsi.fastutil.longs.LongArrayList
@ -317,7 +318,7 @@ class EntityIndex(val geometry: WorldGeometry) {
}
fun <V> walk(rect: AABB, visitor: (AbstractEntity) -> KOptional<V>, withEdges: Boolean = true): KOptional<V> {
val seen = IntAVLTreeSet()
val seen = IntOpenHashSet(256)
for (actualRegion in geometry.split(rect).first) {
val xMin = geometry.x.chunkFromCell(actualRegion.mins.x)
@ -327,15 +328,29 @@ class EntityIndex(val geometry: WorldGeometry) {
val yMax = geometry.y.chunkFromCell(actualRegion.maxs.y)
for (x in xMin .. xMax) {
val xIsEdge = x == xMin || x == xMax
for (y in yMin .. yMax) {
val sector = map[index(x, y)] ?: continue
val yIsEdge = y == yMin || y == yMax
for (entry in sector.entries) {
if (seen.add(entry.id) && entry.intersects(actualRegion, withEdges)) {
val visit = visitor(entry.value)
if (!xIsEdge && !yIsEdge) {
for (entry in sector.entries) {
if (seen.add(entry.id)) {
val visit = visitor(entry.value)
if (visit.isPresent)
return visit
if (visit.isPresent)
return visit
}
}
} else {
for (entry in sector.entries) {
if (seen.add(entry.id) && entry.intersects(actualRegion, withEdges)) {
val visit = visitor(entry.value)
if (visit.isPresent)
return visit
}
}
}
}