Skip to content

Commit 0584c8d

Browse files
emyfopsAvanatiker
andauthored
[1.20.x] [All] [Feature]: Fast vector (#46)
Introduces a zero-allocation position tuple for low-level api world search Closes #45 --------- Co-authored-by: Constructor <fractalminds@protonmail.com>
1 parent 6ce060c commit 0584c8d

File tree

17 files changed

+814
-246
lines changed

17 files changed

+814
-246
lines changed

common/src/main/kotlin/com/lambda/config/groups/Targeting.kt

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import com.lambda.interaction.rotation.Rotation.Companion.rotation
77
import com.lambda.interaction.rotation.Rotation.Companion.rotationTo
88
import com.lambda.threading.runSafe
99
import com.lambda.util.math.VecUtils.distSq
10-
import com.lambda.util.world.WorldUtils.getFastEntities
10+
import com.lambda.util.world.entitySearch
1111
import net.minecraft.client.network.ClientPlayerEntity
1212
import net.minecraft.entity.LivingEntity
1313
import net.minecraft.entity.mob.MobEntity
@@ -31,16 +31,6 @@ abstract class Targeting(
3131
override val invisible by c.setting("Invisible", true) { vis() }
3232
override val dead by c.setting("Dead", false) { vis() }
3333

34-
fun getEntities(): List<LivingEntity> =
35-
mutableListOf<LivingEntity>().apply {
36-
runSafe {
37-
getFastEntities(
38-
player.pos, targetingRange, this@apply,
39-
predicate = { entity -> validate(player, entity) }
40-
)
41-
}
42-
}
43-
4434
open fun validate(player: ClientPlayerEntity, entity: LivingEntity) = when {
4535
!players && entity.isPlayer -> false
4636
!animals && entity is PassiveEntity -> false
@@ -65,24 +55,15 @@ abstract class Targeting(
6555
}
6656

6757
fun getTarget(): LivingEntity? = runSafe {
68-
var best: LivingEntity? = null
69-
var bestFactor = Double.MAX_VALUE
70-
71-
val comparator = { entity: LivingEntity, _: Int ->
72-
val factor = priority.factor(this, entity)
73-
if (factor < bestFactor) {
74-
best = entity
75-
bestFactor = factor
76-
}
77-
}
78-
7958
val predicate = { entity: LivingEntity ->
8059
validate(player, entity)
8160
}
8261

83-
getFastEntities<LivingEntity>(player.pos, targetingRange, null, comparator, predicate)
84-
85-
return@runSafe best
62+
return@runSafe entitySearch<LivingEntity>(targetingRange) {
63+
predicate(it)
64+
}.minBy {
65+
priority.factor(this, it)
66+
}
8667
}
8768
}
8869

@@ -97,4 +78,4 @@ abstract class Targeting(
9778
HEALTH({ it.health.toDouble() }),
9879
FOV({ player.rotation dist player.eyePos.rotationTo(it.pos) })
9980
}
100-
}
81+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.lambda.core.annotations
2+
3+
import kotlin.annotation.AnnotationTarget.*
4+
5+
@RequiresOptIn(
6+
message = "Only use if you know what you are doing, no support will be provided whatsoever, use at your own risk",
7+
)
8+
@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS)
9+
internal annotation class InternalApi

common/src/main/kotlin/com/lambda/module/modules/combat/CrystalAura.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@ import com.lambda.config.groups.InteractionSettings
44
import com.lambda.config.groups.RotationSettings
55
import com.lambda.event.events.TickEvent
66
import com.lambda.event.listener.SafeListener.Companion.concurrentListener
7-
import com.lambda.event.listener.SafeListener.Companion.listener
87
import com.lambda.module.Module
98
import com.lambda.module.tag.ModuleTag
10-
import com.lambda.util.world.WorldUtils.getClosestEntity
11-
import net.minecraft.entity.LivingEntity
129
import net.minecraft.util.Hand
1310

1411
object CrystalAura : Module(
@@ -56,9 +53,5 @@ object CrystalAura : Module(
5653
/*listener<RotationEvent.Pre> { event ->
5754
event.lookAtEntity(rotation, interac, getClosestEntity<LivingEntity>(player.eyePos, placeRange) ?: return@listener)
5855
}*/
59-
60-
listener<TickEvent.Pre> {
61-
getClosestEntity<LivingEntity>(player.eyePos, 64.0)
62-
}
6356
}
6457
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.lambda.module.modules.debug
2+
3+
import com.lambda.event.events.RenderEvent
4+
import com.lambda.event.listener.SafeListener.Companion.listener
5+
import com.lambda.graphics.renderer.esp.builders.build
6+
import com.lambda.module.Module
7+
import com.lambda.module.tag.ModuleTag
8+
import com.lambda.util.world.blockSearch
9+
import net.minecraft.block.Blocks
10+
import net.minecraft.util.math.Vec3i
11+
import java.awt.Color
12+
13+
object BlockTest : Module(
14+
name = "BlockTest",
15+
description = "BlockTest",
16+
defaultTags = setOf(ModuleTag.DEBUG),
17+
) {
18+
private val rangeX by setting("Range X", 5, 1..7, 1, "Range X")
19+
private val rangeY by setting("Range Y", 5, 1..7, 1, "Range Y")
20+
private val rangeZ by setting("Range Z", 5, 1..7, 1, "Range Z")
21+
private val stepX by setting("Step X", 1, 1..7, 1, "Step X")
22+
private val stepY by setting("Step Y", 1, 1..7, 1, "Step Y")
23+
private val stepZ by setting("Step Z", 1, 1..7, 1, "Step Z")
24+
25+
private val range: Vec3i
26+
get() = Vec3i(rangeX, rangeY, rangeZ)
27+
28+
private val step: Vec3i
29+
get() = Vec3i(stepX, stepY, stepZ)
30+
31+
private val filledColor = Color(100, 150, 255, 128)
32+
private val outlineColor = Color(100, 150, 255, 51)
33+
34+
init {
35+
listener<RenderEvent.StaticESP> {
36+
blockSearch(range, step) { _, state ->
37+
state.isOf(Blocks.DIAMOND_BLOCK)
38+
}.forEach { (pos, state) ->
39+
state.getOutlineShape(world, pos).boundingBoxes.forEach { box ->
40+
it.renderer.build(box.offset(pos), filledColor, outlineColor)
41+
}
42+
}
43+
}
44+
}
45+
}

common/src/main/kotlin/com/lambda/module/modules/debug/EntityTest.kt

Lines changed: 0 additions & 22 deletions
This file was deleted.

common/src/main/kotlin/com/lambda/module/modules/debug/RenderTest.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import com.lambda.graphics.renderer.esp.builders.build
77
import com.lambda.module.Module
88
import com.lambda.module.tag.ModuleTag
99
import com.lambda.util.math.ColorUtils.setAlpha
10-
import com.lambda.util.world.WorldUtils.getClosestEntity
10+
import com.lambda.util.world.entitySearch
1111
import net.minecraft.entity.LivingEntity
1212
import net.minecraft.util.math.Box
1313
import java.awt.Color
@@ -29,12 +29,14 @@ object RenderTest : Module(
2929

3030
init {
3131
listener<RenderEvent.DynamicESP> {
32-
val entity = getClosestEntity<LivingEntity>(player.pos, 8.0) ?: return@listener
33-
it.renderer.build(entity.dynamicBox, filledColor, outlineColor)
32+
entitySearch<LivingEntity>(8.0)
33+
.forEach { entity ->
34+
it.renderer.build(entity.dynamicBox, filledColor, outlineColor)
35+
}
3436
}
3537

3638
listener<RenderEvent.StaticESP> {
3739
it.renderer.build(Box.of(player.pos, 0.3, 0.3, 0.3), filledColor, outlineColor)
3840
}
3941
}
40-
}
42+
}

common/src/main/kotlin/com/lambda/module/modules/movement/EntityControl.kt

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import com.lambda.event.events.TickEvent
55
import com.lambda.event.listener.SafeListener.Companion.listener
66
import com.lambda.module.Module
77
import com.lambda.module.tag.ModuleTag
8-
import com.lambda.util.world.WorldUtils.getEntities
8+
import com.lambda.util.world.entitySearch
99
import net.minecraft.entity.passive.AbstractHorseEntity
1010
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket
1111

@@ -15,38 +15,23 @@ object EntityControl : Module(
1515
description = "Control mountable entities",
1616
defaultTags = setOf(ModuleTag.MOVEMENT)
1717
) {
18-
private val page by setting("Page", Page.GENERAL)
19-
20-
/* General */
21-
private val forceMount by setting("Force Mount", true, description = "Attempts to force mount chested entities.", visibility = { page == Page.GENERAL }).apply {
18+
private val forceMount by setting("Force Mount", true, description = "Attempts to force mount chested entities.").apply {
2219
onValueChange { _, _ ->
23-
horses.forEach { horse -> horse.updateSaddle() }
20+
resetMounts()
2421
}
2522
}
26-
27-
/* Movement */
28-
private val speed by setting("Entity Speed", 2.0, 0.1..10.0, 0.1, description = "Speed for entities.", visibility = { page == Page.MOVEMENT })
29-
30-
private enum class Page {
31-
GENERAL, MOVEMENT
32-
}
33-
34-
private val horses = mutableListOf<AbstractHorseEntity>()
23+
private val modified = mutableSetOf<AbstractHorseEntity>()
3524

3625
init {
3726
listener<TickEvent.Pre> {
38-
if (forceMount) {
39-
getEntities(player.pos, 8.0, horses, { horse, _ -> horse.setHorseFlag(4, true) })
40-
}
41-
}
42-
43-
/*listener<MovementEvent.Pre> {
44-
if (!player.isRiding) return@listener
27+
if (!forceMount) return@listener
4528

46-
// We can do this because the player movement depends on the entity movement
47-
player.vehicle?.motionX = speed
48-
player.vehicle?.motionZ = speed
49-
}*/
29+
entitySearch<AbstractHorseEntity>(8.0)
30+
.forEach {
31+
it.setHorseFlag(4, true)
32+
modified.add(it)
33+
}
34+
}
5035

5136
listener<PacketEvent.Send.Pre> { event ->
5237
if (!forceMount) return@listener
@@ -60,7 +45,11 @@ object EntityControl : Module(
6045
}
6146

6247
onDisable {
63-
horses.clear()
48+
resetMounts()
6449
}
6550
}
51+
52+
private fun resetMounts() {
53+
modified.forEach { it.updateSaddle() }
54+
}
6655
}

common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,17 @@ import com.lambda.module.Module
1313
import com.lambda.module.tag.ModuleTag
1414
import com.lambda.util.Nameable
1515
import com.lambda.util.player.MovementUtils.addSpeed
16-
import com.lambda.util.player.MovementUtils.buildMovementInput
1716
import com.lambda.util.player.MovementUtils.calcMoveYaw
1817
import com.lambda.util.player.MovementUtils.handledByBaritone
1918
import com.lambda.util.player.MovementUtils.isInputting
20-
import com.lambda.util.player.MovementUtils.mergeFrom
2119
import com.lambda.util.player.MovementUtils.motionY
2220
import com.lambda.util.player.MovementUtils.moveDelta
2321
import com.lambda.util.player.MovementUtils.newMovementInput
2422
import com.lambda.util.player.MovementUtils.roundedForward
2523
import com.lambda.util.player.MovementUtils.roundedStrafing
2624
import com.lambda.util.player.MovementUtils.setSpeed
2725
import com.lambda.util.extension.contains
28-
import com.lambda.util.world.WorldUtils.getFastEntities
26+
import com.lambda.util.world.entitySearch
2927
import net.minecraft.entity.LivingEntity
3028
import net.minecraft.entity.decoration.ArmorStandEntity
3129
import net.minecraft.entity.vehicle.BoatEntity
@@ -134,22 +132,14 @@ object Speed : Module(
134132

135133
var boostAmount = 0.0
136134

137-
getFastEntities<LivingEntity>(
138-
player.pos, 3.0,
139-
predicate = { player.boundingBox.expand(1.0) in it.boundingBox && it !is ArmorStandEntity },
140-
iterator = { e, _ ->
141-
val colliding = player.boundingBox in e.boundingBox
142-
val multiplier = if (colliding) grimCollideMultiplier else 1.0
143-
boostAmount += 0.08 * grimEntityBoost * multiplier
144-
}
145-
)
135+
boostAmount += entitySearch<LivingEntity>(3.0) {
136+
player.boundingBox.expand(1.0) in it.boundingBox && it !is ArmorStandEntity
137+
}.sumOf { 0.08 * grimEntityBoost }
146138

147139
if (grimBoatBoost > 0.0) {
148-
getFastEntities<BoatEntity>(
149-
player.pos, 4.0,
150-
predicate = { player.boundingBox in it.boundingBox.expand(0.01) },
151-
iterator = { _, _ -> boostAmount += grimBoatBoost }
152-
)
140+
boostAmount += entitySearch<BoatEntity>(4.0) {
141+
player.boundingBox in it.boundingBox.expand(0.01)
142+
}.sumOf { grimBoatBoost }
153143
}
154144

155145
addSpeed(boostAmount)

common/src/main/kotlin/com/lambda/util/collections/Extensions.kt

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.lambda.util.collections
22

3+
import kotlin.reflect.KClass
4+
35
/**
46
* Filters elements of the iterable by their runtime type and a predicate, and adds the matching elements to the specified mutable collection.
57
*
@@ -20,16 +22,47 @@ inline fun <reified R, C : MutableCollection<in R>> Iterable<*>.filterPointer(
2022
predicate: (R) -> Boolean,
2123
) {
2224
var index = 0
23-
for (element in this) {
24-
when {
25-
element is R && predicate(element) && destination != null -> {
26-
iterator(element, index++)
27-
destination.add(element)
28-
}
2925

30-
element is R && predicate(element) && destination == null -> {
31-
iterator(element, index++)
32-
}
26+
forEach { element ->
27+
val fulfilled = predicate(element as R)
28+
29+
if (fulfilled && destination != null) {
30+
destination.add(element)
31+
iterator(element, index)
32+
}
33+
34+
index++
35+
}
36+
}
37+
38+
/**
39+
* Filters elements of the iterable by their runtime type and a predicate, and adds the matching elements to the specified mutable collection.
40+
*
41+
* This function allows filtering elements of an iterable based on their runtime type and a provided predicate function.
42+
* The elements that match both the type constraint and the predicate are added to the destination mutable collection.
43+
* Because we do not want additional overhead, this function acts as pointer receiver to a collection.
44+
* The predicate function determines whether an element should be included based on its type and any additional criteria.
45+
*
46+
* @param R The target type to filter elements to.
47+
* @param C The type of the destination mutable collection.
48+
* @param destination The mutable collection to which the filtered elements will be added.
49+
* @param iterator The iterator function that processes the filtered elements and their index.
50+
* @param predicate The predicate function that determines whether an element should be included based on its type and other criteria.
51+
*/
52+
inline fun <R : Any, C : MutableCollection<in R>> Iterable<*>.filterPointer(
53+
kClass: KClass<out R>,
54+
destination: C?,
55+
iterator: (R) -> Unit,
56+
predicate: (R) -> Boolean,
57+
) {
58+
forEach { element ->
59+
// Cannot be replaced with reified type due to type erasure
60+
(element as? R) ?: return@forEach
61+
val fulfilled = kClass.isInstance(element) && predicate(element)
62+
63+
if (fulfilled && destination != null) {
64+
destination.add(element)
65+
iterator(element)
3366
}
3467
}
3568
}

0 commit comments

Comments
 (0)