Skip to content

Commit 75965ba

Browse files
committed
FakePlayer refactor, ca speed debug
1 parent f181bd4 commit 75965ba

File tree

6 files changed

+106
-40
lines changed

6 files changed

+106
-40
lines changed

common/src/main/kotlin/com/lambda/core/Loader.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@ import com.lambda.Lambda.LOG
2222
import com.lambda.util.Communication.ascii
2323
import com.lambda.util.reflections.getInstances
2424
import kotlin.system.measureTimeMillis
25-
import kotlin.time.DurationUnit
26-
import kotlin.time.toDuration
25+
import kotlin.time.Duration.Companion.milliseconds
2726

2827
object Loader {
2928
private val started = System.currentTimeMillis()
3029

3130
val runtime: String
32-
get() = "${(System.currentTimeMillis() - started).toDuration(DurationUnit.MILLISECONDS)}"
31+
get() = "${(System.currentTimeMillis() - started).milliseconds}"
3332

3433
private val loadables = getInstances<Loadable> { forPackages("com.lambda") }
3534

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

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ import com.lambda.module.tag.ModuleTag
3939
import com.lambda.threading.runSafe
4040
import com.lambda.threading.runSafeGameScheduled
4141
import com.lambda.util.BlockUtils.blockState
42+
import com.lambda.util.Communication.info
4243
import com.lambda.util.Timer
44+
import com.lambda.util.collections.LimitedDecayQueue
4345
import com.lambda.util.combat.CombatUtils.crystalDamage
4446
import com.lambda.util.math.*
4547
import com.lambda.util.math.MathUtils.ceilToInt
@@ -56,8 +58,7 @@ import net.minecraft.util.hit.BlockHitResult
5658
import net.minecraft.util.math.*
5759
import kotlin.concurrent.fixedRateTimer
5860
import kotlin.math.max
59-
import kotlin.time.DurationUnit
60-
import kotlin.time.toDuration
61+
import kotlin.time.Duration.Companion.milliseconds
6162

6263
object CrystalAura : Module(
6364
name = "CrystalAura",
@@ -69,8 +70,8 @@ object CrystalAura : Module(
6970
/* General */
7071
private val placeRange by setting("Place Range", 4.6, 1.0..7.0, 0.1, "Range to place crystals", " blocks") { page == Page.General }
7172
private val explodeRange by setting("Explode Range", 3.0, 1.0..7.0, 0.1, "Range to explode crystals", " blocks") { page == Page.General }
72-
private val placeDelay by setting("Place Delay", 50L, 0L..1000L, 5L, "Delay between placement attempts", " ms") { page == Page.General }
73-
private val explodeDelay by setting("Explode Delay", 10L, 0L..1000L, 5L, "Delay between explosion attempts", " ms") { page == Page.General }
73+
private val placeDelay by setting("Place Delay", 50L, 0L..1000L, 1L, "Delay between placement attempts", " ms") { page == Page.General }
74+
private val explodeDelay by setting("Explode Delay", 10L, 0L..1000L, 1L, "Delay between explosion attempts", " ms") { page == Page.General }
7475
private val updateMode by setting("Update Mode", UpdateMode.Async) { page == Page.General }
7576
private val updateDelaySetting by setting("Update Delay", 25L, 5L..200L, 5L, unit = " ms") { page == Page.General && updateMode == UpdateMode.Async }
7677
private val maxUpdatesPerFrame by setting("Max Updates Per Frame", 5, 1..20, 1) { page == Page.General && updateMode == UpdateMode.Async }
@@ -117,6 +118,8 @@ object CrystalAura : Module(
117118
private val predictionTimer = Timer()
118119
private var lastEntityId = 0
119120

121+
private val decay = LimitedDecayQueue<Int>(10000, 3000L)
122+
120123
private val collidingOffsets = mutableListOf<BlockPos>().apply {
121124
for (x in -1..1) {
122125
for (z in -1..1) {
@@ -140,7 +143,7 @@ object CrystalAura : Module(
140143
if (CrystalAura.isDisabled || updateMode != UpdateMode.Async) return@fixedRateTimer
141144

142145
runSafe {
143-
// timer may spam faster than main thread computes(game freezes completely at the beginning of the frame)
146+
// timer may spam faster than main thread computes (game freezes completely at the beginning of the frame)
144147
if (updatesThisFrame > maxUpdatesPerFrame) return@runSafe
145148
updatesThisFrame++
146149

@@ -151,6 +154,19 @@ object CrystalAura : Module(
151154
}
152155
}
153156

157+
fixedRateTimer(
158+
name = "CA Counter",
159+
daemon = true,
160+
initialDelay = 0L,
161+
period = 1000L
162+
) {
163+
if (CrystalAura.isDisabled || !debug) return@fixedRateTimer
164+
165+
runSafeGameScheduled {
166+
info((decay.size.toDouble() * 0.3333).roundToStep(0.1).toString())
167+
}
168+
}
169+
154170
// Ticking with alignment
155171
listen<TickEvent.Pre> {
156172
if (updateMode == UpdateMode.Ticked) tick()
@@ -211,7 +227,9 @@ object CrystalAura : Module(
211227
val pos = crystal.baseBlockPos
212228

213229
// Invalidate crystal entity
214-
blueprint[pos]?.crystal = null
230+
val opportunity = blueprint[pos] ?: return@listen
231+
opportunity.crystal = null
232+
decay += crystal.id
215233
}
216234

217235
onEnable {
@@ -279,7 +297,7 @@ object CrystalAura : Module(
279297
}
280298

281299
private fun SafeContext.updateBlueprint(target: LivingEntity) =
282-
updateTimer.runIfPassed(updateDelay.toDuration(DurationUnit.MILLISECONDS)) {
300+
updateTimer.runIfPassed(updateDelay.milliseconds) {
283301
resetBlueprint()
284302

285303
// Build damage info
@@ -452,10 +470,10 @@ object CrystalAura : Module(
452470
fun place() {
453471
if (rotation.rotate && !lookAt(placeRotation).requestBy(rotation).done) return
454472

455-
placeTimer.runSafeIfPassed(placeDelay.toDuration(DurationUnit.MILLISECONDS)) {
473+
placeTimer.runSafeIfPassed(placeDelay.milliseconds) {
456474
placeInternal(this@Opportunity, Hand.MAIN_HAND)
457475

458-
if (prediction.onPlace) predictionTimer.runIfNotPassed(packetLifetime.toDuration(DurationUnit.MILLISECONDS), false) {
476+
if (prediction.onPlace) predictionTimer.runIfNotPassed(packetLifetime.milliseconds, false) {
459477
val last = lastEntityId
460478

461479
repeat(placePredictions) {
@@ -475,7 +493,7 @@ object CrystalAura : Module(
475493
fun explode() {
476494
if (rotation.rotate && !lookAt(placeRotation).requestBy(rotation).done) return
477495

478-
explodeTimer.runSafeIfPassed(explodeDelay.toDuration(DurationUnit.MILLISECONDS)) {
496+
explodeTimer.runSafeIfPassed(explodeDelay.milliseconds) {
479497
crystal?.let { crystal ->
480498
explodeInternal(crystal.id)
481499
explodeTimer.reset()

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

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,70 +18,113 @@
1818
package com.lambda.module.modules.combat
1919

2020
import com.lambda.event.events.ConnectionEvent
21+
import com.lambda.event.events.TickEvent
2122
import com.lambda.event.listener.SafeListener.Companion.listen
2223
import com.lambda.http.Method
2324
import com.lambda.http.request
2425
import com.lambda.module.Module
2526
import com.lambda.module.tag.ModuleTag
2627
import com.lambda.threading.onShutdown
27-
import com.lambda.threading.runSafeConcurrent
28+
import com.lambda.threading.runGameScheduled
29+
import com.lambda.threading.runSafe
2830
import com.lambda.util.player.spawnFakePlayer
2931
import com.mojang.authlib.GameProfile
3032
import net.minecraft.client.network.OtherClientPlayerEntity
3133
import net.minecraft.client.network.PlayerListEntry
3234
import net.minecraft.entity.Entity
3335
import java.util.*
36+
import kotlin.concurrent.fixedRateTimer
3437

3538
object FakePlayer : Module(
3639
name = "FakePlayer",
3740
description = "Spawns a fake player",
3841
defaultTags = setOf(ModuleTag.COMBAT, ModuleTag.RENDER)
3942
) {
4043
private val playerName by setting("Name", "Steve")
44+
private val fetchKey get() = playerName.lowercase() // Nicknames aren't case-sensitive
45+
46+
private var fakePlayer: OtherClientPlayerEntity? = null; set(value) {
47+
runSafe {
48+
field?.let {
49+
world.removeEntity(it.id, Entity.RemovalReason.DISCARDED)
50+
}
51+
value?.let {
52+
world.addEntity(it)
53+
}
54+
}
55+
56+
field = value
57+
}
4158

42-
private var fakePlayer: OtherClientPlayerEntity? = null
4359
private val nilUuid = UUID(0, 0)
60+
private val cachedProfiles = hashMapOf<String, GameProfile>()
4461

4562
init {
46-
onEnable {
47-
fakePlayer?.let { fake ->
48-
// Avoid multiple api requests
49-
if (fake.gameProfile.name == playerName) {
50-
fakePlayer = spawnFakePlayer(fake.gameProfile)
51-
return@onEnable
63+
listen<TickEvent.Pre> {
64+
fakePlayer = cachedProfiles[fetchKey]?.let { cached ->
65+
// Keep fetched fake player
66+
fakePlayer?.gameProfile?.also { profile ->
67+
if (profile is FetchedGameProfile && profile.name == cached.name) return@let fakePlayer
5268
}
53-
}
5469

55-
runSafeConcurrent {
56-
val uuid =
57-
request("https://api.mojang.com/users/profiles/minecraft/$playerName") {
70+
// Spawn fetched fake player
71+
spawnFakePlayer(
72+
profile = cached,
73+
reference = fakePlayer ?: player,
74+
addToWorld = false
75+
)
76+
} ?: fakePlayer?.takeIf { it.gameProfile.name == playerName } ?: spawnFakePlayer(
77+
// Spawn offline fake player while fetching
78+
profile = GameProfile(nilUuid, playerName),
79+
reference = fakePlayer ?: player,
80+
addToWorld = false
81+
)
82+
}
83+
84+
fixedRateTimer(
85+
name = "FakePlayer profile fetcher",
86+
daemon = true,
87+
initialDelay = 0L,
88+
period = 2000L
89+
) {
90+
cachedProfiles[fetchKey] ?: runSafe {
91+
val requestedProfile =
92+
request("https://api.mojang.com/users/profiles/minecraft/$fetchKey") {
5893
method(Method.GET)
59-
}.json<GameProfile>().data?.id ?: nilUuid
94+
}.json<GameProfile>().data
95+
96+
val uuid = requestedProfile?.id ?: nilUuid
6097

6198
val fetchedProperties = mc.sessionService.fetchProfile(uuid, true)?.profile?.properties
6299

63-
val profile = GameProfile(nilUuid, playerName).apply {
100+
val profile = FetchedGameProfile(nilUuid, playerName).apply {
64101
fetchedProperties?.forEach { key, value -> properties.put(key, value) }
65102
}
66103

67-
// This is the cache that mc pulls profile data from when it fetches skins.
68-
mc.networkHandler?.playerListEntries?.put(profile.id, PlayerListEntry(profile, false))
69-
spawnFakePlayer(profile)
104+
runGameScheduled {
105+
// This is the cache that mc pulls profile data from when it fetches skins.
106+
mc.networkHandler?.playerListEntries?.put(profile.id, PlayerListEntry(profile, false))
107+
cachedProfiles[fetchKey] = profile
108+
}
70109
}
71110
}
72111

73112
onDisable {
74-
deletePlayer()
113+
fakePlayer = null
114+
}
115+
116+
onShutdown {
117+
disable()
75118
}
76119

77-
onShutdown { disable() }
120+
listen<ConnectionEvent.Connect.Pre> {
121+
disable()
122+
}
78123

79124
listen<ConnectionEvent.Disconnect> {
80125
disable()
81126
}
82127
}
83128

84-
private fun deletePlayer() {
85-
fakePlayer?.setRemoved(Entity.RemovalReason.DISCARDED)
86-
}
129+
private class FetchedGameProfile(id: UUID, name: String) : GameProfile(id, name)
87130
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ object Speed : Module(
5151
@JvmStatic
5252
val mode by setting("Mode", Mode.GRIM_STRAFE).apply {
5353
onValueChange { _, _ ->
54-
reset()
54+
Speed.reset()
5555
}
5656
}
5757

common/src/main/kotlin/com/lambda/module/modules/player/Replay.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import java.lang.reflect.Type
5656
import java.time.format.DateTimeFormatter
5757
import kotlin.io.path.pathString
5858
import kotlin.time.Duration
59+
import kotlin.time.Duration.Companion.milliseconds
5960
import kotlin.time.DurationUnit
6061
import kotlin.time.toDuration
6162

@@ -571,7 +572,7 @@ object Replay : Module(
571572
val endPos: Vec3d
572573
get() = position.lastOrNull() ?: Vec3d.ZERO
573574
val pruneTimesave: Duration
574-
get() = (position.findCyclicPaths(5).size * 50L).toDuration(DurationUnit.MILLISECONDS)
575+
get() = (position.findCyclicPaths(5).size * 50L).milliseconds
575576

576577
fun duplicate() = Recording(
577578
input.take(size).toMutableList(),

common/src/main/kotlin/com/lambda/util/player/PlayerUtils.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.mojang.authlib.GameProfile
55
import net.minecraft.client.network.ClientPlayerEntity
66
import net.minecraft.client.network.OtherClientPlayerEntity
77
import net.minecraft.client.network.PlayerListEntry
8+
import net.minecraft.entity.player.PlayerEntity
89

910
fun SafeContext.copyPlayer(entity: ClientPlayerEntity) =
1011
ClientPlayerEntity(mc, world, mc.networkHandler, null, null, entity.isSneaking, entity.isSprinting).apply {
@@ -22,15 +23,19 @@ fun SafeContext.copyPlayer(entity: ClientPlayerEntity) =
2223
isOnGround = entity.isOnGround
2324
}
2425

25-
fun SafeContext.spawnFakePlayer(profile: GameProfile): OtherClientPlayerEntity {
26+
fun SafeContext.spawnFakePlayer(
27+
profile: GameProfile,
28+
reference: PlayerEntity = player,
29+
addToWorld: Boolean = true
30+
): OtherClientPlayerEntity {
2631
val entity = OtherClientPlayerEntity(world, profile).apply {
27-
copyFrom(player)
32+
copyFrom(reference)
2833

2934
playerListEntry = PlayerListEntry(profile, false)
3035
id = -2024 - 4 - 20
3136
}
3237

33-
world.addEntity(entity)
38+
if (addToWorld) world.addEntity(entity)
3439

3540
return entity
3641
}

0 commit comments

Comments
 (0)