77 */
88package net .wurstclient .hacks ;
99
10+ import java .awt .Color ;
11+
1012import com .mojang .blaze3d .vertex .PoseStack ;
1113import net .minecraft .world .phys .BlockHitResult ;
1214import net .minecraft .world .phys .HitResult ;
1315import net .wurstclient .Category ;
16+ import net .wurstclient .SearchTags ;
17+ import net .wurstclient .WurstClient ;
1418import net .wurstclient .events .RenderListener ;
1519import net .wurstclient .events .UpdateListener ;
1620import net .wurstclient .hack .Hack ;
21+ import net .wurstclient .settings .CheckboxSetting ;
22+ import net .wurstclient .settings .ColorSetting ;
23+ import net .wurstclient .settings .SliderSetting ;
24+ import net .wurstclient .settings .SliderSetting .ValueDisplay ;
1725import net .wurstclient .util .OverlayRenderer ;
26+ import net .wurstclient .util .OverlayRenderer .OverlayConfig ;
1827
28+ @ SearchTags ({"overlay" , "block outline" , "selection box" , "block highlight" ,
29+ "mining progress" , "block color" })
1930public final class OverlayHack extends Hack
2031 implements UpdateListener , RenderListener
2132{
2233 private final OverlayRenderer renderer = new OverlayRenderer ();
2334
35+ // ==================== Selection settings ====================
36+ private final CheckboxSetting selectionMode = new CheckboxSetting (
37+ "Selection overlay" ,
38+ "Show the overlay just by looking at a block, without mining." , false );
39+ private final ColorSetting selectionColor =
40+ new ColorSetting ("Selection color" ,
41+ "Color of the selection block outline." , new Color (0x00FF00 ));
42+ private final CheckboxSetting selectionFill =
43+ new CheckboxSetting ("Selection fill" ,
44+ "Fill the box. Disable for wireframe-only outline." , false );
45+ private final SliderSetting selectionOpacity = new SliderSetting (
46+ "Selection opacity" , 0.5 , 0.05 , 1.0 , 0.05 , ValueDisplay .PERCENTAGE );
47+ private final CheckboxSetting selectionRainbow =
48+ new CheckboxSetting ("Selection rainbow" , "Rainbow cycling." , false );
49+ private final SliderSetting selectionRainbowSpeed = new SliderSetting (
50+ "Selection rainbow speed" , 1.0 , 0.01 , 2.0 , 0.01 , ValueDisplay .DECIMAL );
51+ private final CheckboxSetting selectionPulse =
52+ new CheckboxSetting ("Selection pulse" , "Fade in and out." , false );
53+ private final SliderSetting selectionPulseSpeed = new SliderSetting (
54+ "Selection pulse speed" , 1.0 , 0.01 , 10.0 , 0.01 , ValueDisplay .DECIMAL );
55+ private final CheckboxSetting selectionGlow = new CheckboxSetting (
56+ "Selection glow" , "Glowing shells + corner rays." , false );
57+ private final SliderSetting selectionGlowIntensity =
58+ new SliderSetting ("Selection glow intensity" , 0.5 , 0.1 , 1.0 , 0.1 ,
59+ ValueDisplay .PERCENTAGE );
60+ private final CheckboxSetting selectionThroughWalls = new CheckboxSetting (
61+ "Selection through walls" ,
62+ "Show the selection overlay through walls instead of visible faces only." ,
63+ false );
64+
65+ // ==================== Break progress settings ====================
66+ private final ColorSetting breakStartColor = new ColorSetting (
67+ "Break start color" , "Start color for the break progress transition." ,
68+ new Color (0xFFFF00 ));
69+ private final ColorSetting breakEndColor = new ColorSetting (
70+ "Break end color" , "End color for the break progress transition." ,
71+ new Color (0xFF0000 ));
72+ private final CheckboxSetting breakSolidColor =
73+ new CheckboxSetting ("Break solid color" ,
74+ "Use a single solid color instead of start\u2192 end transition." ,
75+ false );
76+ private final CheckboxSetting breakFill = new CheckboxSetting ("Break fill" ,
77+ "Fill the box. Disable for wireframe-only outline." , true );
78+ private final SliderSetting breakOpacity = new SliderSetting (
79+ "Break opacity" , 0.5 , 0.05 , 1.0 , 0.05 , ValueDisplay .PERCENTAGE );
80+ private final CheckboxSetting breakRainbow =
81+ new CheckboxSetting ("Break rainbow" , "Rainbow cycling." , false );
82+ private final SliderSetting breakRainbowSpeed = new SliderSetting (
83+ "Break rainbow speed" , 1.0 , 0.01 , 2.0 , 0.01 , ValueDisplay .DECIMAL );
84+ private final CheckboxSetting breakPulse =
85+ new CheckboxSetting ("Break pulse" , "Fade in and out." , false );
86+ private final SliderSetting breakPulseSpeed = new SliderSetting (
87+ "Break pulse speed" , 1.0 , 0.01 , 10.0 , 0.01 , ValueDisplay .DECIMAL );
88+ private final CheckboxSetting breakGlow = new CheckboxSetting ("Break glow" ,
89+ "Glowing shells + corner rays." , false );
90+ private final SliderSetting breakGlowIntensity = new SliderSetting (
91+ "Break glow intensity" , 0.5 , 0.1 , 1.0 , 0.1 , ValueDisplay .PERCENTAGE );
92+
2493 public OverlayHack ()
2594 {
26- super ("Overlay " );
95+ super ("BlockOverlay " );
2796 setCategory (Category .RENDER );
97+
98+ // Selection settings
99+ addSetting (selectionMode );
100+ addSetting (selectionColor );
101+ addSetting (selectionFill );
102+ addSetting (selectionOpacity );
103+ addSetting (selectionRainbow );
104+ addSetting (selectionRainbowSpeed );
105+ addSetting (selectionPulse );
106+ addSetting (selectionPulseSpeed );
107+ addSetting (selectionGlow );
108+ addSetting (selectionGlowIntensity );
109+ addSetting (selectionThroughWalls );
110+
111+ // Break progress settings
112+ addSetting (breakStartColor );
113+ addSetting (breakEndColor );
114+ addSetting (breakSolidColor );
115+ addSetting (breakFill );
116+ addSetting (breakOpacity );
117+ addSetting (breakRainbow );
118+ addSetting (breakRainbowSpeed );
119+ addSetting (breakPulse );
120+ addSetting (breakPulseSpeed );
121+ addSetting (breakGlow );
122+ addSetting (breakGlowIntensity );
28123 }
29124
30125 @ Override
@@ -45,7 +140,7 @@ protected void onDisable()
45140 @ Override
46141 public void onUpdate ()
47142 {
48- if (shouldRenderOverlay ())
143+ if (isBreaking ())
49144 renderer .updateProgress ();
50145 else
51146 renderer .resetProgress ();
@@ -54,29 +149,73 @@ public void onUpdate()
54149 @ Override
55150 public void onRender (PoseStack matrixStack , float partialTicks )
56151 {
57- if (! shouldRenderOverlay () )
152+ if (MC . gameMode == null || MC . player == null )
58153 return ;
59154
60155 if (!(MC .hitResult instanceof BlockHitResult blockHitResult )
61156 || blockHitResult .getType () != HitResult .Type .BLOCK )
62157 return ;
63158
64- renderer .render (matrixStack , partialTicks ,
65- blockHitResult .getBlockPos ());
159+ boolean selection = selectionMode .isChecked () && !isBreaking ();
160+ boolean breaking = isBreaking ();
161+
162+ if (selection )
163+ renderer .render (matrixStack , partialTicks ,
164+ blockHitResult .getBlockPos (), buildSelectionConfig ());
165+
166+ if (breaking )
167+ renderer .render (matrixStack , partialTicks ,
168+ blockHitResult .getBlockPos (), buildBreakConfig ());
66169 }
67170
68- private boolean shouldRenderOverlay ()
171+ private boolean isBreaking ()
69172 {
70- if (MC .gameMode == null || MC . player == null )
173+ if (MC .gameMode == null )
71174 return false ;
72175
73176 if (MC .gameMode .isDestroying ())
74177 return true ;
75178
76- // Fallback for hacks/modes that bypass vanilla destroy state.
77179 return MC .options .keyAttack .isDown ()
78180 && MC .hitResult instanceof BlockHitResult blockHitResult
79181 && blockHitResult .getType () == HitResult .Type .BLOCK
80182 && MC .gui .screen () == null ;
81183 }
184+
185+ // --- Config builders ---
186+
187+ private OverlayConfig buildBreakConfig ()
188+ {
189+ return new OverlayConfig (false , breakStartColor .getColor (),
190+ breakEndColor .getColor (), breakSolidColor .isChecked (),
191+ breakFill .isChecked (), breakOpacity .getValueF (),
192+ breakRainbow .isChecked (), breakRainbowSpeed .getValue (),
193+ breakPulse .isChecked (), breakPulseSpeed .getValue (),
194+ breakGlow .isChecked (), breakGlowIntensity .getValueF (), false );
195+ }
196+
197+ private OverlayConfig buildSelectionConfig ()
198+ {
199+ return new OverlayConfig (true , selectionColor .getColor (),
200+ selectionColor .getColor (), true , selectionFill .isChecked (),
201+ selectionOpacity .getValueF (), selectionRainbow .isChecked (),
202+ selectionRainbowSpeed .getValue (), selectionPulse .isChecked (),
203+ selectionPulseSpeed .getValue (), selectionGlow .isChecked (),
204+ selectionGlowIntensity .getValueF (),
205+ !selectionThroughWalls .isChecked ());
206+ }
207+
208+ /**
209+ * Checked by the mixin to cancel vanilla's dark-grey block outline
210+ * when the custom selection overlay is active.
211+ */
212+ public static boolean shouldCancelVanillaBlockOutline ()
213+ {
214+ if (WurstClient .INSTANCE == null
215+ || WurstClient .INSTANCE .getHax () == null )
216+ return false ;
217+ OverlayHack hack = WurstClient .INSTANCE .getHax ().overlayHack ;
218+ return hack != null && hack .isEnabled ()
219+ && hack .selectionMode .isChecked ();
220+ }
82221}
0 commit comments