Skip to content

Commit 7930b71

Browse files
committed
zoom module
1 parent d5976ba commit 7930b71

File tree

4 files changed

+138
-5
lines changed

4 files changed

+138
-5
lines changed

src/main/java/com/lambda/mixin/input/MouseMixin.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@
1919

2020
import com.lambda.event.EventFlow;
2121
import com.lambda.event.events.MouseEvent;
22+
import com.lambda.module.modules.render.Zoom;
2223
import com.lambda.util.math.Vec2d;
2324
import net.minecraft.client.Mouse;
25+
import net.minecraft.client.option.GameOptions;
26+
import net.minecraft.client.option.SimpleOption;
2427
import org.spongepowered.asm.mixin.Mixin;
2528
import org.spongepowered.asm.mixin.Shadow;
2629
import org.spongepowered.asm.mixin.injection.At;
2730
import org.spongepowered.asm.mixin.injection.Inject;
31+
import org.spongepowered.asm.mixin.injection.Redirect;
2832
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
2933

3034
@Mixin(Mouse.class)
@@ -61,4 +65,17 @@ private void onCursorPos(long window, double x, double y, CallbackInfo ci) {
6165
ci.cancel();
6266
}
6367
}
68+
69+
@Redirect(method = "updateMouse", at = @At(value = "FIELD", target = "Lnet/minecraft/client/option/GameOptions;smoothCameraEnabled:Z"))
70+
private boolean redirectSmoothCameraEnabled(GameOptions instance) {
71+
if (Zoom.INSTANCE.isEnabled() && Zoom.getSmoothMovement()) return true;
72+
else return instance.smoothCameraEnabled;
73+
}
74+
75+
@SuppressWarnings("rawtypes")
76+
@Redirect(method = "updateMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/SimpleOption;getValue()Ljava/lang/Object;", ordinal = 0))
77+
private Object redirectGetValue(SimpleOption instance) {
78+
if (Zoom.INSTANCE.isEnabled()) return ((Double) instance.getValue()) / Zoom.getTargetZoom();
79+
else return instance.getValue();
80+
}
6481
}

src/main/java/com/lambda/mixin/render/GameRendererMixin.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import com.lambda.event.events.RenderEvent;
2222
import com.lambda.graphics.RenderMain;
2323
import com.lambda.module.modules.render.NoRender;
24+
import com.lambda.module.modules.render.Zoom;
2425
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
26+
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
2527
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
2628
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
2729
import net.minecraft.client.render.Camera;
@@ -73,4 +75,9 @@ private float modifyMax(float original) {
7375
private void injectShowFloatingItem(ItemStack floatingItem, CallbackInfo ci) {
7476
if (NoRender.INSTANCE.isEnabled() && NoRender.getNoFloatingItemAnimation()) ci.cancel();
7577
}
78+
79+
@ModifyReturnValue(method = "getFov", at = @At("RETURN"))
80+
private float modifyGetFov(float original) {
81+
return original / Zoom.getCurrentZoom();
82+
}
7683
}

src/main/kotlin/com/lambda/module/Module.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package com.lambda.module
1919

20+
import com.lambda.Lambda
2021
import com.lambda.command.LambdaCommand
2122
import com.lambda.config.AbstractSetting
2223
import com.lambda.config.Configurable
@@ -112,7 +113,8 @@ abstract class Module(
112113
private val alwaysListening: Boolean = false,
113114
enabledByDefault: Boolean = false,
114115
defaultKeybind: KeyCode = KeyCode.UNBOUND,
115-
autoDisable: Boolean = false
116+
autoDisable: Boolean = false,
117+
open val disableOnRelease: Boolean = false
116118
) : Nameable, Muteable, Configurable(ModuleConfig) {
117119
private val isEnabledSetting = setting("Enabled", enabledByDefault) { false }
118120
val keybindSetting = setting("Keybind", defaultKeybind) { false }
@@ -129,13 +131,13 @@ abstract class Module(
129131

130132
init {
131133
listen<KeyboardEvent.Press>(alwaysListen = true) { event ->
132-
if (mc.options.commandKey.isPressed) return@listen
133-
if (!event.isPressed) return@listen
134+
if (Lambda.mc.options.commandKey.isPressed) return@listen
134135
if (keybind == KeyCode.UNBOUND) return@listen
135136
if (event.translated != keybind) return@listen
136-
if (mc.currentScreen != null) return@listen
137+
if (Lambda.mc.currentScreen != null) return@listen
137138

138-
toggle()
139+
if (event.isPressed) toggle()
140+
else if (event.isReleased && disableOnRelease) disable()
139141
}
140142

141143
onEnable { LambdaSound.MODULE_ON.play() }
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.module.modules.render
19+
20+
import com.lambda.event.events.MouseEvent
21+
import com.lambda.event.events.RenderEvent
22+
import com.lambda.event.listener.SafeListener.Companion.listen
23+
import com.lambda.module.Module
24+
import com.lambda.module.tag.ModuleTag
25+
import java.lang.Math.clamp
26+
27+
object Zoom : Module(
28+
"Zoom",
29+
"Zooms the current view",
30+
ModuleTag.RENDER
31+
) {
32+
override val disableOnRelease by setting("Disable On Release", true)
33+
private var zoom by setting("Zoom", 2f, 1f..10f, 0.1f)
34+
private val style by setting("Style", ZoomStyle.EaseOut)
35+
private val animationDuration by setting("Animation Duration", 1f, 0.1f..10f, 0.1f) { style != ZoomStyle.Instant }
36+
private val scroll by setting("Scroll", true)
37+
private val persistentScroll by setting("Persistent Scroll", false) { scroll }
38+
private val sensitivity by setting("Sensitivity", 0.4f, 0.1f..1f, 0.1f) { scroll }
39+
@JvmStatic val smoothMovement by setting("Smooth Movement", false)
40+
41+
private var extraZoom = 0f
42+
set(value) {
43+
field = value.coerceAtLeast(-zoom + 1)
44+
}
45+
@JvmStatic val targetZoom: Float
46+
get() = zoom + extraZoom
47+
48+
@JvmStatic var currentZoom = 1f; private set
49+
private var lastZoomTime = 1L
50+
private val zoomProgress
51+
get() =
52+
clamp((System.currentTimeMillis() - lastZoomTime) / (animationDuration * 1000).toDouble(), 0.0, 1.0).toFloat()
53+
54+
init {
55+
listen<MouseEvent.Scroll> { event ->
56+
val yDelta = event.delta.y.toFloat()
57+
val delta = (yDelta * sensitivity) + (((zoom + extraZoom) * sensitivity) * yDelta)
58+
if (persistentScroll) zoom += delta
59+
else extraZoom += delta
60+
updateZoomTime()
61+
event.cancel()
62+
}
63+
64+
listen<RenderEvent.Render>(alwaysListen = true) {
65+
updateCurrentZoom()
66+
}
67+
68+
onEnable {
69+
updateZoomTime()
70+
}
71+
onDisable {
72+
extraZoom = 0f
73+
updateZoomTime()
74+
}
75+
}
76+
77+
private fun updateZoomTime() {
78+
lastZoomTime = System.currentTimeMillis()
79+
}
80+
81+
@JvmStatic
82+
fun updateCurrentZoom() {
83+
val target = if (isEnabled) targetZoom else 1f
84+
if (currentZoom == target) return
85+
currentZoom = when (style) {
86+
ZoomStyle.Instant -> target
87+
ZoomStyle.EaseOut -> easeOut(currentZoom, target, zoomProgress)
88+
ZoomStyle.EaseIn -> easeIn(currentZoom, target, zoomProgress)
89+
}
90+
}
91+
92+
private fun easeOut(start: Float, end: Float, progress: Float): Float {
93+
val easedT = 1f - (1f - progress) * (1f - progress)
94+
return start + ((end - start) * easedT)
95+
}
96+
97+
private fun easeIn(start: Float, end: Float, progress: Float): Float {
98+
val easedT = progress * progress
99+
return start + ((end - start) * easedT)
100+
}
101+
102+
private enum class ZoomStyle {
103+
Instant,
104+
EaseOut,
105+
EaseIn
106+
}
107+
}

0 commit comments

Comments
 (0)