|
| 1 | +package com.lambda.util.world |
| 2 | + |
| 3 | +import com.lambda.context.SafeContext |
| 4 | +import net.minecraft.entity.Entity |
| 5 | +import net.minecraft.util.math.ChunkSectionPos |
| 6 | +import net.minecraft.util.math.Vec3d |
| 7 | +import kotlin.math.ceil |
| 8 | + |
| 9 | + |
| 10 | +/** |
| 11 | + * Utility class for working with entities in a Minecraft environment. |
| 12 | + */ |
| 13 | +object EntityUtils { |
| 14 | + |
| 15 | + // TODO: Tick cache implementation |
| 16 | + |
| 17 | + /** |
| 18 | + * Gets the closest entity of type [T] within a specified range. |
| 19 | + * |
| 20 | + * @param pos The position to search from. |
| 21 | + * @param range The maximum distance to search for entities. |
| 22 | + * @param predicate Optional predicate to filter entities. |
| 23 | + * @return The closest entity of type [T] within the specified range, or null if none is found. |
| 24 | + */ |
| 25 | + inline fun <reified T : Entity> SafeContext.getClosestEntity(pos: Vec3d, range: Double, noinline predicate: (T) -> Boolean = { true }): T? { |
| 26 | + return getFastEntities(pos, range, predicate).firstOrNull { it.pos.squaredDistanceTo(pos) <= range * range } |
| 27 | + } |
| 28 | + |
| 29 | + /** |
| 30 | + * Gets all entities of type [T] within a specified distance from a position. |
| 31 | + * |
| 32 | + * @param pos The position to search from. |
| 33 | + * @param distance The maximum distance to search for entities. |
| 34 | + * @param predicate Optional predicate to filter entities. |
| 35 | + * @return A list of entities of type [T] within the specified distance from the position. |
| 36 | + */ |
| 37 | + inline fun <reified T : Entity> SafeContext.getFastEntities(pos: Vec3d, distance: Double, noinline predicate: (T) -> Boolean = { true }): List<T> { |
| 38 | + val chunks = ceil(distance / 16).toInt() |
| 39 | + val sectionX = pos.x.toInt() shr 4 |
| 40 | + val sectionY = pos.y.toInt() shr 4 |
| 41 | + val sectionZ = pos.z.toInt() shr 4 |
| 42 | + |
| 43 | + val entities = mutableListOf<T>() |
| 44 | + |
| 45 | + // Here we iterate over all sections within the specified distance and add all entities of type [T] to the list. |
| 46 | + // We do not have to worry about performance here, as the number of sections is very limited. |
| 47 | + // For example if the player is on the edge of a section and the distance is 16, we only have to iterate over 9 sections. |
| 48 | + for (x in sectionX - chunks..sectionX + chunks) { |
| 49 | + for (y in sectionY - chunks..sectionY + chunks) { |
| 50 | + for (z in sectionZ - chunks..sectionZ + chunks) { |
| 51 | + val section = world.entityManager.cache.findTrackingSection(ChunkSectionPos.asLong(x, y, z)) ?: continue |
| 52 | + entities.addAll(section.collection.getAllOfType(T::class.java).filter(predicate)) |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + return entities |
| 58 | + } |
| 59 | +} |
0 commit comments