1313import java .util .stream .Collectors ;
1414import java .util .stream .Stream ;
1515import java .util .stream .StreamSupport ;
16+ import net .minecraft .world .entity .Entity ;
1617import net .minecraft .world .entity .LivingEntity ;
1718import net .minecraft .world .entity .player .Player ;
19+ import net .minecraft .world .entity .projectile .ShulkerBullet ;
1820import net .minecraft .world .phys .AABB ;
1921import net .wurstclient .Category ;
2022import net .wurstclient .SearchTags ;
@@ -80,6 +82,7 @@ public final class MobEspHack extends Hack implements UpdateListener,
8082 FilterArmorStandsSetting .genericVision (true ));
8183
8284 private final ArrayList <LivingEntity > mobs = new ArrayList <>();
85+ private final ArrayList <ShulkerBullet > shulkerBullets = new ArrayList <>();
8386
8487 // New: optionally show detected count in HackList
8588 private final CheckboxSetting showCountInHackList = new CheckboxSetting (
@@ -94,6 +97,10 @@ public final class MobEspHack extends Hack implements UpdateListener,
9497 private final SliderSetting aboveGroundY = new SliderSetting (
9598 "Set ESP Y limit" , 62 , -65 , 255 , 1 , SliderSetting .ValueDisplay .INTEGER );
9699
100+ private final CheckboxSetting highlightShulkerProjectiles =
101+ new CheckboxSetting ("Highlight shulker projectiles" ,
102+ "Also outline the tracking projectiles fired by shulkers." , false );
103+
97104 private int foundCount ;
98105
99106 public MobEspHack ()
@@ -108,6 +115,7 @@ public MobEspHack()
108115 entityFilters .forEach (this ::addSetting );
109116 addSetting (onlyAboveGround );
110117 addSetting (aboveGroundY );
118+ addSetting (highlightShulkerProjectiles );
111119 addSetting (showCountInHackList );
112120 }
113121
@@ -126,12 +134,14 @@ protected void onDisable()
126134 EVENTS .remove (CameraTransformViewBobbingListener .class , this );
127135 EVENTS .remove (RenderListener .class , this );
128136 foundCount = 0 ;
137+ shulkerBullets .clear ();
129138 }
130139
131140 @ Override
132141 public void onUpdate ()
133142 {
134143 mobs .clear ();
144+ shulkerBullets .clear ();
135145
136146 Stream <LivingEntity > stream = StreamSupport
137147 .stream (MC .level .entitiesForRendering ().spliterator (), false )
@@ -145,8 +155,20 @@ public void onUpdate()
145155 stream = entityFilters .applyTo (stream );
146156
147157 mobs .addAll (stream .collect (Collectors .toList ()));
158+
159+ if (highlightShulkerProjectiles .isChecked ())
160+ {
161+ for (Entity entity : MC .level .entitiesForRendering ())
162+ if (entity instanceof ShulkerBullet bullet
163+ && !bullet .isRemoved ())
164+ shulkerBullets .add (bullet );
165+ }
166+
148167 // update count for HUD (clamped to 999)
149- foundCount = Math .min (mobs .size (), 999 );
168+ int highlighted = mobs .size ();
169+ if (highlightShulkerProjectiles .isChecked ())
170+ highlighted += shulkerBullets .size ();
171+ foundCount = Math .min (highlighted , 999 );
150172 }
151173
152174 @ Override
@@ -175,12 +197,16 @@ public void onRender(PoseStack matrixStack, float partialTicks)
175197 boolean drawLines = style .hasLines ();
176198 boolean drawFill = drawShape && fillShapes .isChecked ();
177199
200+ int anticipatedSize = mobs .size ();
201+ if (highlightShulkerProjectiles .isChecked ())
202+ anticipatedSize += shulkerBullets .size ();
203+
178204 ArrayList <ColoredBox > outlineShapes =
179- drawShape ? new ArrayList <>(mobs . size () ) : null ;
205+ drawShape ? new ArrayList <>(anticipatedSize ) : null ;
180206 ArrayList <ColoredBox > filledShapes =
181- drawFill ? new ArrayList <>(mobs . size () ) : null ;
207+ drawFill ? new ArrayList <>(anticipatedSize ) : null ;
182208 ArrayList <ColoredPoint > ends =
183- drawLines ? new ArrayList <>(mobs . size () ) : null ;
209+ drawLines ? new ArrayList <>(anticipatedSize ) : null ;
184210
185211 if (drawShape || drawLines )
186212 {
@@ -209,6 +235,34 @@ public void onRender(PoseStack matrixStack, float partialTicks)
209235 ends .add (
210236 new ColoredPoint (lerpedBox .getCenter (), outlineColor ));
211237 }
238+
239+ if (highlightShulkerProjectiles .isChecked ())
240+ {
241+ for (ShulkerBullet bullet : shulkerBullets )
242+ {
243+ AABB lerpedBox =
244+ EntityUtils .getLerpedBox (bullet , partialTicks );
245+ float [] rgb = getColorRgb ();
246+ int outlineColor = RenderUtils .toIntColor (rgb , 0.5F );
247+
248+ if (drawShape )
249+ {
250+ AABB box =
251+ lerpedBox .move (0 , extraSize , 0 ).inflate (extraSize );
252+ outlineShapes .add (new ColoredBox (box , outlineColor ));
253+
254+ if (filledShapes != null )
255+ {
256+ int fillColor = RenderUtils .toIntColor (rgb , 0.15F );
257+ filledShapes .add (new ColoredBox (box , fillColor ));
258+ }
259+ }
260+
261+ if (drawLines && ends != null )
262+ ends .add (new ColoredPoint (lerpedBox .getCenter (),
263+ outlineColor ));
264+ }
265+ }
212266 }
213267
214268 if (!glowMode )
@@ -244,6 +298,28 @@ public void onRender(PoseStack matrixStack, float partialTicks)
244298
245299 if (ends != null && !ends .isEmpty ())
246300 RenderUtils .drawTracers (matrixStack , partialTicks , ends , false );
301+
302+ if (glowMode && highlightShulkerProjectiles .isChecked ()
303+ && !shulkerBullets .isEmpty ())
304+ renderShulkerProjectileFallback (matrixStack , partialTicks );
305+ }
306+
307+ private void renderShulkerProjectileFallback (PoseStack matrixStack ,
308+ float partialTicks )
309+ {
310+ ArrayList <ColoredBox > filledShapes =
311+ new ArrayList <>(shulkerBullets .size ());
312+ double extraSize = boxSize .getExtraSize () / 2D ;
313+ int fillColor = RenderUtils .toIntColor (getColorRgb (), 0.35F );
314+
315+ for (ShulkerBullet bullet : shulkerBullets )
316+ {
317+ AABB box = EntityUtils .getLerpedBox (bullet , partialTicks )
318+ .move (0 , extraSize , 0 ).inflate (extraSize );
319+ filledShapes .add (new ColoredBox (box , fillColor ));
320+ }
321+
322+ RenderUtils .drawSolidBoxes (matrixStack , filledShapes , false );
247323 }
248324
249325 private float [] getColorRgb ()
0 commit comments