77
88import com .google .common .collect .Streams ;
99import meteordevelopment .meteorclient .events .world .TickEvent ;
10+ import meteordevelopment .meteorclient .mixininterface .IVec3d ;
1011import meteordevelopment .meteorclient .pathing .PathManagers ;
1112import meteordevelopment .meteorclient .settings .*;
1213import meteordevelopment .meteorclient .systems .modules .Categories ;
1617import net .minecraft .entity .Entity ;
1718import net .minecraft .entity .attribute .EntityAttributes ;
1819import net .minecraft .entity .decoration .EndCrystalEntity ;
20+ import net .minecraft .util .math .Box ;
21+ import net .minecraft .util .math .Vec2f ;
22+ import net .minecraft .util .math .Vec3d ;
1923
2024import java .util .OptionalDouble ;
2125
@@ -72,13 +76,12 @@ public void onActivate() {
7276 @ EventHandler
7377 private void onTick (TickEvent .Post event ) {
7478 boolean work = (activeWhen .get () == ActiveWhen .Always ) || (activeWhen .get () == ActiveWhen .Sneaking && mc .player .isSneaking ()) || (activeWhen .get () == ActiveWhen .NotSneaking && !mc .player .isSneaking ());
75- mc . player . setBoundingBox ( mc . player . getBoundingBox (). offset ( 0 , 1 , 0 ) );
76- if (work && (! safeStep . get () || ( getHealth () > stepHealth . get () && getHealth () - getExplosionDamage () > stepHealth . get ()))) {
77- mc .player .getAttributeInstance (EntityAttributes .STEP_HEIGHT ).setBaseValue (height . get () );
79+ double height = getMaxSafeHeight ( );
80+ if (work && height > 0 ) {
81+ mc .player .getAttributeInstance (EntityAttributes .STEP_HEIGHT ).setBaseValue (height );
7882 } else {
7983 mc .player .getAttributeInstance (EntityAttributes .STEP_HEIGHT ).setBaseValue (prevStepHeight );
8084 }
81- mc .player .setBoundingBox (mc .player .getBoundingBox ().offset (0 , -1 , 0 ));
8285 }
8386
8487 @ Override
@@ -101,6 +104,56 @@ private double getExplosionDamage() {
101104 return crystalDamage .orElse (0.0 );
102105 }
103106
107+ private boolean isSafe () {
108+ return getHealth () > stepHealth .get () && getHealth () - getExplosionDamage () > stepHealth .get ();
109+ }
110+
111+ private boolean isSaferThanWith (double damage ) {
112+ return isSafe () || getExplosionDamage () - damage <= 0 ;
113+ }
114+
115+ private double getMaxSafeHeight () {
116+ if (!safeStep .get ()) return height .get ();
117+
118+ double max = height .get ();
119+ double h = 0 ;
120+ double currentDamage =getExplosionDamage ();
121+ Box initial = mc .player .getBoundingBox ();
122+
123+ // all of this is to avoid running into crystals which are behind
124+ // one block when holding a movement key because standing on the
125+ // near edge of that block is technically safe
126+
127+ Vec3d inputOffset = mc .player .getRotationVector ();
128+ Vec2f input = mc .player .input .getMovementInput ();
129+ ((IVec3d ) inputOffset ).meteor$setY (0 );
130+ inputOffset = inputOffset .normalize ().multiply (1.2 );
131+ double zdot = inputOffset .z ;
132+ double xdot = inputOffset .x ;
133+ inputOffset = new Vec3d (input .y * xdot + input .x * zdot , 0 , input .x * xdot + input .y * zdot );
134+
135+ for (int i = 1 ; i < max ; i ++) {
136+ mc .player .setBoundingBox (initial .offset (0 , i , 0 ));
137+ if (!isSaferThanWith (currentDamage )) {
138+ mc .player .setBoundingBox (initial );
139+ return h ;
140+ }
141+
142+ mc .player .setBoundingBox (mc .player .getBoundingBox ().offset (inputOffset ));
143+ if (!isSaferThanWith (currentDamage )) {
144+ mc .player .setBoundingBox (initial );
145+ return h ;
146+ }
147+ h += 1 ;
148+ }
149+ mc .player .setBoundingBox (initial .offset (0 , max , 0 ));
150+
151+ if (isSaferThanWith (currentDamage )) h = max ;
152+
153+ mc .player .setBoundingBox (initial );
154+ return h ;
155+ }
156+
104157 public enum ActiveWhen {
105158 Always ,
106159 Sneaking ,
0 commit comments