99
1010import java .util .Comparator ;
1111import java .util .stream .Stream ;
12+ import net .minecraft .network .protocol .game .ServerboundMovePlayerPacket .PosRot ;
1213import net .minecraft .world .InteractionHand ;
1314import net .minecraft .world .entity .Entity ;
1415import net .minecraft .world .phys .EntityHitResult ;
16+ import net .minecraft .world .phys .Vec3 ;
1517import net .wurstclient .Category ;
1618import net .wurstclient .SearchTags ;
1719import net .wurstclient .events .UpdateListener ;
1820import net .wurstclient .hack .Hack ;
1921import net .wurstclient .settings .AttackSpeedSliderSetting ;
22+ import net .wurstclient .settings .CheckboxSetting ;
2023import net .wurstclient .settings .SliderSetting ;
2124import net .wurstclient .settings .SliderSetting .ValueDisplay ;
2225import net .wurstclient .settings .SwingHandSetting ;
2326import net .wurstclient .settings .SwingHandSetting .SwingHand ;
2427import net .wurstclient .settings .filterlists .EntityFilterList ;
2528import net .wurstclient .util .EntityUtils ;
29+ import net .wurstclient .util .Rotation ;
2630import net .wurstclient .util .RotationUtils ;
2731
2832@ SearchTags ({"outreach" , "wall hit" , "wall attack" })
@@ -42,6 +46,10 @@ public final class OutreachHack extends Hack implements UpdateListener
4246 private final SwingHandSetting swingHand =
4347 new SwingHandSetting (this , SwingHand .CLIENT );
4448
49+ private final CheckboxSetting spoofBehind =
50+ new CheckboxSetting ("Spoof from behind" ,
51+ "Pretends to attack from the opposite side of your target." , false );
52+
4553 private final EntityFilterList entityFilters =
4654 EntityFilterList .genericCombat ();
4755
@@ -55,6 +63,7 @@ public OutreachHack()
5563 addSetting (range );
5664 addSetting (fov );
5765 addSetting (swingHand );
66+ addSetting (spoofBehind );
5867 entityFilters .forEach (this ::addSetting );
5968 }
6069
@@ -119,9 +128,89 @@ public void onUpdate()
119128 return ;
120129
121130 WURST .getHax ().autoSwordHack .setSlot (target );
122- MC .gameMode .attack (MC .player , target );
123- swingHand .swing (InteractionHand .MAIN_HAND );
124- swingSpeed .resetTimer ();
131+ boolean attacked = false ;
132+ if (spoofBehind .isChecked ())
133+ attacked = attackWithBehindSpoof (target );
134+
135+ if (!attacked )
136+ attacked = attackNormally (target );
137+
138+ if (attacked )
139+ swingSpeed .resetTimer ();
125140 }
126141 }
142+
143+ private boolean attackNormally (Entity target )
144+ {
145+ MC .gameMode .attack (MC .player , target );
146+ swingHand .swing (InteractionHand .MAIN_HAND );
147+ return true ;
148+ }
149+
150+ private boolean attackWithBehindSpoof (Entity target )
151+ {
152+ if (MC .player == null || MC .player .connection == null )
153+ return false ;
154+
155+ Vec3 spoofPos = calculateSpoofPosition (target );
156+ if (spoofPos == null )
157+ return false ;
158+
159+ Vec3 spoofEyes =
160+ spoofPos .add (0 , MC .player .getEyeHeight (MC .player .getPose ()), 0 );
161+ Vec3 targetCenter = target .getBoundingBox ().getCenter ();
162+ Rotation spoofRot = rotationFrom (spoofEyes , targetCenter );
163+
164+ Vec3 originalPos = MC .player .position ();
165+ Rotation originalRot =
166+ new Rotation (MC .player .getYRot (), MC .player .getXRot ());
167+
168+ sendSpoofedPosRot (spoofPos , spoofRot );
169+ MC .gameMode .attack (MC .player , target );
170+ swingHand .swing (InteractionHand .MAIN_HAND );
171+ sendSpoofedPosRot (originalPos , originalRot );
172+ return true ;
173+ }
174+
175+ private Vec3 calculateSpoofPosition (Entity target )
176+ {
177+ if (MC .player == null )
178+ return null ;
179+
180+ Vec3 center = target .getBoundingBox ().getCenter ();
181+ Vec3 eyes = RotationUtils .getEyesPos ();
182+ Vec3 direction = center .subtract (eyes );
183+ double lenSq = direction .lengthSqr ();
184+ if (lenSq < 1.0e-6 )
185+ return null ;
186+
187+ Vec3 normalized = direction .normalize ();
188+ double extra = Math .max (0.75 , target .getBbWidth () + 0.75 );
189+ Vec3 behind = center .add (normalized .scale (extra ));
190+ return new Vec3 (behind .x , MC .player .getY (), behind .z );
191+ }
192+
193+ private Rotation rotationFrom (Vec3 start , Vec3 end )
194+ {
195+ double diffX = end .x - start .x ;
196+ double diffZ = end .z - start .z ;
197+ double yaw = Math .toDegrees (Math .atan2 (diffZ , diffX )) - 90F ;
198+
199+ double diffY = end .y - start .y ;
200+ double diffXZ = Math .sqrt (diffX * diffX + diffZ * diffZ );
201+ double pitch = -Math .toDegrees (Math .atan2 (diffY , diffXZ ));
202+
203+ return Rotation .wrapped ((float )yaw , (float )pitch );
204+ }
205+
206+ private void sendSpoofedPosRot (Vec3 pos , Rotation rotation )
207+ {
208+ if (MC .player == null || MC .player .connection == null )
209+ return ;
210+
211+ boolean onGround = MC .player .onGround ();
212+ boolean collision = MC .player .horizontalCollision ;
213+ MC .player .connection .send (new PosRot (pos .x , pos .y , pos .z ,
214+ rotation .yaw (), rotation .pitch (), onGround , collision ));
215+ }
127216}
0 commit comments