Skip to content

Commit 93170e3

Browse files
committed
feat: add Legit Mace Kill module v0.1.2
- Add Legit Mace Kill module based on @etianl's original code - Features fall height multiplier system (1.0x-10.0x) - Only activates when falling from minimum height threshold - Includes safety features to prevent fall damage - Cleaned up imports and unnecessary code - Updated version to 0.1.2
1 parent 931526b commit 93170e3

4 files changed

Lines changed: 179 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ Nora Tweaks is a custom addon for the [Meteor Client](https://meteorclient.com/)
77
* **Custom Category Manager:** Create, manage, and sort your own custom module categories, which appear seamlessly in the module list.
88
* **Auto Dirt Path:** Automatically creates paths from dirt-like blocks when holding a shovel.
99
* **Auto Farm Land:** Automatically creates farm land from dirt-like blocks when holding a hoe.
10+
* **Legit Mace Kill:** Makes the Mace powerful when swung by amplifying your actual fall distance (only works when falling).
1011
* **Chat Utility:** A collection of chat-related tools.
1112
* **Hotkey Utility:** Set up quick hotbar changes with key combination.

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ yarn_mappings=1.21.7+build.1
88
loader_version=0.16.14
99

1010
# Mod Properties
11-
mod_version=0.1.1
11+
mod_version=0.1.2
1212
maven_group=me.noramibu
1313
archives_base_name=nora-tweaks
1414

src/main/java/me/noramibu/tweaks/NoraTweaks.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import me.noramibu.tweaks.modules.CategoryManagerModule;
77
import me.noramibu.tweaks.modules.ChatUtility;
88
import me.noramibu.tweaks.modules.HotkeyUtility;
9+
import me.noramibu.tweaks.modules.MaceKill;
910
import com.mojang.logging.LogUtils;
1011
import meteordevelopment.meteorclient.addons.MeteorAddon;
1112
import meteordevelopment.meteorclient.systems.modules.Category;
@@ -28,6 +29,7 @@ public void onInitialize() {
2829
Modules.get().add(new CategoryManagerModule());
2930
Modules.get().add(new ChatUtility());
3031
Modules.get().add(new HotkeyUtility());
32+
Modules.get().add(new MaceKill());
3133
}
3234

3335
@Override
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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

Comments
 (0)