Skip to content

Commit 2bf05ea

Browse files
authored
Improve .macro functionality (#5671)
- prevent recursive macros crashing the game - add ability to call macros with a delay
1 parent b1481a1 commit 2bf05ea

2 files changed

Lines changed: 126 additions & 6 deletions

File tree

src/main/java/meteordevelopment/meteorclient/commands/arguments/MacroArgumentType.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,14 @@ public Macro parse(StringReader reader) throws CommandSyntaxException {
4646

4747
@Override
4848
public CompletableFuture<Suggestions> listSuggestions(CommandContext context, SuggestionsBuilder builder) {
49-
return CommandSource.suggestMatching(Macros.get().getAll().stream().map(macro -> macro.name.get()), builder);
49+
return CommandSource.suggestMatching(Macros.get().getAll().stream().map(macro -> {
50+
String name = macro.name.get();
51+
if (name.contains(" ")) {
52+
name = "\"" + name.replace("\"", "\\\"") + "\"";
53+
}
54+
55+
return name;
56+
}), builder);
5057
}
5158

5259
@Override

src/main/java/meteordevelopment/meteorclient/commands/commands/MacroCommand.java

Lines changed: 118 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,136 @@
55

66
package meteordevelopment.meteorclient.commands.commands;
77

8+
import com.mojang.brigadier.arguments.IntegerArgumentType;
89
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
10+
import meteordevelopment.meteorclient.MeteorClient;
911
import meteordevelopment.meteorclient.commands.Command;
1012
import meteordevelopment.meteorclient.commands.arguments.MacroArgumentType;
13+
import meteordevelopment.meteorclient.events.world.TickEvent;
1114
import meteordevelopment.meteorclient.systems.macros.Macro;
15+
import meteordevelopment.orbit.EventHandler;
1216
import net.minecraft.command.CommandSource;
17+
import net.minecraft.command.argument.TimeArgumentType;
18+
19+
import java.util.ArrayList;
20+
import java.util.List;
1321

1422
public class MacroCommand extends Command {
1523
public MacroCommand() {
1624
super("macro", "Allows you to execute macros.");
25+
26+
MeteorClient.EVENT_BUS.subscribe(this);
1727
}
1828

29+
List<ScheduledMacro> scheduleQueue = new ArrayList<>();
30+
List<ScheduledMacro> scheduledMacros = new ArrayList<>();
31+
1932
@Override
2033
public void build(LiteralArgumentBuilder<CommandSource> builder) {
21-
builder.then(argument("macro", MacroArgumentType.create()).executes(context -> {
22-
Macro macro = MacroArgumentType.get(context);
23-
macro.onAction();
24-
return SINGLE_SUCCESS;
25-
}));
34+
builder
35+
.then(literal("clear")
36+
.executes(context -> {
37+
if (scheduleQueue.isEmpty() && scheduledMacros.isEmpty()) {
38+
error("No macros are currently scheduled.");
39+
return SINGLE_SUCCESS;
40+
}
41+
42+
clearAll();
43+
info("Cleared all scheduled macros.");
44+
45+
return SINGLE_SUCCESS;
46+
})
47+
.then(argument("macro", MacroArgumentType.create())
48+
.executes(context -> {
49+
Macro macro = MacroArgumentType.get(context);
50+
51+
if (!isScheduled(macro)) {
52+
error("This macro is not currently scheduled.");
53+
return SINGLE_SUCCESS;
54+
}
55+
56+
clear(macro);
57+
info("Cleared scheduled macro.");
58+
return SINGLE_SUCCESS;
59+
})
60+
)
61+
)
62+
.then(argument("macro", MacroArgumentType.create())
63+
.executes(context -> {
64+
Macro macro = MacroArgumentType.get(context);
65+
scheduleQueue.add(new ScheduledMacro(0, macro));
66+
67+
return SINGLE_SUCCESS;
68+
})
69+
.then(argument("delay", TimeArgumentType.time())
70+
.executes(context -> {
71+
Macro macro = MacroArgumentType.get(context);
72+
scheduleQueue.add(new ScheduledMacro(IntegerArgumentType.getInteger(context, "delay"), macro));
73+
74+
return SINGLE_SUCCESS;
75+
})
76+
)
77+
)
78+
;
79+
}
80+
81+
public void clearAll() {
82+
scheduleQueue.clear();
83+
scheduledMacros.clear();
84+
}
85+
86+
public boolean isScheduled(Macro macro) {
87+
return scheduleQueue.stream().anyMatch(element -> element.macro == macro) ||
88+
scheduledMacros.stream().anyMatch(element -> element.macro == macro);
89+
}
90+
91+
public void clear(Macro macro) {
92+
scheduleQueue.removeIf(scheduledMacro -> scheduledMacro.macro == macro);
93+
scheduledMacros.removeIf(scheduledMacro -> scheduledMacro.macro == macro);
94+
}
95+
96+
@EventHandler
97+
private void onTick(TickEvent.Post event) {
98+
if (!scheduleQueue.isEmpty()) {
99+
scheduledMacros.addAll(scheduleQueue);
100+
scheduleQueue.clear();
101+
}
102+
103+
if (!scheduledMacros.isEmpty()) {
104+
runMacros();
105+
}
106+
107+
scheduledMacros.forEach(ScheduledMacro::tick);
108+
}
109+
110+
private void runMacros() {
111+
scheduledMacros.removeIf(ScheduledMacro::run);
112+
}
113+
}
114+
115+
class ScheduledMacro {
116+
public int delay;
117+
public Macro macro;
118+
119+
public ScheduledMacro(int tickDelay, Macro scheduledMacro) {
120+
delay = tickDelay;
121+
macro = scheduledMacro;
122+
}
123+
124+
public void tick() {
125+
delay--;
126+
}
127+
128+
public boolean run() {
129+
if (delay > 0) return false;
130+
131+
runMacro();
132+
return true;
133+
}
134+
135+
private void runMacro() {
136+
if (MeteorClient.mc.player == null) return;
137+
138+
macro.onAction();
26139
}
27140
}

0 commit comments

Comments
 (0)