From c1db6fe0e2377a14f0f721b61bc46b3b992f836a Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Fri, 5 Jul 2024 11:40:29 +0300 Subject: [PATCH 01/35] Wtf --- common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt | 2 -- common/src/main/kotlin/com/lambda/graphics/RenderMain.kt | 1 - common/src/main/kotlin/com/lambda/module/HudModule.kt | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt b/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt index e247e328b..3116ed2a8 100644 --- a/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt @@ -20,8 +20,6 @@ abstract class RenderEvent : Event { } abstract class GUI(val scale: Double) : RenderEvent() { - class HUD(scaleFactor: Double) : GUI(scaleFactor) - class Scaled(scaleFactor: Double) : GUI(scaleFactor) class Fixed : GUI(1.0) diff --git a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt index 53216f32d..e4a312ccc 100644 --- a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt +++ b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt @@ -30,7 +30,6 @@ object RenderMain { RenderEvent.GUI.Fixed().post() rescale(GuiSettings.scale) - RenderEvent.GUI.HUD(GuiSettings.scale).post() RenderEvent.GUI.Scaled(GuiSettings.scale).post() } } diff --git a/common/src/main/kotlin/com/lambda/module/HudModule.kt b/common/src/main/kotlin/com/lambda/module/HudModule.kt index 52b0a9e07..41bd9fc02 100644 --- a/common/src/main/kotlin/com/lambda/module/HudModule.kt +++ b/common/src/main/kotlin/com/lambda/module/HudModule.kt @@ -66,7 +66,7 @@ abstract class HudModule( renderCallables.add(block) init { - listener { event -> + listener { event -> screenSize = event.screenSize renderCallables.forEach { function -> From d1ba8a0ebc8fe4615ba94894d38803276c26aa39 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sat, 6 Jul 2024 05:51:13 +0300 Subject: [PATCH 02/35] Offline crash fix --- .../com/lambda/graphics/renderer/gui/font/glyph/EmojiGlyphs.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/glyph/EmojiGlyphs.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/glyph/EmojiGlyphs.kt index bc3efca5f..d8f92e6e6 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/glyph/EmojiGlyphs.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/glyph/EmojiGlyphs.kt @@ -35,6 +35,7 @@ class EmojiGlyphs(zipUrl: String) { LOG.info("Loaded ${emojiMap.size} emojis in $time ms") }.onFailure { LOG.error("Failed to load emojis: ${it.message}", it) + fontTexture = MipmapTexture(BufferedImage(1024, 1024, BufferedImage.TYPE_INT_ARGB)) } } From d76c471ba6573c89624be8e99b067b315e92c43a Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sat, 6 Jul 2024 05:51:56 +0300 Subject: [PATCH 03/35] Settings font scaling --- .../com/lambda/graphics/renderer/gui/font/FontRenderer.kt | 2 +- .../kotlin/com/lambda/gui/impl/clickgui/buttons/ModuleButton.kt | 2 ++ .../main/kotlin/com/lambda/module/modules/client/ClickGui.kt | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt index 96411fac9..eea207f1b 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt @@ -18,7 +18,7 @@ class FontRenderer( ) { private val vao = VAO(VertexMode.TRIANGLES, VertexAttrib.Group.FONT) - private val scaleMultiplier = 1.0 + var scaleMultiplier = 1.0 /** * Builds the vertex array for rendering the text. diff --git a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/ModuleButton.kt b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/ModuleButton.kt index 1a03a8ae9..86ec9933c 100644 --- a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/ModuleButton.kt +++ b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/ModuleButton.kt @@ -96,6 +96,8 @@ class ModuleButton( is GuiEvent.Render -> { super.onEvent(e) + settingsRenderer.font.scaleMultiplier = ClickGui.settingsFontScale + // Shadow renderer.filled.apply { val rect = Rect( diff --git a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt index 263531e42..708cf389d 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt @@ -21,6 +21,7 @@ object ClickGui : Module( val windowPadding by setting("Window Padding", 2.0, 0.0..10.0, 0.1) val buttonHeight by setting("Button Height", 11.0, 8.0..20.0, 0.1) val buttonStep by setting("Button Step", 0.0, 0.0..5.0, 0.1) + val settingsFontScale by setting("Settings Font Scale", 0.92, 0.5..1.0, 0.01) // Animation val openSpeed by setting("Open Speed", 0.5, 0.1..1.0, 0.01) From 6000a84f6332c8568c6f91894fdbd2ebcdc94715 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sat, 6 Jul 2024 06:39:22 +0300 Subject: [PATCH 04/35] Gui window docking & hud serialization fix --- .../gui/CustomModuleWindowSerializer.kt | 13 ++- .../serializer/gui/TagWindowSerializer.kt | 20 +++-- .../com/lambda/gui/AbstractGuiConfigurable.kt | 2 - .../kotlin/com/lambda/gui/GuiConfigurable.kt | 2 +- .../kotlin/com/lambda/gui/api/LambdaGui.kt | 2 +- .../gui/api/component/WindowComponent.kt | 50 ++++++++++- .../gui/api/component/core/DockingRect.kt | 81 +++++++++++++++++ .../com/lambda/gui/impl/AbstractClickGui.kt | 19 ++-- .../impl/clickgui/windows/tag/TagWindow.kt | 9 +- .../kotlin/com/lambda/module/HudModule.kt | 86 ++++++------------- .../lambda/module/modules/client/ClickGui.kt | 4 + .../main/kotlin/com/lambda/util/math/Vec2d.kt | 4 +- 12 files changed, 203 insertions(+), 89 deletions(-) create mode 100644 common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt diff --git a/common/src/main/kotlin/com/lambda/config/serializer/gui/CustomModuleWindowSerializer.kt b/common/src/main/kotlin/com/lambda/config/serializer/gui/CustomModuleWindowSerializer.kt index d394df2ea..cf2c315f9 100644 --- a/common/src/main/kotlin/com/lambda/config/serializer/gui/CustomModuleWindowSerializer.kt +++ b/common/src/main/kotlin/com/lambda/config/serializer/gui/CustomModuleWindowSerializer.kt @@ -1,6 +1,7 @@ package com.lambda.config.serializer.gui import com.google.gson.* +import com.lambda.gui.api.component.core.DockingRect import com.lambda.gui.impl.clickgui.LambdaClickGui import com.lambda.gui.impl.clickgui.windows.tag.CustomModuleWindow import com.lambda.module.ModuleRegistry @@ -24,8 +25,12 @@ object CustomModuleWindowSerializer : JsonSerializer, JsonDe addProperty("height", it.height) addProperty("isOpen", it.isOpen) add("position", JsonArray().apply { - add(it.position.x) - add(it.position.y) + add(it.serializedPosition.x) + add(it.serializedPosition.y) + }) + add("docking", JsonArray().apply { + add(it.dockingH.ordinal) + add(it.dockingV.ordinal) }) } } ?: JsonNull.INSTANCE @@ -47,10 +52,12 @@ object CustomModuleWindowSerializer : JsonSerializer, JsonDe width = it["width"].asDouble height = it["height"].asDouble isOpen = it["isOpen"].asBoolean - position = Vec2d( + serializedPosition = Vec2d( it["position"].asJsonArray[0].asDouble, it["position"].asJsonArray[1].asDouble ) + dockingH = DockingRect.HAlign.entries[it["docking"].asJsonArray[0].asInt] + dockingV = DockingRect.VAlign.entries[it["docking"].asJsonArray[1].asInt] } } ?: throw JsonParseException("Invalid window data") } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/config/serializer/gui/TagWindowSerializer.kt b/common/src/main/kotlin/com/lambda/config/serializer/gui/TagWindowSerializer.kt index 45b288cad..107c81694 100644 --- a/common/src/main/kotlin/com/lambda/config/serializer/gui/TagWindowSerializer.kt +++ b/common/src/main/kotlin/com/lambda/config/serializer/gui/TagWindowSerializer.kt @@ -1,6 +1,7 @@ package com.lambda.config.serializer.gui import com.google.gson.* +import com.lambda.gui.api.component.core.DockingRect import com.lambda.gui.impl.clickgui.LambdaClickGui import com.lambda.gui.impl.clickgui.windows.tag.TagWindow import com.lambda.gui.impl.hudgui.LambdaHudGui @@ -20,9 +21,14 @@ object TagWindowSerializer : JsonSerializer, JsonDeserializer, JsonDeserializer LambdaClickGui - in ModuleTag.hudDefaults -> LambdaHudGui + val gui = when (it["group"].asString) { + "main"-> LambdaClickGui + "hud" -> LambdaHudGui else -> return@let null } @@ -43,10 +49,12 @@ object TagWindowSerializer : JsonSerializer, JsonDeserializer() private val defaultWindows get() = tags.mapIndexed { index, tag -> diff --git a/common/src/main/kotlin/com/lambda/gui/GuiConfigurable.kt b/common/src/main/kotlin/com/lambda/gui/GuiConfigurable.kt index 81c09a471..eff9e86d1 100644 --- a/common/src/main/kotlin/com/lambda/gui/GuiConfigurable.kt +++ b/common/src/main/kotlin/com/lambda/gui/GuiConfigurable.kt @@ -7,5 +7,5 @@ import com.lambda.module.tag.ModuleTag object GuiConfigurable : AbstractGuiConfigurable( LambdaClickGui, ModuleTag.defaults, "gui" ) { - override var customWindows by setting("custom windows", listOf()) + var customWindows by setting("custom windows", listOf()) } diff --git a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt index c8dad409e..46e708b2f 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt @@ -24,7 +24,7 @@ abstract class LambdaGui( override val name: String, private val owner: Module? = null ) : Screen(Text.of(name)), IComponent, Nameable, Muteable { - protected var screenSize = Vec2d.ZERO + var screenSize = Vec2d.ZERO override val rect get() = Rect(Vec2d.ZERO, screenSize) val isOpen get() = mc.currentScreen == this diff --git a/common/src/main/kotlin/com/lambda/gui/api/component/WindowComponent.kt b/common/src/main/kotlin/com/lambda/gui/api/component/WindowComponent.kt index 3fd197816..7cf4c0044 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/component/WindowComponent.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/component/WindowComponent.kt @@ -4,6 +4,7 @@ import com.lambda.graphics.animation.Animation.Companion.exp import com.lambda.graphics.gl.Scissor.scissor import com.lambda.gui.api.GuiEvent import com.lambda.gui.api.RenderLayer +import com.lambda.gui.api.component.core.DockingRect import com.lambda.gui.api.component.core.list.ChildComponent import com.lambda.gui.api.component.core.list.ChildLayer import com.lambda.gui.impl.AbstractClickGui @@ -28,18 +29,33 @@ abstract class WindowComponent( abstract var width: Double abstract var height: Double - var position = Vec2d.ZERO - var isOpen = true override val isActive get() = isOpen private var dragOffset: Vec2d? = null private val padding get() = ClickGui.windowPadding - final override val rect get() = Rect.basedOn(position, width, renderHeightAnimation + titleBarHeight) + private val rectHandler = object : DockingRect() { + override var relativePos = Vec2d.ZERO + override val width get() = this@WindowComponent.width + override val height get() = renderHeightAnimation + titleBarHeight + + override val dockingBase get() = titleBar.center + + override var allowHAlign = ClickGui.allowHAlign + override var allowVAlign = ClickGui.allowVAlign + } + + var serializedPosition by rectHandler::relativePos + var position by rectHandler::position + final override val rect by rectHandler::rect + + var dockingH by rectHandler::dockingH + var dockingV by rectHandler::dockingV + private val contentRect get() = rect.shrink(padding).moveFirst(Vec2d(0.0, titleBarHeight - padding)) - private val titleBar get() = Rect.basedOn(rect.leftTop, rect.size.x, titleBarHeight) + private val titleBar: Rect get() = Rect.basedOn(rect.leftTop, rect.size.x, titleBarHeight) private val titleBarHeight get() = ClickGui.buttonHeight * 1.25 private val renderer = RenderLayer() @@ -65,6 +81,8 @@ abstract class WindowComponent( } is GuiEvent.Render -> { + updateRect() + // TODO: fix blur // BlurPostProcessor.render(rect, ClickGui.windowBlur, guiAnimation) @@ -105,8 +123,14 @@ abstract class WindowComponent( } is GuiEvent.MouseMove -> { + val prevPos = position + dragOffset?.let { position = e.mouse - it + + if (prevPos != position) { + rectHandler.autoDocking() + } } } @@ -133,6 +157,24 @@ abstract class WindowComponent( contentComponents.onEvent(e) } + private fun updateRect() = rectHandler.apply { + screenSize = gui.screenSize + + var updateDocking = false + + if (allowHAlign != ClickGui.allowHAlign) { + allowHAlign = ClickGui.allowHAlign + updateDocking = true + } + + if (allowVAlign != ClickGui.allowVAlign) { + allowVAlign = ClickGui.allowVAlign + updateDocking = true + } + + if (updateDocking) autoDocking() + } + fun focus() { // move window into foreground gui.apply { diff --git a/common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt b/common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt new file mode 100644 index 000000000..909629e65 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt @@ -0,0 +1,81 @@ +package com.lambda.gui.api.component.core + +import com.lambda.util.math.MathUtils.coerceIn +import com.lambda.util.math.Rect +import com.lambda.util.math.Vec2d + +abstract class DockingRect { + abstract var relativePos: Vec2d + protected abstract val width: Double + protected abstract val height: Double + protected val size get() = Vec2d(width, height) + + val rect get() = Rect.basedOn(position, size) + open val dockingBase get() = rect.center + + open val autoDocking = false + open val allowHAlign = true + open val allowVAlign = true + + open var dockingH = HAlign.LEFT; set(to) { + val from = field + field = to + + val delta = to.multiplier - from.multiplier + relativePos += Vec2d.RIGHT * delta * (size.x - screenSize.x) + } + + open var dockingV = VAlign.TOP; set(to) { + val from = field + field = to + + val delta = to.multiplier - from.multiplier + relativePos += Vec2d.BOTTOM * delta * (size.y - screenSize.y) + } + + var screenSize: Vec2d = Vec2d.ZERO + + var position + get() = relativeToAbs(relativePos).coerceIn(0.0, screenSize.x - size.x, 0.0, screenSize.y - size.y) + set(value) { relativePos = absToRelative(value); if (autoDocking) autoDocking() } + + private val dockingOffset get() = (screenSize - size) * Vec2d(dockingH.multiplier, dockingV.multiplier) + + private fun relativeToAbs(posIn: Vec2d) = posIn + dockingOffset + private fun absToRelative(posIn: Vec2d) = posIn - dockingOffset + + fun autoDocking() { + val screenCenterX = (screenSize.x * 0.3333)..(screenSize.x * 0.6666) + val screenCenterY = (screenSize.y * 0.3333)..(screenSize.y * 0.6666) + + val drawableCenter = dockingBase + + dockingH = if (allowHAlign) { + when { + drawableCenter.x < screenCenterX.start -> HAlign.LEFT + drawableCenter.x > screenCenterX.endInclusive -> HAlign.RIGHT + else -> HAlign.CENTER + } + } else HAlign.LEFT + + dockingV = if (allowVAlign) { + when { + drawableCenter.y < screenCenterY.start -> VAlign.TOP + drawableCenter.y > screenCenterY.endInclusive -> VAlign.BOTTOM + else -> VAlign.CENTER + } + } else VAlign.TOP + } + + enum class HAlign(val multiplier: Double) { + LEFT(0.0), + CENTER(0.5), + RIGHT(1.0) + } + + enum class VAlign(val multiplier: Double) { + TOP(0.0), + CENTER(0.5), + BOTTOM(1.0) + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/gui/impl/AbstractClickGui.kt b/common/src/main/kotlin/com/lambda/gui/impl/AbstractClickGui.kt index f2cc6a76b..aca17d474 100644 --- a/common/src/main/kotlin/com/lambda/gui/impl/AbstractClickGui.kt +++ b/common/src/main/kotlin/com/lambda/gui/impl/AbstractClickGui.kt @@ -5,10 +5,12 @@ import com.lambda.graphics.animation.Animation.Companion.exp import com.lambda.graphics.buffer.FrameBuffer import com.lambda.graphics.shader.Shader import com.lambda.gui.AbstractGuiConfigurable +import com.lambda.gui.GuiConfigurable import com.lambda.gui.api.GuiEvent import com.lambda.gui.api.LambdaGui import com.lambda.gui.api.component.WindowComponent import com.lambda.gui.api.component.core.list.ChildLayer +import com.lambda.gui.impl.clickgui.LambdaClickGui import com.lambda.gui.impl.clickgui.buttons.SettingButton import com.lambda.gui.impl.clickgui.windows.ModuleWindow import com.lambda.gui.impl.clickgui.windows.tag.CustomModuleWindow @@ -18,6 +20,8 @@ import com.lambda.module.Module import com.lambda.module.modules.client.ClickGui import com.lambda.util.Mouse import com.mojang.blaze3d.systems.RenderSystem.recordRenderCall +import kotlin.reflect.KMutableProperty +import kotlin.reflect.KMutableProperty0 abstract class AbstractClickGui(name: String, owner: Module? = null) : LambdaGui(name, owner) { protected var hoveredWindow: WindowComponent<*>? = null @@ -97,7 +101,9 @@ abstract class AbstractClickGui(name: String, owner: Module? = null) : LambdaGui } } - private inline fun syncWindows(configWindows: MutableList) = windows.apply { + private inline fun syncWindows(prop: KMutableProperty0>) = windows.apply { + var configWindows by prop + // Add windows from config configWindows.filter { it !in children }.forEach(children::add) @@ -107,15 +113,14 @@ abstract class AbstractClickGui(name: String, owner: Module? = null) : LambdaGui } // Update config - configWindows.clear() - configWindows.addAll(children.filterIsInstance()) + configWindows = children.filterIsInstance().toMutableList() } - fun updateWindows() { - syncWindows(configurable.mainWindows) + private fun updateWindows() { + syncWindows(configurable::mainWindows) - if (this != LambdaHudGui) { - syncWindows(configurable.customWindows) + (configurable as? GuiConfigurable)?.let { + syncWindows(it::customWindows) } } diff --git a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/windows/tag/TagWindow.kt b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/windows/tag/TagWindow.kt index cf5433d95..f8d2e450b 100644 --- a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/windows/tag/TagWindow.kt +++ b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/windows/tag/TagWindow.kt @@ -2,6 +2,9 @@ package com.lambda.gui.impl.clickgui.windows.tag import com.lambda.gui.impl.AbstractClickGui import com.lambda.gui.impl.clickgui.windows.ModuleWindow +import com.lambda.gui.impl.hudgui.LambdaHudGui +import com.lambda.module.HudModule +import com.lambda.module.Module import com.lambda.module.ModuleRegistry import com.lambda.module.tag.ModuleTag @@ -9,6 +12,10 @@ class TagWindow( val tag: ModuleTag, owner: AbstractClickGui, ) : ModuleWindow(tag.name, gui = owner) { + val isHudWindow = gui is LambdaHudGui + private val rawFilter = { m: Module -> m is HudModule } + private val filter get() = if (isHudWindow) rawFilter else { m: Module -> !rawFilter(m) } + override fun getModuleList() = ModuleRegistry.modules - .filter { it.defaultTags.firstOrNull() == tag } + .filter { it.defaultTags.firstOrNull() == tag && filter(it) } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/HudModule.kt b/common/src/main/kotlin/com/lambda/module/HudModule.kt index 41bd9fc02..265a31953 100644 --- a/common/src/main/kotlin/com/lambda/module/HudModule.kt +++ b/common/src/main/kotlin/com/lambda/module/HudModule.kt @@ -3,10 +3,9 @@ package com.lambda.module import com.lambda.event.events.RenderEvent import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.gui.api.RenderLayer +import com.lambda.gui.api.component.core.DockingRect import com.lambda.module.tag.ModuleTag import com.lambda.util.KeyCode -import com.lambda.util.math.MathUtils.coerceIn -import com.lambda.util.math.Rect import com.lambda.util.math.Vec2d abstract class HudModule( @@ -21,45 +20,39 @@ abstract class HudModule( protected abstract val width: Double protected abstract val height: Double - private val size get() = Vec2d(width, height) - private var relativePosX by setting("Position X", 0.0, -10000.0..10000.0, 0.1) { false } - private var relativePosY by setting("Position Y", 0.0, -10000.0..10000.0, 0.1) { false } - private var relativePos get() = Vec2d(relativePosX, relativePosY) - set(value) { relativePosX = value.x; relativePosY = value.y } + private val rectHandler = object : DockingRect() { + private var relativePosX by setting("Position X", 0.0, -10000.0..10000.0, 0.1) { false } + private var relativePosY by setting("Position Y", 0.0, -10000.0..10000.0, 0.1) { false } + override var relativePos get() = Vec2d(relativePosX, relativePosY); set(value) { relativePosX = value.x; relativePosY = value.y } - var position - get() = relativeToAbs(relativePos).coerceIn(0.0, screenSize.x - width, 0.0, screenSize.y - height) - set(value) { relativePos = absToRelative(value); if (autoDocking) autoDocking() } + override val width get() = this@HudModule.width + override val height get() = this@HudModule.height - private val dockingOffset get() = (screenSize - size) * Vec2d(dockingH.multiplier, dockingV.multiplier) - - private fun relativeToAbs(posIn: Vec2d) = posIn + dockingOffset - private fun absToRelative(posIn: Vec2d) = posIn - dockingOffset - - private val autoDocking by setting("Auto Docking", true).apply { - onValueChange { _, _ -> - autoDocking() + override val autoDocking by setting("Auto Docking", true).apply { + onValueChange { _, _ -> + autoDocking() + } } - } - private var dockingH by setting("Docking H", HAlign.LEFT) { !autoDocking }.apply { - onValueChange { from, to -> - val delta = to.multiplier - from.multiplier - relativePosX += delta * (size.x - screenSize.x) + override var dockingH by setting("Docking H", HAlign.LEFT) { !autoDocking }.apply { + onValueChange { from, to -> + val delta = to.multiplier - from.multiplier + relativePosX += delta * (size.x - screenSize.x) + } } - } - private var dockingV by setting("Docking V", VAlign.TOP) { !autoDocking }.apply { - onValueChange { from, to -> - val delta = to.multiplier - from.multiplier - relativePosY += delta * (size.y - screenSize.y) + override var dockingV by setting("Docking V", VAlign.TOP) { !autoDocking }.apply { + onValueChange { from, to -> + val delta = to.multiplier - from.multiplier + relativePosY += delta * (size.y - screenSize.y) + } } } - val rect get() = Rect.basedOn(position, width, height) + var position by rectHandler::position + val rect by rectHandler::rect - private var screenSize = Vec2d.ZERO private val renderer = RenderLayer() protected fun onRender(block: RenderLayer.() -> Unit) = @@ -67,7 +60,7 @@ abstract class HudModule( init { listener { event -> - screenSize = event.screenSize + rectHandler.screenSize = event.screenSize renderCallables.forEach { function -> function.invoke(renderer) @@ -76,35 +69,4 @@ abstract class HudModule( renderer.render() } } - - private fun autoDocking() { - val screenCenterX = (screenSize.x * 0.3333)..(screenSize.x * 0.6666) - val screenCenterY = (screenSize.y * 0.3333)..(screenSize.y * 0.6666) - - val drawableCenter = rect.center - - dockingH = when { - drawableCenter.x < screenCenterX.start -> HAlign.LEFT - drawableCenter.x > screenCenterX.endInclusive -> HAlign.RIGHT - else -> HAlign.CENTER - } - - dockingV = when { - drawableCenter.y < screenCenterY.start -> VAlign.TOP - drawableCenter.y > screenCenterY.endInclusive -> VAlign.BOTTOM - else -> VAlign.CENTER - } - } - - enum class HAlign(val multiplier: Float) { - LEFT(0.0f), - CENTER(0.5f), - RIGHT(1.0f) - } - - enum class VAlign(val multiplier: Float) { - TOP(0.0f), - CENTER(0.5f), - BOTTOM(1.0f) - } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt index 708cf389d..c2255aa9f 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt @@ -27,6 +27,10 @@ object ClickGui : Module( val openSpeed by setting("Open Speed", 0.5, 0.1..1.0, 0.01) val closeSpeed by setting("Close Speed", 0.5, 0.1..1.0, 0.01) + // Alignment + val allowHAlign by setting("Allow H Docking", false) + val allowVAlign by setting("Allow V Docking", true) + init { onEnable { LambdaClickGui.show() diff --git a/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt b/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt index 966d59c95..fe6e58320 100644 --- a/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt +++ b/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt @@ -28,7 +28,7 @@ data class Vec2d(val x: Double, val y: Double) { val LEFT = Vec2d(-1.0, 0.0) val RIGHT = Vec2d(1.0, 0.0) - val TOP = Vec2d(0.0, 1.0) - val BOTTOM = Vec2d(0.0, -1.0) + val TOP = Vec2d(0.0, -1.0) + val BOTTOM = Vec2d(0.0, 1.0) } } From 90c92a15525b6e8ad0f7b0ce0cb8aaf542251f14 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sat, 6 Jul 2024 12:55:41 +0300 Subject: [PATCH 05/35] No vertex caching for custom static esp --- .../lambda/graphics/renderer/esp/global/StaticESP.kt | 2 +- .../graphics/renderer/esp/impl/StaticESPRenderer.kt | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/global/StaticESP.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/global/StaticESP.kt index 79733d92f..454d624b9 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/global/StaticESP.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/global/StaticESP.kt @@ -7,7 +7,7 @@ import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.graphics.buffer.vao.vertex.BufferUsage import com.lambda.graphics.renderer.esp.impl.StaticESPRenderer -object StaticESP : StaticESPRenderer(BufferUsage.DYNAMIC) { +object StaticESP : StaticESPRenderer(BufferUsage.DYNAMIC, false) { init { listener { clear() diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/StaticESPRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/StaticESPRenderer.kt index 0817f17e8..26c7c9140 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/StaticESPRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/StaticESPRenderer.kt @@ -6,7 +6,8 @@ import java.awt.Color import java.util.concurrent.ConcurrentHashMap open class StaticESPRenderer( - usage: BufferUsage = BufferUsage.STATIC + usage: BufferUsage = BufferUsage.STATIC, + private val useVertexCaching: Boolean = true, ) : ESPRenderer(usage, false) { val faceVertices = ConcurrentHashMap() val outlineVertices = ConcurrentHashMap() @@ -37,9 +38,10 @@ open class StaticESPRenderer( x: Double, y: Double, z: Double, color: Color ) = lazy { - storage.getOrPut(Vertex(x, y, z, color)) { - vec3(x, y, z).color(color).end() - } + val vtx = { vec3(x, y, z).color(color).end() } + if (!useVertexCaching) return@lazy vtx() + + storage.getOrPut(Vertex(x, y, z, color), vtx) } data class Vertex(val x: Double, val y: Double, val z: Double, val color: Color) From 45f689db6c452a74022cffda1130f397530750bb Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Mon, 8 Jul 2024 18:48:15 +0300 Subject: [PATCH 06/35] Docking grid --- .../com/lambda/gui/api/component/core/DockingRect.kt | 6 ++++-- .../gui/impl/clickgui/buttons/setting/NumberSlider.kt | 2 +- .../kotlin/com/lambda/module/modules/client/ClickGui.kt | 1 + common/src/main/kotlin/com/lambda/util/math/MathUtils.kt | 8 ++++++++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt b/common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt index 909629e65..87c9a0cac 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/component/core/DockingRect.kt @@ -1,6 +1,8 @@ package com.lambda.gui.api.component.core +import com.lambda.module.modules.client.ClickGui import com.lambda.util.math.MathUtils.coerceIn +import com.lambda.util.math.MathUtils.roundToStep import com.lambda.util.math.Rect import com.lambda.util.math.Vec2d @@ -35,9 +37,9 @@ abstract class DockingRect { var screenSize: Vec2d = Vec2d.ZERO - var position + var position: Vec2d get() = relativeToAbs(relativePos).coerceIn(0.0, screenSize.x - size.x, 0.0, screenSize.y - size.y) - set(value) { relativePos = absToRelative(value); if (autoDocking) autoDocking() } + set(value) { relativePos = absToRelative(value.roundToStep(ClickGui.dockingGridSize)); if (autoDocking) autoDocking() } private val dockingOffset get() = (screenSize - size) * Vec2d(dockingH.multiplier, dockingV.multiplier) diff --git a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/setting/NumberSlider.kt b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/setting/NumberSlider.kt index 859464aac..b4b3ca532 100644 --- a/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/setting/NumberSlider.kt +++ b/common/src/main/kotlin/com/lambda/gui/impl/clickgui/buttons/setting/NumberSlider.kt @@ -38,7 +38,7 @@ class NumberSlider( } } - override fun getText() = "$setting" + override fun getText() = "$setting".replace(',', '.') // "0,0".toDouble() is null override fun setStringValue(string: String) { string.toDoubleOrNull()?.let(::setValue) } diff --git a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt index c2255aa9f..165dd1768 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt @@ -30,6 +30,7 @@ object ClickGui : Module( // Alignment val allowHAlign by setting("Allow H Docking", false) val allowVAlign by setting("Allow V Docking", true) + val dockingGridSize by setting("Docking Grid Size", 1.0, 0.0..20.0, 0.5) init { onEnable { diff --git a/common/src/main/kotlin/com/lambda/util/math/MathUtils.kt b/common/src/main/kotlin/com/lambda/util/math/MathUtils.kt index 8ef87927b..24ca4e575 100644 --- a/common/src/main/kotlin/com/lambda/util/math/MathUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/math/MathUtils.kt @@ -1,10 +1,13 @@ package com.lambda.util.math import com.lambda.interaction.rotation.Rotation +import com.lambda.module.modules.client.ClickGui import com.lambda.util.math.ColorUtils.a import com.lambda.util.math.ColorUtils.b import com.lambda.util.math.ColorUtils.g import com.lambda.util.math.ColorUtils.r +import com.lambda.util.math.MathUtils.roundToStep +import net.fabricmc.loader.impl.lib.sat4j.core.Vec import net.minecraft.util.math.Vec3d import java.awt.Color import java.math.BigDecimal @@ -33,6 +36,8 @@ object MathUtils { fun T.roundToStep(step: T): T { val stepD = step.toDouble() + if (stepD == 0.0) return this + var value = round(toDouble() / stepD) * stepD value = value.roundToPlaces(decimalPlaces(stepD)) if (abs(value) == 0.0) value = 0.0 @@ -40,6 +45,9 @@ object MathUtils { return typeConvert(value) } + fun Vec2d.roundToStep(step: Double): Vec2d = + Vec2d(x.roundToStep(step), y.roundToStep(step)) + fun Double.roundToPlaces(places: Int) = BigDecimal(this).setScale(places, RoundingMode.HALF_EVEN).toDouble() From cfe04d48bf993fde44e57b7836fccb925365f4ac Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Tue, 9 Jul 2024 18:30:13 +0300 Subject: [PATCH 07/35] Travel events --- .../lambda/mixin/entity/LivingEntityMixin.java | 16 ++++++++++++++++ .../com/lambda/event/events/MovementEvent.kt | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/common/src/main/java/com/lambda/mixin/entity/LivingEntityMixin.java b/common/src/main/java/com/lambda/mixin/entity/LivingEntityMixin.java index 8a8dbbc8b..c1f2dc801 100644 --- a/common/src/main/java/com/lambda/mixin/entity/LivingEntityMixin.java +++ b/common/src/main/java/com/lambda/mixin/entity/LivingEntityMixin.java @@ -45,6 +45,22 @@ void onJump(CallbackInfo ci) { self.velocityDirty = true; } + @Inject(method = "travel", at = @At("HEAD"), cancellable = true) + void onTravelPre(Vec3d movementInput, CallbackInfo ci) { + LivingEntity self = (LivingEntity) (Object) this; + if (self != Lambda.getMc().player) return; + + if (EventFlow.post(new MovementEvent.Travel.Pre()).isCanceled()) ci.cancel(); + } + + @Inject(method = "travel", at = @At("TAIL")) + void onTravelPost(Vec3d movementInput, CallbackInfo ci) { + LivingEntity self = (LivingEntity) (Object) this; + if (self != Lambda.getMc().player) return; + + EventFlow.post(new MovementEvent.Travel.Post()); + } + @Redirect(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getPitch()F")) private float hookModifyFallFlyingPitch(LivingEntity entity) { Float pitch = RotationManager.getMovementPitch(); diff --git a/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt b/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt index 543074557..4087c26eb 100644 --- a/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/MovementEvent.kt @@ -9,6 +9,11 @@ abstract class MovementEvent : Event { class Pre : MovementEvent() class Post : MovementEvent() + abstract class Travel : MovementEvent() { + class Pre : MovementEvent(), ICancellable by Cancellable() + class Post : MovementEvent() + } + class InputUpdate( val input: Input, var slowDown: Boolean, From 5c258b8ede45a3df92f1a7aeb7e76d44ea739892 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Tue, 9 Jul 2024 22:29:48 +0300 Subject: [PATCH 08/35] TargetStrafe --- .../lambda/mixin/input/KeyBindingMixin.java | 2 + .../lambda/module/modules/movement/Speed.kt | 19 ++- .../module/modules/movement/TargetStrafe.kt | 114 ++++++++++++++++++ .../com/lambda/util/player/MovementUtils.kt | 31 +++++ 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt diff --git a/common/src/main/java/com/lambda/mixin/input/KeyBindingMixin.java b/common/src/main/java/com/lambda/mixin/input/KeyBindingMixin.java index 224513f02..eb0e87ae6 100644 --- a/common/src/main/java/com/lambda/mixin/input/KeyBindingMixin.java +++ b/common/src/main/java/com/lambda/mixin/input/KeyBindingMixin.java @@ -2,6 +2,7 @@ import com.lambda.module.modules.movement.Speed; import com.lambda.module.modules.movement.Sprint; +import com.lambda.module.modules.movement.TargetStrafe; import net.minecraft.client.option.KeyBinding; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -19,5 +20,6 @@ void autoSprint(CallbackInfoReturnable cir) { if (Sprint.INSTANCE.isEnabled()) cir.setReturnValue(true); if (Speed.INSTANCE.isEnabled() && Speed.getMode() == Speed.Mode.GRIM_STRAFE) cir.setReturnValue(true); + if (TargetStrafe.INSTANCE.isEnabled() && TargetStrafe.isActive()) cir.setReturnValue(true); } } diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt index 3cc3e2dc4..4517a2213 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt @@ -13,9 +13,11 @@ import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.util.Nameable import com.lambda.util.player.MovementUtils.addSpeed +import com.lambda.util.player.MovementUtils.buildMovementInput import com.lambda.util.player.MovementUtils.calcMoveYaw import com.lambda.util.player.MovementUtils.handledByBaritone import com.lambda.util.player.MovementUtils.isInputting +import com.lambda.util.player.MovementUtils.mergeFrom import com.lambda.util.player.MovementUtils.motionY import com.lambda.util.player.MovementUtils.moveDelta import com.lambda.util.player.MovementUtils.newMovementInput @@ -25,6 +27,7 @@ import com.lambda.util.player.MovementUtils.setSpeed import com.lambda.util.primitives.extension.contains import com.lambda.util.world.WorldUtils.getFastEntities import net.minecraft.entity.LivingEntity +import net.minecraft.entity.decoration.ArmorStandEntity import net.minecraft.entity.vehicle.BoatEntity object Speed : Module( @@ -110,7 +113,7 @@ object Speed : Module( listener { event -> if (mode != Mode.GRIM_STRAFE) return@listener if (!shouldWork() || !isInputting) return@listener - if (player.input.handledByBaritone) return@listener + if (player.input.handledByBaritone || TargetStrafe.isActive) return@listener val input = newMovementInput() val yaw = calcMoveYaw(player.yaw, input.roundedForward, input.roundedStrafing) @@ -119,6 +122,18 @@ object Speed : Module( event.context = RotationContext(rotation, rotationConfig) } + listener { event -> + if (mode != Mode.GRIM_STRAFE) return@listener + if (!shouldWork() || !isInputting) return@listener + if (player.input.handledByBaritone || TargetStrafe.isActive) return@listener + + event.input.mergeFrom( + buildMovementInput( + 1.0, 0.0, event.input.jumping, event.input.sneaking + ) + ) + } + onEnable { reset() } @@ -131,7 +146,7 @@ object Speed : Module( getFastEntities( player.pos, 3.0, - predicate = { player.boundingBox.expand(1.0) in it.boundingBox }, + predicate = { player.boundingBox.expand(1.0) in it.boundingBox && it !is ArmorStandEntity }, iterator = { e, _ -> val colliding = player.boundingBox in e.boundingBox val multiplier = if (colliding) grimCollideMultiplier else 1.0 diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt new file mode 100644 index 000000000..e818935ff --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt @@ -0,0 +1,114 @@ +package com.lambda.module.modules.movement + +import com.lambda.config.groups.IRotationConfig +import com.lambda.event.events.MovementEvent +import com.lambda.event.events.RotationEvent +import com.lambda.event.events.TickEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.interaction.rotation.Rotation.Companion.rotationTo +import com.lambda.interaction.rotation.RotationContext +import com.lambda.interaction.rotation.RotationMode +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import com.lambda.util.math.VecUtils.distSq +import com.lambda.util.player.MovementUtils.buildMovementInput +import com.lambda.util.player.MovementUtils.mergeFrom +import com.lambda.util.world.WorldUtils.getClosestEntity +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.decoration.ArmorStandEntity +import kotlin.math.pow + +object TargetStrafe : Module( + name = "TargetStrafe", + description = "Automatically strafes around entities", + defaultTags = setOf(ModuleTag.MOVEMENT) +) { + private val range by setting("Range", 6.0, 2.0..10.0, 0.5) + private val targetDistance by setting("Target Distance", 1.0, 0.0..5.0, 0.5) + private val jitterCompensation by setting("Jitter Compensation", 0.0, 0.0..1.0, 0.1) + private val stabilize by setting("Stabilize", StabilizationMode.NORMAL) + + enum class StabilizationMode { + NONE, WEAK, NORMAL, STRONG + } + + private var targetEntity: LivingEntity? = null + + private var forwardDirection = 1 + private var strafeDirection = 1 + + private val rotationConfig = object : IRotationConfig.Instant { + override val rotationMode = RotationMode.SYNC + } + + @JvmStatic val isActive get() = targetEntity != null + + init { + listener { + // ToDo: Use KillAura.target instead + targetEntity = getClosestEntity( + player.pos, range, + predicate = { e -> e !is ArmorStandEntity } + ) + + if (player.horizontalCollision) strafeDirection *= -1 + + if (targetEntity == null) { + forwardDirection = 1 + strafeDirection = 1 + } + } + + listener { event -> + targetEntity?.let { + event.strafeYaw = player.eyePos.rotationTo(it.boundingBox.center).yaw + } + } + + listener { event -> + targetEntity?.let { + event.context = RotationContext( + player.eyePos.rotationTo(it.boundingBox.center), + rotationConfig + ) + } + } + + listener { event -> + targetEntity?.let { target -> + val distSq = player.pos distSq target.pos + val keepRange = 0.5 * jitterCompensation + + forwardDirection = when { + distSq > (targetDistance + keepRange).pow(2) -> 1 + distSq < (targetDistance - keepRange).pow(2) -> -1 + else -> forwardDirection + } + + val shouldStabilize = when (stabilize) { + StabilizationMode.NONE -> false + StabilizationMode.WEAK -> player.age % 3 == 0 + StabilizationMode.NORMAL -> player.age % 2 == 0 + StabilizationMode.STRONG -> true + } + + var strafe = strafeDirection.toDouble() + if (shouldStabilize && distSq > (targetDistance + 0.5).pow(2)) strafe = 0.0 + + event.input.mergeFrom( + buildMovementInput( + forwardDirection.toDouble(), + strafe, + true + ) + ) + } + } + + onEnable { + targetEntity = null + forwardDirection = 1 + strafeDirection = 1 + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt b/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt index 28a218ad9..7186654bc 100644 --- a/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/player/MovementUtils.kt @@ -41,6 +41,37 @@ object MovementUtils { } } + fun buildMovementInput( + forward: Double, + strafe: Double, + jump: Boolean = false, + sneak: Boolean = false + ) = Input().apply { + movementForward = forward.toFloat() + movementSideways = strafe.toFloat() + + pressingForward = forward > 0.0 + pressingBack = forward < 0.0 + pressingLeft = strafe < 0.0 + pressingRight = strafe > 0.0 + + jumping = jump + sneaking = sneak + } + + fun Input.mergeFrom(input: Input) { + movementForward = input.movementForward + movementSideways = input.movementSideways + + pressingForward = input.pressingForward + pressingBack = input.pressingBack + pressingLeft = input.pressingLeft + pressingRight = input.pressingRight + + jumping = input.jumping + sneaking = input.sneaking + } + fun Input.cancel(cancelVertical: Boolean = true) { movementForward = 0f movementSideways = 0f From b1ca0d8cade764edadfa4d8ef3c14add9932a717 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Wed, 10 Jul 2024 13:15:23 +0300 Subject: [PATCH 09/35] TargetStrafe improvements --- .../com/lambda/module/modules/movement/Speed.kt | 2 ++ .../module/modules/movement/TargetStrafe.kt | 17 ++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt index 4517a2213..545233d1c 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt @@ -45,6 +45,7 @@ object Speed : Module( private val grimEntityBoost by setting("Entity Boost", 1.0, 0.0..2.0, 0.01) { mode == Mode.GRIM_STRAFE } private val grimCollideMultiplier by setting("Entity Collide Multiplier", 0.5, 0.0..1.0, 0.01) { mode == Mode.GRIM_STRAFE && grimEntityBoost > 0.0} private val grimBoatBoost by setting("Boat Boost", 0.4, 0.0..1.0, 0.01) { mode == Mode.GRIM_STRAFE } + private val grimMaxSpeed by setting("Max Speed", 1.0, 0.2..1.0, 0.01) { mode == Mode.GRIM_STRAFE } // NCP private val strict by setting("Strict", true) { mode == Mode.NCP_STRAFE } @@ -141,6 +142,7 @@ object Speed : Module( private fun SafeContext.handleGrim() { if (!isInputting) return + if (player.moveDelta > grimMaxSpeed) return var boostAmount = 0.0 diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt index e818935ff..382f5c17a 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt @@ -23,8 +23,8 @@ object TargetStrafe : Module( description = "Automatically strafes around entities", defaultTags = setOf(ModuleTag.MOVEMENT) ) { - private val range by setting("Range", 6.0, 2.0..10.0, 0.5) - private val targetDistance by setting("Target Distance", 1.0, 0.0..5.0, 0.5) + private val range by setting("Range", 6.0, 2.0..10.0, 0.1) + private val targetDistance by setting("Target Distance", 1.0, 0.0..5.0, 0.1) private val jitterCompensation by setting("Jitter Compensation", 0.0, 0.0..1.0, 0.1) private val stabilize by setting("Stabilize", StabilizationMode.NORMAL) @@ -85,15 +85,18 @@ object TargetStrafe : Module( else -> forwardDirection } - val shouldStabilize = when (stabilize) { + // Premium code, do not touch it bites + var shouldStabilize = when (stabilize) { StabilizationMode.NONE -> false - StabilizationMode.WEAK -> player.age % 3 == 0 - StabilizationMode.NORMAL -> player.age % 2 == 0 - StabilizationMode.STRONG -> true + StabilizationMode.WEAK -> player.age % 4 == 0 // 1/4 + StabilizationMode.NORMAL -> player.age % 2 == 0 // 2/4 + StabilizationMode.STRONG -> player.age % 4 != 0 // 3/4 } + shouldStabilize = shouldStabilize && distSq > (targetDistance + 0.5).pow(2) + var strafe = strafeDirection.toDouble() - if (shouldStabilize && distSq > (targetDistance + 0.5).pow(2)) strafe = 0.0 + if (shouldStabilize) strafe = 0.0 event.input.mergeFrom( buildMovementInput( From 13921018b9c50435700c15fbd49afd1118638f4d Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Wed, 10 Jul 2024 19:10:55 +0300 Subject: [PATCH 10/35] Matrices premuliplying --- .../lambda/graphics/buffer/vao/IRenderContext.kt | 6 ++++++ .../kotlin/com/lambda/graphics/buffer/vao/VAO.kt | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt index cf849d16b..ab3e41419 100644 --- a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt +++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt @@ -1,10 +1,16 @@ package com.lambda.graphics.buffer.vao +import com.lambda.graphics.gl.Matrices +import org.joml.Matrix4f import java.awt.Color interface IRenderContext { fun vec3(x: Double, y: Double, z: Double): IRenderContext fun vec2(x: Double, y: Double): IRenderContext + + fun vec3m(x: Double, y: Double, z: Double, matrix4f: Matrix4f = Matrices.peek()): IRenderContext + fun vec2m(x: Double, y: Double, matrix4f: Matrix4f = Matrices.peek()): IRenderContext + fun float(v: Double): IRenderContext fun color(color: Color): IRenderContext fun end(): Int diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt index af6050689..7acb83097 100644 --- a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt +++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt @@ -21,6 +21,7 @@ import com.lambda.graphics.gl.VaoUtils.unbindIndexBuffer import com.lambda.graphics.gl.VaoUtils.unbindVertexArray import com.lambda.graphics.gl.VaoUtils.unbindVertexBuffer import com.lambda.threading.runGameScheduled +import org.joml.* import org.lwjgl.opengl.GL30C.* import java.awt.Color import java.nio.ByteBuffer @@ -88,6 +89,19 @@ class VAO( return this } + override fun vec3m(x: Double, y: Double, z: Double, matrix4f: Matrix4f): IRenderContext { + // ToDo: optimize at runtime + val vec = Vector4d(x, y, z, 1.0).apply(Matrix4d(matrix4f)::transform) + verticesPosition += vec3(verticesPosition, vec.x, vec.y, vec.z) + return this + } + + override fun vec2m(x: Double, y: Double, matrix4f: Matrix4f): IRenderContext { + val vec = Vector4d(x, y, 0.0, 1.0).apply(Matrix4d(matrix4f)::transform) + verticesPosition += vec2(verticesPosition, vec.x, vec.y) + return this + } + override fun float(v: Double): VAO { verticesPosition += float(verticesPosition, v) return this From 47929ff8200e0a92aa5684a5652e4c3affd4155c Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Thu, 11 Jul 2024 19:20:20 +0300 Subject: [PATCH 11/35] Projection, Particles, Speed fixes --- .../ClientPlayInteractionManagerMixin.java | 14 ++ .../com/lambda/event/events/AttackEvent.kt | 11 ++ .../graphics/buffer/vao/IRenderContext.kt | 6 +- .../com/lambda/graphics/buffer/vao/VAO.kt | 19 +- .../buffer/vao/vertex/VertexAttrib.kt | 6 +- .../kotlin/com/lambda/graphics/gl/Matrices.kt | 19 ++ .../renderer/gui/font/FontRenderer.kt | 8 +- .../renderer/gui/rect/FilledRectRenderer.kt | 8 +- .../renderer/gui/rect/OutlineRectRenderer.kt | 2 +- .../lambda/module/modules/movement/Speed.kt | 12 -- .../module/modules/movement/TargetStrafe.kt | 2 +- .../lambda/module/modules/render/Particles.kt | 171 ++++++++++++++++++ .../shaders/fragment/renderer/particle.frag | 11 ++ .../shaders/vertex/renderer/particle.vert | 19 ++ 14 files changed, 273 insertions(+), 35 deletions(-) create mode 100644 common/src/main/kotlin/com/lambda/event/events/AttackEvent.kt create mode 100644 common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt create mode 100644 common/src/main/resources/assets/lambda/shaders/fragment/renderer/particle.frag create mode 100644 common/src/main/resources/assets/lambda/shaders/vertex/renderer/particle.vert diff --git a/common/src/main/java/com/lambda/mixin/entity/ClientPlayInteractionManagerMixin.java b/common/src/main/java/com/lambda/mixin/entity/ClientPlayInteractionManagerMixin.java index 03da40258..b04d46a98 100644 --- a/common/src/main/java/com/lambda/mixin/entity/ClientPlayInteractionManagerMixin.java +++ b/common/src/main/java/com/lambda/mixin/entity/ClientPlayInteractionManagerMixin.java @@ -1,10 +1,13 @@ package com.lambda.mixin.entity; import com.lambda.event.EventFlow; +import com.lambda.event.events.AttackEvent; import com.lambda.event.events.InteractionEvent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; @@ -13,6 +16,7 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ClientPlayerInteractionManager.class) @@ -27,4 +31,14 @@ public void interactBlockHead(final ClientPlayerEntity player, final Hand hand, if (client.world == null) return; EventFlow.post(new InteractionEvent.Block(client.world, hitResult)); } + + @Inject(method = "attackEntity", at = @At("HEAD"), cancellable = true) + void onAttackPre(PlayerEntity player, Entity target, CallbackInfo ci) { + if (EventFlow.post(new AttackEvent.Pre(target)).isCanceled()) ci.cancel(); + } + + @Inject(method = "attackEntity", at = @At("TAIL")) + void onAttackPost(PlayerEntity player, Entity target, CallbackInfo ci) { + EventFlow.post(new AttackEvent.Post(target)); + } } diff --git a/common/src/main/kotlin/com/lambda/event/events/AttackEvent.kt b/common/src/main/kotlin/com/lambda/event/events/AttackEvent.kt new file mode 100644 index 000000000..c72f93b07 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/event/events/AttackEvent.kt @@ -0,0 +1,11 @@ +package com.lambda.event.events + +import com.lambda.event.Event +import com.lambda.event.callback.Cancellable +import com.lambda.event.callback.ICancellable +import net.minecraft.entity.Entity + +abstract class AttackEvent(val entity: Entity) : Event { + class Pre(entity: Entity) : AttackEvent(entity), ICancellable by Cancellable() + class Post(entity: Entity) : AttackEvent(entity) +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt index ab3e41419..df8765038 100644 --- a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt +++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/IRenderContext.kt @@ -1,15 +1,13 @@ package com.lambda.graphics.buffer.vao -import com.lambda.graphics.gl.Matrices -import org.joml.Matrix4f import java.awt.Color interface IRenderContext { fun vec3(x: Double, y: Double, z: Double): IRenderContext fun vec2(x: Double, y: Double): IRenderContext - fun vec3m(x: Double, y: Double, z: Double, matrix4f: Matrix4f = Matrices.peek()): IRenderContext - fun vec2m(x: Double, y: Double, matrix4f: Matrix4f = Matrices.peek()): IRenderContext + fun vec3m(x: Double, y: Double, z: Double): IRenderContext + fun vec2m(x: Double, y: Double): IRenderContext fun float(v: Double): IRenderContext fun color(color: Color): IRenderContext diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt index 7acb83097..b6cb584cc 100644 --- a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt +++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/VAO.kt @@ -3,6 +3,7 @@ package com.lambda.graphics.buffer.vao import com.lambda.graphics.buffer.vao.vertex.BufferUsage import com.lambda.graphics.buffer.vao.vertex.VertexAttrib import com.lambda.graphics.buffer.vao.vertex.VertexMode +import com.lambda.graphics.gl.Matrices import com.lambda.graphics.gl.Memory.address import com.lambda.graphics.gl.Memory.byteBuffer import com.lambda.graphics.gl.Memory.capacity @@ -89,16 +90,20 @@ class VAO( return this } - override fun vec3m(x: Double, y: Double, z: Double, matrix4f: Matrix4f): IRenderContext { - // ToDo: optimize at runtime - val vec = Vector4d(x, y, z, 1.0).apply(Matrix4d(matrix4f)::transform) - verticesPosition += vec3(verticesPosition, vec.x, vec.y, vec.z) + override fun vec3m(x: Double, y: Double, z: Double): IRenderContext { + Matrices.vertexTransformer?.let { mat -> + val vec = Vector4d(x, y, z, 1.0).apply(mat::transform) + vec3(vec.x, vec.y, vec.z) + } ?: vec3(x, y, z) + return this } - override fun vec2m(x: Double, y: Double, matrix4f: Matrix4f): IRenderContext { - val vec = Vector4d(x, y, 0.0, 1.0).apply(Matrix4d(matrix4f)::transform) - verticesPosition += vec2(verticesPosition, vec.x, vec.y) + override fun vec2m(x: Double, y: Double): IRenderContext { + Matrices.vertexTransformer?.let { mat -> + val vec = Vector4d(x, y, 0.0, 1.0).apply(mat::transform) + vec2(vec.x, vec.y) + } ?: vec2(x, y) return this } diff --git a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/vertex/VertexAttrib.kt b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/vertex/VertexAttrib.kt index 752e12293..399416eac 100644 --- a/common/src/main/kotlin/com/lambda/graphics/buffer/vao/vertex/VertexAttrib.kt +++ b/common/src/main/kotlin/com/lambda/graphics/buffer/vao/vertex/VertexAttrib.kt @@ -16,13 +16,15 @@ enum class VertexAttrib(val componentCount: Int, componentSize: Int, val normali POS_UV(Vec2, Vec2), // GUI - FONT(Vec2, Vec2, Color), // pos, uv, color + FONT(Vec3, Vec2, Color), // pos, uv, color RECT_FILLED(Vec2, Vec2, Vec2, Float, Float, Color), // pos, uv, size, roundRadius, shade, color RECT_OUTLINE(Vec2, Float, Float, Color), // pos, alpha, shade, color // WORLD DYNAMIC_RENDERER(Vec3, Vec3, Color), // prev pos, pos, color - STATIC_RENDERER(Vec3, Color); // pos, color + STATIC_RENDERER(Vec3, Color), // pos, color + + PARTICLE(Vec3, Vec2, Color); // pos, uv, color val stride = attributes.sumOf { attribute -> attribute.size } } diff --git a/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt b/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt index 245d9dc35..1b515d5fc 100644 --- a/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt +++ b/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt @@ -1,11 +1,16 @@ package com.lambda.graphics.gl +import com.lambda.Lambda.mc +import net.minecraft.util.math.Vec3d +import org.joml.Matrix4d import org.joml.Matrix4f import org.joml.Quaternionf object Matrices { private val stack = ArrayDeque(1) + var vertexTransformer: Matrix4d? = null + fun translate(x: Double, y: Double, z: Double) { translate(x.toFloat(), y.toFloat(), z.toFloat()) } @@ -51,4 +56,18 @@ object Matrices { stack.clear() stack.add(entry) } + + fun withVertexTransform(matrix: Matrix4f, block: () -> Unit) { + vertexTransformer = Matrix4d(matrix) + block() + vertexTransformer = null + } + + fun buildWorldProjection(pos: Vec3d, scale: Double = 1.0) = Matrix4f().apply { + val s = 0.025f * scale.toFloat() + + translate(pos.x.toFloat(), pos.y.toFloat(), pos.z.toFloat()) + rotate(mc.gameRenderer.camera.rotation) + scale(-s, -s, s) + } } diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt index eea207f1b..1155946ad 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/font/FontRenderer.kt @@ -33,10 +33,10 @@ class FontRenderer( iterateText(text, scale, shadow, color) { char, pos1, pos2, color -> grow(4) putQuad( - vec2(pos1.x + position.x, pos1.y + position.y).vec2(char.uv1.x, char.uv1.y).color(color).end(), - vec2(pos1.x + position.x, pos2.y + position.y).vec2(char.uv1.x, char.uv2.y).color(color).end(), - vec2(pos2.x + position.x, pos2.y + position.y).vec2(char.uv2.x, char.uv2.y).color(color).end(), - vec2(pos2.x + position.x, pos1.y + position.y).vec2(char.uv2.x, char.uv1.y).color(color).end() + vec3m(pos1.x + position.x, pos1.y + position.y, 0.0).vec2(char.uv1.x, char.uv1.y).color(color).end(), + vec3m(pos1.x + position.x, pos2.y + position.y, 0.0).vec2(char.uv1.x, char.uv2.y).color(color).end(), + vec3m(pos2.x + position.x, pos2.y + position.y, 0.0).vec2(char.uv2.x, char.uv2.y).color(color).end(), + vec3m(pos2.x + position.x, pos1.y + position.y, 0.0).vec2(char.uv2.x, char.uv1.y).color(color).end() ) } } diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt index 8637e560e..86cee4a31 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt @@ -50,10 +50,10 @@ class FilledRectRenderer : AbstractRectRenderer( grow(4) putQuad( - vec2(p1.x, p1.y).vec2(0.0, 0.0).vec2(size.x, size.y).float(round).float(s).color(leftTop).end(), - vec2(p1.x, p2.y).vec2(0.0, 1.0).vec2(size.x, size.y).float(round).float(s).color(leftBottom).end(), - vec2(p2.x, p2.y).vec2(1.0, 1.0).vec2(size.x, size.y).float(round).float(s).color(rightBottom).end(), - vec2(p2.x, p1.y).vec2(1.0, 0.0).vec2(size.x, size.y).float(round).float(s).color(rightTop).end() + vec2m(p1.x, p1.y).vec2(0.0, 0.0).vec2(size.x, size.y).float(round).float(s).color(leftTop).end(), + vec2m(p1.x, p2.y).vec2(0.0, 1.0).vec2(size.x, size.y).float(round).float(s).color(leftBottom).end(), + vec2m(p2.x, p2.y).vec2(1.0, 1.0).vec2(size.x, size.y).float(round).float(s).color(rightBottom).end(), + vec2m(p2.x, p1.y).vec2(1.0, 0.0).vec2(size.x, size.y).float(round).float(s).color(rightTop).end() ) } diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt index 8e584c61c..f23822ab7 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt @@ -57,7 +57,7 @@ class OutlineRectRenderer : AbstractRectRenderer( val pos = base + Vec2d(cos(angle), -sin(angle)) * round val s = shade.toInt().toDouble() - add(vec2(pos.x, pos.y).float(a).float(s).color(c).end()) + add(vec2m(pos.x, pos.y).float(a).float(s).color(c).end()) } val rt = r.rightTop + Vec2d(-round, round) diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt index 545233d1c..7a41590b9 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt @@ -123,18 +123,6 @@ object Speed : Module( event.context = RotationContext(rotation, rotationConfig) } - listener { event -> - if (mode != Mode.GRIM_STRAFE) return@listener - if (!shouldWork() || !isInputting) return@listener - if (player.input.handledByBaritone || TargetStrafe.isActive) return@listener - - event.input.mergeFrom( - buildMovementInput( - 1.0, 0.0, event.input.jumping, event.input.sneaking - ) - ) - } - onEnable { reset() } diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt index 382f5c17a..0671dab33 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt @@ -41,7 +41,7 @@ object TargetStrafe : Module( override val rotationMode = RotationMode.SYNC } - @JvmStatic val isActive get() = targetEntity != null + @JvmStatic val isActive get() = isEnabled && targetEntity != null init { listener { diff --git a/common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt b/common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt new file mode 100644 index 000000000..5c865ba28 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt @@ -0,0 +1,171 @@ +package com.lambda.module.modules.render + +import com.lambda.event.events.AttackEvent +import com.lambda.event.events.MovementEvent +import com.lambda.event.events.RenderEvent +import com.lambda.event.events.TickEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.graphics.buffer.vao.VAO +import com.lambda.graphics.buffer.vao.vertex.VertexAttrib +import com.lambda.graphics.buffer.vao.vertex.VertexMode +import com.lambda.graphics.gl.GlStateUtils.withBlendFunc +import com.lambda.graphics.gl.GlStateUtils.withDepth +import com.lambda.graphics.gl.Matrices.buildWorldProjection +import com.lambda.graphics.gl.Matrices.withVertexTransform +import com.lambda.graphics.shader.Shader +import com.lambda.module.Module +import com.lambda.module.modules.client.GuiSettings +import com.lambda.module.modules.client.GuiSettings.colorSpeed +import com.lambda.module.tag.ModuleTag +import com.lambda.threading.runSafe +import com.lambda.util.math.ColorUtils.multAlpha +import com.lambda.util.math.MathUtils.lerp +import com.lambda.util.math.MathUtils.random +import com.lambda.util.math.transform +import com.lambda.util.player.MovementUtils.moveDelta +import com.lambda.util.player.MovementUtils.movementVector +import com.lambda.util.player.MovementUtils.randomDirection +import com.lambda.util.primitives.extension.partialTicks +import net.minecraft.entity.Entity +import net.minecraft.util.math.Vec3d + +import org.lwjgl.opengl.GL11.GL_ONE +import org.lwjgl.opengl.GL11.GL_SRC_ALPHA +import kotlin.math.sin + +object Particles : Module( + name = "Particles", + description = "Spawns fancy particles", + defaultTags = setOf(ModuleTag.RENDER) +) { + private val duration by setting("Duration", 5.0, 1.0..500.0, 1.0) + private val fadeDuration by setting("Fade Ticks", 5.0, 1.0..30.0, 1.0) + private val spawnAmount by setting("Spawn Amount", 30.0, 3.0..500.0, 1.0) + private val size by setting("Size", 2.0, 0.1..50.0, 0.1) + private val alphaSetting by setting("Alpha", 1.5, 0.01..2.0, 0.01) + private val speedH by setting("Speed H", 1.0, 0.0..10.0, 0.1) + private val speedV by setting("Speed V", 1.0, 0.0..10.0, 0.1) + private val inertia by setting("Inertia", 0.0, 0.0..1.0, 0.01) + private val gravity by setting("Gravity", 0.2, 0.0..1.0, 0.01) + + private val onMove by setting("On Move", true) + + private var particles = mutableListOf() + private val vao = VAO(VertexMode.TRIANGLES, VertexAttrib.Group.PARTICLE) + private val shader = Shader("renderer/particle", "renderer/particle") + + init { + listener { + particles.forEach(Particle::tick) + particles.removeIf(Particle::shouldRemove) + } + + listener { + // Todo: interpolated tickbased upload? + particles.forEach(Particle::build) + + withBlendFunc(GL_SRC_ALPHA, GL_ONE) { + shader.use() + shader["u_CameraPosition"] = mc.gameRenderer.camera.pos + + vao.upload() + withDepth(vao::render) + vao.clear() + } + } + + listener { event -> + spawnForEntity(event.entity) + } + + listener { + if (!onMove || player.moveDelta < 0.05) return@listener + spawnForEntity(player) + } + } + + private fun spawnForEntity(entity: Entity) { + repeat(spawnAmount.toInt()) { + val i = (it + 1) / spawnAmount + + val pos = entity.pos + val height = entity.boundingBox.lengthY + val spawnHeight = height * transform(i, 0.0, 1.0, 0.2, 0.8) + val particlePos = pos.add(0.0, spawnHeight, 0.0) + + particles.add(Particle(particlePos)) + } + } + + private class Particle(posIn: Vec3d) { + var initTick = 0 + var maxAge = 0 + var fadeTicks = fadeDuration + + var shouldRemove = false + + var prevPos = posIn + var pos = posIn + + var motion: Vec3d = Vec3d.ZERO + + init { + runSafe { + initTick = player.age + maxAge = (duration + random(0.0, 20.0)).toInt() + + + motion = movementVector(randomDirection(), sin(random(0.0, Math.PI))) + .multiply(random(0.0, 1.0), random(0.0, 1.0), random(0.0, 1.0)) + .multiply( + speedH * random(0.9, 1.1), + speedV * random(0.9, 1.1), + speedH * random(0.9, 1.1) + ).multiply(0.1) + } + } + + fun tick() = runSafe { + prevPos = pos + pos = pos.add(motion) + + motion = motion + .subtract(0.0, gravity * 0.01, 0.0) + .multiply(0.9 + inertia * 0.1) + + shouldRemove = player.age - initTick > 5.0 + maxAge + fadeTicks * 2 + } + + fun build() = runSafe { + val age = player.age - initTick + mc.partialTicks + val colorTicks = age * 0.1 / colorSpeed + + val alpha = when { + age < fadeTicks -> age / fadeTicks + age in fadeTicks..fadeTicks + maxAge -> 1.0 + else -> { + val min = fadeTicks + maxAge + val max = fadeTicks * 2 + maxAge + transform(age, min, max, 1.0, 0.0) + } + } * alphaSetting + + val (c1, c2) = GuiSettings.primaryColor to GuiSettings.secondaryColor + val color = lerp(c1, c2, sin(colorTicks) * 0.5 + 0.5).multAlpha(alpha) + + val position = lerp(prevPos, pos, mc.partialTicks) + + withVertexTransform(buildWorldProjection(position, size)) { + vao.use { + grow(4) // DO NOT FUCKING FORGOTEOIJTOWKET TO GROW (cost me an hour) + putQuad( + vec3m(-1.0, -1.0, 0.0).vec2(0.0, 0.0).color(color).end(), + vec3m(-1.0, 1.0, 0.0).vec2(0.0, 1.0).color(color).end(), + vec3m(1.0, 1.0, 0.0).vec2(1.0, 1.0).color(color).end(), + vec3m(1.0, -1.0, 0.0).vec2(1.0, 0.0).color(color).end() + ) + } + } + } + } +} \ No newline at end of file diff --git a/common/src/main/resources/assets/lambda/shaders/fragment/renderer/particle.frag b/common/src/main/resources/assets/lambda/shaders/fragment/renderer/particle.frag new file mode 100644 index 000000000..53b683d85 --- /dev/null +++ b/common/src/main/resources/assets/lambda/shaders/fragment/renderer/particle.frag @@ -0,0 +1,11 @@ +#version 330 core + +in vec2 v_TexCoord; +in vec4 v_Color; + +out vec4 color; + +void main() { + float a = 1.0 - length(v_TexCoord - 0.5) * 2.0; + color = v_Color * vec4(1.0, 1.0, 1.0, a); +} \ No newline at end of file diff --git a/common/src/main/resources/assets/lambda/shaders/vertex/renderer/particle.vert b/common/src/main/resources/assets/lambda/shaders/vertex/renderer/particle.vert new file mode 100644 index 000000000..6e3fed3d9 --- /dev/null +++ b/common/src/main/resources/assets/lambda/shaders/vertex/renderer/particle.vert @@ -0,0 +1,19 @@ +#version 330 core + +layout (location = 0) in vec3 pos; +layout (location = 1) in vec2 uv; +layout (location = 2) in vec4 color; + +uniform mat4 u_ProjModel; +uniform vec3 u_CameraPosition; + +out vec2 v_TexCoord; +out vec4 v_Color; + +#define VERTEX_POSITION pos - u_CameraPosition + +void main() { + gl_Position = u_ProjModel * vec4(VERTEX_POSITION, 1.0); + v_TexCoord = uv; + v_Color = color; +} From e57a6119439c2d437af8808a6a148d0f2cc5b588 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Tue, 16 Jul 2024 13:11:45 +0300 Subject: [PATCH 12/35] Simple jesus --- .../world/BlockCollisionSpliteratorMixin.java | 24 ++++++++++++++++++ .../com/lambda/event/events/WorldEvent.kt | 3 +++ .../lambda/module/modules/movement/Jesus.kt | 25 +++++++++++++++++++ .../main/resources/lambda.mixins.common.json | 1 + 4 files changed, 53 insertions(+) create mode 100644 common/src/main/java/com/lambda/mixin/world/BlockCollisionSpliteratorMixin.java create mode 100644 common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt diff --git a/common/src/main/java/com/lambda/mixin/world/BlockCollisionSpliteratorMixin.java b/common/src/main/java/com/lambda/mixin/world/BlockCollisionSpliteratorMixin.java new file mode 100644 index 000000000..336f9ee14 --- /dev/null +++ b/common/src/main/java/com/lambda/mixin/world/BlockCollisionSpliteratorMixin.java @@ -0,0 +1,24 @@ +package com.lambda.mixin.world; + +import com.google.common.collect.AbstractIterator; +import com.lambda.event.EventFlow; +import com.lambda.event.events.WorldEvent; +import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.BlockCollisionSpliterator; +import net.minecraft.world.BlockView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(BlockCollisionSpliterator.class) +public abstract class BlockCollisionSpliteratorMixin > { + @Redirect(method = "computeNext", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getCollisionShape(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/ShapeContext;)Lnet/minecraft/util/shape/VoxelShape;")) + private VoxelShape collisionShapeRedirect(BlockState instance, BlockView blockView, BlockPos blockPos, ShapeContext shapeContext) { + VoxelShape collisionShape = instance.getCollisionShape(blockView, blockPos, shapeContext); + WorldEvent.Collision event = EventFlow.post(new WorldEvent.Collision(blockPos, instance, collisionShape)); + return event.getShape(); + } +} diff --git a/common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt b/common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt index ffb715aed..f1fab7628 100644 --- a/common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/WorldEvent.kt @@ -7,6 +7,7 @@ import net.minecraft.block.BlockState import net.minecraft.client.world.ClientWorld import net.minecraft.entity.Entity import net.minecraft.util.math.BlockPos +import net.minecraft.util.shape.VoxelShape import net.minecraft.world.chunk.WorldChunk abstract class WorldEvent : Event { @@ -34,4 +35,6 @@ abstract class WorldEvent : Event { class EntitySpawn( val entity: Entity ) : WorldEvent(), ICancellable by Cancellable() + + class Collision(val pos: BlockPos, val state: BlockState, var shape: VoxelShape) : WorldEvent() } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt new file mode 100644 index 000000000..3c11d9901 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt @@ -0,0 +1,25 @@ +package com.lambda.module.modules.movement + +import com.lambda.event.events.WorldEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import net.minecraft.block.Blocks +import net.minecraft.util.shape.VoxelShapes + +object Jesus : Module( + name = "Jesus", + description = "Allows to walk on water", + defaultTags = setOf(ModuleTag.MOVEMENT) +) { + private val waterState by lazy { Blocks.WATER.defaultState } + private val fullShape = VoxelShapes.fullCube() + + init { + listener { event -> + if (event.state == waterState) { + event.shape = fullShape + } + } + } +} \ No newline at end of file diff --git a/common/src/main/resources/lambda.mixins.common.json b/common/src/main/resources/lambda.mixins.common.json index 4a8f53c42..ff8a0378b 100644 --- a/common/src/main/resources/lambda.mixins.common.json +++ b/common/src/main/resources/lambda.mixins.common.json @@ -33,6 +33,7 @@ "render.ScreenHandlerMixin", "render.VertexBufferMixin", "render.WorldRendererMixin", + "world.BlockCollisionSpliteratorMixin", "world.ClientChunkManagerMixin", "world.ClientWorldMixin" ], From 99d4b8f23ea9a165b53ad9cae280b4a4a03e435a Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Tue, 16 Jul 2024 17:13:11 +0300 Subject: [PATCH 13/35] Refactored movement handlers --- .../mixin/entity/ClientPlayerEntityMixin.java | 1 + .../com/lambda/event/events/RotationEvent.kt | 2 +- .../com/lambda/interaction/RotationManager.kt | 56 ++++++++----------- .../module/modules/movement/TargetStrafe.kt | 29 ++++------ 4 files changed, 36 insertions(+), 52 deletions(-) diff --git a/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java b/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java index 1e1ca65da..8dfb2803a 100644 --- a/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java +++ b/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java @@ -55,6 +55,7 @@ void onMove(MovementType movementType, Vec3d movement, CallbackInfo ci) { @Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(ZF)V")) void processMovement(Input input, boolean slowDown, float slowDownFactor) { input.tick(slowDown, slowDownFactor); + RotationManager.BaritoneProcessor.processPlayerMovement(input, slowDown, slowDownFactor); EventFlow.post(new MovementEvent.InputUpdate(input, slowDown, slowDownFactor)); } diff --git a/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt b/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt index bfc1b547c..95f330600 100644 --- a/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/RotationEvent.kt @@ -24,7 +24,7 @@ abstract class RotationEvent : Event { * @property strafeYaw The angle at which the player will move when pressing W * Changing this value will never force the anti cheat to flag you because RotationManager is designed to modify the key input instead */ - class Strafe(var strafeYaw: Double, val input: Input) : RotationEvent() + class StrafeInput(var strafeYaw: Double, val input: Input) : RotationEvent() class Post(val context: RotationContext) : RotationEvent() } diff --git a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt index fe9fb046c..d8149ab46 100644 --- a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt +++ b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt @@ -1,10 +1,8 @@ package com.lambda.interaction import com.lambda.Lambda.mc -import com.lambda.config.groups.IRotationConfig import com.lambda.config.groups.RotationSettings import com.lambda.core.Loadable -import com.lambda.context.SafeContext import com.lambda.event.EventFlow.post import com.lambda.event.events.* import com.lambda.event.listener.SafeListener.Companion.listener @@ -20,19 +18,17 @@ import com.lambda.threading.runSafe import com.lambda.util.math.MathUtils.lerp import com.lambda.util.math.MathUtils.toRadian import com.lambda.util.math.Vec2d -import com.lambda.util.player.MovementUtils.handledByBaritone import com.lambda.util.primitives.extension.partialTicks import com.lambda.util.primitives.extension.rotation +import net.minecraft.client.input.Input import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket -import net.minecraft.util.math.MathHelper -import kotlin.math.roundToInt -import kotlin.math.sign +import kotlin.math.* object RotationManager : Loadable { var currentRotation = Rotation.ZERO var prevRotation = Rotation.ZERO - var currentContext: RotationContext? = null + private var currentContext: RotationContext? = null private var keepTicks = 0 private var pauseTicks = 0 @@ -175,12 +171,6 @@ object RotationManager : Loadable { 270.0, 315.0, ) - init { - listener(Int.MAX_VALUE) { - processPlayerMovement(it) - } - } - @JvmStatic fun handleBaritoneRotation(yaw: Float, pitch: Float) { baritoneContext = RotationContext(Rotation(yaw, pitch), Baritone.rotation.apply { @@ -189,47 +179,45 @@ object RotationManager : Loadable { }) } - private fun SafeContext.processPlayerMovement(event: MovementEvent.InputUpdate) { - val config = currentContext?.config ?: return + @JvmStatic + fun processPlayerMovement(input: Input, slowDown: Boolean, slowDownFactor: Float) = runSafe { + // The yaw relative to which the movement was constructed + val baritoneYaw = baritoneContext?.rotation?.yaw + val strafeEvent = RotationEvent.StrafeInput(baritoneYaw ?: player.yaw.toDouble(), input) + val movementYaw = strafeEvent.post().strafeYaw - val input = event.input + // No changes are needed, when we don't modify the yaw used to move the player + // val config = currentContext?.config ?: return@runSafe + // if (config.rotationMode == RotationMode.SILENT && !input.handledByBaritone && baritoneContext == null) return@runSafe // Sign it to remove previous speed modifier val signForward = sign(input.movementForward) val signStrafe = sign(input.movementSideways) // No changes are needed when no inputs are pressed - if (signForward == 0f && signStrafe == 0f) return - - // Movement speed modifier - val multiplier = if (event.slowDown) event.slowDownFactor else 1f - - // No changes are needed, when we don't modify the yaw used to move the player - if (config.rotationMode == RotationMode.SILENT && !input.handledByBaritone && baritoneContext == null) return - - // The yaw relative to which the movement was constructed - val baritoneYaw = baritoneContext?.rotation?.yaw - val strafeEvent = RotationEvent.Strafe(baritoneYaw ?: player.yaw.toDouble(), input) - val movementYaw = strafeEvent.post().strafeYaw + if (signForward == 0f && signStrafe == 0f) return@runSafe // Actual yaw used to move the player val actualYaw = currentRotation.yaw - val yawRad = (movementYaw - actualYaw).toRadian().toFloat() + val yawRad = (movementYaw - actualYaw).toRadian() - val cosDelta = MathHelper.cos(yawRad) - val sinDelta = MathHelper.sin(yawRad) + val cosDelta = cos(yawRad) + val sinDelta = sin(yawRad) val newX = signStrafe * cosDelta - signForward * sinDelta val newZ = signForward * cosDelta + signStrafe * sinDelta // Apply new movement input.apply { - movementSideways = newX.roundToInt().toFloat() * multiplier - movementForward = newZ.roundToInt().toFloat() * multiplier + // Movement speed modifier + val multiplier = if (slowDown) slowDownFactor else 1f + + movementSideways = round(newX).toFloat() * multiplier + movementForward = round(newZ).toFloat() * multiplier } - baritoneYaw ?: return + baritoneYaw ?: return@runSafe // Makes baritone movement safe // when yaw difference is too big to compensate it by modifying keyboard input diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt index 0671dab33..1e93f3410 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt @@ -1,7 +1,6 @@ package com.lambda.module.modules.movement import com.lambda.config.groups.IRotationConfig -import com.lambda.event.events.MovementEvent import com.lambda.event.events.RotationEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listener @@ -59,23 +58,10 @@ object TargetStrafe : Module( } } - listener { event -> - targetEntity?.let { - event.strafeYaw = player.eyePos.rotationTo(it.boundingBox.center).yaw - } - } - - listener { event -> - targetEntity?.let { - event.context = RotationContext( - player.eyePos.rotationTo(it.boundingBox.center), - rotationConfig - ) - } - } - - listener { event -> + listener { event -> targetEntity?.let { target -> + event.strafeYaw = player.eyePos.rotationTo(target.boundingBox.center).yaw + val distSq = player.pos distSq target.pos val keepRange = 0.5 * jitterCompensation @@ -108,6 +94,15 @@ object TargetStrafe : Module( } } + listener { event -> + targetEntity?.let { + event.context = RotationContext( + player.eyePos.rotationTo(it.boundingBox.center), + rotationConfig + ) + } + } + onEnable { targetEntity = null forwardDirection = 1 From 391adc8fa4144ced4cac94bea6f57f8bd1227833 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Wed, 17 Jul 2024 21:31:09 +0300 Subject: [PATCH 14/35] many ncp jesus modes --- .../lambda/module/modules/movement/Jesus.kt | 132 +++++++++++++++++- .../lambda/module/modules/movement/Speed.kt | 2 +- 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt index 3c11d9901..51f91ba63 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Jesus.kt @@ -1,10 +1,22 @@ package com.lambda.module.modules.movement +import com.lambda.context.SafeContext +import com.lambda.event.events.MovementEvent +import com.lambda.event.events.PlayerPacketEvent +import com.lambda.event.events.TickEvent import com.lambda.event.events.WorldEvent import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.module.Module import com.lambda.module.tag.ModuleTag +import com.lambda.util.Nameable +import com.lambda.util.math.MathUtils.toInt +import com.lambda.util.math.VecUtils.minus +import com.lambda.util.player.MovementUtils.isInputting +import com.lambda.util.player.MovementUtils.motionY +import com.lambda.util.player.MovementUtils.setSpeed import net.minecraft.block.Blocks +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Vec3d import net.minecraft.util.shape.VoxelShapes object Jesus : Module( @@ -12,14 +24,130 @@ object Jesus : Module( description = "Allows to walk on water", defaultTags = setOf(ModuleTag.MOVEMENT) ) { - private val waterState by lazy { Blocks.WATER.defaultState } + private val mode by setting("Mode", Mode.NCP) + + // Dolphin + private val dolphinStrength by setting("Dolphin Strength", 0.1, 0.01..0.2, 0.01) { mode == Mode.NCP_DOLPHIN } + + // NCP New + private val slowDown by setting("Slow Down", true) { mode == Mode.NCP_NEW } + private val fullShape = VoxelShapes.fullCube() + private var goUp = true + private var swimmingTicks = 0 + + enum class Mode(override val displayName: String, val collision: Boolean) : Nameable.NamedEnum { + NCP("NCP", true), + NCP_DOLPHIN("NCP Dolphin", false), + NCP_NEW("NCP New", true) + } + + private var shouldWork = false init { + listener { event -> + if (!shouldWork || !waterAt(-0.0001)) return@listener + event.onGround = false + + if (!player.isOnGround) return@listener + + when (mode) { + Mode.NCP -> { + val offset = if (player.age % 2 == 0) 0.001 else 0.002 + event.position -= Vec3d(0.0, offset, 0.0) + } + + Mode.NCP_NEW-> { + event.position -= Vec3d(0.0, 0.02 + 0.0001 * swimmingTicks, 0.0) + } + + else -> {} + } + } + + listener { + if (!shouldWork) return@listener + + goUp = waterAt(0.0001) + val collidingWater = waterAt(-0.0001) + + when (mode) { + Mode.NCP -> { + if (!collidingWater || !player.isOnGround) return@listener + setSpeed(Speed.NCP_BASE_SPEED * isInputting.toInt()) + } + + Mode.NCP_DOLPHIN -> { + if (goUp) { + player.motionY = dolphinStrength + + if (!waterAt(0.2)) { + setSpeed(Speed.NCP_BASE_SPEED * isInputting.toInt()) + } else player.motionY = 0.18 + } + } + + Mode.NCP_NEW -> { + if (!collidingWater) { + swimmingTicks = 0 + return@listener + } + + if (++swimmingTicks < 15) { + if (player.isOnGround) { + setSpeed(Speed.NCP_BASE_SPEED * isInputting.toInt()) + } + + return@listener + } + + swimmingTicks = 0 + + if (slowDown) setSpeed(0.0) + player.motionY = 0.08000001 + } + } + } + listener { event -> - if (event.state == waterState) { + if (!shouldWork || goUp || !mode.collision) return@listener + + if (event.state.block == Blocks.WATER) { event.shape = fullShape } } + + listener { + if (!shouldWork || !goUp || mode == Mode.NCP_DOLPHIN) return@listener + it.input.jumping = true + } + + listener { + shouldWork = !player.abilities.flying && !player.isFallFlying && !player.input.sneaking + } + + onEnable { + goUp = false + swimmingTicks = 0 + shouldWork = false + } + } + + private fun SafeContext.waterAt(yOffset: Double) : Boolean { + val b = player.boundingBox + val y = b.minY + yOffset + + for (xref in 0..1) { + for (zref in 0..1) { + val x = if (xref == 0) b.minX else b.maxX + val z = if (zref == 0) b.minZ else b.maxZ + + val pos = BlockPos.ofFloored(x, y, z) + val state = world.getBlockState(pos) + if (state.block != Blocks.WATER) return false + } + } + + return true } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt index 7a41590b9..ea49516a9 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt @@ -59,7 +59,7 @@ object Speed : Module( } // NCP - private const val NCP_BASE_SPEED = 0.2873 + const val NCP_BASE_SPEED = 0.2873 private const val NCP_AIR_DECAY = 0.9937 private var ncpPhase = NCPPhase.SLOWDOWN From 08f880a7f75c20f7afb7f9684ae076faaee36046 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Fri, 19 Jul 2024 20:37:19 +0300 Subject: [PATCH 15/35] Laying particles --- .../kotlin/com/lambda/graphics/RenderMain.kt | 8 +- .../kotlin/com/lambda/graphics/gl/Matrices.kt | 21 ++- .../lambda/module/modules/render/Particles.kt | 124 +++++++++++------- .../kotlin/com/lambda/util/math/VecUtils.kt | 3 + 4 files changed, 96 insertions(+), 60 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt index e4a312ccc..1e53573db 100644 --- a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt +++ b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt @@ -5,8 +5,7 @@ import com.lambda.event.EventFlow.post import com.lambda.event.events.RenderEvent import com.lambda.graphics.gl.GlStateUtils.setupGL import com.lambda.graphics.gl.Matrices -import com.lambda.graphics.gl.Matrices.resetMatrix -import com.lambda.graphics.gl.Matrices.translate +import com.lambda.graphics.gl.Matrices.resetMatrices import com.lambda.graphics.renderer.esp.global.StaticESP import com.lambda.graphics.renderer.esp.global.DynamicESP import com.lambda.module.modules.client.GuiSettings @@ -22,8 +21,7 @@ object RenderMain { @JvmStatic fun render2D() { - resetMatrix() - translate(0.0, 0.0, -3000.0) + resetMatrices(Matrix4f().translate(0f, 0f, -3000f)) setupGL { rescale(1.0) @@ -36,7 +34,7 @@ object RenderMain { @JvmStatic fun render3D(matrix: Matrix4f) { - resetMatrix(matrix) + resetMatrices(matrix) projectionMatrix.set(getProjectionMatrix()) setupGL { diff --git a/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt b/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt index 1b515d5fc..0cf5748c2 100644 --- a/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt +++ b/common/src/main/kotlin/com/lambda/graphics/gl/Matrices.kt @@ -1,10 +1,9 @@ package com.lambda.graphics.gl import com.lambda.Lambda.mc +import net.minecraft.util.math.RotationAxis import net.minecraft.util.math.Vec3d -import org.joml.Matrix4d -import org.joml.Matrix4f -import org.joml.Quaternionf +import org.joml.* object Matrices { private val stack = ArrayDeque(1) @@ -52,7 +51,7 @@ object Matrices { fun peek() = stack.last() - fun resetMatrix(entry: Matrix4f = Matrix4f()) { + fun resetMatrices(entry: Matrix4f) { stack.clear() stack.add(entry) } @@ -63,11 +62,21 @@ object Matrices { vertexTransformer = null } - fun buildWorldProjection(pos: Vec3d, scale: Double = 1.0) = Matrix4f().apply { + fun buildWorldProjection(pos: Vec3d, scale: Double = 1.0, mode: ProjRotationMode = ProjRotationMode.TO_CAMERA) = Matrix4f().apply { val s = 0.025f * scale.toFloat() + val rotation = when(mode) { + ProjRotationMode.TO_CAMERA -> mc.gameRenderer.camera.rotation + ProjRotationMode.UP -> RotationAxis.POSITIVE_X.rotationDegrees(90f) + } + translate(pos.x.toFloat(), pos.y.toFloat(), pos.z.toFloat()) - rotate(mc.gameRenderer.camera.rotation) + rotate(rotation) scale(-s, -s, s) } + + enum class ProjRotationMode { + TO_CAMERA, + UP + } } diff --git a/common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt b/common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt index 5c865ba28..7e23e5d65 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/render/Particles.kt @@ -1,5 +1,7 @@ package com.lambda.module.modules.render +import com.lambda.Lambda.mc +import com.lambda.context.SafeContext import com.lambda.event.events.AttackEvent import com.lambda.event.events.MovementEvent import com.lambda.event.events.RenderEvent @@ -10,22 +12,25 @@ import com.lambda.graphics.buffer.vao.vertex.VertexAttrib import com.lambda.graphics.buffer.vao.vertex.VertexMode import com.lambda.graphics.gl.GlStateUtils.withBlendFunc import com.lambda.graphics.gl.GlStateUtils.withDepth +import com.lambda.graphics.gl.Matrices import com.lambda.graphics.gl.Matrices.buildWorldProjection import com.lambda.graphics.gl.Matrices.withVertexTransform import com.lambda.graphics.shader.Shader +import com.lambda.interaction.rotation.Rotation import com.lambda.module.Module import com.lambda.module.modules.client.GuiSettings import com.lambda.module.modules.client.GuiSettings.colorSpeed import com.lambda.module.tag.ModuleTag -import com.lambda.threading.runSafe import com.lambda.util.math.ColorUtils.multAlpha import com.lambda.util.math.MathUtils.lerp import com.lambda.util.math.MathUtils.random +import com.lambda.util.math.VecUtils +import com.lambda.util.math.VecUtils.plus +import com.lambda.util.math.VecUtils.times import com.lambda.util.math.transform import com.lambda.util.player.MovementUtils.moveDelta -import com.lambda.util.player.MovementUtils.movementVector -import com.lambda.util.player.MovementUtils.randomDirection import com.lambda.util.primitives.extension.partialTicks +import com.lambda.util.world.raycast.RayCastMask import net.minecraft.entity.Entity import net.minecraft.util.math.Vec3d @@ -38,17 +43,24 @@ object Particles : Module( description = "Spawns fancy particles", defaultTags = setOf(ModuleTag.RENDER) ) { + // ToDo: resort, cleanup settings private val duration by setting("Duration", 5.0, 1.0..500.0, 1.0) private val fadeDuration by setting("Fade Ticks", 5.0, 1.0..30.0, 1.0) - private val spawnAmount by setting("Spawn Amount", 30.0, 3.0..500.0, 1.0) - private val size by setting("Size", 2.0, 0.1..50.0, 0.1) + private val spawnAmount by setting("Spawn Amount", 20, 3..500, 1) + private val sizeSetting by setting("Size", 2.0, 0.1..50.0, 0.1) private val alphaSetting by setting("Alpha", 1.5, 0.01..2.0, 0.01) private val speedH by setting("Speed H", 1.0, 0.0..10.0, 0.1) private val speedV by setting("Speed V", 1.0, 0.0..10.0, 0.1) private val inertia by setting("Inertia", 0.0, 0.0..1.0, 0.01) private val gravity by setting("Gravity", 0.2, 0.0..1.0, 0.01) + private val onMove by setting("On Move", false) - private val onMove by setting("On Move", true) + private val environment by setting("Environment", true) + private val environmentSpawnAmount by setting("E Spawn Amount", 10, 3..100, 1) { environment } + private val environmentSize by setting("E Size", 2.0, 0.1..50.0, 0.1) { environment } + private val environmentRange by setting("E Spread", 5.0, 1.0..20.0, 0.1) { environment } + private val environmentSpeedH by setting("E Speed H", 0.0, 0.0..10.0, 0.1) { environment } + private val environmentSpeedV by setting("E Speed V", 0.1, 0.0..10.0, 0.1) { environment } private var particles = mutableListOf() private val vao = VAO(VertexMode.TRIANGLES, VertexAttrib.Group.PARTICLE) @@ -56,8 +68,8 @@ object Particles : Module( init { listener { - particles.forEach(Particle::tick) - particles.removeIf(Particle::shouldRemove) + if (environment) spawnForEnvironment() + particles.removeIf(Particle::update) } listener { @@ -85,77 +97,91 @@ object Particles : Module( } private fun spawnForEntity(entity: Entity) { - repeat(spawnAmount.toInt()) { - val i = (it + 1) / spawnAmount + repeat(spawnAmount) { + val i = (it + 1) / spawnAmount.toDouble() val pos = entity.pos val height = entity.boundingBox.lengthY val spawnHeight = height * transform(i, 0.0, 1.0, 0.2, 0.8) val particlePos = pos.add(0.0, spawnHeight, 0.0) + val particleMotion = Rotation( + random(-180.0, 180.0), + random(-90.0, 90.0) + ).vector * Vec3d(speedH, speedV, speedH) * 0.1 - particles.add(Particle(particlePos)) + particles += Particle(particlePos, particleMotion, false) } } - private class Particle(posIn: Vec3d) { - var initTick = 0 - var maxAge = 0 - var fadeTicks = fadeDuration + private fun SafeContext.spawnForEnvironment() { + if (mc.paused) return + repeat(environmentSpawnAmount) { + var particlePos = player.pos + Rotation(random(-180.0, 180.0), 0.0).vector * random(0.0, environmentRange) - var shouldRemove = false + Rotation.DOWN.rayCast(6.0, particlePos + VecUtils.UP * 2.0, true, RayCastMask.BLOCK)?.pos?.let { + particlePos = it + VecUtils.UP * 0.03 + } ?: return@repeat - var prevPos = posIn - var pos = posIn + val particleMotion = Rotation( + random(-180.0, 180.0), + random(-90.0, 90.0) + ).vector * Vec3d(environmentSpeedH, environmentSpeedV, environmentSpeedH) * 0.1 - var motion: Vec3d = Vec3d.ZERO + particles += Particle(particlePos, particleMotion, true) + } + } - init { - runSafe { - initTick = player.age - maxAge = (duration + random(0.0, 20.0)).toInt() + private class Particle( + initialPosition: Vec3d, + initialMotion: Vec3d, + val lay: Boolean + ) { + private val fadeTicks = fadeDuration + private var age = 0 + private val maxAge = (duration + random(0.0, 20.0)).toInt() - motion = movementVector(randomDirection(), sin(random(0.0, Math.PI))) - .multiply(random(0.0, 1.0), random(0.0, 1.0), random(0.0, 1.0)) - .multiply( - speedH * random(0.9, 1.1), - speedV * random(0.9, 1.1), - speedH * random(0.9, 1.1) - ).multiply(0.1) - } - } + private var prevPos = initialPosition + private var position = initialPosition + private var motion = initialMotion - fun tick() = runSafe { - prevPos = pos - pos = pos.add(motion) + private val projRotation = if (lay) Matrices.ProjRotationMode.UP else Matrices.ProjRotationMode.TO_CAMERA - motion = motion - .subtract(0.0, gravity * 0.01, 0.0) - .multiply(0.9 + inertia * 0.1) + fun update(): Boolean { + if (mc.paused) return false + age++ - shouldRemove = player.age - initTick > 5.0 + maxAge + fadeTicks * 2 + prevPos = position + + if (!lay) motion += VecUtils.DOWN * gravity * 0.01 + motion *= 0.9 + inertia * 0.1 + + position += motion + + return age > maxAge + fadeTicks * 2 + 5 } - fun build() = runSafe { - val age = player.age - initTick + mc.partialTicks - val colorTicks = age * 0.1 / colorSpeed + fun build() { + val smoothAge = age + mc.partialTicks + val colorTicks = smoothAge * 0.1 / colorSpeed val alpha = when { - age < fadeTicks -> age / fadeTicks - age in fadeTicks..fadeTicks + maxAge -> 1.0 + smoothAge < fadeTicks -> smoothAge / fadeTicks + smoothAge in fadeTicks..fadeTicks + maxAge -> 1.0 else -> { val min = fadeTicks + maxAge val max = fadeTicks * 2 + maxAge - transform(age, min, max, 1.0, 0.0) + transform(smoothAge, min, max, 1.0, 0.0) } - } * alphaSetting + } val (c1, c2) = GuiSettings.primaryColor to GuiSettings.secondaryColor - val color = lerp(c1, c2, sin(colorTicks) * 0.5 + 0.5).multAlpha(alpha) + val color = lerp(c1, c2, sin(colorTicks) * 0.5 + 0.5).multAlpha(alpha * alphaSetting) - val position = lerp(prevPos, pos, mc.partialTicks) + val position = lerp(prevPos, position, mc.partialTicks) + val size = if (lay) environmentSize else sizeSetting * lerp(0.5, 1.0, alpha) - withVertexTransform(buildWorldProjection(position, size)) { + withVertexTransform(buildWorldProjection(position, size, projRotation)) { vao.use { grow(4) // DO NOT FUCKING FORGOTEOIJTOWKET TO GROW (cost me an hour) putQuad( diff --git a/common/src/main/kotlin/com/lambda/util/math/VecUtils.kt b/common/src/main/kotlin/com/lambda/util/math/VecUtils.kt index 6f1b4d072..21d3626fc 100644 --- a/common/src/main/kotlin/com/lambda/util/math/VecUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/math/VecUtils.kt @@ -32,4 +32,7 @@ object VecUtils { infix operator fun Vec3d.times(other: Double): Vec3d = this.multiply(other) infix operator fun Vec3d.div(other: Double): Vec3d = this.multiply(1.0 / other) + + val UP = Vec3d(0.0, 1.0, 0.0) + val DOWN = Vec3d(0.0, -1.0, 0.0) } From 26b9e7d534f1a1a4f4e66059f91f31d08947c41a Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sun, 21 Jul 2024 15:58:29 +0300 Subject: [PATCH 16/35] Targeting Config --- .../com/lambda/config/groups/Targeting.kt | 100 ++++++++++++++++++ .../lambda/config/groups/TargetingConfig.kt | 12 +++ .../lambda/interaction/rotation/Rotation.kt | 2 +- 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 common/src/main/kotlin/com/lambda/config/groups/Targeting.kt create mode 100644 common/src/main/kotlin/com/lambda/config/groups/TargetingConfig.kt diff --git a/common/src/main/kotlin/com/lambda/config/groups/Targeting.kt b/common/src/main/kotlin/com/lambda/config/groups/Targeting.kt new file mode 100644 index 000000000..aef28e9bf --- /dev/null +++ b/common/src/main/kotlin/com/lambda/config/groups/Targeting.kt @@ -0,0 +1,100 @@ +package com.lambda.config.groups + +import com.lambda.config.Configurable +import com.lambda.context.SafeContext +import com.lambda.interaction.rotation.Rotation.Companion.dist +import com.lambda.interaction.rotation.Rotation.Companion.rotation +import com.lambda.interaction.rotation.Rotation.Companion.rotationTo +import com.lambda.threading.runSafe +import com.lambda.util.math.VecUtils.distSq +import com.lambda.util.world.WorldUtils.getFastEntities +import net.minecraft.client.network.ClientPlayerEntity +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.mob.MobEntity +import net.minecraft.entity.passive.PassiveEntity + +abstract class Targeting( + c: Configurable, + vis: () -> Boolean = { true }, + defaultRange: Double, + maxRange: Double +) : TargetingConfig { + override val targetingRange by c.setting("Targeting Range", defaultRange, 1.0..maxRange, 0.05) { vis() } + + override val players by c.setting("Players", true) { vis() } + private val mobs by c.setting("Mobs", true) { vis() } + private val hostilesSetting by c.setting("Hostiles", true) { vis() && mobs } + private val animalsSetting by c.setting("Animals", true) { vis() && mobs } + override val hostiles get() = mobs && hostilesSetting + override val animals get() = mobs && animalsSetting + + override val invisible by c.setting("Invisible", true) { vis() } + override val dead by c.setting("Dead", false) { vis() } + + fun getEntities(): List = + mutableListOf().apply { + runSafe { + getFastEntities( + player.pos, targetingRange, this@apply, + predicate = { entity -> validate(player, entity) } + ) + } + } + + open fun validate(player: ClientPlayerEntity, entity: LivingEntity) = when { + !players && entity.isPlayer -> false + !animals && entity is PassiveEntity -> false + !hostiles && entity is MobEntity -> false + + !invisible && entity.isInvisibleTo(player) -> false + !dead && entity.isDead -> false + + else -> true + } + + class Combat( + c: Configurable, + vis: () -> Boolean = { true }, + ) : Targeting(c, vis, 5.0, 16.0) { + val fov by c.setting("FOV Limit", 180, 5..180, 1) { vis() } + val priority by c.setting("Priority", Priority.DISTANCE) { vis() } + + override fun validate(player: ClientPlayerEntity, entity: LivingEntity): Boolean { + if (fov < 180 && player.rotation dist player.eyePos.rotationTo(entity.pos) > fov) return false + return super.validate(player, entity) + } + + fun getTarget(): LivingEntity? = runSafe { + var best: LivingEntity? = null + var bestFactor = Double.MAX_VALUE + + val comparator = { entity: LivingEntity, _: Int -> + val factor = priority.factor(this, entity) + if (factor < bestFactor) { + best = entity + bestFactor = factor + } + } + + val predicate = { entity: LivingEntity -> + validate(player, entity) + } + + getFastEntities(player.pos, targetingRange, null, comparator, predicate) + + return@runSafe best + } + } + + class ESP( + c: Configurable, + vis: () -> Boolean = { true }, + ) : Targeting(c, vis, 128.0, 1024.0) + + @Suppress("Unused") + enum class Priority(val factor: SafeContext.(LivingEntity) -> Double) { + DISTANCE({ player.pos distSq it.pos }), + HEALTH({ it.health.toDouble() }), + FOV({ player.rotation dist player.eyePos.rotationTo(it.pos) }) + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/config/groups/TargetingConfig.kt b/common/src/main/kotlin/com/lambda/config/groups/TargetingConfig.kt new file mode 100644 index 000000000..731e5e0a2 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/config/groups/TargetingConfig.kt @@ -0,0 +1,12 @@ +package com.lambda.config.groups + +interface TargetingConfig { + val targetingRange: Double + + val players: Boolean + val hostiles: Boolean + val animals: Boolean + + val invisible: Boolean + val dead: Boolean +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt b/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt index b462e22cb..99bd2820f 100644 --- a/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt +++ b/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt @@ -109,7 +109,7 @@ data class Rotation(val yaw: Double, val pitch: Double) { return Rotation(yaw, pitch) } - fun Rotation.distance(b: Rotation) = + infix fun Rotation.dist(b: Rotation) = hypot( wrap(yaw - b.yaw), wrap(pitch - b.pitch) From 3c1ca3dfd8f61ba9559805b85bcbe9164c0e3135 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Mon, 22 Jul 2024 22:04:33 +0300 Subject: [PATCH 17/35] Kill aura --- .../lambda/mixin/MinecraftClientMixin.java | 3 +- .../mixin/entity/PlayerEntityMixin.java | 10 + .../config/groups/InteractionSettings.kt | 6 +- .../lambda/config/groups/RotationSettings.kt | 2 +- .../lambda/interaction/PlayerPacketManager.kt | 3 - .../com/lambda/interaction/RotationManager.kt | 43 ++- .../construction/simulation/BuildSimulator.kt | 6 +- .../lambda/interaction/rotation/Rotation.kt | 31 +- .../interaction/rotation/RotationContext.kt | 3 +- .../visibilty/VisibilityChecker.kt | 29 +- .../lambda/module/modules/combat/KillAura.kt | 301 ++++++++++++++++++ .../module/modules/movement/TargetStrafe.kt | 38 +-- .../main/kotlin/com/lambda/util/math/Vec2d.kt | 4 + .../src/main/resources/lambda.accesswidener | 1 + 14 files changed, 405 insertions(+), 75 deletions(-) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt diff --git a/common/src/main/java/com/lambda/mixin/MinecraftClientMixin.java b/common/src/main/java/com/lambda/mixin/MinecraftClientMixin.java index 3d2e07027..9ffcd5c65 100644 --- a/common/src/main/java/com/lambda/mixin/MinecraftClientMixin.java +++ b/common/src/main/java/com/lambda/mixin/MinecraftClientMixin.java @@ -6,10 +6,10 @@ import com.lambda.event.events.ScreenEvent; import com.lambda.event.events.ScreenHandlerEvent; import com.lambda.event.events.TickEvent; +import com.lambda.interaction.RotationManager; import com.lambda.module.modules.player.Interact; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider; import net.minecraft.client.network.ClientPlayerInteractionManager; import org.jetbrains.annotations.Nullable; @@ -27,6 +27,7 @@ public class MinecraftClientMixin { @Inject(method = "tick", at = @At("HEAD")) void onTickPre(CallbackInfo ci) { EventFlow.post(new TickEvent.Pre()); + RotationManager.update(); } @Inject(method = "tick", at = @At("RETURN")) diff --git a/common/src/main/java/com/lambda/mixin/entity/PlayerEntityMixin.java b/common/src/main/java/com/lambda/mixin/entity/PlayerEntityMixin.java index 128bec35a..603808b24 100644 --- a/common/src/main/java/com/lambda/mixin/entity/PlayerEntityMixin.java +++ b/common/src/main/java/com/lambda/mixin/entity/PlayerEntityMixin.java @@ -28,4 +28,14 @@ private float injectHeadYaw(PlayerEntity instance) { Float yaw = RotationManager.getRenderYaw(); return (yaw != null) ? yaw : instance.getYaw(); } + + @Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;getYaw()F")) + private float injectAttackFix(PlayerEntity instance) { + if ((Object) this != MinecraftClient.getInstance().player) { + return instance.getYaw(); + } + + Float yaw = RotationManager.getMovementYaw(); + return (yaw != null) ? yaw : instance.getYaw(); + } } diff --git a/common/src/main/kotlin/com/lambda/config/groups/InteractionSettings.kt b/common/src/main/kotlin/com/lambda/config/groups/InteractionSettings.kt index 1ddb53ea6..bcaf64897 100644 --- a/common/src/main/kotlin/com/lambda/config/groups/InteractionSettings.kt +++ b/common/src/main/kotlin/com/lambda/config/groups/InteractionSettings.kt @@ -1,14 +1,14 @@ package com.lambda.config.groups import com.lambda.config.Configurable -import com.lambda.util.world.raycast.RayCastMask class InteractionSettings( c: Configurable, + defaultReach: Double = 4.9, vis: () -> Boolean = { true }, ) : InteractionConfig { - override val reach by c.setting("Reach", 4.9, 0.1..10.0, 0.1, "Players reach / range", " blocks", vis) + override val reach by c.setting("Reach", defaultReach, 0.1..10.0, 0.1, "Players reach / range", " blocks", vis) override val useRayCast by c.setting("Raycast", false, "Verify hit vector with ray casting (for very strict ACs)", vis) - override val resolution by c.setting("Resolution", 5, 1..20, 1, "How many raycast checks per surface (will be squared)") { vis() && useRayCast } + override val resolution by c.setting("Resolution", 10, 1..30, 1, "How many raycast checks per surface (will be squared)") { vis() && useRayCast } override val swingHand by c.setting("Swing Hand", true, "Swing hand on interactions", vis) } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt b/common/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt index 8dae291d3..f5e038bb0 100644 --- a/common/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt +++ b/common/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt @@ -22,7 +22,7 @@ class RotationSettings( /** * If true, rotation will be instant without any transition. If false, rotation will transition over time. */ - private var instant by c.setting("Instant Rotation", true, "Instantly rotate", vis) + var instant by c.setting("Instant Rotation", true, "Instantly rotate", vis) /** * The mean (average/base) value used to calculate rotation speed. diff --git a/common/src/main/kotlin/com/lambda/interaction/PlayerPacketManager.kt b/common/src/main/kotlin/com/lambda/interaction/PlayerPacketManager.kt index c1922f55e..05f26ca5b 100644 --- a/common/src/main/kotlin/com/lambda/interaction/PlayerPacketManager.kt +++ b/common/src/main/kotlin/com/lambda/interaction/PlayerPacketManager.kt @@ -50,9 +50,6 @@ object PlayerPacketManager : Loadable { val (yaw, pitch) = rotation.float val onGround = new.onGround - // Fix sensitivity for absolutely any outgoing angle - RotationManager.currentRotation = rotation.fixSensitivity(RotationManager.prevRotation) - if (player.hasVehicle()) { connection.sendPacket( Full( diff --git a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt index d8149ab46..c3724b192 100644 --- a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt +++ b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt @@ -2,6 +2,7 @@ package com.lambda.interaction import com.lambda.Lambda.mc import com.lambda.config.groups.RotationSettings +import com.lambda.context.SafeContext import com.lambda.core.Loadable import com.lambda.event.EventFlow.post import com.lambda.event.events.* @@ -9,6 +10,7 @@ import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.event.listener.UnsafeListener.Companion.unsafeListener import com.lambda.interaction.rotation.Rotation import com.lambda.interaction.rotation.Rotation.Companion.angleDifference +import com.lambda.interaction.rotation.Rotation.Companion.fixSensitivity import com.lambda.interaction.rotation.Rotation.Companion.slerp import com.lambda.interaction.rotation.RotationContext import com.lambda.interaction.rotation.RotationMode @@ -33,17 +35,43 @@ object RotationManager : Loadable { private var keepTicks = 0 private var pauseTicks = 0 - init { - listener { - RotationEvent.Update(BaritoneProcessor.poolContext()).post { - rotate(context) + fun Any.requestRotation( + priority: Int = 0, + alwaysListen: Boolean = false, + onUpdate: SafeContext.() -> RotationContext?, + onReceive: SafeContext.() -> Unit + ) { + var lastCtx: RotationContext? = null - currentContext?.let { - RotationEvent.Post(it).post() - } + this.listener(priority, alwaysListen) { event -> + val rotationContext = onUpdate() + + rotationContext?.let { + event.context = it + } + + lastCtx = rotationContext + } + + this.listener { event -> + if (event.context == lastCtx && event.context.isValid) { + onReceive() } } + } + @JvmStatic + fun update() = runSafe { + RotationEvent.Update(BaritoneProcessor.poolContext()).post { + rotate(context) + + currentContext?.let { + RotationEvent.Post(it).post() + } + } + } + + init { listener { event -> val packet = event.packet if (packet !is PlayerPositionLookS2CPacket) return@listener @@ -85,6 +113,7 @@ object RotationManager : Loadable { currentRotation .slerp(rotationTo, turnSpeed) + .fixSensitivity(prevRotation) .apply { if (context.config.rotationMode != RotationMode.LOCK) return@apply player.yaw = this.yawF diff --git a/common/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt b/common/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt index b75318aaf..29af0d786 100644 --- a/common/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt +++ b/common/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt @@ -12,7 +12,7 @@ import com.lambda.interaction.construction.verify.TargetState import com.lambda.interaction.material.ContainerManager.findBestAvailableTool import com.lambda.interaction.rotation.Rotation.Companion.rotationTo import com.lambda.interaction.rotation.RotationContext -import com.lambda.interaction.visibilty.VisibilityChecker.mostCenter +import com.lambda.interaction.visibilty.VisibilityChecker.optimum import com.lambda.interaction.visibilty.VisibilityChecker.scanVisibleSurfaces import com.lambda.module.modules.client.TaskFlow import com.lambda.threading.runSafe @@ -160,7 +160,7 @@ object BuildSimulator { return@forEach } - validHits.keys.mostCenter?.let { optimum -> + validHits.keys.optimum?.let { optimum -> validHits.minByOrNull { optimum distSq it.key }?.let { closest -> val optimumRotation = eye.rotationTo(closest.key) RotationContext(optimumRotation, rotation, closest.value, verify) @@ -368,7 +368,7 @@ object BuildSimulator { } } - validHits.keys.mostCenter?.let { optimum -> + validHits.keys.optimum?.let { optimum -> validHits.minByOrNull { optimum distSq it.key }?.let { closest -> val optimumRotation = eye.rotationTo(closest.key) RotationContext(optimumRotation, rotation, closest.value, verify) diff --git a/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt b/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt index 99bd2820f..321dac45f 100644 --- a/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt +++ b/common/src/main/kotlin/com/lambda/interaction/rotation/Rotation.kt @@ -4,9 +4,13 @@ import com.lambda.Lambda.mc import com.lambda.threading.runSafe import com.lambda.util.math.MathUtils.toDegree import com.lambda.util.math.MathUtils.toRadian +import com.lambda.util.math.Vec2d +import com.lambda.util.math.VecUtils.plus +import com.lambda.util.math.VecUtils.times import com.lambda.util.world.raycast.RayCastMask import com.lambda.util.world.raycast.RayCastUtils.rayCast import net.minecraft.entity.Entity +import net.minecraft.util.math.Box import net.minecraft.util.math.Direction import net.minecraft.util.math.MathHelper import net.minecraft.util.math.Vec3d @@ -42,6 +46,15 @@ data class Rotation(val yaw: Double, val pitch: Double) { rayCast(eye ?: player.eyePos, vector, reach, mask, fluids) } + fun castBox( + box: Box, + reach: Double, + eye: Vec3d? = null + ) = runSafe { + val eyeVec = eye ?: player.eyePos + box.raycast(eyeVec, eyeVec + vector * reach).orElse(null) + } + val Direction.yaw: Float get() = when (this) { Direction.NORTH -> -180.0f @@ -79,20 +92,16 @@ data class Rotation(val yaw: Double, val pitch: Double) { return Rotation(yaw, pitch) } - fun Rotation.fixSensitivity(last: Rotation): Rotation { + fun Rotation.fixSensitivity(prev: Rotation): Rotation { val f = mc.options.mouseSensitivity.value * 0.6 + 0.2 - val step = f * f * f * 8.0 * 0.15F - - val deltaYaw = yaw - last.yaw - var fixedYaw = (deltaYaw / step).roundToInt() * step - fixedYaw += last.yaw + val gcd = f * f * f * 8.0 * 0.15F - val deltaPitch = pitch - last.pitch - var fixedPitch = (deltaPitch / step).roundToInt() * step - fixedPitch += last.pitch - fixedPitch = fixedPitch.coerceIn(-90.0, 90.0) + val r1 = Vec2d(prev.yaw, prev.pitch) + val r2 = Vec2d(this.yaw, this.pitch) + val delta = ((r2 - r1) / gcd).roundToInt() * gcd + val fixed = r1 + delta - return Rotation(fixedYaw, fixedPitch) + return Rotation(fixed.x, fixed.y.coerceIn(-90.0, 90.0)) } fun Vec3d.rotationTo(vec: Vec3d): Rotation { diff --git a/common/src/main/kotlin/com/lambda/interaction/rotation/RotationContext.kt b/common/src/main/kotlin/com/lambda/interaction/rotation/RotationContext.kt index 0d55a028a..a35216e07 100644 --- a/common/src/main/kotlin/com/lambda/interaction/rotation/RotationContext.kt +++ b/common/src/main/kotlin/com/lambda/interaction/rotation/RotationContext.kt @@ -1,6 +1,7 @@ package com.lambda.interaction.rotation import com.lambda.config.groups.IRotationConfig +import com.lambda.util.world.raycast.RayCastUtils.orMiss import net.minecraft.util.hit.HitResult data class RotationContext( @@ -9,5 +10,5 @@ data class RotationContext( val hitResult: HitResult? = null, val verify: HitResult.() -> Boolean = { true }, ) { - val isValid: Boolean get() = hitResult?.verify() == true + val isValid: Boolean get() = verify(hitResult.orMiss) } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt b/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt index 5e8d6a6f2..ae3f9f118 100644 --- a/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt +++ b/common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt @@ -4,6 +4,7 @@ import com.lambda.config.groups.IRotationConfig import com.lambda.config.groups.InteractionConfig import com.lambda.context.SafeContext import com.lambda.interaction.RotationManager +import com.lambda.interaction.rotation.Rotation.Companion.dist import com.lambda.interaction.rotation.Rotation.Companion.rotationTo import com.lambda.interaction.rotation.RotationContext import com.lambda.module.modules.client.TaskFlow @@ -46,37 +47,42 @@ object VisibilityChecker { fun SafeContext.findRotation( boxes: List, - rotationConfig: IRotationConfig = TaskFlow.rotation, - interact: InteractionConfig = TaskFlow.interact, + rotationConfig: IRotationConfig, + interact: InteractionConfig, sides: Set = emptySet(), + reach: Double = interact.reach, + eye: Vec3d = player.getCameraPosVec(1f), verify: HitResult.() -> Boolean, ): RotationContext? { - val eye = player.getCameraPosVec(mc.tickDelta) - val currentRotation = RotationManager.currentRotation - val currentCast = currentRotation.rayCast(interact.reach, eye) + val currentCast = currentRotation.rayCast(reach, eye) if (boxes.any { it.contains(eye) }) { return RotationContext(currentRotation, rotationConfig, currentCast, verify) } val validHits = mutableMapOf() - val reachSq = interact.reach.pow(2) + val reachSq = reach.pow(2) boxes.forEach { box -> - scanVisibleSurfaces(player.eyePos, box, sides, interact.resolution) { _, vec -> + scanVisibleSurfaces(eye, box, sides, interact.resolution) { _, vec -> if (eye distSq vec > reachSq) return@scanVisibleSurfaces val newRotation = eye.rotationTo(vec) - val cast = newRotation.rayCast(interact.reach, eye) ?: return@scanVisibleSurfaces + val cast = newRotation.rayCast(reach, eye) ?: return@scanVisibleSurfaces if (!cast.verify()) return@scanVisibleSurfaces validHits[vec] = cast } } - validHits.keys.mostCenter?.let { optimum -> + // Way stable + /*validHits.minByOrNull { eye.rotationTo(it.key) dist currentRotation }?.let { closest -> + return RotationContext(eye.rotationTo(closest.key), rotationConfig, closest.value, verify) + }*/ + + validHits.keys.optimum?.let { optimum -> validHits.minByOrNull { optimum distSq it.key }?.let { closest -> val optimumRotation = eye.rotationTo(closest.key) return RotationContext(optimumRotation, rotationConfig, closest.value, verify) @@ -93,11 +99,10 @@ object VisibilityChecker { resolution: Int, check: (Direction, Vec3d) -> Unit, ) { - val shrunk = box.expand(-0.005) box.getVisibleSurfaces(eyes) .forEach { side -> if (sides.isNotEmpty() && side !in sides) return@forEach - val (minX, minY, minZ, maxX, maxY, maxZ) = shrunk.bounds(side) + val (minX, minY, minZ, maxX, maxY, maxZ) = box.shrink(0.01, 0.01, 0.01).bounds(side) val stepX = (maxX - minX) / resolution val stepY = (maxY - minY) / resolution val stepZ = (maxZ - minZ) / resolution @@ -112,7 +117,7 @@ object VisibilityChecker { } } - val Set.mostCenter: Vec3d? + val Set.optimum: Vec3d? get() = reduceOrNull { acc, vec3d -> acc.add(vec3d) }?.multiply(1.0 / size.toDouble()) diff --git a/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt b/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt new file mode 100644 index 000000000..be5d58b35 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt @@ -0,0 +1,301 @@ +package com.lambda.module.modules.combat + +import com.lambda.config.groups.InteractionSettings +import com.lambda.config.groups.RotationSettings +import com.lambda.config.groups.Targeting +import com.lambda.context.SafeContext +import com.lambda.event.events.PacketEvent +import com.lambda.event.events.PlayerPacketEvent +import com.lambda.event.events.TickEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.interaction.RotationManager +import com.lambda.interaction.RotationManager.requestRotation +import com.lambda.interaction.rotation.Rotation +import com.lambda.interaction.rotation.Rotation.Companion.dist +import com.lambda.interaction.rotation.Rotation.Companion.rotationTo +import com.lambda.interaction.rotation.RotationContext +import com.lambda.interaction.visibilty.VisibilityChecker.scanVisibleSurfaces +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import com.lambda.threading.runConcurrent +import com.lambda.threading.runSafe +import com.lambda.util.math.MathUtils.lerp +import com.lambda.util.math.MathUtils.random +import com.lambda.util.math.VecUtils.distSq +import com.lambda.util.math.VecUtils.minus +import com.lambda.util.math.VecUtils.plus +import com.lambda.util.math.VecUtils.times +import com.lambda.util.player.MovementUtils.moveDiff +import com.lambda.util.world.raycast.RayCastUtils.entityResult +import kotlinx.coroutines.delay +import net.minecraft.entity.EquipmentSlot +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.attribute.EntityAttributeModifier +import net.minecraft.entity.attribute.EntityAttributes +import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket +import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket +import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket +import net.minecraft.util.Hand +import net.minecraft.util.math.Vec3d +import kotlin.math.pow + +object KillAura : Module( + name = "KillAura", + description = "Attacks entities", + defaultTags = setOf(ModuleTag.COMBAT, ModuleTag.RENDER) +) { + private val page by setting("Page", Page.Interact) + + // Interact + private val interactionSettings = InteractionSettings(this, 3.0) { page == Page.Interact } + private val attackMode by setting("Attack Mode", AttackMode.Cooldown) { page == Page.Interact } + private val delaySync by setting("Client-side Delay", true) { page == Page.Interact && attackMode == AttackMode.Cooldown } + private val cooldownSync by setting("Client-side Cooldown", true) { page == Page.Interact && attackMode == AttackMode.Cooldown } + private val timerSync by setting("Assume Timer", true) { page == Page.Interact && attackMode == AttackMode.Cooldown && delaySync } + private val cooldownOffset by setting("Cooldown Offset", 0, -5..5, 1) { page == Page.Interact && attackMode == AttackMode.Cooldown } + private val hitDelay1 by setting("Hit Delay 1", 2.0, 0.0..20.0, 1.0) { page == Page.Interact && attackMode == AttackMode.Delay } + private val hitDelay2 by setting("Hit Delay 2", 6.0, 0.0..20.0, 1.0) { page == Page.Interact && attackMode == AttackMode.Delay } + private val criticalSync by setting("Critical Sync", true) { page == Page.Interact && attackMode == AttackMode.Cooldown } + + // Targeting + private val targeting = Targeting.Combat(this) { page == Page.Targeting } + + // Aiming + private val rotation = RotationSettings(this) { page == Page.Aiming } + private val stabilize by setting("Stabilize", true) { page == Page.Aiming && !rotation.instant } + private val centerFactor by setting("Center Factor", 0.4, 0.0..1.0, 0.01) { page == Page.Aiming } + private val shakeFactor by setting("Shake Factor", 0.4, 0.0..1.0, 0.01) { page == Page.Aiming } + private val shakeChance by setting("Shake Chance", 0.2, 0.05..1.0, 0.01) { page == Page.Aiming && shakeFactor > 0.0 } + private val selfPredict by setting("Self Predict", 1.0, 0.0..2.0, 0.1) { page == Page.Aiming } + private val targetPredict by setting("Target Predict", 0.0, 0.0..2.0, 0.1) { page == Page.Aiming } + + var target: LivingEntity? = null; private set + + private var shakeRandom = Vec3d.ZERO + + private var attackTicks = 0 + private var lastAttackTime = 0L + private var hitDelay = 100.0 + + private var prevY = 0.0 + private var lastY = 0.0 + private var lastOnGround = true + private var onGroundTicks = 0 + + enum class Page { + Interact, + Targeting, + Aiming + } + + enum class AttackMode { + Cooldown, + Delay + } + + init { + requestRotation( + onUpdate = { + target?.let { target -> + buildRotation(target) + } + }, + onReceive = { + target?.let { entity -> + runAttack(entity) + } + } + ) + + listener(Int.MIN_VALUE) { event -> + prevY = lastY + lastY = event.position.y + lastOnGround = event.onGround + } + + listener { + target = targeting.getTarget() + if (!timerSync) attackTicks++ + } + + runConcurrent { + while (true) { + delay(50) // ToDo: tps sync + + runSafe { + if (timerSync && isEnabled) attackTicks++ + } + } + } + + listener { event -> + if (event.packet !is HandSwingC2SPacket && + event.packet !is UpdateSelectedSlotC2SPacket && + event.packet !is PlayerInteractEntityC2SPacket + ) return@listener + + attackTicks = 0 + } + + onEnable(::reset) + onDisable(::reset) + } + + private fun SafeContext.buildRotation(target: LivingEntity): RotationContext? { + val currentRotation = RotationManager.currentRotation + + val eye = player.getCameraPosVec(1f) + val box = target.boundingBox + + val reach = targeting.targetingRange + 2.0 + val reachSq = reach.pow(2) + + // Do not rotate if the eyes are inside the target's AABB + if (box.contains(eye)) { + return RotationContext(currentRotation, rotation) + } + + // Rotation stabilizer + rotation.speedMultiplier = if (stabilize && !rotation.instant) { + val slowDown = currentRotation.castBox(box, reach) != null + + with(rotation) { + val targetSpeed = if (slowDown) 0.0 else 1.0 + val acceleration = if (slowDown) 0.2 else 0.1 + + targetSpeed.coerceIn( + speedMultiplier - acceleration, + speedMultiplier + acceleration + ) + } + } else 1.0 + + // Update shake vector + if (random(0.0, 1.0) < shakeChance) { + shakeRandom = Vec3d( + random(0.0, 1.0), + random(0.0, 1.0), + random(0.0, 1.0), + ) + } + + // Find the closest point to the player's eyes + var vec = Vec3d( + eye.x.coerceIn(box.minX, box.maxX), + eye.y.coerceIn(box.minY, box.maxY), + eye.z.coerceIn(box.minZ, box.maxZ) + ) + + val random = Vec3d( + lerp(box.minX, box.maxX, shakeRandom.x), + lerp(box.minY, box.maxY, shakeRandom.x), + lerp(box.minZ, box.maxZ, shakeRandom.x) + ) + + vec = lerp(vec, box.center, centerFactor) // Mix with center + vec = lerp(vec, random, shakeFactor) // Apply shaking + + // Raycast + run { + if (!interactionSettings.useRayCast) return@run + + val vecRotation = eye.rotationTo(vec) + if (vecRotation.rayCast(reach, eye)?.entityResult?.entity == target) return@run + + // Get visible point set + val validHits = mutableMapOf() + + scanVisibleSurfaces(eye, box, emptySet(), interactionSettings.resolution) { _, vec -> + if (eye distSq vec > reachSq) return@scanVisibleSurfaces + + val newRotation = eye.rotationTo(vec) + + val cast = newRotation.rayCast(reach, eye) ?: return@scanVisibleSurfaces + if (cast.entityResult?.entity != target) return@scanVisibleSurfaces + + validHits[vec] = newRotation + } + + // Switch to the closest visible point + vec = validHits.minByOrNull { vecRotation dist it.value }?.key ?: return null + } + + val predictOffset = target.velocity * targetPredict - player.moveDiff * Vec3d(1.0, -0.5, 1.0) * selfPredict + return RotationContext(eye.rotationTo(vec + predictOffset), rotation) + } + + private fun SafeContext.runAttack(target: LivingEntity) { + // Critical hit check + run { + if (!criticalSync || attackMode != AttackMode.Cooldown) return@run + + onGroundTicks++ + if (!lastOnGround) onGroundTicks = 0 + + val motionY = lastY - prevY + if (motionY > -0.05 || (lastOnGround && onGroundTicks < 5)) return + } + + // Cooldown check + run { + when (attackMode) { + AttackMode.Cooldown -> { + val attackedTicks = if (delaySync) attackTicks else player.lastAttackedTicks + if (attackedTicks < getAttackCooldown() + cooldownOffset) return + } + + AttackMode.Delay -> { + if (System.currentTimeMillis() - lastAttackTime < hitDelay) return + } + } + } + + // Rotation check + run { + val angle = RotationManager.currentRotation + + if (interactionSettings.useRayCast) { + val cast = angle.rayCast(interactionSettings.reach) + if (cast?.entityResult?.entity != target) return + } + + // Perform a raycast without checking the environment + angle.castBox(target.boundingBox, interactionSettings.reach) ?: return + } + + // Attack + interaction.attackEntity(player, target) + if (interactionSettings.swingHand) player.swingHand(Hand.MAIN_HAND) + + lastAttackTime = System.currentTimeMillis() + hitDelay = random(hitDelay1, hitDelay2) * 50 + } + + private fun SafeContext.getAttackCooldown(): Double { + val attr = EntityAttributes.GENERIC_ATTACK_SPEED + + val attackSpeed = if (!cooldownSync) player.getAttributeValue(attr) else { + player.mainHandStack.item + .getAttributeModifiers(EquipmentSlot.MAINHAND)[attr] + .filter { it.operation == EntityAttributeModifier.Operation.ADDITION } + .sumOf { it.value } + 4 + } + + return 20.0 / attackSpeed + } + + private fun reset(ctx: SafeContext) = ctx.apply { + target = null + attackTicks = player.lastAttackedTicks + rotation.speedMultiplier = 1.0 + shakeRandom = Vec3d.ZERO + + lastY = 0.0 + prevY = 0.0 + lastOnGround = true + onGroundTicks = 0 + + lastAttackTime = 0L + hitDelay = 100.0 + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt index 1e93f3410..c8bbc9329 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TargetStrafe.kt @@ -1,20 +1,15 @@ package com.lambda.module.modules.movement -import com.lambda.config.groups.IRotationConfig import com.lambda.event.events.RotationEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.interaction.rotation.Rotation.Companion.rotationTo -import com.lambda.interaction.rotation.RotationContext -import com.lambda.interaction.rotation.RotationMode import com.lambda.module.Module +import com.lambda.module.modules.combat.KillAura import com.lambda.module.tag.ModuleTag import com.lambda.util.math.VecUtils.distSq import com.lambda.util.player.MovementUtils.buildMovementInput import com.lambda.util.player.MovementUtils.mergeFrom -import com.lambda.util.world.WorldUtils.getClosestEntity -import net.minecraft.entity.LivingEntity -import net.minecraft.entity.decoration.ArmorStandEntity import kotlin.math.pow object TargetStrafe : Module( @@ -22,8 +17,7 @@ object TargetStrafe : Module( description = "Automatically strafes around entities", defaultTags = setOf(ModuleTag.MOVEMENT) ) { - private val range by setting("Range", 6.0, 2.0..10.0, 0.1) - private val targetDistance by setting("Target Distance", 1.0, 0.0..5.0, 0.1) + private val targetDistance by setting("Strafe Distance", 1.0, 0.0..5.0, 0.1) private val jitterCompensation by setting("Jitter Compensation", 0.0, 0.0..1.0, 0.1) private val stabilize by setting("Stabilize", StabilizationMode.NORMAL) @@ -31,35 +25,23 @@ object TargetStrafe : Module( NONE, WEAK, NORMAL, STRONG } - private var targetEntity: LivingEntity? = null - private var forwardDirection = 1 private var strafeDirection = 1 - private val rotationConfig = object : IRotationConfig.Instant { - override val rotationMode = RotationMode.SYNC - } - - @JvmStatic val isActive get() = isEnabled && targetEntity != null + @JvmStatic val isActive get() = isEnabled && KillAura.isEnabled && KillAura.target != null init { listener { - // ToDo: Use KillAura.target instead - targetEntity = getClosestEntity( - player.pos, range, - predicate = { e -> e !is ArmorStandEntity } - ) - if (player.horizontalCollision) strafeDirection *= -1 - if (targetEntity == null) { + if (KillAura.target == null) { forwardDirection = 1 strafeDirection = 1 } } listener { event -> - targetEntity?.let { target -> + KillAura.target?.let { target -> event.strafeYaw = player.eyePos.rotationTo(target.boundingBox.center).yaw val distSq = player.pos distSq target.pos @@ -94,17 +76,7 @@ object TargetStrafe : Module( } } - listener { event -> - targetEntity?.let { - event.context = RotationContext( - player.eyePos.rotationTo(it.boundingBox.center), - rotationConfig - ) - } - } - onEnable { - targetEntity = null forwardDirection = 1 strafeDirection = 1 } diff --git a/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt b/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt index fe6e58320..6da6ef000 100644 --- a/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt +++ b/common/src/main/kotlin/com/lambda/util/math/Vec2d.kt @@ -1,5 +1,7 @@ package com.lambda.util.math +import kotlin.math.roundToInt + data class Vec2d(val x: Double, val y: Double) { constructor(x: Int, y: Int) : this(x.toDouble(), y.toDouble()) constructor(x: Float, y: Float) : this(x.toDouble(), y.toDouble()) @@ -22,6 +24,8 @@ data class Vec2d(val x: Double, val y: Double) { operator fun div(divider: Double) = div(divider, divider) fun div(x: Double, y: Double) = Vec2d(this.x / x, this.y / y) + fun roundToInt(): Vec2d = Vec2d(this.x.roundToInt(), this.y.roundToInt()) + companion object { val ZERO = Vec2d(0.0, 0.0) val ONE = Vec2d(1.0, 1.0) diff --git a/common/src/main/resources/lambda.accesswidener b/common/src/main/resources/lambda.accesswidener index 4a8c265d5..a48d8976a 100644 --- a/common/src/main/resources/lambda.accesswidener +++ b/common/src/main/resources/lambda.accesswidener @@ -18,6 +18,7 @@ accessible field net/minecraft/entity/projectile/FireworkRocketEntity shooter Ln accessible method net/minecraft/entity/Entity movementInputToVelocity (Lnet/minecraft/util/math/Vec3d;FF)Lnet/minecraft/util/math/Vec3d; accessible method net/minecraft/entity/passive/AbstractHorseEntity setHorseFlag (IZ)V accessible method net/minecraft/entity/passive/AbstractHorseEntity updateSaddle ()V +accessible field net/minecraft/entity/LivingEntity lastAttackedTicks I # Camera accessible method net/minecraft/client/render/Camera setPos (DDD)V From bd7ac3eda50cb1bf539698044cdda508cdc084f8 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Wed, 24 Jul 2024 12:24:15 +0300 Subject: [PATCH 18/35] Strafe event fix for silent rotations --- .../main/kotlin/com/lambda/interaction/RotationManager.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt index c3724b192..9f1f4f7f3 100644 --- a/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt +++ b/common/src/main/kotlin/com/lambda/interaction/RotationManager.kt @@ -226,8 +226,12 @@ object RotationManager : Loadable { // No changes are needed when no inputs are pressed if (signForward == 0f && signStrafe == 0f) return@runSafe - // Actual yaw used to move the player - val actualYaw = currentRotation.yaw + // Actual yaw used by the physics engine + var actualYaw = currentRotation.yaw + + if (currentContext?.config?.rotationMode == RotationMode.SILENT) { + actualYaw = player.yaw.toDouble() + } val yawRad = (movementYaw - actualYaw).toRadian() From 594c91341b454e914784667eef48477d52a0c7a5 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Fri, 26 Jul 2024 08:02:28 +0300 Subject: [PATCH 19/35] Criticals --- .../lambda/module/modules/combat/Criticals.kt | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/combat/Criticals.kt diff --git a/common/src/main/kotlin/com/lambda/module/modules/combat/Criticals.kt b/common/src/main/kotlin/com/lambda/module/modules/combat/Criticals.kt new file mode 100644 index 000000000..9dc83d2ab --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/combat/Criticals.kt @@ -0,0 +1,55 @@ +package com.lambda.module.modules.combat + +import com.lambda.context.SafeContext +import com.lambda.event.events.AttackEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.interaction.rotation.Rotation +import com.lambda.interaction.rotation.Rotation.Companion.rotationTo +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import com.lambda.util.primitives.extension.component1 +import com.lambda.util.primitives.extension.component2 +import com.lambda.util.primitives.extension.component3 +import com.lambda.util.primitives.extension.rotation +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket +import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket +import net.minecraft.util.Hand +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Direction + +object Criticals : Module( + name = "Criticals", + description = "Forces your hits to be critical", + defaultTags = setOf(ModuleTag.COMBAT) +) { + private val mode by setting("Mode", Mode.Grim) + + enum class Mode { + Grim + } + + init { + listener { + when (mode) { + Mode.Grim -> { + if (player.isOnGround) posPacket(0.00000001, rotation = player.rotation) + posPacket(-0.000000001, rotation = player.eyePos.rotationTo(it.entity.boundingBox.center)) + + connection.sendPacket(PlayerInteractItemC2SPacket(Hand.OFF_HAND, 0)) + connection.sendPacket(PlayerActionC2SPacket(PlayerActionC2SPacket.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, Direction.DOWN)) + } + } + } + } + + private fun SafeContext.posPacket(yOffset: Double, ground: Boolean = false, rotation: Rotation?) { + val (x, y, z) = player.pos + + val packet = rotation?.let { + PlayerMoveC2SPacket.Full(x, y + yOffset, z, it.yawF, it.pitchF, ground) + } ?: PlayerMoveC2SPacket.PositionAndOnGround(x, y + yOffset, z, ground) + + connection.sendPacket(packet) + } +} \ No newline at end of file From e802a53a1d478d3119e7b3b821b6fd87b3f37a43 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Fri, 26 Jul 2024 08:02:39 +0300 Subject: [PATCH 20/35] NoFall --- .../lambda/module/modules/movement/NoFall.kt | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/movement/NoFall.kt diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/NoFall.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/NoFall.kt new file mode 100644 index 000000000..73f630a8f --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/NoFall.kt @@ -0,0 +1,49 @@ +package com.lambda.module.modules.movement + +import com.lambda.event.events.MovementEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import com.lambda.util.player.MovementUtils.motion +import com.lambda.util.player.MovementUtils.motionY +import com.lambda.util.primitives.extension.component1 +import com.lambda.util.primitives.extension.component2 +import com.lambda.util.primitives.extension.component3 +import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket +import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket +import net.minecraft.util.Hand +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Direction +import net.minecraft.util.math.Vec3d + +object NoFall : Module( + name = "NoFall", + description = "Reduces fall damage", + defaultTags = setOf(ModuleTag.MOVEMENT) +) { + private val mode by setting("Mode", Mode.Grim) + + enum class Mode { + Grim + } + + init { + listener { + when (mode) { + Mode.Grim -> { + if (player.fallDistance + player.motionY < 3.0) return@listener + + val (x, y, z) = player.pos + connection.sendPacket(PlayerMoveC2SPacket.Full(x, y + 0.0000000001, z, 0.01f, 90f, false)) + connection.sendPacket(PlayerInteractItemC2SPacket(Hand.OFF_HAND, 0)) + connection.sendPacket(PlayerActionC2SPacket(PlayerActionC2SPacket.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, Direction.DOWN)) + player.motion = Vec3d.ZERO + + player.fallDistance = 0f + } + } + } + } + +} \ No newline at end of file From 72f88ad6de5449e635e195a8eb2e91165f747261 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Fri, 26 Jul 2024 20:16:45 +0300 Subject: [PATCH 21/35] Grim TickShift, Blink --- .../mixin/entity/ClientPlayerEntityMixin.java | 11 ++ .../mixin/render/RenderTickCounterMixin.java | 2 +- .../kotlin/com/lambda/core/TimerManager.kt | 18 +-- .../com/lambda/event/events/TickEvent.kt | 17 ++- .../graphics/renderer/esp/DynamicAABB.kt | 4 +- .../lambda/module/modules/combat/KillAura.kt | 24 ++-- .../lambda/module/modules/movement/Blink.kt | 98 ++++++++++++++++ .../module/modules/movement/TickShift.kt | 111 ++++++++++++++++++ .../lambda/module/modules/player/Replay.kt | 2 +- .../kotlin/com/lambda/util/PacketUtils.kt | 10 ++ 10 files changed, 277 insertions(+), 20 deletions(-) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt create mode 100644 common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt create mode 100644 common/src/main/kotlin/com/lambda/util/PacketUtils.kt diff --git a/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java b/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java index 8dfb2803a..89cb14a95 100644 --- a/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java +++ b/common/src/main/java/com/lambda/mixin/entity/ClientPlayerEntityMixin.java @@ -3,6 +3,7 @@ import com.lambda.Lambda; import com.lambda.event.EventFlow; import com.lambda.event.events.MovementEvent; +import com.lambda.event.events.TickEvent; import com.lambda.interaction.PlayerPacketManager; import com.lambda.interaction.RotationManager; import net.minecraft.client.input.Input; @@ -71,6 +72,16 @@ void sendBegin(CallbackInfo ci) { autoJumpEnabled = Lambda.getMc().options.getAutoJump().getValue(); } + @Inject(method = "tick", at = @At(value = "HEAD")) + void onTickPre(CallbackInfo ci) { + EventFlow.post(new TickEvent.Player.Pre()); + } + + @Inject(method = "tick", at = @At(value = "RETURN")) + void onTickPost(CallbackInfo ci) { + EventFlow.post(new TickEvent.Player.Post()); + } + @Redirect(method = "tickNewAi", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getYaw()F")) float fixHeldItemYaw(ClientPlayerEntity instance) { return Objects.requireNonNullElse(RotationManager.getHandYaw(), instance.getYaw()); diff --git a/common/src/main/java/com/lambda/mixin/render/RenderTickCounterMixin.java b/common/src/main/java/com/lambda/mixin/render/RenderTickCounterMixin.java index dd0f62f6e..7b87a3c11 100644 --- a/common/src/main/java/com/lambda/mixin/render/RenderTickCounterMixin.java +++ b/common/src/main/java/com/lambda/mixin/render/RenderTickCounterMixin.java @@ -20,7 +20,7 @@ public class RenderTickCounterMixin { @Inject(method = "beginRenderTick", at = @At("HEAD"), cancellable = true) private void beginRenderTick(long timeMillis, CallbackInfoReturnable ci) { - lastFrameDuration = (timeMillis - prevTimeMillis) / TimerManager.getTickLength(); + lastFrameDuration = (timeMillis - prevTimeMillis) / TimerManager.INSTANCE.getLength(); prevTimeMillis = timeMillis; tickDelta += lastFrameDuration; int i = (int) tickDelta; diff --git a/common/src/main/kotlin/com/lambda/core/TimerManager.kt b/common/src/main/kotlin/com/lambda/core/TimerManager.kt index 65196829b..ae78bf77d 100644 --- a/common/src/main/kotlin/com/lambda/core/TimerManager.kt +++ b/common/src/main/kotlin/com/lambda/core/TimerManager.kt @@ -2,18 +2,18 @@ package com.lambda.core import com.lambda.event.EventFlow.post import com.lambda.event.events.ClientEvent -import com.lambda.event.events.TickEvent -import com.lambda.event.listener.UnsafeListener.Companion.unsafeListener object TimerManager : Loadable { - @JvmStatic - var tickLength = 50f; private set + var lastTickLength: Float = 50f - init { - unsafeListener { - ClientEvent.Timer(1.0).post { - tickLength = 50f / speed.toFloat() - } + fun getLength(): Float { + var length = 50f + + ClientEvent.Timer(1.0).post { + length /= speed.toFloat() } + + lastTickLength = length + return length } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/event/events/TickEvent.kt b/common/src/main/kotlin/com/lambda/event/events/TickEvent.kt index 9e310ac0b..85f9b1a0a 100644 --- a/common/src/main/kotlin/com/lambda/event/events/TickEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/TickEvent.kt @@ -26,4 +26,19 @@ abstract class TickEvent : Event { * A class representing a [TickEvent] that is triggered after each tick of the game loop. */ class Post : TickEvent() -} \ No newline at end of file + + /** + * A class representing a [TickEvent] that is triggered when the player gets ticked. + */ + abstract class Player : TickEvent() { + /** + * A class representing a [TickEvent.Player] that is triggered before each player tick. + */ + class Pre : Player() + + /** + * A class representing a [TickEvent.Player] that is triggered after each player tick. + */ + class Post : Player() + } +} diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt index 35dd9d6ec..d9bc48e72 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt @@ -12,13 +12,15 @@ class DynamicAABB { private var prev: Box? = null private var curr: Box? = null - fun update(box: Box) { + fun update(box: Box): DynamicAABB { prev = curr curr = box if (prev == null) { prev = box } + + return this } fun reset() { diff --git a/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt b/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt index be5d58b35..72828cea1 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt @@ -61,13 +61,14 @@ object KillAura : Module( private val targeting = Targeting.Combat(this) { page == Page.Targeting } // Aiming - private val rotation = RotationSettings(this) { page == Page.Aiming } - private val stabilize by setting("Stabilize", true) { page == Page.Aiming && !rotation.instant } - private val centerFactor by setting("Center Factor", 0.4, 0.0..1.0, 0.01) { page == Page.Aiming } - private val shakeFactor by setting("Shake Factor", 0.4, 0.0..1.0, 0.01) { page == Page.Aiming } - private val shakeChance by setting("Shake Chance", 0.2, 0.05..1.0, 0.01) { page == Page.Aiming && shakeFactor > 0.0 } - private val selfPredict by setting("Self Predict", 1.0, 0.0..2.0, 0.1) { page == Page.Aiming } - private val targetPredict by setting("Target Predict", 0.0, 0.0..2.0, 0.1) { page == Page.Aiming } + private val rotate by setting("Rotate", true) { page == Page.Aiming } + private val rotation = RotationSettings(this) { page == Page.Aiming && rotate } + private val stabilize by setting("Stabilize", true) { page == Page.Aiming && !rotation.instant && rotate } + private val centerFactor by setting("Center Factor", 0.4, 0.0..1.0, 0.01) { page == Page.Aiming && rotate } + private val shakeFactor by setting("Shake Factor", 0.4, 0.0..1.0, 0.01) { page == Page.Aiming && rotate } + private val shakeChance by setting("Shake Chance", 0.2, 0.05..1.0, 0.01) { page == Page.Aiming && shakeFactor > 0.0 && rotate } + private val selfPredict by setting("Self Predict", 1.0, 0.0..2.0, 0.1) { page == Page.Aiming && rotate } + private val targetPredict by setting("Target Predict", 0.0, 0.0..2.0, 0.1) { page == Page.Aiming && rotate } var target: LivingEntity? = null; private set @@ -96,6 +97,8 @@ object KillAura : Module( init { requestRotation( onUpdate = { + if (!rotate) return@requestRotation null + target?.let { target -> buildRotation(target) } @@ -116,6 +119,12 @@ object KillAura : Module( listener { target = targeting.getTarget() if (!timerSync) attackTicks++ + + if (!rotate) { + target?.let { entity -> + runAttack(entity) + } + } } runConcurrent { @@ -252,6 +261,7 @@ object KillAura : Module( // Rotation check run { + if (!rotate) return@run val angle = RotationManager.currentRotation if (interactionSettings.useRayCast) { diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt new file mode 100644 index 000000000..68d5b708c --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt @@ -0,0 +1,98 @@ +package com.lambda.module.modules.movement + +import com.lambda.context.SafeContext +import com.lambda.event.events.PacketEvent +import com.lambda.event.events.RenderEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.graphics.renderer.esp.DynamicAABB +import com.lambda.graphics.renderer.esp.builders.build +import com.lambda.module.Module +import com.lambda.module.modules.client.GuiSettings +import com.lambda.module.modules.combat.KillAura +import com.lambda.module.tag.ModuleTag +import com.lambda.util.PacketUtils.sendPacketSilently +import com.lambda.util.math.ColorUtils.setAlpha +import net.minecraft.network.ClientConnection +import net.minecraft.network.packet.Packet +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket +import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Box +import java.util.concurrent.ConcurrentLinkedDeque + +object Blink : Module( + name = "Blink", + description = "Holds packets", + defaultTags = setOf(ModuleTag.MOVEMENT) +) { + private var delay by setting("Delay", 500, 50..10000, 10) + private val shiftVelocity by setting("Shift velocity", true) + private val requiresAura by setting("Requires Aura", false) + + private val isActive get() = (KillAura.isEnabled && KillAura.target != null) || !requiresAura + + private var packetPool = ConcurrentLinkedDeque>() + private var lastVelocity: EntityVelocityUpdateS2CPacket? = null + private var lastUpdate = 0L + + private var box = DynamicAABB() + private var lastBox = Box(BlockPos.ORIGIN) + + init { + listener { + val time = System.currentTimeMillis() + + if (isActive && time - lastUpdate < delay) return@listener + lastUpdate = time + + poolPackets() + } + + listener { event -> + val color = GuiSettings.primaryColor + event.renderer.build(box.update(lastBox), color.setAlpha(0.3), color) + } + + listener { event -> + if (!isActive) return@listener + + packetPool.add(event.packet) + event.cancel() + return@listener + } + + listener { event -> + if (!isActive || !shiftVelocity) return@listener + + if (event.packet !is EntityVelocityUpdateS2CPacket) return@listener + if (event.packet.id != player.id) return@listener + + lastVelocity = event.packet + event.cancel() + return@listener + } + + onDisable { + poolPackets() + } + } + + private fun SafeContext.poolPackets() { + while (packetPool.isNotEmpty()) { + packetPool.poll().let { packet -> + connection.sendPacketSilently(packet) + + if (packet is PlayerMoveC2SPacket && packet.changesPosition()) { + lastBox = player.boundingBox + .offset(player.pos.negate()) + .offset(packet.getX(0.0), packet.getY(0.0), packet.getZ(0.0)) + } + } + } + + lastVelocity?.let { velocity -> + ClientConnection.handlePacket(velocity, connection.connection.packetListener) + lastVelocity = null + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt new file mode 100644 index 000000000..a0a3b6d35 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt @@ -0,0 +1,111 @@ +package com.lambda.module.modules.movement + +import com.lambda.context.SafeContext +import com.lambda.event.events.ClientEvent +import com.lambda.event.events.PacketEvent +import com.lambda.event.events.TickEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.module.Module +import com.lambda.module.modules.combat.KillAura +import com.lambda.module.tag.ModuleTag +import com.lambda.threading.runConcurrent +import com.lambda.util.Communication.info +import com.lambda.util.PacketUtils.sendPacketSilently +import kotlinx.coroutines.delay +import net.minecraft.network.ClientConnection +import net.minecraft.network.packet.c2s.common.CommonPongC2SPacket +import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket + +object TickShift : Module( + name = "TickShift", + description = "Smort tickshift for smort anticheats", + defaultTags = setOf(ModuleTag.MOVEMENT) +) { + private val maxBalance by setting("Max Balance", 20, 3..400, 1) + private val boostAmount by setting("Boost", 3.0, 1.1..20.0, 0.01) + private val slowdown by setting("Slowdown", 0.35, 0.01..0.9, 0.01) + private val shiftVelocity by setting("Shift velocity", true) + private val requiresAura by setting("Requires Aura", false) + + private val isActive get() = (KillAura.isEnabled && KillAura.target != null) || !requiresAura + + private var pingPool = ArrayDeque() + private var lastVelocity: EntityVelocityUpdateS2CPacket? = null + + private var balance = 0 + private var boost = false + + init { + listener { + if (Blink.isEnabled) { + this@TickShift.info("TickShift is incompatible with blink") + disable() + } + + if (--balance <= 0) { + balance = 0 + boost = false + poolPackets() + } + } + + runConcurrent { + while (true) { + delay(50) + + if (++balance >= maxBalance) { + balance = maxBalance + boost = isActive + } + } + } + + listener { + if (!isActive) return@listener + it.speed = if (boost) boostAmount else slowdown + } + + listener { event -> + if (!isActive) return@listener + if (event.packet !is CommonPongC2SPacket) return@listener + + pingPool.add(event.packet) + event.cancel() + return@listener + } + + listener { event -> + if (!isActive || !shiftVelocity) return@listener + + if (event.packet !is EntityVelocityUpdateS2CPacket) return@listener + if (event.packet.id != player.id) return@listener + + lastVelocity = event.packet + event.cancel() + return@listener + } + + onEnable { + balance = 0 + boost = false + + pingPool.clear() + lastVelocity = null + } + + onDisable { + poolPackets() + } + } + + private fun SafeContext.poolPackets() { + while (pingPool.isNotEmpty()) { + connection.sendPacketSilently(pingPool.removeFirst()) + } + + lastVelocity?.let { velocity -> + ClientConnection.handlePacket(velocity, connection.connection.packetListener) + lastVelocity = null + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/player/Replay.kt b/common/src/main/kotlin/com/lambda/module/modules/player/Replay.kt index 62ea5d341..a25bba4ec 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/player/Replay.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/player/Replay.kt @@ -548,7 +548,7 @@ object Replay : Module( val size: Int get() = minOf(input.size, rotation.size, sprint.size, position.size) val duration: Duration - get() = (size * TimerManager.tickLength * 1.0).toDuration(DurationUnit.MILLISECONDS) + get() = (size * TimerManager.lastTickLength * 1.0).toDuration(DurationUnit.MILLISECONDS) val startPos: Vec3d get() = position.firstOrNull() ?: Vec3d.ZERO val endPos: Vec3d diff --git a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt new file mode 100644 index 000000000..4b7513253 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt @@ -0,0 +1,10 @@ +package com.lambda.util + +import net.minecraft.client.network.ClientPlayNetworkHandler +import net.minecraft.network.packet.Packet + +object PacketUtils { + fun ClientPlayNetworkHandler.sendPacketSilently(packet: Packet<*>) { + connection.send(packet, null, true) + } +} \ No newline at end of file From 54b93ad38dfeb1749c33b5d98e2608d3c42f4cad Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:30:55 -0400 Subject: [PATCH 22/35] fix: Check for open connection --- .../kotlin/com/lambda/module/modules/movement/Blink.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt index 68d5b708c..074cdab31 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt @@ -55,6 +55,7 @@ object Blink : Module( listener { event -> if (!isActive) return@listener + if (!connection.connection.isOpen) return@listener packetPool.add(event.packet) event.cancel() @@ -63,6 +64,8 @@ object Blink : Module( listener { event -> if (!isActive || !shiftVelocity) return@listener + if (!connection.connection.isOpen) return@listener + if (connection.connection.packetListener?.accepts(event.packet) == false) return@listener if (event.packet !is EntityVelocityUpdateS2CPacket) return@listener if (event.packet.id != player.id) return@listener @@ -81,6 +84,7 @@ object Blink : Module( while (packetPool.isNotEmpty()) { packetPool.poll().let { packet -> connection.sendPacketSilently(packet) + connection.connection.packetsSentCounter++ if (packet is PlayerMoveC2SPacket && packet.changesPosition()) { lastBox = player.boundingBox @@ -92,7 +96,8 @@ object Blink : Module( lastVelocity?.let { velocity -> ClientConnection.handlePacket(velocity, connection.connection.packetListener) + connection.connection.packetsReceivedCounter++ lastVelocity = null } } -} \ No newline at end of file +} From 7407fad2b4eacd5fa95e5f5cf0298b354709cc33 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Fri, 26 Jul 2024 21:04:57 -0400 Subject: [PATCH 23/35] refactor: packet event types --- .../lambda/mixin/ClientConnectionMixin.java | 10 +++-- .../com/lambda/event/events/PacketEvent.kt | 42 +++++++++++++++---- .../lambda/module/modules/movement/Blink.kt | 11 ++--- .../kotlin/com/lambda/util/PacketUtils.kt | 31 +++++++++++++- 4 files changed, 72 insertions(+), 22 deletions(-) diff --git a/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java b/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java index 29cc5bb7a..78542b841 100644 --- a/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java +++ b/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java @@ -6,7 +6,9 @@ import io.netty.channel.ChannelHandlerContext; import net.minecraft.network.ClientConnection; import net.minecraft.network.NetworkSide; +import net.minecraft.network.listener.ClientPacketListener; import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.listener.ServerPacketListener; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.handshake.ConnectionIntent; import net.minecraft.text.Text; @@ -25,14 +27,14 @@ public class ClientConnectionMixin { @Inject(method = "send(Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true) private void sendingPacket(Packet packet, final CallbackInfo callbackInfo) { - if (EventFlow.post(new PacketEvent.Send.Pre(packet)).isCanceled()) { + if (EventFlow.post(new PacketEvent.Send.Pre((Packet) packet)).isCanceled()) { callbackInfo.cancel(); } } @Inject(method = "send(Lnet/minecraft/network/packet/Packet;)V", at = @At("RETURN")) private void sendingPacketPost(Packet packet, final CallbackInfo callbackInfo) { - EventFlow.post(new PacketEvent.Send.Post(packet)); + EventFlow.post(new PacketEvent.Send.Post((Packet) packet)); } @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;handlePacket(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;)V", shift = At.Shift.BEFORE), cancellable = true, require = 1) @@ -42,7 +44,7 @@ private void receivingPacket( CallbackInfo callbackInfo ) { if (side != NetworkSide.CLIENTBOUND) return; - if (EventFlow.post(new PacketEvent.Receive.Pre(packet)).isCanceled()) { + if (EventFlow.post(new PacketEvent.Receive.Pre((Packet) packet)).isCanceled()) { callbackInfo.cancel(); } } @@ -55,7 +57,7 @@ private void receivingPacketPost( ) { if (side != NetworkSide.CLIENTBOUND) return; - EventFlow.post(new PacketEvent.Receive.Post(packet)); + EventFlow.post(new PacketEvent.Receive.Post((Packet) packet)); } @Inject(method = "connect(Ljava/lang/String;ILnet/minecraft/network/listener/PacketListener;Lnet/minecraft/network/packet/c2s/handshake/ConnectionIntent;)V", at = @At("HEAD")) diff --git a/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt b/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt index af8ada9fc..989145eb4 100644 --- a/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt @@ -6,13 +6,15 @@ import com.lambda.event.callback.Cancellable import com.lambda.event.callback.ICancellable import com.lambda.event.events.PacketEvent.Receive import com.lambda.event.events.PacketEvent.Send +import net.minecraft.network.listener.ClientPacketListener +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet /** * An abstract class representing a [PacketEvent] in the [EventFlow]. * * A [PacketEvent] is a type of [Event] that is triggered when a packet is sent or received. - * It has two subclasses: [Send] and [Receive], + * It has two sealed subclasses: [Send] and [Receive], * which are triggered when a packet is sent and received, respectively. * * Each subclass has two further subclasses: `Pre` and `Post`, @@ -25,20 +27,42 @@ import net.minecraft.network.packet.Packet */ abstract class PacketEvent : Event { /** - * Representing a [PacketEvent] that is triggered when a packet is sent. + * Represents a [PacketEvent] that is triggered when a packet is sent. * It has two subclasses: [Pre] and [Post], which are triggered before and after the packet is sent. */ - abstract class Send : PacketEvent() { - class Pre(val packet: Packet<*>) : Send(), ICancellable by Cancellable() - class Post(val packet: Packet<*>) : Send() + sealed class Send : PacketEvent() { + /** + * Represents the event triggered before a packet is sent. + * + * @param packet the packet that is about to be sent. + */ + class Pre(val packet: Packet) : Send(), ICancellable by Cancellable() + + /** + * Represents the event triggered after a packet is sent. + * + * @param packet the packet that has been sent. + */ + class Post(val packet: Packet) : Send() } /** - * Representing a `PacketEvent` that is triggered when a packet is received. + * Represents a [PacketEvent] that is triggered when a packet is received. * It has two subclasses: [Pre] and [Post], which are triggered before and after the packet is received. */ - abstract class Receive : PacketEvent() { - class Pre(val packet: Packet<*>) : Receive(), ICancellable by Cancellable() - class Post(val packet: Packet<*>) : Receive() + sealed class Receive : PacketEvent() { + /** + * Represents the event triggered before a packet is received. + * + * @param packet the packet that is about to be received. + */ + class Pre(val packet: Packet) : Receive(), ICancellable by Cancellable() + + /** + * Represents the event triggered after a packet is received. + * + * @param packet the packet that has been received. + */ + class Post(val packet: Packet) : Receive() } } diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt index 074cdab31..467d2da32 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt @@ -10,9 +10,10 @@ import com.lambda.module.Module import com.lambda.module.modules.client.GuiSettings import com.lambda.module.modules.combat.KillAura import com.lambda.module.tag.ModuleTag +import com.lambda.util.PacketUtils.handlePacketSilently import com.lambda.util.PacketUtils.sendPacketSilently import com.lambda.util.math.ColorUtils.setAlpha -import net.minecraft.network.ClientConnection +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket @@ -31,7 +32,7 @@ object Blink : Module( private val isActive get() = (KillAura.isEnabled && KillAura.target != null) || !requiresAura - private var packetPool = ConcurrentLinkedDeque>() + private var packetPool = ConcurrentLinkedDeque>() private var lastVelocity: EntityVelocityUpdateS2CPacket? = null private var lastUpdate = 0L @@ -64,8 +65,6 @@ object Blink : Module( listener { event -> if (!isActive || !shiftVelocity) return@listener - if (!connection.connection.isOpen) return@listener - if (connection.connection.packetListener?.accepts(event.packet) == false) return@listener if (event.packet !is EntityVelocityUpdateS2CPacket) return@listener if (event.packet.id != player.id) return@listener @@ -84,7 +83,6 @@ object Blink : Module( while (packetPool.isNotEmpty()) { packetPool.poll().let { packet -> connection.sendPacketSilently(packet) - connection.connection.packetsSentCounter++ if (packet is PlayerMoveC2SPacket && packet.changesPosition()) { lastBox = player.boundingBox @@ -95,8 +93,7 @@ object Blink : Module( } lastVelocity?.let { velocity -> - ClientConnection.handlePacket(velocity, connection.connection.packetListener) - connection.connection.packetsReceivedCounter++ + connection.handlePacketSilently(velocity) lastVelocity = null } } diff --git a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt index 4b7513253..7ba4ba86f 100644 --- a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt @@ -1,10 +1,37 @@ package com.lambda.util import net.minecraft.client.network.ClientPlayNetworkHandler +import net.minecraft.network.ClientConnection +import net.minecraft.network.listener.ClientPacketListener +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet object PacketUtils { - fun ClientPlayNetworkHandler.sendPacketSilently(packet: Packet<*>) { + /** + * Sends a packet to the server without notifying the client. + * It bypasses the mixins that would normally intercept the packet + * and send it through the client's event bus. + * + * @param packet The packet to send. + */ + fun ClientPlayNetworkHandler.sendPacketSilently(packet: Packet) { + if (!connection.isOpen) return connection.send(packet, null, true) + connection.packetsSentCounter++ } -} \ No newline at end of file + + /** + * Handles a packet without notifying the client. + * It bypasses the mixins that would normally intercept the packet + * and send it through the client's event bus. + * + * @param packet The packet to handle. + */ + fun ClientPlayNetworkHandler.handlePacketSilently(packet: Packet) { + if (!connection.isOpen) return + if (connection.packetListener?.accepts(packet) == false) return + + ClientConnection.handlePacket(packet, connection.packetListener) + connection.packetsReceivedCounter++ + } +} From 2906fe3ff738514ba1df0a3e95c0c981226f2167 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Fri, 26 Jul 2024 21:05:32 -0400 Subject: [PATCH 24/35] feat: static & dynamic delay mode --- .../module/modules/network/PacketDelay.kt | 108 +++++++++++++----- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt b/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt index 69ff8ef3a..4f1acfd53 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt @@ -1,66 +1,120 @@ package com.lambda.module.modules.network +import com.lambda.context.SafeContext import com.lambda.event.events.PacketEvent +import com.lambda.event.events.RenderEvent import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.threading.runConcurrent import com.lambda.threading.runGameScheduled +import com.lambda.util.PacketUtils.handlePacketSilently +import com.lambda.util.PacketUtils.sendPacketSilently import kotlinx.coroutines.delay -import net.minecraft.network.ClientConnection +import net.minecraft.network.listener.ClientPacketListener +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet import net.minecraft.network.packet.c2s.common.KeepAliveC2SPacket +import java.util.concurrent.ConcurrentLinkedDeque object PacketDelay : Module( name = "PacketDelay", description = "Delays packets client-side & server-side.", defaultTags = setOf(ModuleTag.NETWORK), ) { + private val mode by setting("Mode", Mode.STATIC) private val networkScope by setting("Network Scope", Direction.BOTH) private val packetScope by setting("Packet Scope", PacketType.ANY) private val inboundDelay by setting("Inbound Delay", 250L, 0L..5000L, 10L, unit = "ms") { networkScope != Direction.OUTBOUND } private val outboundDelay by setting("Outbound Delay", 250L, 0L..5000L, 10L, unit = "ms") { networkScope != Direction.INBOUND } - enum class Direction { - BOTH, - INBOUND, - OUTBOUND - } - - enum class PacketType(val filter: (Packet<*>) -> Boolean) { - ANY({ true }), - KEEP_ALIVE({ it is KeepAliveC2SPacket }) - } + private var outboundPool = ConcurrentLinkedDeque>() + private var inboundPool = ConcurrentLinkedDeque>() + private var outboundLastUpdate = 0L + private var inboundLastUpdate = 0L init { - listener(Int.MIN_VALUE) { event -> - if (!connection.connection.isOpen) return@listener + listener { + if (mode != Mode.STATIC) return@listener + + flushPools(System.currentTimeMillis()) + } + + listener(Int.MIN_VALUE) { event -> if (!packetScope.filter(event.packet)) return@listener - event.cancel() - runConcurrent { - delay(inboundDelay) - runGameScheduled { - if (connection.connection.packetListener?.accepts(event.packet) == false) return@runGameScheduled + when (mode) { + Mode.STATIC -> { + outboundPool.add(event.packet) + event.cancel() + } - ClientConnection.handlePacket(event.packet, connection.connection.packetListener) - connection.connection.packetsReceivedCounter++ + Mode.PULSE -> { + runConcurrent { + delay(outboundDelay) + runGameScheduled { + connection.sendPacketSilently(event.packet) + } + } + event.cancel() } } } - listener(Int.MIN_VALUE) { event -> - if (!connection.connection.isOpen) return@listener + listener(Int.MIN_VALUE) { event -> if (!packetScope.filter(event.packet)) return@listener + + when (mode) { + Mode.STATIC -> { + inboundPool.add(event.packet) + event.cancel() + } + + Mode.PULSE -> { + runConcurrent { + delay(inboundDelay) + runGameScheduled { + connection.handlePacketSilently(event.packet) + } + } + event.cancel() + } + } + event.cancel() + } + + onDisable { + flushPools(System.currentTimeMillis()) + } + } + + private fun SafeContext.flushPools(time: Long) { + if (time - outboundLastUpdate >= outboundDelay) { + while (outboundPool.isNotEmpty()) { + outboundPool.poll().let { packet -> + connection.sendPacketSilently(packet) + } + } + + outboundLastUpdate = time + } - runConcurrent { - delay(outboundDelay) - runGameScheduled { - connection.connection.send(event.packet, null) - connection.connection.packetsSentCounter++ + if (time - inboundLastUpdate >= inboundDelay) { + while (inboundPool.isNotEmpty()) { + inboundPool.poll().let { packet -> + connection.handlePacketSilently(packet) } } + + inboundLastUpdate = time } } + + enum class Mode { STATIC, PULSE, } + enum class Direction { BOTH, INBOUND, OUTBOUND } + enum class PacketType(val filter: (Packet<*>) -> Boolean) { + ANY({ true }), + KEEP_ALIVE({ it is KeepAliveC2SPacket }) + } } From f87fc2bc35a05b36b2cfe99a0c669a0c38c5405a Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sun, 28 Jul 2024 16:20:00 +0300 Subject: [PATCH 25/35] Gui window skrilling --- .../kotlin/com/lambda/gui/api/GuiEvent.kt | 2 ++ .../kotlin/com/lambda/gui/api/LambdaGui.kt | 10 ++++++ .../lambda/gui/api/component/ListWindow.kt | 33 ++++++++++++++++--- .../gui/api/component/core/list/ChildLayer.kt | 2 +- .../lambda/module/modules/client/ClickGui.kt | 1 + 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/gui/api/GuiEvent.kt b/common/src/main/kotlin/com/lambda/gui/api/GuiEvent.kt index a9daccdac..abaeddd69 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/GuiEvent.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/GuiEvent.kt @@ -4,6 +4,7 @@ import com.lambda.event.Event import com.lambda.util.KeyCode import com.lambda.util.Mouse import com.lambda.util.math.Vec2d +import net.minecraft.world.gen.feature.DeltaFeature abstract class GuiEvent : Event { class Show : GuiEvent() @@ -14,4 +15,5 @@ abstract class GuiEvent : Event { class CharTyped(val char: Char) : GuiEvent() class MouseClick(val button: Mouse.Button, val action: Mouse.Action, val mouse: Vec2d) : GuiEvent() class MouseMove(val mouse: Vec2d) : GuiEvent() + class MouseScroll(val mouse: Vec2d, val delta: Double) : GuiEvent() } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt index 46e708b2f..d495a43e9 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt @@ -131,6 +131,16 @@ abstract class LambdaGui( onEvent(GuiEvent.MouseMove(rescaleMouse(mouseX, mouseY))) } + override fun mouseScrolled( + mouseX: Double, + mouseY: Double, + horizontalAmount: Double, + verticalAmount: Double + ): Boolean { + onEvent(GuiEvent.MouseScroll(rescaleMouse(mouseX, mouseY), verticalAmount)) + return true + } + final override fun shouldPause() = false private fun rescaleMouse(mouseX: Double, mouseY: Double): Vec2d { diff --git a/common/src/main/kotlin/com/lambda/gui/api/component/ListWindow.kt b/common/src/main/kotlin/com/lambda/gui/api/component/ListWindow.kt index 3128a9190..0329f3dcf 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/component/ListWindow.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/component/ListWindow.kt @@ -3,16 +3,39 @@ package com.lambda.gui.api.component import com.lambda.gui.api.GuiEvent import com.lambda.gui.api.component.button.ListButton import com.lambda.gui.impl.AbstractClickGui +import com.lambda.module.modules.client.ClickGui abstract class ListWindow( owner: AbstractClickGui, ) : WindowComponent(owner) { + private var scrollOffset: Double = 0.0 + private var rubberbandRequest = 0.0 + private var rubberbandDelta = 0.0 + override fun onEvent(e: GuiEvent) { - if (e is GuiEvent.Tick) { - var y = 0.0 - contentComponents.children.forEach { button -> - button.heightOffset = y - y += button.size.y + button.listStep + when (e) { + is GuiEvent.Tick -> { + rubberbandDelta += rubberbandRequest + rubberbandRequest = 0.0 + + rubberbandDelta *= 0.5 + if (rubberbandDelta < 0.05) rubberbandDelta = 0.0 + + var y = scrollOffset + rubberbandDelta + contentComponents.children.forEach { button -> + button.heightOffset = y + y += button.size.y + button.listStep + } + } + is GuiEvent.MouseScroll -> { + val delta = e.delta * 10.0 * ClickGui.scrollSpeed + scrollOffset += delta + + val prevOffset = scrollOffset + val range = -contentComponents.children.sumOf { it.size.y + it.listStep } + scrollOffset = scrollOffset.coerceAtLeast(range).coerceAtMost(0.0) + + rubberbandRequest += prevOffset - scrollOffset } } diff --git a/common/src/main/kotlin/com/lambda/gui/api/component/core/list/ChildLayer.kt b/common/src/main/kotlin/com/lambda/gui/api/component/core/list/ChildLayer.kt index f27b4329e..a1ec50eff 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/component/core/list/ChildLayer.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/component/core/list/ChildLayer.kt @@ -28,7 +28,7 @@ open class ChildLayer( childAccessible(child) && child.rect in rect && ownerAccessible && ownerComponent.isActive } - is GuiEvent.KeyPress, is GuiEvent.CharTyped -> { + is GuiEvent.KeyPress, is GuiEvent.CharTyped, is GuiEvent.MouseScroll -> { if (!child.accessible) return@forEach } diff --git a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt index 165dd1768..49d01f942 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/client/ClickGui.kt @@ -26,6 +26,7 @@ object ClickGui : Module( // Animation val openSpeed by setting("Open Speed", 0.5, 0.1..1.0, 0.01) val closeSpeed by setting("Close Speed", 0.5, 0.1..1.0, 0.01) + val scrollSpeed by setting("Scroll Speed", 1.0, 0.1..10.0, 0.01) // Alignment val allowHAlign by setting("Allow H Docking", false) From d94821b9b39b489d44bf36032f1136e596dc642e Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:30:55 -0400 Subject: [PATCH 26/35] fix: Check for open connection --- .../kotlin/com/lambda/module/modules/movement/Blink.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt index 68d5b708c..074cdab31 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt @@ -55,6 +55,7 @@ object Blink : Module( listener { event -> if (!isActive) return@listener + if (!connection.connection.isOpen) return@listener packetPool.add(event.packet) event.cancel() @@ -63,6 +64,8 @@ object Blink : Module( listener { event -> if (!isActive || !shiftVelocity) return@listener + if (!connection.connection.isOpen) return@listener + if (connection.connection.packetListener?.accepts(event.packet) == false) return@listener if (event.packet !is EntityVelocityUpdateS2CPacket) return@listener if (event.packet.id != player.id) return@listener @@ -81,6 +84,7 @@ object Blink : Module( while (packetPool.isNotEmpty()) { packetPool.poll().let { packet -> connection.sendPacketSilently(packet) + connection.connection.packetsSentCounter++ if (packet is PlayerMoveC2SPacket && packet.changesPosition()) { lastBox = player.boundingBox @@ -92,7 +96,8 @@ object Blink : Module( lastVelocity?.let { velocity -> ClientConnection.handlePacket(velocity, connection.connection.packetListener) + connection.connection.packetsReceivedCounter++ lastVelocity = null } } -} \ No newline at end of file +} From 5883c884b46ee8906c5a46e7485d5bcc5341b576 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Fri, 26 Jul 2024 21:04:57 -0400 Subject: [PATCH 27/35] refactor: packet event types --- .../lambda/mixin/ClientConnectionMixin.java | 10 +++-- .../com/lambda/event/events/PacketEvent.kt | 42 +++++++++++++++---- .../lambda/module/modules/movement/Blink.kt | 11 ++--- .../kotlin/com/lambda/util/PacketUtils.kt | 31 +++++++++++++- 4 files changed, 72 insertions(+), 22 deletions(-) diff --git a/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java b/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java index 29cc5bb7a..78542b841 100644 --- a/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java +++ b/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java @@ -6,7 +6,9 @@ import io.netty.channel.ChannelHandlerContext; import net.minecraft.network.ClientConnection; import net.minecraft.network.NetworkSide; +import net.minecraft.network.listener.ClientPacketListener; import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.listener.ServerPacketListener; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.c2s.handshake.ConnectionIntent; import net.minecraft.text.Text; @@ -25,14 +27,14 @@ public class ClientConnectionMixin { @Inject(method = "send(Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true) private void sendingPacket(Packet packet, final CallbackInfo callbackInfo) { - if (EventFlow.post(new PacketEvent.Send.Pre(packet)).isCanceled()) { + if (EventFlow.post(new PacketEvent.Send.Pre((Packet) packet)).isCanceled()) { callbackInfo.cancel(); } } @Inject(method = "send(Lnet/minecraft/network/packet/Packet;)V", at = @At("RETURN")) private void sendingPacketPost(Packet packet, final CallbackInfo callbackInfo) { - EventFlow.post(new PacketEvent.Send.Post(packet)); + EventFlow.post(new PacketEvent.Send.Post((Packet) packet)); } @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;handlePacket(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;)V", shift = At.Shift.BEFORE), cancellable = true, require = 1) @@ -42,7 +44,7 @@ private void receivingPacket( CallbackInfo callbackInfo ) { if (side != NetworkSide.CLIENTBOUND) return; - if (EventFlow.post(new PacketEvent.Receive.Pre(packet)).isCanceled()) { + if (EventFlow.post(new PacketEvent.Receive.Pre((Packet) packet)).isCanceled()) { callbackInfo.cancel(); } } @@ -55,7 +57,7 @@ private void receivingPacketPost( ) { if (side != NetworkSide.CLIENTBOUND) return; - EventFlow.post(new PacketEvent.Receive.Post(packet)); + EventFlow.post(new PacketEvent.Receive.Post((Packet) packet)); } @Inject(method = "connect(Ljava/lang/String;ILnet/minecraft/network/listener/PacketListener;Lnet/minecraft/network/packet/c2s/handshake/ConnectionIntent;)V", at = @At("HEAD")) diff --git a/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt b/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt index af8ada9fc..989145eb4 100644 --- a/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt @@ -6,13 +6,15 @@ import com.lambda.event.callback.Cancellable import com.lambda.event.callback.ICancellable import com.lambda.event.events.PacketEvent.Receive import com.lambda.event.events.PacketEvent.Send +import net.minecraft.network.listener.ClientPacketListener +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet /** * An abstract class representing a [PacketEvent] in the [EventFlow]. * * A [PacketEvent] is a type of [Event] that is triggered when a packet is sent or received. - * It has two subclasses: [Send] and [Receive], + * It has two sealed subclasses: [Send] and [Receive], * which are triggered when a packet is sent and received, respectively. * * Each subclass has two further subclasses: `Pre` and `Post`, @@ -25,20 +27,42 @@ import net.minecraft.network.packet.Packet */ abstract class PacketEvent : Event { /** - * Representing a [PacketEvent] that is triggered when a packet is sent. + * Represents a [PacketEvent] that is triggered when a packet is sent. * It has two subclasses: [Pre] and [Post], which are triggered before and after the packet is sent. */ - abstract class Send : PacketEvent() { - class Pre(val packet: Packet<*>) : Send(), ICancellable by Cancellable() - class Post(val packet: Packet<*>) : Send() + sealed class Send : PacketEvent() { + /** + * Represents the event triggered before a packet is sent. + * + * @param packet the packet that is about to be sent. + */ + class Pre(val packet: Packet) : Send(), ICancellable by Cancellable() + + /** + * Represents the event triggered after a packet is sent. + * + * @param packet the packet that has been sent. + */ + class Post(val packet: Packet) : Send() } /** - * Representing a `PacketEvent` that is triggered when a packet is received. + * Represents a [PacketEvent] that is triggered when a packet is received. * It has two subclasses: [Pre] and [Post], which are triggered before and after the packet is received. */ - abstract class Receive : PacketEvent() { - class Pre(val packet: Packet<*>) : Receive(), ICancellable by Cancellable() - class Post(val packet: Packet<*>) : Receive() + sealed class Receive : PacketEvent() { + /** + * Represents the event triggered before a packet is received. + * + * @param packet the packet that is about to be received. + */ + class Pre(val packet: Packet) : Receive(), ICancellable by Cancellable() + + /** + * Represents the event triggered after a packet is received. + * + * @param packet the packet that has been received. + */ + class Post(val packet: Packet) : Receive() } } diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt index 074cdab31..467d2da32 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt @@ -10,9 +10,10 @@ import com.lambda.module.Module import com.lambda.module.modules.client.GuiSettings import com.lambda.module.modules.combat.KillAura import com.lambda.module.tag.ModuleTag +import com.lambda.util.PacketUtils.handlePacketSilently import com.lambda.util.PacketUtils.sendPacketSilently import com.lambda.util.math.ColorUtils.setAlpha -import net.minecraft.network.ClientConnection +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket @@ -31,7 +32,7 @@ object Blink : Module( private val isActive get() = (KillAura.isEnabled && KillAura.target != null) || !requiresAura - private var packetPool = ConcurrentLinkedDeque>() + private var packetPool = ConcurrentLinkedDeque>() private var lastVelocity: EntityVelocityUpdateS2CPacket? = null private var lastUpdate = 0L @@ -64,8 +65,6 @@ object Blink : Module( listener { event -> if (!isActive || !shiftVelocity) return@listener - if (!connection.connection.isOpen) return@listener - if (connection.connection.packetListener?.accepts(event.packet) == false) return@listener if (event.packet !is EntityVelocityUpdateS2CPacket) return@listener if (event.packet.id != player.id) return@listener @@ -84,7 +83,6 @@ object Blink : Module( while (packetPool.isNotEmpty()) { packetPool.poll().let { packet -> connection.sendPacketSilently(packet) - connection.connection.packetsSentCounter++ if (packet is PlayerMoveC2SPacket && packet.changesPosition()) { lastBox = player.boundingBox @@ -95,8 +93,7 @@ object Blink : Module( } lastVelocity?.let { velocity -> - ClientConnection.handlePacket(velocity, connection.connection.packetListener) - connection.connection.packetsReceivedCounter++ + connection.handlePacketSilently(velocity) lastVelocity = null } } diff --git a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt index 4b7513253..7ba4ba86f 100644 --- a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt @@ -1,10 +1,37 @@ package com.lambda.util import net.minecraft.client.network.ClientPlayNetworkHandler +import net.minecraft.network.ClientConnection +import net.minecraft.network.listener.ClientPacketListener +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet object PacketUtils { - fun ClientPlayNetworkHandler.sendPacketSilently(packet: Packet<*>) { + /** + * Sends a packet to the server without notifying the client. + * It bypasses the mixins that would normally intercept the packet + * and send it through the client's event bus. + * + * @param packet The packet to send. + */ + fun ClientPlayNetworkHandler.sendPacketSilently(packet: Packet) { + if (!connection.isOpen) return connection.send(packet, null, true) + connection.packetsSentCounter++ } -} \ No newline at end of file + + /** + * Handles a packet without notifying the client. + * It bypasses the mixins that would normally intercept the packet + * and send it through the client's event bus. + * + * @param packet The packet to handle. + */ + fun ClientPlayNetworkHandler.handlePacketSilently(packet: Packet) { + if (!connection.isOpen) return + if (connection.packetListener?.accepts(packet) == false) return + + ClientConnection.handlePacket(packet, connection.packetListener) + connection.packetsReceivedCounter++ + } +} From b0995e7c9fb54e0445473a72aa4c3e5768ab2b90 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Fri, 26 Jul 2024 21:05:32 -0400 Subject: [PATCH 28/35] feat: static & dynamic delay mode --- .../module/modules/network/PacketDelay.kt | 108 +++++++++++++----- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt b/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt index 69ff8ef3a..4f1acfd53 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt @@ -1,66 +1,120 @@ package com.lambda.module.modules.network +import com.lambda.context.SafeContext import com.lambda.event.events.PacketEvent +import com.lambda.event.events.RenderEvent import com.lambda.event.listener.SafeListener.Companion.listener import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.threading.runConcurrent import com.lambda.threading.runGameScheduled +import com.lambda.util.PacketUtils.handlePacketSilently +import com.lambda.util.PacketUtils.sendPacketSilently import kotlinx.coroutines.delay -import net.minecraft.network.ClientConnection +import net.minecraft.network.listener.ClientPacketListener +import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet import net.minecraft.network.packet.c2s.common.KeepAliveC2SPacket +import java.util.concurrent.ConcurrentLinkedDeque object PacketDelay : Module( name = "PacketDelay", description = "Delays packets client-side & server-side.", defaultTags = setOf(ModuleTag.NETWORK), ) { + private val mode by setting("Mode", Mode.STATIC) private val networkScope by setting("Network Scope", Direction.BOTH) private val packetScope by setting("Packet Scope", PacketType.ANY) private val inboundDelay by setting("Inbound Delay", 250L, 0L..5000L, 10L, unit = "ms") { networkScope != Direction.OUTBOUND } private val outboundDelay by setting("Outbound Delay", 250L, 0L..5000L, 10L, unit = "ms") { networkScope != Direction.INBOUND } - enum class Direction { - BOTH, - INBOUND, - OUTBOUND - } - - enum class PacketType(val filter: (Packet<*>) -> Boolean) { - ANY({ true }), - KEEP_ALIVE({ it is KeepAliveC2SPacket }) - } + private var outboundPool = ConcurrentLinkedDeque>() + private var inboundPool = ConcurrentLinkedDeque>() + private var outboundLastUpdate = 0L + private var inboundLastUpdate = 0L init { - listener(Int.MIN_VALUE) { event -> - if (!connection.connection.isOpen) return@listener + listener { + if (mode != Mode.STATIC) return@listener + + flushPools(System.currentTimeMillis()) + } + + listener(Int.MIN_VALUE) { event -> if (!packetScope.filter(event.packet)) return@listener - event.cancel() - runConcurrent { - delay(inboundDelay) - runGameScheduled { - if (connection.connection.packetListener?.accepts(event.packet) == false) return@runGameScheduled + when (mode) { + Mode.STATIC -> { + outboundPool.add(event.packet) + event.cancel() + } - ClientConnection.handlePacket(event.packet, connection.connection.packetListener) - connection.connection.packetsReceivedCounter++ + Mode.PULSE -> { + runConcurrent { + delay(outboundDelay) + runGameScheduled { + connection.sendPacketSilently(event.packet) + } + } + event.cancel() } } } - listener(Int.MIN_VALUE) { event -> - if (!connection.connection.isOpen) return@listener + listener(Int.MIN_VALUE) { event -> if (!packetScope.filter(event.packet)) return@listener + + when (mode) { + Mode.STATIC -> { + inboundPool.add(event.packet) + event.cancel() + } + + Mode.PULSE -> { + runConcurrent { + delay(inboundDelay) + runGameScheduled { + connection.handlePacketSilently(event.packet) + } + } + event.cancel() + } + } + event.cancel() + } + + onDisable { + flushPools(System.currentTimeMillis()) + } + } + + private fun SafeContext.flushPools(time: Long) { + if (time - outboundLastUpdate >= outboundDelay) { + while (outboundPool.isNotEmpty()) { + outboundPool.poll().let { packet -> + connection.sendPacketSilently(packet) + } + } + + outboundLastUpdate = time + } - runConcurrent { - delay(outboundDelay) - runGameScheduled { - connection.connection.send(event.packet, null) - connection.connection.packetsSentCounter++ + if (time - inboundLastUpdate >= inboundDelay) { + while (inboundPool.isNotEmpty()) { + inboundPool.poll().let { packet -> + connection.handlePacketSilently(packet) } } + + inboundLastUpdate = time } } + + enum class Mode { STATIC, PULSE, } + enum class Direction { BOTH, INBOUND, OUTBOUND } + enum class PacketType(val filter: (Packet<*>) -> Boolean) { + ANY({ true }), + KEEP_ALIVE({ it is KeepAliveC2SPacket }) + } } From 4b950ba3873f1fc6409ab092c1626c0400e87b4f Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Tue, 30 Jul 2024 20:19:16 +0300 Subject: [PATCH 29/35] Tick Shift renderer & refactor --- .../com/lambda/event/events/PacketEvent.kt | 10 ++-- .../renderer/gui/rect/FilledRectRenderer.kt | 2 +- .../renderer/gui/rect/OutlineRectRenderer.kt | 2 +- .../kotlin/com/lambda/module/HudModule.kt | 8 +++ .../com/lambda/module/hud/TickShiftCharge.kt | 55 +++++++++++++++++++ .../module/modules/movement/TickShift.kt | 55 ++++++++++++++----- .../kotlin/com/lambda/util/PacketUtils.kt | 7 ++- 7 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 common/src/main/kotlin/com/lambda/module/hud/TickShiftCharge.kt diff --git a/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt b/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt index 989145eb4..7a9156882 100644 --- a/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/PacketEvent.kt @@ -6,6 +6,8 @@ import com.lambda.event.callback.Cancellable import com.lambda.event.callback.ICancellable import com.lambda.event.events.PacketEvent.Receive import com.lambda.event.events.PacketEvent.Send +import com.lambda.util.ClientPacket +import com.lambda.util.ServerPacket import net.minecraft.network.listener.ClientPacketListener import net.minecraft.network.listener.ServerPacketListener import net.minecraft.network.packet.Packet @@ -36,14 +38,14 @@ abstract class PacketEvent : Event { * * @param packet the packet that is about to be sent. */ - class Pre(val packet: Packet) : Send(), ICancellable by Cancellable() + class Pre(val packet: ClientPacket) : Send(), ICancellable by Cancellable() /** * Represents the event triggered after a packet is sent. * * @param packet the packet that has been sent. */ - class Post(val packet: Packet) : Send() + class Post(val packet: ClientPacket) : Send() } /** @@ -56,13 +58,13 @@ abstract class PacketEvent : Event { * * @param packet the packet that is about to be received. */ - class Pre(val packet: Packet) : Receive(), ICancellable by Cancellable() + class Pre(val packet: ServerPacket) : Receive(), ICancellable by Cancellable() /** * Represents the event triggered after a packet is received. * * @param packet the packet that has been received. */ - class Post(val packet: Packet) : Receive() + class Post(val packet: ServerPacket) : Receive() } } diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt index 86cee4a31..c19f128b1 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/FilledRectRenderer.kt @@ -41,7 +41,7 @@ class FilledRectRenderer : AbstractRectRenderer( val halfSize = size * 0.5 val maxRadius = min(halfSize.x, halfSize.y) - val round = min(roundRadius, maxRadius) + val round = roundRadius.coerceAtMost(maxRadius).coerceAtLeast(0.0) val p1 = pos1 - 0.25 val p2 = pos2 + 0.25 diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt index f23822ab7..84aa4ed88 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/rect/OutlineRectRenderer.kt @@ -47,7 +47,7 @@ class OutlineRectRenderer : AbstractRectRenderer( val halfSize = r.size * 0.5 val maxRadius = min(halfSize.x, halfSize.y) - 0.5 - val round = (roundRadius + size).coerceAtMost(maxRadius) + val round = (roundRadius + size).coerceAtMost(maxRadius).coerceAtLeast(0.0) fun MutableList.buildCorners(base: Vec2d, c: Color, angleRange: IntRange) = repeat(quality) { val min = angleRange.first.toDouble() diff --git a/common/src/main/kotlin/com/lambda/module/HudModule.kt b/common/src/main/kotlin/com/lambda/module/HudModule.kt index 265a31953..60e03b88e 100644 --- a/common/src/main/kotlin/com/lambda/module/HudModule.kt +++ b/common/src/main/kotlin/com/lambda/module/HudModule.kt @@ -1,7 +1,10 @@ package com.lambda.module import com.lambda.event.events.RenderEvent +import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.graphics.animation.AnimationTicker +import com.lambda.gui.api.GuiEvent import com.lambda.gui.api.RenderLayer import com.lambda.gui.api.component.core.DockingRect import com.lambda.module.tag.ModuleTag @@ -52,6 +55,7 @@ abstract class HudModule( var position by rectHandler::position val rect by rectHandler::rect + val animation = AnimationTicker() private val renderer = RenderLayer() @@ -68,5 +72,9 @@ abstract class HudModule( renderer.render() } + + listener { + animation.tick() + } } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/hud/TickShiftCharge.kt b/common/src/main/kotlin/com/lambda/module/hud/TickShiftCharge.kt new file mode 100644 index 000000000..fb7e8701e --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/hud/TickShiftCharge.kt @@ -0,0 +1,55 @@ +package com.lambda.module.hud + +import com.lambda.graphics.animation.Animation.Companion.exp +import com.lambda.module.HudModule +import com.lambda.module.modules.client.ClickGui +import com.lambda.module.modules.client.GuiSettings +import com.lambda.module.modules.client.GuiSettings.primaryColor +import com.lambda.module.modules.movement.TickShift +import com.lambda.module.tag.ModuleTag +import com.lambda.util.math.ColorUtils.multAlpha +import com.lambda.util.math.Rect +import java.awt.Color + +object TickShiftCharge : HudModule( + name = "TickShiftCharge", + defaultTags = setOf(ModuleTag.CLIENT), +) { + private val isActive get() = TickShift.isEnabled && TickShift.isActive && TickShift.boost + private val activeAnimation by animation.exp(0.0, 1.0, 0.6, ::isActive) + + private val progress get() = if (!TickShift.isActive) 0.0 + else (TickShift.balance / TickShift.maxBalance.toDouble()).coerceIn(0.0..1.0) + + private val renderProgress by animation.exp(::progress, 0.8) + + override val width = 70.0 + override val height = 14.0 + + init { + onRender { + filled.build( + rect = rect, + roundRadius = ClickGui.windowRadius, + color = GuiSettings.backgroundColor, + shade = GuiSettings.shadeBackground + ) + + val padding = 1.0 + filled.build( + rect = Rect.basedOn(rect.leftTop, rect.size.x * renderProgress, rect.size.y).shrink(padding), + roundRadius = ClickGui.windowRadius - padding, + color = GuiSettings.mainColor.multAlpha(0.3), + shade = true + ) + + outline.build( + rect = rect, + roundRadius = ClickGui.windowRadius, + color = (if (GuiSettings.shadeBackground) Color.WHITE else primaryColor).multAlpha(activeAnimation), + glowRadius = ClickGui.glowRadius * activeAnimation, + shade = true + ) + } + } +} \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt index a0a3b6d35..1f9d92f1c 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt @@ -10,10 +10,11 @@ import com.lambda.module.modules.combat.KillAura import com.lambda.module.tag.ModuleTag import com.lambda.threading.runConcurrent import com.lambda.util.Communication.info +import com.lambda.util.PacketUtils.handlePacketSilently import com.lambda.util.PacketUtils.sendPacketSilently import kotlinx.coroutines.delay -import net.minecraft.network.ClientConnection import net.minecraft.network.packet.c2s.common.CommonPongC2SPacket +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket object TickShift : Module( @@ -21,19 +22,25 @@ object TickShift : Module( description = "Smort tickshift for smort anticheats", defaultTags = setOf(ModuleTag.MOVEMENT) ) { - private val maxBalance by setting("Max Balance", 20, 3..400, 1) + val maxBalance by setting("Max Balance", 20, 3..400, 1) private val boostAmount by setting("Boost", 3.0, 1.1..20.0, 0.01) private val slowdown by setting("Slowdown", 0.35, 0.01..0.9, 0.01) + private val delaySetting by setting("Delay", 0, 0..2000, 10) + private val strict by setting("Strict", true) private val shiftVelocity by setting("Shift velocity", true) private val requiresAura by setting("Requires Aura", false) - private val isActive get() = (KillAura.isEnabled && KillAura.target != null) || !requiresAura + val isActive: Boolean get() { + if (requiresAura && (!KillAura.isEnabled || KillAura.target == null)) return false + return System.currentTimeMillis() - lastBoost > delaySetting + } private var pingPool = ArrayDeque() private var lastVelocity: EntityVelocityUpdateS2CPacket? = null - private var balance = 0 - private var boost = false + var balance = 0 + var boost = false + private var lastBoost = 0L init { listener { @@ -42,26 +49,43 @@ object TickShift : Module( disable() } - if (--balance <= 0) { + if (strict) balance-- + + if (balance <= 0) { balance = 0 - boost = false poolPackets() + + if (boost) { + boost = false + lastBoost = System.currentTimeMillis() + } } } + listener { + if (it.packet !is PlayerMoveC2SPacket) return@listener + if (!strict) balance-- + } + runConcurrent { while (true) { delay(50) - if (++balance >= maxBalance) { - balance = maxBalance - boost = isActive + if (isEnabled) { + if (++balance >= maxBalance) { + balance = maxBalance + boost = isActive + } } } } listener { - if (!isActive) return@listener + if (!isActive) { + poolPackets() + return@listener + } + it.speed = if (boost) boostAmount else slowdown } @@ -94,17 +118,20 @@ object TickShift : Module( } onDisable { + balance = 0 + boost = false + poolPackets() } } - + private fun SafeContext.poolPackets() { while (pingPool.isNotEmpty()) { connection.sendPacketSilently(pingPool.removeFirst()) } - lastVelocity?.let { velocity -> - ClientConnection.handlePacket(velocity, connection.connection.packetListener) + lastVelocity?.let { + connection.handlePacketSilently(it) lastVelocity = null } } diff --git a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt index 7ba4ba86f..5b6404729 100644 --- a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt @@ -14,7 +14,7 @@ object PacketUtils { * * @param packet The packet to send. */ - fun ClientPlayNetworkHandler.sendPacketSilently(packet: Packet) { + fun ClientPlayNetworkHandler.sendPacketSilently(packet: ClientPacket) { if (!connection.isOpen) return connection.send(packet, null, true) connection.packetsSentCounter++ @@ -27,7 +27,7 @@ object PacketUtils { * * @param packet The packet to handle. */ - fun ClientPlayNetworkHandler.handlePacketSilently(packet: Packet) { + fun ClientPlayNetworkHandler.handlePacketSilently(packet: ServerPacket) { if (!connection.isOpen) return if (connection.packetListener?.accepts(packet) == false) return @@ -35,3 +35,6 @@ object PacketUtils { connection.packetsReceivedCounter++ } } + +typealias ClientPacket = Packet +typealias ServerPacket = Packet From 3396537871ab97b150eab1884f5ef95da10e33f5 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:23:22 -0400 Subject: [PATCH 30/35] Destroyable listener --- .../com/lambda/event/listener/SafeListener.kt | 49 +++++++++++++++++++ .../lambda/event/listener/UnsafeListener.kt | 46 +++++++++++++++++ .../kotlin/com/lambda/util/SelfReference.kt | 10 ++++ 3 files changed, 105 insertions(+) create mode 100644 common/src/main/kotlin/com/lambda/util/SelfReference.kt diff --git a/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt b/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt index 4cd9b0cbc..67d149785 100644 --- a/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt +++ b/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt @@ -7,6 +7,7 @@ import com.lambda.event.Muteable import com.lambda.task.Task import com.lambda.threading.runConcurrent import com.lambda.threading.runSafe +import com.lambda.util.selfReference /** @@ -87,6 +88,54 @@ class SafeListener( return listener } + /** + * This function registers a new [SafeListener] for a generic [Event] type [T]. + * The [function] is executed on the same thread where the [Event] was dispatched. + * The [function] will only be executed when the context satisfies certain safety conditions. + * These conditions are met when none of the following [SafeContext] properties are null: + * - [SafeContext.world] + * - [SafeContext.player] + * - [SafeContext.interaction] + * - [SafeContext.connection] + * + * This typically occurs when the user is in-game. + * + * After the [function] is executed once, the [SafeListener] will be automatically unsubscribed. + * + * Usage: + * ```kotlin + * listenerOnce { event -> + * player.sendMessage("Event received: $event") + * } + * + * listenerOnce(priority = 1) { event -> + * player.sendMessage("Event received before the previous listener: $event") + * } + * ``` + * + * @param T The type of the event to listen for. This should be a subclass of Event. + * @param priority The priority of the listener. Listeners with higher priority will be executed first. The Default value is 0. + * @param alwaysListen If true, the listener will be executed even if it is muted. The Default value is false. + * @param function The function to be executed when the event is posted. This function should take a SafeContext and an event of type T as parameters. + * @return The newly created and registered [SafeListener]. + */ + inline fun Any.listenOnce( + priority: Int = 0, + alwaysListen: Boolean = false, + noinline function: SafeContext.(T) -> Unit, + ): SafeListener { + val destroyable by selfReference { + SafeListener(priority, this@listenOnce, alwaysListen) { event -> + function(event as T) + EventFlow.syncListeners.unsubscribe(self) + } + } + + EventFlow.syncListeners.subscribe(destroyable) + + return destroyable + } + /** * Registers a new [SafeListener] for a generic [Event] type [T] within the context of a [Task]. * The [function] is executed on the same thread where the [Event] was dispatched. diff --git a/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt b/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt index 26147cd9d..f139d1b94 100644 --- a/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt +++ b/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt @@ -5,7 +5,9 @@ import com.lambda.event.Event import com.lambda.event.EventFlow import com.lambda.event.Muteable import com.lambda.event.listener.SafeListener.Companion.concurrentListener +import com.lambda.event.listener.SafeListener.Companion.listenOnce import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.util.selfReference /** * An [UnsafeListener] is a specialized type of [Listener] that operates without a [SafeContext]. @@ -79,6 +81,50 @@ class UnsafeListener( return listener } + /** + * Registers a new [UnsafeListener] for a generic [Event] type [T]. + * The [function] is executed only once when the [Event] is dispatched. + * This function should only be used when the [function] performs read actions on the game data. + * For only in-game related contexts, use the [SafeListener.listenOnce] function instead. + * The listener will be automatically unsubscribed after the first execution. + * This function is useful for one-time event handling. + * + * Usage: + * ```kotlin + * unsafeListenOnce { event -> + * println("Unsafe event received only once: $event") + * } + * + * unsafeListenOnce(priority = 1) { event -> + * println("Unsafe event received only once before the previous listener: $event") + * } + * ``` + * + * After the [function] is executed once, the [SafeListener] will be automatically unsubscribed. + * + * @param T The type of the event to listen for. This should be a subclass of Event. + * @param priority The priority of the listener. Listeners with higher priority will be executed first. The Default value is 0. + * @param alwaysListen If true, the listener will be executed even if it is muted. The Default value is false. + * @param function The function to be executed when the event is posted. This function should take an event of type T as a parameter. + * @return The newly created and registered [UnsafeListener]. + */ + inline fun Any.unsafeListenOnce( + priority: Int = 0, + alwaysListen: Boolean = false, + noinline function: (T) -> Unit, + ): UnsafeListener { + val destroyable by selfReference { + UnsafeListener(priority, this@unsafeListenOnce, alwaysListen) { event -> + function(event as T) + EventFlow.syncListeners.unsubscribe(self) + } + } + + EventFlow.syncListeners.subscribe(destroyable) + + return destroyable + } + /** * Registers a new [UnsafeListener] for a generic [Event] type [T]. * The [function] is executed on a new thread running asynchronously to the game thread. diff --git a/common/src/main/kotlin/com/lambda/util/SelfReference.kt b/common/src/main/kotlin/com/lambda/util/SelfReference.kt new file mode 100644 index 000000000..c1cc3f018 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/util/SelfReference.kt @@ -0,0 +1,10 @@ +package com.lambda.util + +class SelfReference(initializer: SelfReference.() -> T) { + val self: T by lazy { inner ?: throw IllegalStateException("Do not use `self` until initialized.") } + + private val inner = initializer() + operator fun getValue(thisRef: Any?, property: Any?) = self +} + +fun selfReference(initializer: SelfReference.() -> T): SelfReference = SelfReference(initializer) From ad8946e95c1a88ebdde9734891336e631ed71c00 Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:54:41 -0400 Subject: [PATCH 31/35] Better destroyable listeners --- .../com/lambda/event/listener/SafeListener.kt | 21 +++++++++++-------- .../lambda/event/listener/UnsafeListener.kt | 18 +++++++++------- .../kotlin/com/lambda/util/SelfReference.kt | 2 +- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt b/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt index 67d149785..4b0c653e6 100644 --- a/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt +++ b/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt @@ -104,12 +104,10 @@ class SafeListener( * * Usage: * ```kotlin - * listenerOnce { event -> - * player.sendMessage("Event received: $event") - * } - * - * listenerOnce(priority = 1) { event -> - * player.sendMessage("Event received before the previous listener: $event") + * private val event by listenOnce { event -> + * player.sendMessage("Event received only once: $event") + * // event is stored in the value + * // event is unsubscribed after execution * } * ``` * @@ -122,18 +120,23 @@ class SafeListener( inline fun Any.listenOnce( priority: Int = 0, alwaysListen: Boolean = false, - noinline function: SafeContext.(T) -> Unit, - ): SafeListener { + noinline function: SafeContext.(T) -> Unit = {}, + ): Lazy { + // This doesn't leak memory because the owner still has a reference to the listener + var value: T? = null + val destroyable by selfReference { SafeListener(priority, this@listenOnce, alwaysListen) { event -> function(event as T) + value = event + EventFlow.syncListeners.unsubscribe(self) } } EventFlow.syncListeners.subscribe(destroyable) - return destroyable + return lazy { value } } /** diff --git a/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt b/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt index f139d1b94..be8a7d997 100644 --- a/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt +++ b/common/src/main/kotlin/com/lambda/event/listener/UnsafeListener.kt @@ -91,12 +91,11 @@ class UnsafeListener( * * Usage: * ```kotlin - * unsafeListenOnce { event -> + * private val event by unsafeListenOnce { event -> * println("Unsafe event received only once: $event") - * } - * - * unsafeListenOnce(priority = 1) { event -> - * println("Unsafe event received only once before the previous listener: $event") + * // no safe access to player or world + * // event is stored in the value + * // event is unsubscribed after execution * } * ``` * @@ -112,17 +111,22 @@ class UnsafeListener( priority: Int = 0, alwaysListen: Boolean = false, noinline function: (T) -> Unit, - ): UnsafeListener { + ): Lazy { + // This doesn't leak memory because the owner still has a reference to the listener + var value: T? = null + val destroyable by selfReference { UnsafeListener(priority, this@unsafeListenOnce, alwaysListen) { event -> function(event as T) + value = event + EventFlow.syncListeners.unsubscribe(self) } } EventFlow.syncListeners.subscribe(destroyable) - return destroyable + return lazy { value } } /** diff --git a/common/src/main/kotlin/com/lambda/util/SelfReference.kt b/common/src/main/kotlin/com/lambda/util/SelfReference.kt index c1cc3f018..2392316bd 100644 --- a/common/src/main/kotlin/com/lambda/util/SelfReference.kt +++ b/common/src/main/kotlin/com/lambda/util/SelfReference.kt @@ -1,7 +1,7 @@ package com.lambda.util class SelfReference(initializer: SelfReference.() -> T) { - val self: T by lazy { inner ?: throw IllegalStateException("Do not use `self` until initialized.") } + val self: T by lazy { inner } private val inner = initializer() operator fun getValue(thisRef: Any?, property: Any?) = self From 146957db4fc1571aa0403c61b9699b02196533ae Mon Sep 17 00:00:00 2001 From: Kamigen <46357922+Edouard127@users.noreply.github.com> Date: Wed, 31 Jul 2024 20:08:06 -0400 Subject: [PATCH 32/35] Workaround #47 --- .../main/java/com/lambda/mixin/ClientConnectionMixin.java | 5 +++++ .../main/kotlin/com/lambda/module/modules/movement/Blink.kt | 6 ++---- common/src/main/kotlin/com/lambda/util/PacketUtils.kt | 6 +++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java b/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java index 78542b841..bed77b462 100644 --- a/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java +++ b/common/src/main/java/com/lambda/mixin/ClientConnectionMixin.java @@ -27,6 +27,8 @@ public class ClientConnectionMixin { @Inject(method = "send(Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true) private void sendingPacket(Packet packet, final CallbackInfo callbackInfo) { + if (side != NetworkSide.SERVERBOUND) return; + if (EventFlow.post(new PacketEvent.Send.Pre((Packet) packet)).isCanceled()) { callbackInfo.cancel(); } @@ -34,6 +36,8 @@ private void sendingPacket(Packet packet, final CallbackInfo callbackInfo) { @Inject(method = "send(Lnet/minecraft/network/packet/Packet;)V", at = @At("RETURN")) private void sendingPacketPost(Packet packet, final CallbackInfo callbackInfo) { + if (side != NetworkSide.SERVERBOUND) return; + EventFlow.post(new PacketEvent.Send.Post((Packet) packet)); } @@ -44,6 +48,7 @@ private void receivingPacket( CallbackInfo callbackInfo ) { if (side != NetworkSide.CLIENTBOUND) return; + if (EventFlow.post(new PacketEvent.Receive.Pre((Packet) packet)).isCanceled()) { callbackInfo.cancel(); } diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt index 467d2da32..ddae9757b 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Blink.kt @@ -10,11 +10,10 @@ import com.lambda.module.Module import com.lambda.module.modules.client.GuiSettings import com.lambda.module.modules.combat.KillAura import com.lambda.module.tag.ModuleTag +import com.lambda.util.ClientPacket import com.lambda.util.PacketUtils.handlePacketSilently import com.lambda.util.PacketUtils.sendPacketSilently import com.lambda.util.math.ColorUtils.setAlpha -import net.minecraft.network.listener.ServerPacketListener -import net.minecraft.network.packet.Packet import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket import net.minecraft.util.math.BlockPos @@ -32,7 +31,7 @@ object Blink : Module( private val isActive get() = (KillAura.isEnabled && KillAura.target != null) || !requiresAura - private var packetPool = ConcurrentLinkedDeque>() + private var packetPool = ConcurrentLinkedDeque() private var lastVelocity: EntityVelocityUpdateS2CPacket? = null private var lastUpdate = 0L @@ -56,7 +55,6 @@ object Blink : Module( listener { event -> if (!isActive) return@listener - if (!connection.connection.isOpen) return@listener packetPool.add(event.packet) event.cancel() diff --git a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt index 5b6404729..994bc1a0b 100644 --- a/common/src/main/kotlin/com/lambda/util/PacketUtils.kt +++ b/common/src/main/kotlin/com/lambda/util/PacketUtils.kt @@ -16,6 +16,9 @@ object PacketUtils { */ fun ClientPlayNetworkHandler.sendPacketSilently(packet: ClientPacket) { if (!connection.isOpen) return + if (connection.packetListener?.accepts(packet) == true) + return // LOG.debug("Client tried to send client-bound packet {} to server ", packet) + connection.send(packet, null, true) connection.packetsSentCounter++ } @@ -29,7 +32,8 @@ object PacketUtils { */ fun ClientPlayNetworkHandler.handlePacketSilently(packet: ServerPacket) { if (!connection.isOpen) return - if (connection.packetListener?.accepts(packet) == false) return + if (connection.packetListener?.accepts(packet) == false) + return // LOG.debug("Client tried to handle server-bound packet {}", packet) ClientConnection.handlePacket(packet, connection.packetListener) connection.packetsReceivedCounter++ From db4a96190687370616e9bfd859f946326678ed0d Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Fri, 2 Aug 2024 08:21:33 +0300 Subject: [PATCH 33/35] Fix: Setting unit at the end of inputbar string --- .../com/lambda/gui/api/component/button/InputBarOverlay.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/kotlin/com/lambda/gui/api/component/button/InputBarOverlay.kt b/common/src/main/kotlin/com/lambda/gui/api/component/button/InputBarOverlay.kt index 94024f164..1cc6a8509 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/component/button/InputBarOverlay.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/component/button/InputBarOverlay.kt @@ -123,6 +123,6 @@ abstract class InputBarOverlay (val renderer: RenderLayer, owner: ChildLayer.Dra fun toggle() { isActive = !isActive - if (isActive) typed = getText() + if (isActive) typed = getText().filter { isCharAllowed("", it) } } } \ No newline at end of file From b50193f2fe4fc5002e50a030f19f4b71f85ed093 Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sat, 3 Aug 2024 13:46:28 +0300 Subject: [PATCH 34/35] BackTrack --- .../graphics/renderer/esp/DynamicAABB.kt | 15 +- .../lambda/module/modules/combat/KillAura.kt | 2 +- .../module/modules/movement/BackTrack.kt | 160 ++++++++++++++++++ .../src/main/resources/lambda.accesswidener | 1 + 4 files changed, 165 insertions(+), 13 deletions(-) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/movement/BackTrack.kt diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt index d9bc48e72..852f78901 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/DynamicAABB.kt @@ -13,13 +13,9 @@ class DynamicAABB { private var curr: Box? = null fun update(box: Box): DynamicAABB { - prev = curr + prev = curr ?: box curr = box - if (prev == null) { - prev = box - } - return this } @@ -40,13 +36,8 @@ class DynamicAABB { companion object { val Entity.dynamicBox get() = DynamicAABB().apply { - val box = boundingBox - - val delta = prevPos - pos - val prevBox = Box(box.min + delta, box.max + delta) - - update(prevBox) - update(box) + update(boundingBox.offset(prevPos - pos)) + update(boundingBox) } } } \ No newline at end of file diff --git a/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt b/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt index 72828cea1..a17f46a0e 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/combat/KillAura.kt @@ -229,7 +229,7 @@ object KillAura : Module( vec = validHits.minByOrNull { vecRotation dist it.value }?.key ?: return null } - val predictOffset = target.velocity * targetPredict - player.moveDiff * Vec3d(1.0, -0.5, 1.0) * selfPredict + val predictOffset = target.moveDiff * targetPredict - player.moveDiff * Vec3d(1.0, -0.5, 1.0) * selfPredict return RotationContext(eye.rotationTo(vec + predictOffset), rotation) } diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/BackTrack.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/BackTrack.kt new file mode 100644 index 000000000..5b3fe71d2 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/BackTrack.kt @@ -0,0 +1,160 @@ +package com.lambda.module.modules.movement + +import com.lambda.context.SafeContext +import com.lambda.event.events.ConnectionEvent +import com.lambda.event.events.PacketEvent +import com.lambda.event.events.RenderEvent +import com.lambda.event.events.TickEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.graphics.renderer.esp.DynamicAABB +import com.lambda.graphics.renderer.esp.builders.build +import com.lambda.module.Module +import com.lambda.module.modules.client.GuiSettings +import com.lambda.module.modules.combat.KillAura +import com.lambda.module.tag.ModuleTag +import com.lambda.util.PacketUtils.handlePacketSilently +import com.lambda.util.ServerPacket +import com.lambda.util.math.ColorUtils.multAlpha +import com.lambda.util.math.MathUtils.lerp +import com.lambda.util.math.VecUtils.dist +import com.lambda.util.math.VecUtils.minus +import com.lambda.util.math.VecUtils.plus +import net.minecraft.network.packet.s2c.play.EntityAnimationS2CPacket +import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket +import net.minecraft.network.packet.s2c.play.EntityS2CPacket +import net.minecraft.network.packet.s2c.play.EntityStatusEffectS2CPacket +import net.minecraft.network.packet.s2c.play.ParticleS2CPacket +import net.minecraft.network.packet.s2c.play.PlaySoundFromEntityS2CPacket +import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket +import net.minecraft.network.packet.s2c.play.StopSoundS2CPacket +import net.minecraft.network.packet.s2c.play.WorldEventS2CPacket +import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket +import net.minecraft.util.math.Vec3d +import java.awt.Color +import java.util.concurrent.ConcurrentLinkedDeque + +object BackTrack : Module( + name = "BackTrack", + description = "Gives reach advantage by delaying your packets", + defaultTags = setOf(ModuleTag.MOVEMENT) +) { + private val mode by setting("Mode", Mode.FIXED) + private val delay by setting("Delay", 500, 100..2000) { mode == Mode.FIXED } + private val maxDelay by setting("Max Delay", 1000, 100..2000) { mode == Mode.RANGED || mode == Mode.ADAPTIVE } + private val distance by setting("Distance", 3.0, 1.0..5.0, 0.1) { mode == Mode.RANGED || mode == Mode.ADAPTIVE } + + private val target get() = if (KillAura.isDisabled) null else KillAura.target + private var targetPos: Vec3d? = null + + private val box = DynamicAABB() + + private const val POSITION_PACKET_SCALE = 1 / 4096.0 + private val currentTime get() = System.currentTimeMillis() + private val packetPool = ConcurrentLinkedDeque>() + + enum class Mode(val shouldSend: SafeContext.(Vec3d, Vec3d, Long) -> Boolean) { + FIXED({ _, _, timing -> + currentTime > timing + delay + }), + RANGED({ _, serverPos, timing -> + val serverDist = player.pos dist serverPos + currentTime > timing + maxDelay * serverDist.coerceIn(0.0, distance) / distance + }), + ADAPTIVE({ clientPos, serverPos, timing -> + val clientDist = player.pos dist clientPos + val serverDist = player.pos dist serverPos + val advantage = serverDist - clientDist + currentTime > timing + maxDelay * advantage.coerceIn(0.0, distance) / distance + }) + } + + init { + listener { + target?.let { target -> + val pos = targetPos ?: target.pos + targetPos = pos + + box.update(target.boundingBox.offset(pos - target.pos)) + poolPackets() + return@listener + } + + poolPackets(true) + targetPos = null + box.reset() + } + + listener { + val target = target ?: return@listener + + val c1 = GuiSettings.primaryColor + val c2 = Color.RED + val p = target.hurtTime / 10.0 + val c = lerp(c1, c2, p) + + it.renderer.build(box, c.multAlpha(0.3), c.multAlpha(0.8)) + } + + listener { event -> + val target = target ?: return@listener + + val packet = event.packet + + when (packet) { + is EntityS2CPacket -> { + if (target.id == packet.id) { + targetPos = targetPos?.plus( + Vec3d( + packet.deltaX * POSITION_PACKET_SCALE, + packet.deltaY * POSITION_PACKET_SCALE, + packet.deltaZ * POSITION_PACKET_SCALE + ) + ) + } + } + + is EntityPositionS2CPacket -> { + if (target.id == packet.id) { + targetPos = Vec3d(packet.x, packet.y, packet.z) + } + } + + is PlaySoundS2CPacket, is PlaySoundFromEntityS2CPacket, is StopSoundS2CPacket, + /*is EntityStatusS2CPacket,*/ is EntityStatusEffectS2CPacket, is EntityAnimationS2CPacket, + is ParticleS2CPacket, is WorldTimeUpdateS2CPacket, is WorldEventS2CPacket -> { + return@listener + } + } + + packetPool.add(packet to currentTime) + event.cancel() + } + + listener { + packetPool.clear() + } + + onEnable { + poolPackets(true) + } + + onDisable { + poolPackets(true) + } + } + + private fun SafeContext.poolPackets(all: Boolean = false) { + while (packetPool.isNotEmpty()) { + val (packet, timing) = packetPool.poll() ?: break + + val send = all || targetPos?.let { serverPos -> + target?.pos?.let { clientPos -> + mode.shouldSend(this, clientPos, serverPos, timing) + } + } ?: true + + if (!send) break + connection.handlePacketSilently(packet) + } + } +} \ No newline at end of file diff --git a/common/src/main/resources/lambda.accesswidener b/common/src/main/resources/lambda.accesswidener index a48d8976a..bd4ab6ec7 100644 --- a/common/src/main/resources/lambda.accesswidener +++ b/common/src/main/resources/lambda.accesswidener @@ -47,6 +47,7 @@ accessible field net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPa accessible field net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket type Lnet/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractTypeHandler; accessible class net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractTypeHandler accessible class net/minecraft/network/packet/c2s/play/PlayerInteractEntityC2SPacket$InteractAtHandler +accessible field net/minecraft/network/packet/s2c/play/EntityS2CPacket id I accessible method net/minecraft/network/ClientConnection handlePacket (Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;)V accessible field net/minecraft/network/ClientConnection packetsReceivedCounter I accessible field net/minecraft/network/ClientConnection packetsSentCounter I From 5dc06b72a54d91f95468b8af35a9563bcfecc91b Mon Sep 17 00:00:00 2001 From: Blade-gl Date: Sat, 3 Aug 2024 14:33:48 +0300 Subject: [PATCH 35/35] HUD hiding --- .../com/lambda/event/events/RenderEvent.kt | 1 + .../kotlin/com/lambda/graphics/RenderMain.kt | 38 ++++++++++++++++++- .../graphics/renderer/gui/TextureRenderer.kt | 4 +- .../kotlin/com/lambda/module/HudModule.kt | 2 +- .../kotlin/com/lambda/module/hud/Watermark.kt | 2 +- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt b/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt index 3116ed2a8..afe989011 100644 --- a/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt @@ -21,6 +21,7 @@ abstract class RenderEvent : Event { abstract class GUI(val scale: Double) : RenderEvent() { class Scaled(scaleFactor: Double) : GUI(scaleFactor) + class HUD(scaleFactor: Double) : GUI(scaleFactor) class Fixed : GUI(1.0) val screenSize = Vec2d(mc.window.framebufferWidth, mc.window.framebufferHeight) / scale diff --git a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt index 1e53573db..fdf63e1f0 100644 --- a/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt +++ b/common/src/main/kotlin/com/lambda/graphics/RenderMain.kt @@ -3,11 +3,18 @@ package com.lambda.graphics import com.lambda.Lambda.mc import com.lambda.event.EventFlow.post import com.lambda.event.events.RenderEvent +import com.lambda.event.events.TickEvent +import com.lambda.event.listener.SafeListener.Companion.listener +import com.lambda.graphics.animation.Animation.Companion.exp +import com.lambda.graphics.animation.AnimationTicker +import com.lambda.graphics.buffer.FrameBuffer import com.lambda.graphics.gl.GlStateUtils.setupGL import com.lambda.graphics.gl.Matrices import com.lambda.graphics.gl.Matrices.resetMatrices import com.lambda.graphics.renderer.esp.global.StaticESP import com.lambda.graphics.renderer.esp.global.DynamicESP +import com.lambda.graphics.shader.Shader +import com.lambda.module.modules.client.ClickGui import com.lambda.module.modules.client.GuiSettings import com.lambda.util.math.Vec2d import com.mojang.blaze3d.systems.RenderSystem.getProjectionMatrix @@ -16,9 +23,22 @@ import org.joml.Matrix4f object RenderMain { val projectionMatrix = Matrix4f() val modelViewMatrix: Matrix4f get() = Matrices.peek() - var screenSize = Vec2d.ZERO + private val hudAnimation0 = with(AnimationTicker()) { + listener { + tick() + } + + exp(0.0, 1.0, { + if (mc.currentScreen == null) ClickGui.closeSpeed else ClickGui.openSpeed + }) { mc.currentScreen == null } + } + + private val frameBuffer = FrameBuffer() + private val shader = Shader("post/cgui_animation", "renderer/pos_tex") + private val hudAnimation by hudAnimation0 + @JvmStatic fun render2D() { resetMatrices(Matrix4f().translate(0f, 0f, -3000f)) @@ -28,6 +48,7 @@ object RenderMain { RenderEvent.GUI.Fixed().post() rescale(GuiSettings.scale) + drawHUD() RenderEvent.GUI.Scaled(GuiSettings.scale).post() } } @@ -54,4 +75,19 @@ object RenderMain { screenSize = Vec2d(scaledWidth, scaledHeight) projectionMatrix.setOrtho(0f, scaledWidth.toFloat(), scaledHeight.toFloat(), 0f, 1000f, 21000f) } + + private fun drawHUD() { + if (hudAnimation < 0.001) return + + if (hudAnimation > 0.999) { + RenderEvent.GUI.HUD(GuiSettings.scale).post() + return + } + + frameBuffer.write { + RenderEvent.GUI.HUD(GuiSettings.scale).post() + }.read(shader) { + it["u_Progress"] = hudAnimation + } + } } diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt index f4caab953..fa1c65ad1 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt @@ -23,14 +23,14 @@ object TextureRenderer { drawInternal(rect) } - fun drawTextureShaded(texture: Texture, rect: Rect, shadeWidthScale: Double = 1.0) { + fun drawTextureShaded(texture: Texture, rect: Rect) { texture.bind() shaderColored.use() shaderColored["u_Time"] = glfwGetTime() * GuiSettings.colorSpeed * 5.0 shaderColored["u_Color1"] = GuiSettings.shadeColor1 shaderColored["u_Color2"] = GuiSettings.shadeColor2 - shaderColored["u_Size"] = RenderMain.screenSize / Vec2d(GuiSettings.colorWidth, GuiSettings.colorHeight) / shadeWidthScale + shaderColored["u_Size"] = RenderMain.screenSize / Vec2d(GuiSettings.colorWidth, GuiSettings.colorHeight) drawInternal(rect) } diff --git a/common/src/main/kotlin/com/lambda/module/HudModule.kt b/common/src/main/kotlin/com/lambda/module/HudModule.kt index 60e03b88e..3bdef54db 100644 --- a/common/src/main/kotlin/com/lambda/module/HudModule.kt +++ b/common/src/main/kotlin/com/lambda/module/HudModule.kt @@ -63,7 +63,7 @@ abstract class HudModule( renderCallables.add(block) init { - listener { event -> + listener { event -> rectHandler.screenSize = event.screenSize renderCallables.forEach { function -> diff --git a/common/src/main/kotlin/com/lambda/module/hud/Watermark.kt b/common/src/main/kotlin/com/lambda/module/hud/Watermark.kt index 0e631dc50..15f9190e9 100644 --- a/common/src/main/kotlin/com/lambda/module/hud/Watermark.kt +++ b/common/src/main/kotlin/com/lambda/module/hud/Watermark.kt @@ -20,7 +20,7 @@ object Watermark : HudModule( init { onRender { - if (shade) drawTextureShaded(monoTexture, rect, 0.1) + if (shade) drawTextureShaded(monoTexture, rect) else drawTexture(normalTexture, rect) } }