1010import net .minecraft .network .protocol .game .ServerboundMovePlayerPacket .Pos ;
1111import net .minecraft .world .entity .Entity ;
1212import net .minecraft .world .item .Items ;
13- import net .minecraft .world .phys .HitResult ;
13+ import net .minecraft .world .phys .AABB ;
1414import net .wurstclient .Category ;
1515import net .wurstclient .SearchTags ;
1616import net .wurstclient .events .PlayerAttacksEntityListener ;
1717import net .wurstclient .hack .Hack ;
18+ import net .wurstclient .settings .CheckboxSetting ;
1819import net .wurstclient .settings .SliderSetting ;
1920import net .wurstclient .settings .SliderSetting .ValueDisplay ;
2021
@@ -23,16 +24,26 @@ public final class MaceDmgHack extends Hack
2324 implements PlayerAttacksEntityListener
2425{
2526 private static final double DEFAULT_HEIGHT = Math .sqrt (500 );
26-
27+ private static final double MIN_FALL = 1.6 ;
28+ private static final double SCAN_STEP = 0.25 ;
29+
2730 private final SliderSetting height = new SliderSetting ("Height" ,
2831 "How high to fake before slamming. Height determines the damage boost." ,
2932 DEFAULT_HEIGHT , 1.6 , 50 , 0.1 , ValueDisplay .DECIMAL );
30-
33+
34+ private final CheckboxSetting caveMode = new CheckboxSetting ("Cave mode" ,
35+ "Scans for an air gap above you to fall through, so smashes work under"
36+ + " a ceiling. Fully sealed spaces still can't be smashed." ,
37+ true );
38+
39+ private long lastSmashTick = -1 ;
40+
3141 public MaceDmgHack ()
3242 {
3343 super ("MaceDMG" );
3444 setCategory (Category .COMBAT );
3545 addSetting (height );
46+ addSetting (caveMode );
3647 }
3748
3849 @ Override
@@ -50,22 +61,45 @@ protected void onDisable()
5061 @ Override
5162 public void onPlayerAttacksEntity (Entity target )
5263 {
53- if (MC .hitResult == null
54- || MC .hitResult .getType () != HitResult .Type .ENTITY )
64+ doSmash ();
65+ }
66+
67+ public void doSmash ()
68+ {
69+ if (!isEnabled () || MC .player == null || MC .player .connection == null )
5570 return ;
56-
5771 if (!MC .player .getMainHandItem ().is (Items .MACE ))
5872 return ;
59-
73+
74+ long now = MC .player .tickCount ;
75+ if (now == lastSmashTick )
76+ return ;
77+ lastSmashTick = now ;
6078 // See ServerGamePacketListenerImpl.handleMovePlayer()
6179 // for why it's using these numbers.
6280 // Also, let me know if you find a way to bypass that check.
6381 for (int i = 0 ; i < 4 ; i ++)
6482 sendFakeY (0 );
65- sendFakeY (height . getValue ());
83+ sendFakeY (findFallOffset ());
6684 sendFakeY (0 );
6785 }
68-
86+
87+ private double findFallOffset ()
88+ {
89+ double cap = height .getValue ();
90+ if (!caveMode .isChecked () || MC .level == null )
91+ return cap ;
92+
93+ for (double off = cap ; off >= MIN_FALL ; off -= SCAN_STEP )
94+ {
95+ AABB box = MC .player .getBoundingBox ().move (0 , off , 0 );
96+ if (MC .level .noCollision (MC .player , box ))
97+ return off ;
98+ }
99+
100+ return cap ;
101+ }
102+
69103 private void sendFakeY (double offset )
70104 {
71105 MC .player .connection
0 commit comments