Skip to content

Commit d132f3a

Browse files
committed
Added Spam, Fixed Anti/Auto Drop
1 parent ccd30f1 commit d132f3a

7 files changed

Lines changed: 588 additions & 6 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public final class HackList implements UpdateListener
5656
public final AutoArmorHack autoArmorHack = new AutoArmorHack();
5757
public final AutoBuildHack autoBuildHack = new AutoBuildHack();
5858
public final AutoChatHack autoChatHack = new AutoChatHack();
59+
public final ChatSpamHack chatSpamHack = new ChatSpamHack();
60+
public final CommandSpamHack commandSpamHack = new CommandSpamHack();
5961
public final CommandScannerHack commandScannerHack =
6062
new CommandScannerHack();
6163
public final AutoCompleteHack autoCompleteHack = new AutoCompleteHack();

src/main/java/net/wurstclient/hacks/AntiVoidHack.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,15 @@ public final class AntiVoidHack extends Hack implements UpdateListener
3737
"Prevents falling into the void/lava by air-walking instead of rubberbanding.",
3838
false);
3939

40-
private final CheckboxSetting falseFloor =
41-
new CheckboxSetting("False floor",
42-
"Treat the Nether and End as if they had a solid floor below you.",
43-
false);
40+
private final CheckboxSetting falseFloor = new CheckboxSetting(
41+
"False floor",
42+
"Treat the Overworld, Nether and End as if they had a solid floor below you.",
43+
false);
44+
45+
private final SliderSetting overworldFalseFloorY = new SliderSetting(
46+
"Overworld floor Y",
47+
"Block Y for the fake Overworld floor. The walkable surface is one block above this.",
48+
-4, -64, 320, 1, ValueDisplay.INTEGER);
4449

4550
private final SliderSetting netherFalseFloorY = new SliderSetting(
4651
"Nether floor Y",
@@ -204,6 +209,7 @@ public AntiVoidHack()
204209
setCategory(Category.MOVEMENT);
205210
addSetting(useAirWalk);
206211
addSetting(falseFloor);
212+
addSetting(overworldFalseFloorY);
207213
addSetting(netherFalseFloorY);
208214
addSetting(endFalseFloorY);
209215
addSetting(detectLava);
@@ -383,7 +389,9 @@ private boolean applyFalseFloor(LocalPlayer player)
383389
return false;
384390

385391
double floorY;
386-
if(MC.level.dimension() == Level.NETHER)
392+
if(MC.level.dimension() == Level.OVERWORLD)
393+
floorY = overworldFalseFloorY.getValue() + 1.0;
394+
else if(MC.level.dimension() == Level.NETHER)
387395
floorY = netherFalseFloorY.getValue() + 1.0;
388396
else if(MC.level.dimension() == Level.END)
389397
floorY = endFalseFloorY.getValue() + 1.0;

src/main/java/net/wurstclient/hacks/AutoDropHack.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,21 @@
77
*/
88
package net.wurstclient.hacks;
99

10+
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
1011
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
1112
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
13+
import net.minecraft.client.multiplayer.ClientPacketListener;
1214
import net.minecraft.core.registries.BuiltInRegistries;
15+
import net.minecraft.network.HashedStack;
16+
import net.minecraft.network.protocol.game.ServerboundContainerClickPacket;
17+
import net.minecraft.world.inventory.ContainerInput;
1318
import net.minecraft.world.item.Item;
1419
import net.minecraft.world.item.ItemStack;
1520
import net.wurstclient.Category;
1621
import net.wurstclient.SearchTags;
1722
import net.wurstclient.events.UpdateListener;
1823
import net.wurstclient.hack.Hack;
24+
import net.wurstclient.settings.CheckboxSetting;
1925
import net.wurstclient.settings.ItemListSetting;
2026

2127
@SearchTags({"auto drop", "AutoEject", "auto-eject", "auto eject",
@@ -32,6 +38,13 @@ public final class AutoDropHack extends Hack implements UpdateListener
3238
"minecraft:rose_bush", "minecraft:rotten_flesh", "minecraft:sunflower",
3339
"minecraft:wheat_seeds", "minecraft:white_tulip");
3440

41+
private final CheckboxSetting packetOnly = new CheckboxSetting(
42+
"Packet-only mode",
43+
"Sends raw drop packets instead of using Minecraft's normal inventory"
44+
+ " click handler. Experimental: may reduce local animations, but can"
45+
+ " cause temporary inventory desync if a server rejects the packet.",
46+
false);
47+
3548
private final String renderName =
3649
Math.random() < 0.01 ? "AutoLinus" : getName();
3750

@@ -40,6 +53,7 @@ public AutoDropHack()
4053
super("AutoDrop");
4154
setCategory(Category.ITEMS);
4255
addSetting(items);
56+
addSetting(packetOnly);
4357
}
4458

4559
@Override
@@ -84,7 +98,30 @@ public void onUpdate()
8498
if(!items.getItemNames().contains(itemName))
8599
continue;
86100

87-
IMC.getInteractionManager().windowClick_THROW(slot);
101+
if(packetOnly.isChecked())
102+
sendThrowPacket(slot, adjustedSlot);
103+
else
104+
IMC.getInteractionManager().windowClick_THROW(slot);
88105
}
89106
}
107+
108+
private void sendThrowPacket(int slot, int inventorySlot)
109+
{
110+
ClientPacketListener connection = MC.getConnection();
111+
if(connection == null)
112+
return;
113+
114+
ServerboundContainerClickPacket packet =
115+
new ServerboundContainerClickPacket(
116+
MC.player.containerMenu.containerId,
117+
MC.player.containerMenu.getStateId(), (short)slot, (byte)1,
118+
ContainerInput.THROW, new Int2ObjectOpenHashMap<>(),
119+
HashedStack.EMPTY);
120+
121+
connection.send(packet);
122+
123+
// Vanilla normally predicts click results locally. Packet-only mode
124+
// skips that path, so clear the slot to avoid resending it every tick.
125+
MC.player.getInventory().setItem(inventorySlot, ItemStack.EMPTY);
126+
}
90127
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
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.io.IOException;
11+
import java.nio.charset.StandardCharsets;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
17+
import net.wurstclient.Category;
18+
import net.wurstclient.SearchTags;
19+
import net.wurstclient.events.UpdateListener;
20+
import net.wurstclient.hack.DontSaveState;
21+
import net.wurstclient.hack.Hack;
22+
import net.wurstclient.settings.CheckboxSetting;
23+
import net.wurstclient.settings.FileSetting;
24+
import net.wurstclient.settings.SliderSetting;
25+
import net.wurstclient.settings.SliderSetting.ValueDisplay;
26+
import net.wurstclient.settings.TextFieldSetting;
27+
import net.wurstclient.util.ChatUtils;
28+
29+
@SearchTags({"chat spam", "chatspam", "spam chat", "message spam"})
30+
@DontSaveState
31+
public final class ChatSpamHack extends Hack implements UpdateListener
32+
{
33+
private static final int CHAT_LIMIT = 256;
34+
35+
private final TextFieldSetting message = new TextFieldSetting("Message",
36+
"Chat message to send repeatedly when file mode is disabled.", "",
37+
s -> s != null && s.length() <= CHAT_LIMIT);
38+
39+
private final SliderSetting amount =
40+
new SliderSetting("Amount", "How many times to send the message.", 10,
41+
1, 10000, 1, ValueDisplay.INTEGER);
42+
43+
private final SliderSetting pause =
44+
new SliderSetting("Pause", "Seconds to wait between messages.", 1, 0,
45+
60, 0.05, ValueDisplay.DECIMAL.withSuffix("s"));
46+
47+
private final CheckboxSetting useFile = new CheckboxSetting("Use file",
48+
"Send each line from the selected text file instead of the Message field.",
49+
false);
50+
51+
private final FileSetting textFile = new FileSetting("File",
52+
"Select a text file to read line by line.", "chatspam", folder -> {
53+
try
54+
{
55+
Files.createDirectories(folder);
56+
Path file = folder.resolve("messages.txt");
57+
if(Files.notExists(file))
58+
{
59+
Files.writeString(file,
60+
"Hello from ChatSpam!\n" + "This is the second line.\n",
61+
StandardCharsets.UTF_8);
62+
}
63+
}catch(IOException e)
64+
{
65+
throw new RuntimeException(e);
66+
}
67+
});
68+
69+
private final ArrayList<String> pendingMessages = new ArrayList<>();
70+
private int currentIndex;
71+
private int timer;
72+
private boolean fileMode;
73+
74+
public ChatSpamHack()
75+
{
76+
super("ChatSpam");
77+
setCategory(Category.CHAT);
78+
addSetting(message);
79+
addSetting(amount);
80+
addSetting(pause);
81+
addSetting(useFile);
82+
addSetting(textFile);
83+
}
84+
85+
@Override
86+
public String getRenderName()
87+
{
88+
if(!isEnabled())
89+
return getName();
90+
91+
int total = getTotalMessages();
92+
return getName() + " [" + Math.min(currentIndex, total) + "/" + total
93+
+ "]";
94+
}
95+
96+
@Override
97+
public String getStatusText()
98+
{
99+
if(!isEnabled())
100+
return null;
101+
102+
int total = getTotalMessages();
103+
return Math.min(currentIndex, total) + "/" + total;
104+
}
105+
106+
@Override
107+
protected void onEnable()
108+
{
109+
timer = 0;
110+
currentIndex = 0;
111+
fileMode = useFile.isChecked();
112+
pendingMessages.clear();
113+
114+
if(fileMode)
115+
{
116+
if(!loadMessagesFromFile())
117+
{
118+
setEnabled(false);
119+
return;
120+
}
121+
}else
122+
{
123+
String configuredMessage = normalizeMessage(message.getValue());
124+
if(configuredMessage.isEmpty())
125+
{
126+
ChatUtils.error("ChatSpam: enter a message first.");
127+
setEnabled(false);
128+
return;
129+
}
130+
131+
pendingMessages.add(configuredMessage);
132+
}
133+
134+
EVENTS.add(UpdateListener.class, this);
135+
}
136+
137+
@Override
138+
protected void onDisable()
139+
{
140+
EVENTS.remove(UpdateListener.class, this);
141+
pendingMessages.clear();
142+
currentIndex = 0;
143+
timer = 0;
144+
fileMode = false;
145+
}
146+
147+
@Override
148+
public void onUpdate()
149+
{
150+
if(MC.player == null || MC.getConnection() == null)
151+
return;
152+
153+
if(timer > 0)
154+
{
155+
timer--;
156+
return;
157+
}
158+
159+
int total = getTotalMessages();
160+
if(currentIndex >= total)
161+
{
162+
setEnabled(false);
163+
return;
164+
}
165+
166+
String chatMessage = fileMode ? pendingMessages.get(currentIndex)
167+
: pendingMessages.get(0);
168+
if(chatMessage == null || chatMessage.isBlank())
169+
{
170+
currentIndex++;
171+
return;
172+
}
173+
174+
MC.getConnection().sendChat(chatMessage);
175+
currentIndex++;
176+
177+
if(currentIndex >= total)
178+
{
179+
setEnabled(false);
180+
return;
181+
}
182+
183+
timer = getPauseTicks();
184+
}
185+
186+
private int getTotalMessages()
187+
{
188+
if(fileMode)
189+
return pendingMessages.size();
190+
191+
return amount.getValueI();
192+
}
193+
194+
private int getPauseTicks()
195+
{
196+
return Math.max(0, (int)Math.round(pause.getValue() * 20));
197+
}
198+
199+
private boolean loadMessagesFromFile()
200+
{
201+
Path selectedFile = textFile.getSelectedFile();
202+
if(selectedFile == null)
203+
{
204+
ChatUtils.error("ChatSpam: no file selected.");
205+
return false;
206+
}
207+
208+
List<String> lines;
209+
try
210+
{
211+
lines = Files.readAllLines(selectedFile, StandardCharsets.UTF_8);
212+
}catch(IOException e)
213+
{
214+
ChatUtils.error(
215+
"ChatSpam: couldn't read " + selectedFile.getFileName() + ".");
216+
return false;
217+
}
218+
219+
for(String line : lines)
220+
{
221+
String normalized = normalizeMessage(line);
222+
if(!normalized.isEmpty())
223+
pendingMessages.add(normalized);
224+
}
225+
226+
if(pendingMessages.isEmpty())
227+
{
228+
ChatUtils.error("ChatSpam: the selected file has no messages.");
229+
return false;
230+
}
231+
232+
return true;
233+
}
234+
235+
private static String normalizeMessage(String message)
236+
{
237+
if(message == null)
238+
return "";
239+
240+
String trimmed = message.replace("\r", "");
241+
if(trimmed.length() > CHAT_LIMIT)
242+
trimmed = trimmed.substring(0, CHAT_LIMIT);
243+
244+
return trimmed;
245+
}
246+
}

0 commit comments

Comments
 (0)