Skip to content

Commit 1292031

Browse files
committed
Added UseItemSpam Hack
1 parent 044624d commit 1292031

4 files changed

Lines changed: 296 additions & 29 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ public final class HackList implements UpdateListener
289289
public final StepHack stepHack = new StepHack();
290290
public final TemplateToolHack templateToolHack = new TemplateToolHack();
291291
public final ThrowHack throwHack = new ThrowHack();
292+
public final UseItemSpamHack useItemSpamHack = new UseItemSpamHack();
292293
public final TillauraHack tillauraHack = new TillauraHack();
293294
public final TimerHack timerHack = new TimerHack();
294295
public final TargetPlaceHack targetPlaceHack = new TargetPlaceHack();

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

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -991,35 +991,37 @@ private UUID resolveOwnerUuid(int ownerId)
991991
return null;
992992
}
993993

994-
private void rememberPearlOwnersForEntityId(int ownerId, UUID ownerUuid)
995-
{
996-
if(ownerUuid == null)
997-
return;
998-
999-
// Walk all known pearl spawn owner ids
1000-
for(Map.Entry<UUID, Integer> entry : pearlSpawnOwnerIds.entrySet())
1001-
{
1002-
Integer pearlOwnerId = entry.getValue();
1003-
if(pearlOwnerId == null || pearlOwnerId != ownerId)
1004-
continue;
1005-
1006-
rememberPearlOwnerUuid(entry.getKey(), ownerUuid);
1007-
}
1008-
1009-
// Also walk pearl identities that have this owner entity id
1010-
for(Map.Entry<UUID, PearlIdentity> entry : pearlIdentities.entrySet())
1011-
{
1012-
PearlIdentity pid = entry.getValue();
1013-
if(pid.ownerEntityId() != null && pid.ownerEntityId() == ownerId)
1014-
{
1015-
UUID pearlUuid = entry.getKey();
1016-
if(!pearlSpawnOwnerIds.containsKey(pearlUuid)
1017-
|| pearlSpawnOwnerIds.get(pearlUuid) != ownerId)
1018-
// Already handled above
1019-
continue;
1020-
rememberPearlOwnerUuid(pearlUuid, ownerUuid);
1021-
}
1022-
}
994+
private void rememberPearlOwnersForEntityId(int ownerId, UUID ownerUuid)
995+
{
996+
if(ownerUuid == null)
997+
return;
998+
999+
// Walk all known pearl spawn owner ids
1000+
for(Map.Entry<UUID, Integer> entry : new ArrayList<>(
1001+
pearlSpawnOwnerIds.entrySet()))
1002+
{
1003+
Integer pearlOwnerId = entry.getValue();
1004+
if(pearlOwnerId == null || pearlOwnerId != ownerId)
1005+
continue;
1006+
1007+
rememberPearlOwnerUuid(entry.getKey(), ownerUuid);
1008+
}
1009+
1010+
// Also walk pearl identities that have this owner entity id
1011+
for(Map.Entry<UUID, PearlIdentity> entry : new ArrayList<>(
1012+
pearlIdentities.entrySet()))
1013+
{
1014+
PearlIdentity pid = entry.getValue();
1015+
if(pid.ownerEntityId() != null && pid.ownerEntityId() == ownerId)
1016+
{
1017+
UUID pearlUuid = entry.getKey();
1018+
if(pearlSpawnOwnerIds.containsKey(pearlUuid)
1019+
&& pearlSpawnOwnerIds.get(pearlUuid) == ownerId)
1020+
// Already handled above
1021+
continue;
1022+
rememberPearlOwnerUuid(pearlUuid, ownerUuid);
1023+
}
1024+
}
10231025
}
10241026

10251027
private String getOwnerUuidLabel(UUID ownerUuid)
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
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.lang.reflect.Field;
11+
import java.lang.reflect.Method;
12+
import java.util.Locale;
13+
import net.minecraft.core.component.DataComponents;
14+
import net.minecraft.core.registries.BuiltInRegistries;
15+
import net.minecraft.network.protocol.game.ServerboundUseItemPacket;
16+
import net.minecraft.resources.Identifier;
17+
import net.minecraft.world.InteractionHand;
18+
import net.minecraft.world.item.CrossbowItem;
19+
import net.minecraft.world.item.EggItem;
20+
import net.minecraft.world.item.EnderpearlItem;
21+
import net.minecraft.world.item.Item;
22+
import net.minecraft.world.item.ItemStack;
23+
import net.minecraft.world.item.ProjectileWeaponItem;
24+
import net.minecraft.world.item.ShieldItem;
25+
import net.minecraft.world.item.SnowballItem;
26+
import net.minecraft.world.item.ThrowablePotionItem;
27+
import net.minecraft.world.item.component.Consumable;
28+
import net.wurstclient.Category;
29+
import net.wurstclient.SearchTags;
30+
import net.wurstclient.events.UpdateListener;
31+
import net.wurstclient.hack.Hack;
32+
import net.wurstclient.settings.CheckboxSetting;
33+
import net.wurstclient.settings.SliderSetting;
34+
import net.wurstclient.settings.SliderSetting.ValueDisplay;
35+
36+
@SearchTags({"use item spam", "useitemspam", "crossbow machine gun",
37+
"crossbow spam"})
38+
public final class UseItemSpamHack extends Hack implements UpdateListener
39+
{
40+
private final CheckboxSetting crossbow =
41+
new CheckboxSetting("Crossbow", true);
42+
private final CheckboxSetting throwables =
43+
new CheckboxSetting("Throwables", false);
44+
private final CheckboxSetting consumables =
45+
new CheckboxSetting("Consumables", false);
46+
private final CheckboxSetting utilityItems =
47+
new CheckboxSetting("Utility Items", false);
48+
private final CheckboxSetting all = new CheckboxSetting("All", false);
49+
50+
private final SliderSetting delay =
51+
new SliderSetting("Delay", "Ticks between packets.", 0, 0, 20, 1,
52+
ValueDisplay.INTEGER.withSuffix(" ticks"));
53+
54+
private final CheckboxSetting correctSequence = new CheckboxSetting(
55+
"Correct sequence", "Use current prediction sequence.", true);
56+
57+
private final CheckboxSetting requireRightClick = new CheckboxSetting(
58+
"Require right click", "Only repeat while holding use.", true);
59+
60+
private final CheckboxSetting onlyWhenUsingItem =
61+
new CheckboxSetting("Only when using item",
62+
"Only repeat if Minecraft already thinks you are using the item.",
63+
false);
64+
65+
private int timer;
66+
67+
public UseItemSpamHack()
68+
{
69+
super("UseItemSpam");
70+
71+
setCategory(Category.ITEMS);
72+
addSetting(crossbow);
73+
addSetting(throwables);
74+
addSetting(consumables);
75+
addSetting(utilityItems);
76+
addSetting(all);
77+
addSetting(delay);
78+
addSetting(correctSequence);
79+
addSetting(requireRightClick);
80+
addSetting(onlyWhenUsingItem);
81+
}
82+
83+
@Override
84+
protected void onEnable()
85+
{
86+
timer = 0;
87+
EVENTS.add(UpdateListener.class, this);
88+
}
89+
90+
@Override
91+
protected void onDisable()
92+
{
93+
EVENTS.remove(UpdateListener.class, this);
94+
}
95+
96+
@Override
97+
public void onUpdate()
98+
{
99+
if(MC.player == null || MC.level == null || MC.options == null
100+
|| MC.getConnection() == null)
101+
return;
102+
103+
if(requireRightClick.isChecked() && !MC.options.keyUse.isDown())
104+
{
105+
timer = 0;
106+
return;
107+
}
108+
109+
if(delay.getValueI() > 0)
110+
{
111+
if(timer < delay.getValueI())
112+
{
113+
timer++;
114+
return;
115+
}
116+
117+
timer = 0;
118+
}
119+
120+
InteractionHand crossbowHand = findCrossbowHand();
121+
if(crossbowHand != null)
122+
{
123+
spamCrossbow(crossbowHand);
124+
return;
125+
}
126+
127+
InteractionHand genericHand = findGenericMatchingHand();
128+
if(genericHand == null)
129+
return;
130+
131+
if(onlyWhenUsingItem.isChecked() && !isAlreadyUsing(genericHand))
132+
return;
133+
134+
MC.startUseItem();
135+
}
136+
137+
private void spamCrossbow(InteractionHand hand)
138+
{
139+
ItemStack stack = MC.player.getItemInHand(hand);
140+
if(stack.isEmpty() || !(stack.getItem() instanceof CrossbowItem))
141+
return;
142+
143+
if(onlyWhenUsingItem.isChecked() && !isAlreadyUsing(hand))
144+
return;
145+
146+
// Vanilla sometimes hasn't entered the using state yet, so kick off
147+
// the initial use locally before relying on packet spam.
148+
if(!MC.player.isUsingItem() && !CrossbowItem.isCharged(stack))
149+
{
150+
MC.startUseItem();
151+
return;
152+
}
153+
154+
MC.getConnection().send(new ServerboundUseItemPacket(hand,
155+
getPredictionSequence(), MC.player.getYRot(), MC.player.getXRot()));
156+
}
157+
158+
private InteractionHand findCrossbowHand()
159+
{
160+
if(!crossbow.isChecked())
161+
return null;
162+
163+
ItemStack mainHand = MC.player.getMainHandItem();
164+
if(mainHand.getItem() instanceof CrossbowItem)
165+
return InteractionHand.MAIN_HAND;
166+
167+
ItemStack offHand = MC.player.getOffhandItem();
168+
if(offHand.getItem() instanceof CrossbowItem)
169+
return InteractionHand.OFF_HAND;
170+
171+
return null;
172+
}
173+
174+
private InteractionHand findGenericMatchingHand()
175+
{
176+
ItemStack mainHand = MC.player.getMainHandItem();
177+
if(matchesGenericType(mainHand))
178+
return InteractionHand.MAIN_HAND;
179+
180+
ItemStack offHand = MC.player.getOffhandItem();
181+
if(matchesGenericType(offHand))
182+
return InteractionHand.OFF_HAND;
183+
184+
return null;
185+
}
186+
187+
private boolean matchesGenericType(ItemStack stack)
188+
{
189+
if(stack == null || stack.isEmpty())
190+
return false;
191+
192+
if(all.isChecked())
193+
return true;
194+
195+
Item item = stack.getItem();
196+
return throwables.isChecked() && isThrowable(item)
197+
|| consumables.isChecked() && isConsumable(stack)
198+
|| utilityItems.isChecked() && isUtilityItem(item);
199+
}
200+
201+
private boolean isAlreadyUsing(InteractionHand hand)
202+
{
203+
return MC.player.isUsingItem() && MC.player.getUsedItemHand() == hand;
204+
}
205+
206+
private boolean isThrowable(Item item)
207+
{
208+
return item instanceof SnowballItem || item instanceof EggItem
209+
|| item instanceof EnderpearlItem
210+
|| item instanceof ThrowablePotionItem;
211+
}
212+
213+
private boolean isConsumable(ItemStack stack)
214+
{
215+
Consumable consumable = stack.get(DataComponents.CONSUMABLE);
216+
return consumable != null;
217+
}
218+
219+
private boolean isUtilityItem(Item item)
220+
{
221+
if(item instanceof ShieldItem || item instanceof ProjectileWeaponItem
222+
|| item instanceof SnowballItem || item instanceof EggItem
223+
|| item instanceof EnderpearlItem
224+
|| item instanceof ThrowablePotionItem)
225+
return false;
226+
227+
Identifier id = BuiltInRegistries.ITEM.getKey(item);
228+
if(id == null)
229+
return false;
230+
231+
String path = id.getPath().toLowerCase(Locale.ROOT);
232+
return item instanceof ShieldItem || path.contains("bucket")
233+
|| path.contains("spyglass") || path.contains("goat_horn")
234+
|| path.contains("brush") || path.contains("flint_and_steel")
235+
|| path.contains("fire_charge") || path.contains("bundle")
236+
|| path.contains("writable_book") || path.contains("written_book");
237+
}
238+
239+
private int getPredictionSequence()
240+
{
241+
if(!correctSequence.isChecked())
242+
return 0;
243+
244+
try
245+
{
246+
Field handlerField = MC.level.getClass()
247+
.getDeclaredField("blockStatePredictionHandler");
248+
handlerField.setAccessible(true);
249+
Object handler = handlerField.get(MC.level);
250+
if(handler == null)
251+
return 0;
252+
253+
Method currentSequence =
254+
handler.getClass().getMethod("currentSequence");
255+
Object value = currentSequence.invoke(handler);
256+
return value instanceof Integer i ? i : 0;
257+
258+
}catch(ReflectiveOperationException e)
259+
{
260+
return 0;
261+
}
262+
}
263+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@
597597
"hack.wurst.staffmonitor": "StaffMonitor",
598598
"description.wurst.hack.staffmonitor": "Monitors the tab list for players entering or leaving spectator mode, with optional alerts for hidden staff and visible player entities missing from the tab list.",
599599
"description.wurst.hack.ui-utils": "Adds UI utilities like packet control, chat-in-GUI input, and resource pack bypass tools.",
600+
"description.wurst.hack.useitemspam": "Repeatedly sends use-item packets for selected item types while holding right click. Credit: aisiaiiad (github.com/aisiaiiad).",
600601
"hack.wurst.pearlesp": "PearlESP",
601602
"description.wurst.hack.pearlesp": "Highlights ender pearls thrown by other players, shows predicted landing with a purple box, draws a trajectory line, and highlights when players are holding an ender pearl.",
602603
"hack.wurst.pearldrop": "PearlDrop",

0 commit comments

Comments
 (0)