Skip to content

Commit e1c9b90

Browse files
committed
feat(PacketLimiter): Add click packet limit to PacketLimiter
1 parent bdda54d commit e1c9b90

File tree

6 files changed

+142
-6
lines changed

6 files changed

+142
-6
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.mixin.render;
19+
20+
import com.lambda.event.EventFlow;
21+
import com.lambda.event.events.RenderEvent;
22+
import net.minecraft.client.gui.DrawContext;
23+
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
24+
import org.spongepowered.asm.mixin.Mixin;
25+
import org.spongepowered.asm.mixin.injection.At;
26+
import org.spongepowered.asm.mixin.injection.Inject;
27+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
28+
29+
/*
30+
* @author IceTank
31+
* @since 21.05.2025
32+
*/
33+
@Mixin(GenericContainerScreen.class)
34+
public class GenericContainerScreenMixin extends HandledScreenMixin {
35+
@Inject(method = "render", at = @At("TAIL"))
36+
public void onRender(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
37+
RenderEvent.GUI.Container event = new RenderEvent.GUI.Container(((GenericContainerScreen) (Object) this), context, mouseX, mouseY, delta);
38+
EventFlow.post(event);
39+
}
40+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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.mixin.render;
19+
20+
import net.minecraft.client.gui.screen.ingame.HandledScreen;
21+
import org.spongepowered.asm.mixin.Mixin;
22+
import org.spongepowered.asm.mixin.Shadow;
23+
import org.spongepowered.asm.mixin.Unique;
24+
25+
/*
26+
* @author IceTank
27+
* @since 21.05.2025
28+
*/
29+
@Mixin(HandledScreen.class)
30+
public class HandledScreenMixin {
31+
}

common/src/main/kotlin/com/lambda/event/events/RenderEvent.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import com.lambda.event.callback.ICancellable
2424
import com.lambda.graphics.renderer.esp.global.DynamicESP
2525
import com.lambda.graphics.renderer.esp.global.StaticESP
2626
import com.lambda.util.math.Vec2d
27+
import net.minecraft.client.gui.DrawContext
28+
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
2729

2830
sealed class RenderEvent {
2931
class World : Event
@@ -40,6 +42,9 @@ sealed class RenderEvent {
4042
class Scaled(scaleFactor: Double) : GUI(scaleFactor)
4143
class HUD(scaleFactor: Double) : GUI(scaleFactor)
4244
class Fixed : GUI(1.0)
45+
class Container(val genericContainerScreen: GenericContainerScreen, val drawContext: DrawContext, val mouseX: Int, val mouseY: Int, val delta: Float) : GUI(1.0) {
46+
val mouse = Vec2d(mouseX, mouseY)
47+
}
4348

4449
val screenSize = Vec2d(mc.window.framebufferWidth, mc.window.framebufferHeight) / scale
4550
}

common/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,31 @@
1818
package com.lambda.module.modules.network
1919

2020
import com.lambda.event.events.PacketEvent
21+
import com.lambda.event.events.PlayerEvent
22+
import com.lambda.event.events.RenderEvent
2123
import com.lambda.event.listener.SafeListener.Companion.listen
2224
import com.lambda.module.Module
2325
import com.lambda.module.tag.ModuleTag
2426
import com.lambda.util.Communication.info
2527
import com.lambda.util.collections.LimitedDecayQueue
28+
import com.mojang.blaze3d.systems.RenderSystem
29+
import net.minecraft.client.gui.DrawContext
30+
import net.minecraft.client.gui.screen.ingame.HandledScreen
2631
import net.minecraft.network.packet.c2s.common.CommonPongC2SPacket
32+
import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket
2733
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.*
2834
import net.minecraft.network.packet.c2s.play.TeleportConfirmC2SPacket
35+
import net.minecraft.text.Text
2936

3037
// ToDo: HUD info
3138
object PacketLimiter : Module(
3239
name = "PacketLimiter",
3340
description = "Limits the amount of packets sent to the server",
3441
defaultTags = setOf(ModuleTag.NETWORK)
3542
) {
36-
private var packetQueue = LimitedDecayQueue<PacketEvent.Send.Pre>(99, 1000)
37-
private val limit by setting("Limit", 99, 1..100, 1, "The maximum amount of packets to send per given time interval", unit = " packets")
43+
private var packetQueue = LimitedDecayQueue<PacketEvent.Send.Pre>(999, 1000)
44+
private var clickPacketQueue = LimitedDecayQueue<Long>(500, 30000)
45+
private val limit by setting("Limit", 99, 1..1000, 1, "The maximum amount of packets to send per given time interval", unit = " packets")
3846
.onValueChange { _, to -> packetQueue.setSizeLimit(to) }
3947

4048
private val interval by setting("Duration", 4000L, 1L..10000L, 50L, "The interval / duration in milliseconds to limit packets for", unit = " ms")
@@ -48,7 +56,18 @@ object PacketLimiter : Module(
4856
OnGroundOnly::class,
4957
TeleportConfirmC2SPacket::class
5058
)
51-
private val ignorePackets by setting("Ignore Packets", defaultIgnorePackets.mapNotNull { it.simpleName }, "Packets to ignore when limiting")
59+
private val limitAllPackets by setting("Limit All", false, "Limit all send packets")
60+
private val ignorePackets by setting("Ignore Packets", defaultIgnorePackets.mapNotNull { it.simpleName }, "Packets to ignore when limiting") { limitAllPackets }
61+
private val limitClickPackets by setting("Clicks limit", true, "Limits the amount of click packets you can send to prevent kicks.")
62+
private val limitClickWindowSize by setting("Click limit window size", 4f, 0.1f..10.0f, 0.1f, "Click limit window size", unit = " s") {
63+
limitClickPackets
64+
}.onValueChange { _, to -> clickPacketQueue.setDecayTime((to * 1000).toLong()) }
65+
private val limitClickRate by setting("Click limit rate", 19.3f, 0.1f..40f, 0.1f, "Click limit rate", unit = " packets/sec") {
66+
limitClickPackets
67+
}.onValueChange { _, to -> clickPacketQueue.setSizeLimit((limitClickWindowSize * to).toInt()) }
68+
private val limitClickRender by setting("Render Limit in Container", true, "Render the amount of clicks remaining in the container screen") {
69+
limitClickPackets
70+
}
5271

5372
init {
5473
onEnable {
@@ -58,11 +77,46 @@ object PacketLimiter : Module(
5877
listen<PacketEvent.Send.Pre>(Int.MAX_VALUE) {
5978
if (it.packet::class.simpleName in ignorePackets) return@listen
6079

80+
if (limitClickPackets && it.packet is ClickSlotC2SPacket) {
81+
if (!canSendClickPackets(1)) {
82+
it.cancel()
83+
return@listen
84+
} else {
85+
clickPacketQueue.add(System.currentTimeMillis())
86+
}
87+
}
88+
6189
// [email protected]("Packet sent: ${it.packet::class.simpleName} (${packetQueue.size} / $limit) ${Instant.now()}")
6290
if (packetQueue.add(it)) return@listen
6391

6492
it.cancel()
6593
this@PacketLimiter.info("Packet limit reached, dropping packet: ${it.packet::class.simpleName} (${packetQueue.size} / $limit)")
6694
}
95+
96+
listen<PlayerEvent.SlotClick>{
97+
if (!limitClickPackets) return@listen
98+
if (!canSendClickPackets(1)) {
99+
it.cancel()
100+
return@listen
101+
}
102+
}
103+
104+
listen<RenderEvent.GUI.Container> {
105+
if (!limitClickRender) return@listen
106+
val renderScreen: HandledScreen<*> = it.genericContainerScreen
107+
val context: DrawContext = it.drawContext
108+
val x = renderScreen.x
109+
val y = renderScreen.y
110+
111+
RenderSystem.disableDepthTest()
112+
val remainingText = "Clicks Remaining: " + clickPacketsRemaining().toInt().toString()
113+
context.drawText(renderScreen.textRenderer, Text.literal(remainingText), x + renderScreen.backgroundWidth, y, 4210752, false)
114+
RenderSystem.enableDepthTest()
115+
}
67116
}
117+
118+
fun canSendClickPackets(packets: Int) = clickPacketQueue.size + packets < clickPacketsWindowAmount()
119+
fun clickPacketsRemaining() = clickPacketsWindowAmount() - clickPacketQueue.size
120+
121+
private fun clickPacketsWindowAmount() = limitClickWindowSize * limitClickRate
68122
}

common/src/main/resources/lambda.accesswidener

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ accessible field com/mojang/blaze3d/systems/RenderSystem$ShapeIndexBuffer id I
4040
accessible field net/minecraft/client/render/BufferRenderer currentVertexBuffer Lnet/minecraft/client/gl/VertexBuffer;
4141
accessible field net/minecraft/client/texture/NativeImage pointer J
4242
accessible class net/minecraft/client/gui/screen/SplashOverlay$LogoTexture
43+
accessible field net/minecraft/client/gui/screen/ingame/HandledScreen x I
44+
accessible field net/minecraft/client/gui/screen/ingame/HandledScreen y I
45+
accessible field net/minecraft/client/gui/screen/ingame/HandledScreen backgroundWidth I
46+
accessible field net/minecraft/client/gui/screen/Screen textRenderer Lnet/minecraft/client/font/TextRenderer;
4347

4448
# Text
4549
accessible field net/minecraft/text/Style color Lnet/minecraft/text/TextColor;

common/src/main/resources/lambda.mixins.common.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"package": "com.lambda.mixin",
55
"compatibilityLevel": "JAVA_17",
66
"client": [
7+
"CrashReportMixin",
78
"MinecraftClientMixin",
89
"baritone.MixinBaritonePlayerContext",
910
"baritone.MixinLookBehavior",
@@ -36,7 +37,9 @@
3637
"render.DebugHudMixin",
3738
"render.ElytraFeatureRendererMixin",
3839
"render.GameRendererMixin",
40+
"render.GenericContainerScreenMixin",
3941
"render.GlStateManagerMixin",
42+
"render.HandledScreenMixin",
4043
"render.InGameHudMixin",
4144
"render.InGameOverlayRendererMixin",
4245
"render.LightmapTextureManagerMixin",
@@ -54,10 +57,9 @@
5457
"world.BlockCollisionSpliteratorMixin",
5558
"world.ClientChunkManagerMixin",
5659
"world.ClientWorldMixin",
57-
"world.StructureTemplateMixin",
5860
"world.ExplosionMixin",
59-
"world.WorldMixin",
60-
"CrashReportMixin"
61+
"world.StructureTemplateMixin",
62+
"world.WorldMixin"
6163
],
6264
"injectors": {
6365
"defaultRequire": 1

0 commit comments

Comments
 (0)