1+ package me .noramibu .tweaks .modules ;
2+
3+ /**
4+ * Original code written by @etianl https://github.com/etianl/Trouser-Streak/blob/main/src/main/java/pwn/noobs/trouserstreak/modules/MaceKill.java
5+ */
6+
7+ import me .noramibu .tweaks .NoraTweaks ;
8+ import meteordevelopment .meteorclient .events .packets .PacketEvent ;
9+ import meteordevelopment .meteorclient .mixininterface .IPlayerInteractEntityC2SPacket ;
10+ import meteordevelopment .meteorclient .mixininterface .IPlayerMoveC2SPacket ;
11+ import meteordevelopment .meteorclient .settings .*;
12+ import meteordevelopment .meteorclient .systems .modules .Module ;
13+ import meteordevelopment .orbit .EventHandler ;
14+ import net .minecraft .block .Blocks ;
15+ import net .minecraft .entity .LivingEntity ;
16+ import net .minecraft .item .Items ;
17+ import net .minecraft .network .packet .c2s .play .PlayerMoveC2SPacket ;
18+ import net .minecraft .network .packet .c2s .play .VehicleMoveC2SPacket ;
19+ import net .minecraft .util .math .BlockPos ;
20+ import net .minecraft .util .math .Vec3d ;
21+
22+ public class MaceKill extends Module {
23+ private final SettingGroup sgGeneral = settings .getDefaultGroup ();
24+ private final SettingGroup sgInfo = settings .createGroup ("Note: Disable \" Smash Attack\" in the Criticals module to make this work properly." );
25+ private final Setting <Boolean > preventDeath = sgGeneral .add (new BoolSetting .Builder ()
26+ .name ("Prevent Fall damage" )
27+ .description ("Attempts to prevent fall damage even on packet hiccups." )
28+ .defaultValue (true )
29+ .build ());
30+ private final Setting <Double > fallMultiplier = sgGeneral .add (new DoubleSetting .Builder ()
31+ .name ("Fall Height Multiplier" )
32+ .description ("Multiplies your current fall distance by this amount (e.g., 1.5x means 10 blocks becomes 15 blocks)" )
33+ .defaultValue (1.5 )
34+ .min (1.0 )
35+ .max (10.0 )
36+ .sliderMin (1.0 )
37+ .sliderMax (5.0 )
38+ .build ());
39+ private final Setting <Double > minFallHeight = sgGeneral .add (new DoubleSetting .Builder ()
40+ .name ("Minimum Fall Height" )
41+ .description ("Only activates if you fall from at least this height" )
42+ .defaultValue (2.0 )
43+ .min (0.5 )
44+ .max (20.0 )
45+ .sliderMax (10.0 )
46+ .build ());
47+
48+ private final Setting <Boolean > packetDisable = sgGeneral .add (new BoolSetting .Builder ()
49+ .name ("Disable When Blocked" )
50+ .description ("Does not send movement packets if the attack was blocked. (prevents death)" )
51+ .defaultValue (true )
52+ .build ());
53+
54+ public MaceKill () {
55+ super (NoraTweaks .CATEGORY , "legit-mace-kill" , "Amplifies mace damage based on fall distance. Only works when falling from minimum height." );
56+ }
57+
58+ private Vec3d previouspos ;
59+
60+ @ EventHandler
61+ private void onSendPacket (PacketEvent .Send event ) {
62+ if (mc .player == null ) return ;
63+ if (mc .player .getMainHandStack ().getItem () != Items .MACE ) return ;
64+ if (!(event .packet instanceof IPlayerInteractEntityC2SPacket packet )) return ;
65+ // Check if this is an attack packet by checking the type
66+ if (packet .meteor$getEntity () == null ) return ;
67+
68+ LivingEntity targetEntity = (LivingEntity ) packet .meteor$getEntity ();
69+ if (packetDisable .get () && (targetEntity .isBlocking () || targetEntity .isInvulnerable () || targetEntity .isInCreativeMode ()))
70+ return ;
71+
72+ previouspos = mc .player .getPos ();
73+
74+ // Don't activate if fall distance is below minimum height threshold
75+ if (mc .player .fallDistance < minFallHeight .get ()) return ;
76+
77+ int blocks = getMaxHeightAbovePlayer ();
78+
79+ int packetsRequired = (int ) Math .ceil (Math .abs (blocks / 10.0 ));
80+ if (packetsRequired > 20 ) packetsRequired = 1 ;
81+
82+ BlockPos isopenair1 = mc .player .getBlockPos ().add (0 , blocks , 0 );
83+ BlockPos isopenair2 = mc .player .getBlockPos ().add (0 , blocks + 1 , 0 );
84+ if (!isSafeBlock (isopenair1 ) || !isSafeBlock (isopenair2 )) return ;
85+
86+ if (blocks <= 22 ) {
87+ if (mc .player .hasVehicle ()) {
88+ for (int i = 0 ; i < 4 ; i ++) {
89+ mc .player .networkHandler .sendPacket (VehicleMoveC2SPacket .fromVehicle (mc .player .getVehicle ()));
90+ }
91+ double maxHeight = Math .min (mc .player .getVehicle ().getY () + 22 , mc .player .getVehicle ().getY () + blocks );
92+ doVehicleTeleports (maxHeight , blocks );
93+ } else {
94+ for (int i = 0 ; i < 4 ; i ++) {
95+ mc .player .networkHandler .sendPacket (new PlayerMoveC2SPacket .OnGroundOnly (false , mc .player .horizontalCollision ));
96+ }
97+ double heightY = Math .min (mc .player .getY () + 22 , mc .player .getY () + blocks );
98+ doPlayerTeleports (heightY );
99+ }
100+ } else {
101+ if (mc .player .hasVehicle ()) {
102+ for (int packetNumber = 0 ; packetNumber < (packetsRequired - 1 ); packetNumber ++) {
103+ mc .player .networkHandler .sendPacket (VehicleMoveC2SPacket .fromVehicle (mc .player .getVehicle ()));
104+ }
105+ double maxHeight = mc .player .getVehicle ().getY () + blocks ;
106+ doVehicleTeleports (maxHeight , blocks );
107+ } else {
108+ for (int i = 0 ; i < packetsRequired - 1 ; i ++) {
109+ mc .player .networkHandler .sendPacket (new PlayerMoveC2SPacket .OnGroundOnly (false , mc .player .horizontalCollision ));
110+ }
111+ double heightY = mc .player .getY () + blocks ;
112+ doPlayerTeleports (heightY );
113+ }
114+ }
115+ }
116+ private void doPlayerTeleports (double height ) {
117+ PlayerMoveC2SPacket movepacket = new PlayerMoveC2SPacket .PositionAndOnGround (
118+ mc .player .getX (), height , mc .player .getZ (), false , mc .player .horizontalCollision );
119+ PlayerMoveC2SPacket homepacket = new PlayerMoveC2SPacket .PositionAndOnGround (
120+ previouspos .getX (), previouspos .getY (), previouspos .getZ (),
121+ false , mc .player .horizontalCollision );
122+ if (preventDeath .get ()) {
123+ homepacket = new PlayerMoveC2SPacket .PositionAndOnGround (
124+ previouspos .getX (), previouspos .getY () + 0.25 , previouspos .getZ (),
125+ false , mc .player .horizontalCollision );
126+ }
127+ ((IPlayerMoveC2SPacket ) homepacket ).meteor$setTag (1337 );
128+ ((IPlayerMoveC2SPacket ) movepacket ).meteor$setTag (1337 );
129+ mc .player .networkHandler .sendPacket (movepacket );
130+ mc .player .networkHandler .sendPacket (homepacket );
131+ if (preventDeath .get ()) {
132+ mc .player .setVelocity (mc .player .getVelocity ().x , 0.1 , mc .player .getVelocity ().z );
133+ mc .player .fallDistance = 0 ;
134+ }
135+ }
136+ private void doVehicleTeleports (double height , int blocks ) {
137+ mc .player .getVehicle ().setPosition (mc .player .getVehicle ().getX (), height + blocks , mc .player .getVehicle ().getZ ());
138+ mc .player .networkHandler .sendPacket (VehicleMoveC2SPacket .fromVehicle (mc .player .getVehicle ()));
139+ mc .player .getVehicle ().setPosition (previouspos );
140+ mc .player .networkHandler .sendPacket (VehicleMoveC2SPacket .fromVehicle (mc .player .getVehicle ()));
141+ }
142+ private int getMaxHeightAbovePlayer () {
143+ BlockPos playerPos = mc .player .getBlockPos ();
144+
145+ // Use multiplier mode based on current fall distance
146+ double currentFallDistance = mc .player .fallDistance ;
147+
148+ // Only activate if falling from at least the minimum height
149+ if (currentFallDistance < minFallHeight .get ()) {
150+ return 0 ; // Don't activate if not falling from minimum height
151+ }
152+
153+ int multipliedHeight = (int ) (currentFallDistance * fallMultiplier .get ());
154+
155+ // Cap at reasonable maximum to prevent issues
156+ multipliedHeight = Math .min (multipliedHeight , 170 );
157+
158+ // Check if we can safely teleport to this height
159+ int targetHeight = playerPos .getY () + multipliedHeight ;
160+ for (int i = targetHeight ; i > playerPos .getY (); i --) {
161+ BlockPos up1 = new BlockPos (playerPos .getX (), i , playerPos .getZ ());
162+ BlockPos up2 = up1 .up (1 );
163+ if (isSafeBlock (up1 ) && isSafeBlock (up2 )) return i - playerPos .getY ();
164+ }
165+
166+ // If no safe position found, return 0 (don't activate)
167+ return 0 ;
168+ }
169+
170+ private boolean isSafeBlock (BlockPos pos ) {
171+ return mc .world .getBlockState (pos ).isReplaceable ()
172+ && mc .world .getFluidState (pos ).isEmpty ()
173+ && !mc .world .getBlockState (pos ).isOf (Blocks .POWDER_SNOW );
174+ }
175+ }
0 commit comments