Skip to content

Commit 76edfda

Browse files
committed
refactor(cli): migrate legacy commands' chat output to Report
Bring the remaining commands (reload, dump, info, migrate, debug) onto the same Report builder used by the new resource-based subcommands, so chat formatting is consistent everywhere: muted-key/colored-value kvs, accent section headers, summary blocks, list items, [Label] action buttons. Their console rendering is left untouched (CliOutput + CliTable + ProgressBarComponent) because each has bespoke needs that do not benefit from the unified path; the builder exposes sendChatOnly for that case. Replace ReloadCommand's broken [View scripts] click target — it ran the removed /cb scripts command — with [Scripts] -> /cb script list. Switch HelpCommand entries to suggestCommand so clicking a command that requires arguments inserts it into chat input rather than running it with missing args. Drop the open-coded getActiveClients duplicated across Reload/Ping/List in favour of SessionHub.authenticated().
1 parent c8a60c3 commit 76edfda

5 files changed

Lines changed: 158 additions & 249 deletions

File tree

velocity/src/main/java/dev/objz/commandbridge/velocity/cli/subcommands/DebugCommand.java

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,45 @@
22

33
import com.velocitypowered.api.command.CommandSource;
44
import dev.objz.commandbridge.logging.Log;
5-
import dev.objz.commandbridge.util.MM;
6-
import dev.objz.commandbridge.velocity.ui.chat.ChatFrame;
7-
8-
import dev.objz.commandbridge.velocity.ui.cli.CliOutput;
95
import dev.objz.commandbridge.velocity.ui.RenderContext;
6+
import dev.objz.commandbridge.velocity.ui.Report;
7+
import dev.objz.commandbridge.velocity.ui.Report.Action;
8+
import dev.objz.commandbridge.velocity.ui.Report.Status;
109
import dev.objz.commandbridge.velocity.ui.Theme;
11-
import net.kyori.adventure.text.Component;
10+
import dev.objz.commandbridge.velocity.ui.cli.CliOutput;
1211

1312
public final class DebugCommand extends AbstractCliCommand {
13+
14+
private static final String SECTION = "Debug";
15+
1416
public void execute(CommandSource sender) {
1517
boolean newState = !Log.isDebug();
1618
Log.setDebug(newState);
17-
18-
RenderContext ctx = new RenderContext(sender);
19-
20-
if (ctx.isPlayer()) {
21-
renderChat(ctx, newState);
19+
20+
if (new RenderContext(sender).isPlayer()) {
21+
renderChat(sender, newState);
2222
} else {
2323
renderConsole(newState);
2424
}
2525
}
26-
27-
private void renderChat(RenderContext ctx, boolean enabled) {
28-
String status = enabled ? "ENABLED" : "DISABLED";
29-
String color = enabled ? Theme.C_SUCCESS : Theme.C_WARN;
30-
Component statusComp = MM.parse("<" + Theme.C_MUTED + ">Debug Mode</" + Theme.C_MUTED + "> <" + color + "><bold>" + status + "</bold></" + color + ">");
31-
Component toggle = MM.parse(" <" + Theme.C_ACCENT + "><bold>[Toggle]</bold></" + Theme.C_ACCENT + ">")
32-
.clickEvent(net.kyori.adventure.text.event.ClickEvent.runCommand("/cb debug"))
33-
.hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText(
34-
MM.parse("<" + Theme.C_MUTED + ">Click to toggle debug</" + Theme.C_MUTED + ">")));
35-
Component line = statusComp.append(toggle);
36-
ChatFrame frame = new ChatFrame("Debug");
37-
frame.line(line);
38-
frame.send(ctx.source());
26+
27+
private void renderChat(CommandSource sender, boolean enabled) {
28+
String label = enabled ? "ENABLED" : "DISABLED";
29+
Status status = enabled ? Status.SUCCESS : Status.WARN;
30+
31+
Report report = Report.of(SECTION)
32+
.kv("Debug Mode", label, status)
33+
.blank()
34+
.actions(Action.of("Toggle", "/cb debug", "toggle debug mode"));
35+
report.sendChatOnly(sender);
3936
}
40-
37+
4138
private void renderConsole(boolean enabled) {
42-
CliOutput output = cli("Debug Mode");
39+
CliOutput output = cli(SECTION);
4340
String status = enabled ? "ENABLED" : "DISABLED";
44-
String statusColor = enabled ? Theme.ANSI_SUCCESS : Theme.ANSI_WARN;
45-
46-
output.appendRaw("Debug is now ");
47-
output.appendRaw(statusColor).appendRaw(Theme.ANSI_BOLD);
48-
output.appendRaw(status);
49-
output.appendRaw(Theme.ANSI_RESET).appendRaw("\n");
50-
41+
String color = enabled ? Theme.ANSI_SUCCESS : Theme.ANSI_WARN;
42+
output.appendRaw("Debug is now ").appendRaw(color).appendRaw(Theme.ANSI_BOLD)
43+
.appendRaw(status).appendRaw(Theme.ANSI_RESET).appendRaw("\n");
5144
log(output);
5245
}
5346
}

velocity/src/main/java/dev/objz/commandbridge/velocity/cli/subcommands/DumpCommand.java

Lines changed: 18 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,11 @@
1111
import dev.objz.commandbridge.velocity.dump.RemoteDumpCollector;
1212
import dev.objz.commandbridge.velocity.dump.SupportDumpBuilder;
1313
import dev.objz.commandbridge.velocity.net.session.SessionHub;
14-
import dev.objz.commandbridge.util.MM;
15-
import dev.objz.commandbridge.velocity.ui.chat.ChatFrame;
16-
1714
import dev.objz.commandbridge.velocity.ui.cli.CliOutput;
1815
import dev.objz.commandbridge.velocity.ui.RenderContext;
19-
import dev.objz.commandbridge.velocity.ui.Theme;
20-
import net.kyori.adventure.text.Component;
2116

2217
import java.nio.file.Path;
2318
import java.time.Duration;
24-
import java.util.ArrayList;
2519
import java.util.List;
2620

2721
public final class DumpCommand extends AbstractCliCommand {
@@ -96,56 +90,37 @@ private void renderChatSuccess(
9690
String kb = String.format("%.1f KB", result.bytes() / 1024.0d);
9791
String snapshots = remoteCollected + " ok, " + remoteFailed + " failed";
9892

99-
List<Component> lines = new ArrayList<>();
100-
lines.add(chatBullet("Clients", String.valueOf(clientCount)));
101-
lines.add(chatBullet("Snapshots", snapshots));
102-
lines.add(chatBullet("Size", kb));
93+
var report = dev.objz.commandbridge.velocity.ui.Report.of("Dump")
94+
.success("Dump created")
95+
.blank()
96+
.kv("Clients", String.valueOf(clientCount),
97+
dev.objz.commandbridge.velocity.ui.Report.Status.ACCENT)
98+
.kv("Snapshots", snapshots)
99+
.kv("Size", kb);
103100

104101
if (result.uploaded()) {
105-
String url = result.upload().url();
106-
Component linkLine = MM.parse(
107-
"<" + Theme.C_ACCENT + ">•</" + Theme.C_ACCENT
108-
+ "> <" + Theme.C_MUTED + ">Viewer:</" + Theme.C_MUTED + "> ")
109-
.append(MM.parse(
110-
"<" + Theme.C_ACCENT + "><underlined>"
111-
+ url + "</underlined></" + Theme.C_ACCENT + ">")
112-
.clickEvent(net.kyori.adventure.text.event.ClickEvent.openUrl(url))
113-
.hoverEvent(net.kyori.adventure.text.event.HoverEvent.showText(
114-
MM.parse("<" + Theme.C_MUTED
115-
+ ">Click to open</" + Theme.C_MUTED + ">"))));
116-
lines.add(linkLine);
117-
102+
report.link("Viewer", result.upload().url(), "Click to open");
118103
if (result.upload().id() != null && !result.upload().id().isBlank()) {
119-
lines.add(chatBullet("Dump ID", result.upload().id()));
104+
report.kv("Dump ID", result.upload().id());
120105
}
121106
if (result.upload().expiresAt() != null
122107
&& !result.upload().expiresAt().isBlank()) {
123-
lines.add(chatBullet("Expires", result.upload().expiresAt()));
108+
report.kv("Expires", result.upload().expiresAt());
124109
}
125110
} else {
126-
lines.add(MM.warn("Upload failed — use local file."));
111+
report.warn("Upload failed — use local file");
127112
if (result.uploadError() != null) {
128-
lines.add(MM.parse("<" + Theme.C_ERROR + ">"
129-
+ safeMessage(result.uploadError()) + "</" + Theme.C_ERROR + ">"));
113+
report.error(safeMessage(result.uploadError()));
130114
}
131115
}
132116

133117
if (result.localPath() != null) {
134-
lines.add(chatBullet("Local copy", result.localPath().toString()));
118+
report.kv("Local copy", result.localPath().toString());
135119
} else if (result.localError() != null) {
136-
lines.add(MM.parse("<" + Theme.C_ERROR + ">Local save failed: "
137-
+ safeMessage(result.localError()) + "</" + Theme.C_ERROR + ">"));
120+
report.error("Local save failed: " + safeMessage(result.localError()));
138121
}
139122

140-
ChatFrame frame = new ChatFrame("Dump");
141-
frame.lines(lines);
142-
frame.send(ctx.source());
143-
}
144-
145-
private static Component chatBullet(String label, String value) {
146-
return MM.parse("<" + Theme.C_ACCENT + ">•</" + Theme.C_ACCENT
147-
+ "> <" + Theme.C_MUTED + ">" + label + ":</" + Theme.C_MUTED
148-
+ "> <white>" + value + "</white>");
123+
report.sendChatOnly(ctx.source());
149124
}
150125

151126
private void renderConsoleSuccess(int clientCount, int remoteCollected, int remoteFailed, DumpExportResult result) {
@@ -179,10 +154,9 @@ private void renderConsoleSuccess(int clientCount, int remoteCollected, int remo
179154
}
180155

181156
private void renderChatError(RenderContext ctx, Exception ex) {
182-
Component line = MM.error("Failed to build dump: " + safeMessage(ex));
183-
ChatFrame frame = new ChatFrame("Dump");
184-
frame.line(line);
185-
frame.send(ctx.source());
157+
dev.objz.commandbridge.velocity.ui.Report.of("Dump")
158+
.error("Failed to build dump: " + safeMessage(ex))
159+
.sendChatOnly(ctx.source());
186160
}
187161

188162
private void renderConsoleError(Exception ex) {

velocity/src/main/java/dev/objz/commandbridge/velocity/cli/subcommands/InfoCommand.java

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@
22

33
import com.velocitypowered.api.command.CommandSource;
44
import dev.objz.commandbridge.util.MM;
5-
import dev.objz.commandbridge.velocity.ui.chat.ChatFrame;
6-
75
import dev.objz.commandbridge.velocity.ui.cli.CliOutput;
86
import dev.objz.commandbridge.velocity.ui.cli.CliTable;
97
import dev.objz.commandbridge.velocity.ui.RenderContext;
108
import dev.objz.commandbridge.velocity.ui.Theme;
119
import dev.objz.commandbridge.velocity.ui.components.ProgressBarComponent;
1210
import net.kyori.adventure.text.Component;
1311

14-
import java.util.ArrayList;
15-
import java.util.List;
16-
1712
import java.lang.management.ManagementFactory;
1813

1914
public final class InfoCommand extends AbstractCliCommand {
@@ -33,27 +28,28 @@ private void renderChat(CommandSource sender, RenderContext ctx) {
3328
long memUsed = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024 / 1024;
3429
long memTotal = Runtime.getRuntime().totalMemory() / 1024 / 1024;
3530

36-
List<Component> lines = new ArrayList<>();
37-
lines.add(MM.parse("<" + Theme.C_ACCENT + ">•</" + Theme.C_ACCENT + "> <" + Theme.C_MUTED + ">OS:</" + Theme.C_MUTED + "> <white>" + System.getProperty("os.name") + " (" + System.getProperty("os.arch") + ")</white>"));
38-
lines.add(MM.parse("<" + Theme.C_ACCENT + ">•</" + Theme.C_ACCENT + "> <" + Theme.C_MUTED + ">Java:</" + Theme.C_MUTED + "> <white>" + System.getProperty("java.version") + "</white>"));
39-
lines.add(MM.parse("<" + Theme.C_ACCENT + ">•</" + Theme.C_ACCENT + "> <" + Theme.C_MUTED + ">Uptime:</" + Theme.C_MUTED + "> <white>" + formatDuration(uptime) + "</white>"));
40-
lines.add(MM.parse("<" + Theme.C_ACCENT + ">•</" + Theme.C_ACCENT + "> <" + Theme.C_MUTED + ">Memory:</" + Theme.C_MUTED + "> <white>" + memUsed + "MB / " + memTotal + "MB</white>"));
41-
lines.add(MM.parse("<" + Theme.C_ACCENT + ">•</" + Theme.C_ACCENT + "> <" + Theme.C_MUTED + ">Cores:</" + Theme.C_MUTED + "> <white>" + Runtime.getRuntime().availableProcessors() + "</white>"));
42-
4331
double ratio = memTotal == 0 ? 0 : (double) memUsed / (double) memTotal;
44-
String barColor = ratio > 0.85 ? Theme.C_ERROR : (ratio > 0.65 ? Theme.C_WARN : Theme.C_SUCCESS);
32+
String barColor = ratio > 0.85 ? Theme.C_ERROR
33+
: (ratio > 0.65 ? Theme.C_WARN : Theme.C_SUCCESS);
4534
ProgressBarComponent bar = new ProgressBarComponent(ratio, 18, barColor);
4635
int percent = (int) (ratio * 100);
47-
var barLine = MM.parse("<" + Theme.C_MUTED + ">Memory Load</" + Theme.C_MUTED + "> ")
36+
37+
Component barLine = MM.parse("<" + Theme.C_MUTED + ">Memory Load:</"
38+
+ Theme.C_MUTED + "> ")
4839
.append(bar.renderChat(ctx))
49-
.append(MM.parse(" <" + Theme.C_MUTED + ">" + memUsed + "MB / " + memTotal + "MB (" + percent + "%)</" + Theme.C_MUTED + ">"));
40+
.append(MM.parse(" <" + Theme.C_MUTED + ">" + memUsed + "MB / "
41+
+ memTotal + "MB (" + percent + "%)</" + Theme.C_MUTED + ">"));
42+
String barConsole = "Memory Load: " + memUsed + "MB / " + memTotal + "MB (" + percent + "%)";
5043

51-
ChatFrame frame = new ChatFrame("System Info")
52-
.hint(MM.parse("<" + Theme.C_MUTED + "><italic>Snapshot from this proxy</italic></" + Theme.C_MUTED + ">"));
53-
frame.lines(lines);
54-
frame.space();
55-
frame.line(barLine);
56-
frame.send(sender);
44+
dev.objz.commandbridge.velocity.ui.Report.of("System Info")
45+
.kv("OS", System.getProperty("os.name") + " (" + System.getProperty("os.arch") + ")")
46+
.kv("Java", System.getProperty("java.version"))
47+
.kv("Uptime", formatDuration(uptime))
48+
.kv("Memory", memUsed + "MB / " + memTotal + "MB")
49+
.kv("Cores", String.valueOf(Runtime.getRuntime().availableProcessors()))
50+
.blank()
51+
.line(barLine, barConsole)
52+
.sendChatOnly(sender);
5753
}
5854

5955
private void renderConsole() {

0 commit comments

Comments
 (0)