Skip to content

Commit e95acfd

Browse files
committed
Packet Delay
1 parent 27b5141 commit e95acfd

File tree

5 files changed

+222
-7
lines changed

5 files changed

+222
-7
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ I did not, nor could I copy their code directly as most are Meteor based mods. S
108108

109109
---
110110

111-
## Whats new in this fork?
111+
## What's new in this fork?
112112

113113
### MobSearch
114114
- Search mobs by fuzzy name/ID or exact type (e.g., `minecraft:zombie` or `zombie`).
@@ -457,6 +457,13 @@ I did not, nor could I copy their code directly as most are Meteor based mods. S
457457

458458
![Live](https://i.imgur.com/38r4wYF.png)
459459

460+
### Packet Delay
461+
- Delays incoming and/or outgoing packets into a queue.
462+
- Optional tick delay, then releases queued packets all at once.
463+
- Flushes the queue when disabled.
464+
- Keybind works even with GUIs open (chests, portals, etc.).
465+
- Tick count displayed in HackList
466+
460467
## What’s changed or improved in this fork?
461468

462469
### ChestESP

src/main/java/net/wurstclient/hack/HackList.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ public final class HackList implements UpdateListener
178178
public final LavaWaterEspHack lavaWaterEspHack = new LavaWaterEspHack();
179179
public final OverlayHack overlayHack = new OverlayHack();
180180
public final PanicHack panicHack = new PanicHack();
181+
public final PacketDelayHack packetDelayHack = new PacketDelayHack();
181182
public final ParkourHack parkourHack = new ParkourHack();
182183
public final PlayerEspHack playerEspHack = new PlayerEspHack();
183184
public final PortalEspHack portalEspHack = new PortalEspHack();
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (c) 2014-2026 Wurst-Imperium and contributors.
3+
*
4+
* This source code is subject to the terms of the GNU General Public
5+
* License, version 3. If a copy of the GPL was not distributed with this
6+
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
7+
*/
8+
package net.wurstclient.hacks;
9+
10+
import java.util.ArrayDeque;
11+
import net.minecraft.client.multiplayer.ClientPacketListener;
12+
import net.minecraft.network.protocol.Packet;
13+
import net.wurstclient.Category;
14+
import net.wurstclient.SearchTags;
15+
import net.wurstclient.events.PacketInputListener;
16+
import net.wurstclient.events.PacketInputListener.PacketInputEvent;
17+
import net.wurstclient.events.PacketOutputListener;
18+
import net.wurstclient.events.PacketOutputListener.PacketOutputEvent;
19+
import net.wurstclient.events.UpdateListener;
20+
import net.wurstclient.hack.Hack;
21+
import net.wurstclient.settings.CheckboxSetting;
22+
import net.wurstclient.settings.SliderSetting;
23+
import net.wurstclient.settings.SliderSetting.ValueDisplay;
24+
25+
@SearchTags({"LagSwitch", "lag switch"})
26+
public final class PacketDelayHack extends Hack
27+
implements UpdateListener, PacketInputListener, PacketOutputListener
28+
{
29+
private final CheckboxSetting delayS2c = new CheckboxSetting("Delay S2C",
30+
"Delays incoming server packets.", true);
31+
private final CheckboxSetting delayC2s = new CheckboxSetting("Delay C2S",
32+
"Delays outgoing client packets.", true);
33+
private final CheckboxSetting timeDelay = new CheckboxSetting("Time delay",
34+
"Release queued packets once the delay has passed.", false);
35+
private final SliderSetting delay = new SliderSetting("Delay",
36+
"How long to wait in ticks before releasing queued packets.", 0, 0, 200,
37+
1, ValueDisplay.INTEGER);
38+
39+
private final ArrayDeque<PacketAndTime> s2cQueue = new ArrayDeque<>();
40+
private final ArrayDeque<PacketAndTime> c2sQueue = new ArrayDeque<>();
41+
private boolean flushingC2s;
42+
43+
public PacketDelayHack()
44+
{
45+
super("PacketDelay");
46+
setCategory(Category.OTHER);
47+
addSetting(delayS2c);
48+
addSetting(delayC2s);
49+
addSetting(timeDelay);
50+
addSetting(delay);
51+
}
52+
53+
@Override
54+
public String getRenderName()
55+
{
56+
int total = s2cQueue.size() + c2sQueue.size();
57+
return getName() + " [" + total + "]";
58+
}
59+
60+
@Override
61+
protected void onEnable()
62+
{
63+
s2cQueue.clear();
64+
c2sQueue.clear();
65+
66+
EVENTS.add(UpdateListener.class, this);
67+
EVENTS.add(PacketInputListener.class, this);
68+
EVENTS.add(PacketOutputListener.class, this);
69+
}
70+
71+
@Override
72+
protected void onDisable()
73+
{
74+
EVENTS.remove(UpdateListener.class, this);
75+
EVENTS.remove(PacketInputListener.class, this);
76+
EVENTS.remove(PacketOutputListener.class, this);
77+
78+
flushQueues(true);
79+
}
80+
81+
@Override
82+
public void onUpdate()
83+
{
84+
if(timeDelay.isChecked())
85+
flushQueues(false);
86+
}
87+
88+
@Override
89+
public void onReceivedPacket(PacketInputEvent event)
90+
{
91+
if(!delayS2c.isChecked())
92+
return;
93+
94+
long time = MC.level != null ? MC.level.getGameTime() : 0;
95+
s2cQueue.addLast(new PacketAndTime(event.getPacket(), time));
96+
event.cancel();
97+
}
98+
99+
@Override
100+
public void onSentPacket(PacketOutputEvent event)
101+
{
102+
if(flushingC2s || !delayC2s.isChecked())
103+
return;
104+
105+
long time = MC.level != null ? MC.level.getGameTime() : 0;
106+
c2sQueue.addLast(new PacketAndTime(event.getPacket(), time));
107+
event.cancel();
108+
}
109+
110+
private void flushQueues(boolean forceAll)
111+
{
112+
if(forceAll || delay.getValueI() <= 0)
113+
forceAll = true;
114+
115+
long now = MC.level != null ? MC.level.getGameTime() : 0;
116+
117+
if(forceAll || shouldReleaseQueue(s2cQueue, now, delay.getValueI()))
118+
{
119+
while(!s2cQueue.isEmpty())
120+
applyPacket(s2cQueue.removeFirst().packet);
121+
}
122+
123+
if(forceAll || shouldReleaseQueue(c2sQueue, now, delay.getValueI()))
124+
{
125+
sendQueuedPackets();
126+
}
127+
}
128+
129+
private boolean shouldReleaseQueue(ArrayDeque<PacketAndTime> queue,
130+
long now, int delayTicks)
131+
{
132+
if(queue.isEmpty())
133+
return false;
134+
135+
return queue.peekFirst().time <= now - delayTicks;
136+
}
137+
138+
private void sendQueuedPackets()
139+
{
140+
if(c2sQueue.isEmpty())
141+
return;
142+
143+
ClientPacketListener connection = MC.getConnection();
144+
if(connection == null)
145+
{
146+
c2sQueue.clear();
147+
return;
148+
}
149+
150+
flushingC2s = true;
151+
try
152+
{
153+
while(!c2sQueue.isEmpty())
154+
connection.send(c2sQueue.removeFirst().packet);
155+
156+
}finally
157+
{
158+
flushingC2s = false;
159+
}
160+
}
161+
162+
private void applyPacket(Packet<?> packet)
163+
{
164+
ClientPacketListener connection = MC.getConnection();
165+
if(connection == null)
166+
return;
167+
168+
@SuppressWarnings("unchecked")
169+
Packet<ClientPacketListener> typedPacket =
170+
(Packet<ClientPacketListener>)packet;
171+
typedPacket.handle(connection);
172+
}
173+
174+
private static class PacketAndTime
175+
{
176+
private final Packet<?> packet;
177+
private final long time;
178+
179+
private PacketAndTime(Packet<?> packet, long time)
180+
{
181+
this.packet = packet;
182+
this.time = time;
183+
}
184+
}
185+
}

src/main/java/net/wurstclient/keybinds/KeybindProcessor.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,26 @@ public void onKeyPress(KeyPressEvent event)
4545
GLFW.GLFW_KEY_F3))
4646
return;
4747

48+
String keyName = getKeyName(event);
49+
String cmds = keybinds.getCommands(keyName);
50+
boolean isPacketDelayKeybind =
51+
cmds != null && isPacketDelayKeybind(cmds);
52+
4853
Screen screen = WurstClient.MC.screen;
4954
// Allow processing when no screen is open, when the Click GUI is open,
5055
// or when Waypoints or ItemHandler screens are open so their keybinds
5156
// can toggle/close them with the same key.
5257
if(screen != null && !(screen instanceof ClickGuiScreen)
5358
&& !(screen instanceof net.wurstclient.clickgui.screens.WaypointsScreen)
5459
&& !(screen instanceof net.wurstclient.hacks.itemhandler.ItemHandlerScreen))
55-
return;
56-
60+
{
61+
if(!isPacketDelayKeybind)
62+
return;
63+
}
64+
5765
// if ClickGuiScreen is open and user typed a printable key, open
5866
// navigator and pass the initial character
59-
if(screen instanceof ClickGuiScreen)
67+
if(screen instanceof ClickGuiScreen && !isPacketDelayKeybind)
6068
{
6169
ClickGui gui = WurstClient.INSTANCE.getGui();
6270
if(gui != null && gui.isKeyboardInputCaptured())
@@ -75,9 +83,6 @@ public void onKeyPress(KeyPressEvent event)
7583
}
7684
}
7785

78-
String keyName = getKeyName(event);
79-
80-
String cmds = keybinds.getCommands(keyName);
8186
if(cmds == null)
8287
return;
8388

@@ -121,6 +126,22 @@ private void processCmds(String cmds)
121126
processCmd(cmd.trim());
122127
}
123128

129+
private boolean isPacketDelayKeybind(String cmds)
130+
{
131+
cmds = cmds.replace(";", "\u00a7").replace("\u00a7\u00a7", ";");
132+
for(String cmd : cmds.split("\u00a7"))
133+
{
134+
String trimmed = cmd.trim();
135+
if(trimmed.startsWith("."))
136+
trimmed = trimmed.substring(1).trim();
137+
138+
if(trimmed.equalsIgnoreCase("packetdelay"))
139+
return true;
140+
}
141+
142+
return false;
143+
}
144+
124145
private void processCmd(String cmd)
125146
{
126147
String trimmed = cmd.trim();

src/main/resources/assets/wurst/translations/en_us.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
"description.wurst.hack.openwateresp": "Shows whether or not you are fishing in 'open water' and draws a box around the area used for the open water calculation.",
155155
"description.wurst.hack.overlay": "Renders the Nuker animation whenever you mine a block.",
156156
"description.wurst.hack.panic": "Instantly turns off all enabled hacks.\nBe careful with this one!",
157+
"description.wurst.hack.packetdelay": "Delays network packets and releases them all at once.",
157158
"description.wurst.hack.parkour": "Makes you jump automatically when reaching the edge of a block.\nUseful for parkours and jump'n'runs.",
158159
"description.wurst.hack.playeresp": "Highlights nearby players.\nESP boxes of friends will appear in blue.",
159160
"description.wurst.hack.portalesp": "Highlights nearby portals.",

0 commit comments

Comments
 (0)