Skip to content

Commit 6c0ac27

Browse files
committed
[feat] add tool-saver; adjust auto-tool
1 parent a2fa3cb commit 6c0ac27

File tree

3 files changed

+214
-30
lines changed

3 files changed

+214
-30
lines changed

src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ private void initPlayer() {
449449
add(new Reach());
450450
add(new Rotation());
451451
add(new SpeedMine());
452+
add(new ToolSaver());
452453
}
453454

454455
private void initMovement() {

src/main/java/meteordevelopment/meteorclient/systems/modules/player/AutoTool.java

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package meteordevelopment.meteorclient.systems.modules.player;
77

88

9+
import meteordevelopment.meteorclient.MeteorClient;
910
import meteordevelopment.meteorclient.events.entity.player.StartBreakingBlockEvent;
1011
import meteordevelopment.meteorclient.events.world.TickEvent;
1112
import meteordevelopment.meteorclient.settings.*;
@@ -51,37 +52,34 @@ public class AutoTool extends Module {
5152
.build()
5253
);
5354

54-
private final Setting<Boolean> fortuneForOresCrops = sgGeneral.add(new BoolSetting.Builder()
55-
.name("fortune-for-ores-and-crops")
56-
.description("Mines Ores and crops only with the Fortune enchantment.")
57-
.defaultValue(false)
55+
private final Setting<Boolean> silkTouchForGlass = sgGeneral.add(new BoolSetting.Builder()
56+
.name("silk-touch-for-glass")
57+
.description("Prefer to mine glass with silk touch")
58+
.defaultValue(true)
5859
.build()
5960
);
6061

61-
private final Setting<Boolean> antiBreak = sgGeneral.add(new BoolSetting.Builder()
62-
.name("anti-break")
63-
.description("Stops you from breaking your tool.")
62+
private final Setting<Boolean> fortuneForOresCrops = sgGeneral.add(new BoolSetting.Builder()
63+
.name("fortune-for-ores-and-crops")
64+
.description("Mines Ores and crops only with the Fortune enchantment.")
6465
.defaultValue(false)
6566
.build()
6667
);
6768

68-
private final Setting<Integer> breakDurability = sgGeneral.add(new IntSetting.Builder()
69-
.name("anti-break-percentage")
70-
.description("The durability percentage to stop using a tool.")
71-
.defaultValue(10)
72-
.range(1, 100)
73-
.sliderRange(1, 100)
74-
.visible(antiBreak::get)
75-
.build()
76-
);
77-
7869
private final Setting<Boolean> switchBack = sgGeneral.add(new BoolSetting.Builder()
7970
.name("switch-back")
8071
.description("Switches your hand to whatever was selected when releasing your attack key.")
8172
.defaultValue(false)
8273
.build()
8374
);
8475

76+
private final Setting<Boolean> switchAway = sgGeneral.add(new BoolSetting.Builder()
77+
.name("switch-away")
78+
.description("Switch to hand when no correct tool is found")
79+
.defaultValue(true)
80+
.build()
81+
);
82+
8583
private final Setting<Integer> switchDelay = sgGeneral.add((new IntSetting.Builder()
8684
.name("switch-delay")
8785
.description("Delay in ticks before switching tools.")
@@ -164,7 +162,7 @@ private void onStartBreakingBlock(StartBreakingBlockEvent event) {
164162
if (listMode.get() == ListMode.Whitelist && !whitelist.get().contains(itemStack.getItem())) continue;
165163
if (listMode.get() == ListMode.Blacklist && blacklist.get().contains(itemStack.getItem())) continue;
166164

167-
double score = getScore(itemStack, blockState, silkTouchForEnderChest.get(), fortuneForOresCrops.get(), prefer.get(), itemStack2 -> !shouldStopUsing(itemStack2));
165+
double score = getScore(itemStack, blockState, silkTouchForEnderChest.get(), fortuneForOresCrops.get(), prefer.get(), ToolSaver::canUse);
168166
if (score < 0) continue;
169167

170168
if (score > bestScore) {
@@ -173,28 +171,28 @@ private void onStartBreakingBlock(StartBreakingBlockEvent event) {
173171
}
174172
}
175173

176-
if ((bestSlot != -1 && (bestScore > getScore(currentStack, blockState, silkTouchForEnderChest.get(), fortuneForOresCrops.get(), prefer.get(), itemStack -> !shouldStopUsing(itemStack))) || shouldStopUsing(currentStack) || !isTool(currentStack))) {
174+
if (bestSlot == -1 && ToolSaver.isTool(mc.player.getMainHandStack()) && switchAway.get()) {
175+
for (int i = 0; i < 9; i++) {
176+
if (!ToolSaver.isTool(mc.player.getInventory().getStack(i))) {
177+
bestSlot = i;
178+
bestScore = 0;
179+
break;
180+
}
181+
}
182+
}
183+
184+
if ((bestSlot != -1 && (bestScore > getScore(currentStack, blockState, silkTouchForEnderChest.get(), fortuneForOresCrops.get(), prefer.get(), itemStack -> ToolSaver.canUse(itemStack) || ToolSaver.canUse(currentStack) || !isTool(currentStack))))) {
177185
ticks = switchDelay.get();
178186

179187
if (ticks == 0) InvUtils.swap(bestSlot, true);
180188
else shouldSwitch = true;
181189
}
182190

183-
// Anti break
184-
currentStack = mc.player.getMainHandStack();
185-
186-
if (shouldStopUsing(currentStack) && isTool(currentStack)) {
187-
mc.options.attackKey.setPressed(false);
188-
event.cancel();
189-
}
190-
}
191-
192-
private boolean shouldStopUsing(ItemStack itemStack) {
193-
return antiBreak.get() && (itemStack.getMaxDamage() - itemStack.getDamage()) < (itemStack.getMaxDamage() * breakDurability.get() / 100);
194191
}
195192

196193
public static double getScore(ItemStack itemStack, BlockState state, boolean silkTouchEnderChest, boolean fortuneOre, EnchantPreference enchantPreference, Predicate<ItemStack> good) {
197194
if (!good.test(itemStack) || !isTool(itemStack)) return -1;
195+
198196
if (!itemStack.isSuitableFor(state) &&
199197
!(itemStack.isIn(ItemTags.SWORDS) && (state.getBlock() instanceof BambooBlock || state.getBlock() instanceof BambooShootBlock)) &&
200198
!(itemStack.getItem() instanceof ShearsItem && state.getBlock() instanceof LeavesBlock || state.isIn(BlockTags.WOOL)))
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client).
3+
* Copyright (c) Meteor Development.
4+
*/
5+
6+
package meteordevelopment.meteorclient.systems.modules.player;
7+
8+
import meteordevelopment.meteorclient.events.entity.player.AttackEntityEvent;
9+
import meteordevelopment.meteorclient.events.entity.player.StartBreakingBlockEvent;
10+
import meteordevelopment.meteorclient.settings.*;
11+
import meteordevelopment.meteorclient.systems.modules.Categories;
12+
import meteordevelopment.meteorclient.systems.modules.Module;
13+
import meteordevelopment.meteorclient.systems.modules.Modules;
14+
import meteordevelopment.meteorclient.utils.Utils;
15+
import meteordevelopment.meteorclient.utils.world.BlockUtils;
16+
import meteordevelopment.orbit.EventHandler;
17+
import meteordevelopment.orbit.EventPriority;
18+
import net.minecraft.enchantment.Enchantments;
19+
import net.minecraft.item.*;
20+
import net.minecraft.registry.tag.ItemTags;
21+
22+
import java.util.List;
23+
24+
public class ToolSaver extends Module {
25+
private final SettingGroup sgGeneral = settings.getDefaultGroup();
26+
27+
private final Setting<Integer> durability = sgGeneral.add(new IntSetting.Builder()
28+
.name("percentage")
29+
.description("The durability percentage to stop using a tool at")
30+
.defaultValue(10)
31+
.range(1, 100)
32+
.sliderRange(1, 100)
33+
.build()
34+
);
35+
36+
private final Setting<Boolean> onlyMending = sgGeneral.add(new BoolSetting.Builder()
37+
.name("only-mending")
38+
.description("Only avoid breaking tools which have mending")
39+
.build()
40+
);
41+
42+
private final Setting<Boolean> onlyUnique = sgGeneral.add(new BoolSetting.Builder()
43+
.name("only-last-tool")
44+
.description("Only avoid breaking the last tool of a type unless the other tools are all worse")
45+
.build()
46+
);
47+
48+
private final Setting<Boolean> allowAttack = sgGeneral.add(new BoolSetting.Builder()
49+
.name("allow-manual-attack")
50+
.description("Never prevent manual attacks")
51+
.build()
52+
);
53+
54+
private final Setting<ListMode> listMode = sgGeneral.add(new EnumSetting.Builder<ListMode>()
55+
.name("list-mode")
56+
.description("Selection mode")
57+
.defaultValue(ListMode.Blacklist)
58+
.build()
59+
);
60+
61+
private final Setting<List<Item>> whitelist = sgGeneral.add(new ItemListSetting.Builder()
62+
.name("whitelist")
63+
.description("Do not allow breaking these tools")
64+
.visible(() -> listMode.get() == ListMode.Whitelist)
65+
.filter(ToolSaver::isTool)
66+
.build()
67+
);
68+
69+
private final Setting<List<Item>> blacklist = sgGeneral.add(new ItemListSetting.Builder()
70+
.name("blacklist")
71+
.description("Allow breaking these tools")
72+
.visible(() -> listMode.get() == ListMode.Blacklist)
73+
.filter(ToolSaver::isTool)
74+
.build()
75+
);
76+
77+
public ToolSaver() {
78+
super(Categories.Player, "tool-saver", "Prevents breaking tools");
79+
}
80+
81+
@EventHandler(priority = EventPriority.HIGH - 1)
82+
private void onStartBreakingBlock(StartBreakingBlockEvent event) {
83+
if (!_canUse(mc.player.getMainHandStack()) && mc.world.getBlockState(event.blockPos).getHardness(mc.world, event.blockPos) > 0) {
84+
mc.options.attackKey.setPressed(false);
85+
event.cancel();
86+
}
87+
}
88+
89+
90+
@EventHandler(priority = EventPriority.HIGH)
91+
private void onAttackEntity(AttackEntityEvent event) {
92+
if (!allowAttack.get() && !_canUse(mc.player.getMainHandStack())) event.cancel();
93+
}
94+
95+
private static ToolType toolType(ItemStack is) {
96+
if (is.isIn(ItemTags.AXES)) return ToolType.AXE;
97+
if (is.isIn(ItemTags.HOES)) return ToolType.HOE;
98+
if (is.isIn(ItemTags.PICKAXES)) return ToolType.PICKAXE;
99+
if (is.isIn(ItemTags.SHOVELS)) return ToolType.SHOVEL;
100+
if (is.isIn(ItemTags.SWORDS)) return ToolType.SWORD;
101+
if (is.getItem() instanceof ShearsItem) return ToolType.SHEAR;
102+
if (is.getItem() instanceof MaceItem) return ToolType.MACE;
103+
return ToolType.NONE;
104+
}
105+
106+
public static boolean isTool(Item item) {
107+
return isTool(item.getDefaultStack());
108+
}
109+
110+
public static boolean isTool(ItemStack is) {
111+
return toolType(is) != ToolType.NONE;
112+
}
113+
114+
private boolean isWorse(ItemStack a, ItemStack b) {
115+
// lower material tier (no-one cares about gold)
116+
if (a.getMaxDamage() < b.getMaxDamage()) return true;
117+
118+
// non-mending tools can always be broken if only-mending is set
119+
if (onlyMending.get() && Utils.getEnchantmentLevel(a, Enchantments.MENDING) < Utils.getEnchantmentLevel(b, Enchantments.MENDING))
120+
return true;
121+
122+
// don't break the more enchanted tool
123+
if (Utils.getEnchantmentLevel(a, Enchantments.FORTUNE) > 0 && Utils.getEnchantmentLevel(a, Enchantments.FORTUNE) < Utils.getEnchantmentLevel(b, Enchantments.FORTUNE))
124+
return true;
125+
return Utils.getEnchantmentLevel(a, Enchantments.EFFICIENCY) < Utils.getEnchantmentLevel(b, Enchantments.EFFICIENCY);
126+
}
127+
128+
private boolean canBreak(ItemStack is) {
129+
if (!isTool(is)) return true;
130+
if (onlyMending.get() && Utils.getEnchantmentLevel(is, Enchantments.MENDING) == 0) return true;
131+
if (!onlyUnique.get()) return false;
132+
133+
ToolType tt = toolType(is);
134+
135+
boolean silkTouch = Utils.getEnchantmentLevel(is, Enchantments.SILK_TOUCH) > 0;
136+
137+
int counter = 0;
138+
139+
for (int i = 0; i < 40; i++) {
140+
ItemStack isi = mc.player.getInventory().getStack(i);
141+
142+
if (tt != toolType(isi)) continue;
143+
if (silkTouch != Utils.getEnchantmentLevel(isi, Enchantments.SILK_TOUCH) > 0) continue;
144+
145+
if (!isWorse(isi, is)) counter++;
146+
if (counter > 1) return true;
147+
}
148+
149+
return false;
150+
}
151+
152+
private boolean isBroken(ItemStack tool) {
153+
return tool.getMaxDamage() - tool.getDamage() < tool.getMaxDamage() * durability.get() / 100;
154+
}
155+
156+
private boolean isIgnored(ItemStack tool) {
157+
if (listMode.get() == ListMode.Whitelist) return !whitelist.get().contains(tool.getItem());
158+
return blacklist.get().contains(tool.getItem());
159+
}
160+
161+
private boolean _canUse(ItemStack tool) {
162+
ToolSaver ts = Modules.get().get(ToolSaver.class);
163+
return !ts.isActive() || ts.isIgnored(tool) || !ts.isBroken(tool) || ts.canBreak(tool);
164+
}
165+
166+
public static boolean canUse(ItemStack tool) {
167+
return Modules.get().get(ToolSaver.class)._canUse(tool);
168+
}
169+
170+
public enum ListMode {
171+
Whitelist,
172+
Blacklist
173+
}
174+
175+
public enum ToolType {
176+
NONE,
177+
AXE,
178+
HOE,
179+
PICKAXE,
180+
SHOVEL,
181+
SWORD,
182+
MACE,
183+
SHEAR,
184+
}
185+
}

0 commit comments

Comments
 (0)