Skip to content

Commit a11e642

Browse files
committed
Add AutoSpawnProofer: automatically places torches on nearby spawnable tiles
1 parent d2d4470 commit a11e642

3 files changed

Lines changed: 230 additions & 0 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
@@ -86,6 +86,8 @@ public final class HackList implements UpdateListener
8686
public final AutoSoupHack autoSoupHack = new AutoSoupHack();
8787
public final AutoSprintHack autoSprintHack = new AutoSprintHack();
8888
public final AutoStealHack autoStealHack = new AutoStealHack();
89+
public final AutoSpawnProoferHack autoSpawnProoferHack =
90+
new AutoSpawnProoferHack();
8991
public final AutoSwimHack autoSwimHack = new AutoSwimHack();
9092
public final AutoSwitchHack autoSwitchHack = new AutoSwitchHack();
9193
public final AutoSwordHack autoSwordHack = new AutoSwordHack();
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
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 com.mojang.blaze3d.vertex.PoseStack;
11+
import java.awt.Color;
12+
import java.util.Comparator;
13+
import java.util.List;
14+
import net.minecraft.core.BlockPos;
15+
import net.minecraft.world.InteractionHand;
16+
import net.minecraft.world.entity.EntityTypes;
17+
import net.minecraft.world.entity.SpawnPlacements;
18+
import net.minecraft.world.entity.player.Inventory;
19+
import net.minecraft.world.item.BlockItem;
20+
import net.minecraft.world.item.ItemStack;
21+
import net.minecraft.world.level.LightLayer;
22+
import net.minecraft.world.level.block.Block;
23+
import net.minecraft.world.phys.AABB;
24+
import net.minecraft.world.phys.Vec3;
25+
import net.wurstclient.Category;
26+
import net.wurstclient.SearchTags;
27+
import net.wurstclient.events.RenderListener;
28+
import net.wurstclient.events.UpdateListener;
29+
import net.wurstclient.hack.Hack;
30+
import net.wurstclient.settings.BlockListSetting;
31+
import net.wurstclient.settings.CheckboxSetting;
32+
import net.wurstclient.settings.ColorSetting;
33+
import net.wurstclient.settings.EspStyleSetting;
34+
import net.wurstclient.settings.SliderSetting;
35+
import net.wurstclient.settings.SliderSetting.ValueDisplay;
36+
import net.wurstclient.settings.SwingHandSetting;
37+
import net.wurstclient.settings.SwingHandSetting.SwingHand;
38+
import net.wurstclient.util.BlockPlacer;
39+
import net.wurstclient.util.BlockPlacer.BlockPlacingParams;
40+
import net.wurstclient.util.BlockUtils;
41+
import net.wurstclient.util.InteractionSimulator;
42+
import net.wurstclient.util.InventoryUtils;
43+
import net.wurstclient.util.RenderUtils;
44+
import net.wurstclient.util.RotationUtils;
45+
46+
@SearchTags({"auto spawn proofer", "AutoTorch", "auto torch", "torch placer",
47+
"spawn proof", "spawnproof", "anti spawn"})
48+
public final class AutoSpawnProoferHack extends Hack
49+
implements UpdateListener, RenderListener
50+
{
51+
private final SliderSetting range =
52+
new SliderSetting("Range", 5, 1, 7, 0.05, ValueDisplay.DECIMAL);
53+
54+
private final CheckboxSetting autoPlace = new CheckboxSetting("Auto place",
55+
"Automatically places light sources on highlighted spawn spots.\n"
56+
+ "When off, AutoSpawnProofer only highlights where mobs can spawn.",
57+
true);
58+
59+
private final SliderSetting lightLevel = new SliderSetting("Light level",
60+
"Maximum block light at which a tile still counts as spawnable.\n"
61+
+ "Hostile mobs spawn at block light 0, so the default of 1 proofs"
62+
+ " exactly the tiles where they can appear.",
63+
1, 0, 7, 1, ValueDisplay.INTEGER);
64+
65+
private final BlockListSetting lightBlocks = new BlockListSetting(
66+
"Light blocks", "The light sources AutoSpawnProofer is allowed to use.",
67+
"minecraft:torch", "minecraft:soul_torch", "minecraft:jack_o_lantern",
68+
"minecraft:shroomlight", "minecraft:glowstone",
69+
"minecraft:sea_lantern");
70+
71+
private final EspStyleSetting style = new EspStyleSetting();
72+
private final ColorSetting color = new ColorSetting("Color",
73+
"Spawnable tiles are highlighted in this color.", new Color(0xFF0000));
74+
private final SliderSetting fillAlpha = new SliderSetting("Fill opacity",
75+
"Opacity of the highlighted spawn tiles.", 64, 0, 255, 1,
76+
ValueDisplay.INTEGER);
77+
private final SliderSetting outlineAlpha = new SliderSetting(
78+
"Outline opacity", "Opacity of the highlight outlines.", 255, 0, 255, 1,
79+
ValueDisplay.INTEGER);
80+
81+
private final SwingHandSetting swingHand =
82+
new SwingHandSetting(this, SwingHand.SERVER);
83+
84+
private List<BlockPos> targets = List.of();
85+
private BlockPos currentTarget;
86+
87+
public AutoSpawnProoferHack()
88+
{
89+
super("AutoSpawnProofer");
90+
setCategory(Category.BLOCKS);
91+
addSetting(range);
92+
addSetting(autoPlace);
93+
addSetting(lightLevel);
94+
addSetting(lightBlocks);
95+
addSetting(style);
96+
addSetting(color);
97+
addSetting(fillAlpha);
98+
addSetting(outlineAlpha);
99+
addSetting(swingHand);
100+
}
101+
102+
@Override
103+
protected void onEnable()
104+
{
105+
EVENTS.add(UpdateListener.class, this);
106+
EVENTS.add(RenderListener.class, this);
107+
}
108+
109+
@Override
110+
protected void onDisable()
111+
{
112+
EVENTS.remove(UpdateListener.class, this);
113+
EVENTS.remove(RenderListener.class, this);
114+
115+
targets = List.of();
116+
currentTarget = null;
117+
}
118+
119+
@Override
120+
public void onUpdate()
121+
{
122+
currentTarget = null;
123+
124+
Vec3 eyesVec = RotationUtils.getEyesPos();
125+
BlockPos eyesBlock = BlockPos.containing(eyesVec);
126+
double rangeSq = range.getValueSq();
127+
int blockRange = range.getValueCeil();
128+
129+
targets = BlockUtils.getAllInBoxStream(eyesBlock, blockRange)
130+
.filter(pos -> pos.distToCenterSqr(eyesVec) <= rangeSq)
131+
.filter(this::isSpawnable)
132+
.sorted(
133+
Comparator.comparingDouble(pos -> pos.distToCenterSqr(eyesVec)))
134+
.toList();
135+
136+
if(autoPlace.isChecked())
137+
placeLight(rangeSq);
138+
}
139+
140+
@Override
141+
public void onRender(PoseStack matrixStack, float partialTicks)
142+
{
143+
if(targets.isEmpty())
144+
return;
145+
146+
List<AABB> boxes = targets.stream().map(AABB::new).toList();
147+
148+
if(style.getSelected().hasBoxes())
149+
{
150+
RenderUtils.drawSolidBoxes(matrixStack, boxes,
151+
color.getColorI(fillAlpha.getValueI()), false);
152+
RenderUtils.drawOutlinedBoxes(matrixStack, boxes,
153+
color.getColorI(outlineAlpha.getValueI()), false);
154+
}
155+
156+
if(style.getSelected().hasLines())
157+
RenderUtils.drawTracers(matrixStack, partialTicks,
158+
boxes.stream().map(AABB::getCenter).toList(),
159+
color.getColorI(outlineAlpha.getValueI()), false);
160+
}
161+
162+
private boolean placeLight(double rangeSq)
163+
{
164+
if(MC.rightClickDelay > 0 || MC.gameMode.isDestroying()
165+
|| MC.player.isHandsBusy())
166+
return false;
167+
168+
for(BlockPos pos : targets)
169+
{
170+
BlockPlacingParams params = BlockPlacer.getBlockPlacingParams(pos);
171+
if(params == null || params.requiresSneaking()
172+
|| params.distanceSq() > rangeSq)
173+
continue;
174+
175+
if(!selectLightBlock())
176+
return false;
177+
178+
ItemStack heldStack = MC.player.getMainHandItem();
179+
if(!isLightBlock(heldStack))
180+
return false;
181+
182+
currentTarget = pos;
183+
MC.rightClickDelay = 4;
184+
WURST.getRotationFaker().faceVectorPacket(params.hitVec());
185+
InteractionSimulator.rightClickBlock(params.toHitResult(),
186+
InteractionHand.MAIN_HAND, swingHand.getSelected());
187+
return true;
188+
}
189+
190+
return false;
191+
}
192+
193+
private boolean selectLightBlock()
194+
{
195+
if(isLightBlock(MC.player.getMainHandItem()))
196+
return true;
197+
198+
return InventoryUtils.selectItem(this::isLightBlock);
199+
}
200+
201+
private boolean isLightBlock(ItemStack stack)
202+
{
203+
if(!(stack.getItem() instanceof BlockItem blockItem))
204+
return false;
205+
206+
Block block = blockItem.getBlock();
207+
if(!lightBlocks.matchesBlock(block))
208+
return false;
209+
210+
Inventory inventory = MC.player.getInventory();
211+
return !stack.isEmpty() && (MC.player.getAbilities().instabuild
212+
|| inventory.countItem(stack.getItem()) > 0);
213+
}
214+
215+
private boolean isSpawnable(BlockPos pos)
216+
{
217+
if(!BlockUtils.getState(pos).canBeReplaced())
218+
return false;
219+
220+
if(!SpawnPlacements.isSpawnPositionOk(EntityTypes.CREEPER, MC.level,
221+
pos))
222+
return false;
223+
224+
return MC.level.getBrightness(LightLayer.BLOCK, pos) <= lightLevel
225+
.getValueI();
226+
}
227+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"description.wurst.hack.antiwobble": "Disables the wobble effect caused by nausea and portals.",
3333
"description.wurst.hack.arrowdmg": "Massively increases arrow damage, but also consumes a lot of hunger and reduces accuracy.\n\nDoes not work with crossbows and seems to be patched on Paper servers.",
3434
"description.wurst.hack.areanuker": "Combines Excavator's area selection with SpeedNuker's speed.",
35+
"description.wurst.hack.autospawnproofer": "Automatically places light sources (torches by default) on nearby tiles where hostile mobs could spawn.",
3536
"description.wurst.setting.arrowdmg.strength": "Strength of the effect. 10 is the highest possible as of Minecraft 1.21.",
3637
"description.wurst.setting.arrowdmg.trident_yeet_mode": "When enabled, tridents fly much further. Doesn't seem to affect damage or Riptide.\n\nWARNING: You can easily lose your trident by enabling this option!",
3738
"description.wurst.hack.attributeswap": "Swaps main-hand item attributes with the target slot.",

0 commit comments

Comments
 (0)