368 lines
22 KiB
Diff
368 lines
22 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: SakuraiMochi0721 <sakuraimochi0721@163.com>
|
|
Date: Sun, 12 Jul 2026 10:15:29 +0800
|
|
Subject: [PATCH] Improved server health command
|
|
|
|
This is generated by calude
|
|
As it's only change the display, no tests and review are required
|
|
|
|
diff --git a/io/papermc/paper/threadedregions/commands/CommandServerHealth.java b/io/papermc/paper/threadedregions/commands/CommandServerHealth.java
|
|
index aa860cfe9de616f185163fe74e0f4f49bd13a805..a1ec1475280c377240eac0cd12d32688c73391bf 100644
|
|
--- a/io/papermc/paper/threadedregions/commands/CommandServerHealth.java
|
|
+++ b/io/papermc/paper/threadedregions/commands/CommandServerHealth.java
|
|
@@ -42,46 +42,88 @@ public final class CommandServerHealth extends Command {
|
|
return new DecimalFormat("#,##0");
|
|
});
|
|
|
|
- private static final TextColor HEADER = TextColor.color(79, 164, 240);
|
|
- private static final TextColor PRIMARY = TextColor.color(48, 145, 237);
|
|
- private static final TextColor SECONDARY = TextColor.color(104, 177, 240);
|
|
- private static final TextColor INFORMATION = TextColor.color(145, 198, 243);
|
|
- private static final TextColor LIST = TextColor.color(33, 97, 188);
|
|
+ private static final TextColor HEADER = TextColor.color(0xcb, 0xa6, 0xf7); // Shiroha - Catppuccin Mocha: Mauve
|
|
+ private static final TextColor PRIMARY = TextColor.color(0xa6, 0xad, 0xc8); // Shiroha - Catppuccin Mocha: Subtext0
|
|
+ private static final TextColor SECONDARY = TextColor.color(0xb4, 0xbe, 0xfe); // Shiroha - Catppuccin Mocha: Lavender
|
|
+ private static final TextColor INFORMATION = TextColor.color(0xcd, 0xd6, 0xf4); // Shiroha - Catppuccin Mocha: Text
|
|
+ private static final TextColor LIST = TextColor.color(0x74, 0xc7, 0xec); // Shiroha - Catppuccin Mocha: Sapphire
|
|
+ // Shiroha start - prettier /tps output
|
|
+ private static final TextColor MUTED = TextColor.color(0x6c, 0x70, 0x86); // Catppuccin Mocha: Overlay0
|
|
+ private static final int DIVIDER_WIDTH = 44;
|
|
+ private static final int BAR_SEGMENTS = 20;
|
|
+ private static final String[] RANK_ICONS = {"①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨", "⑩"};
|
|
+ // Shiroha end
|
|
|
|
public CommandServerHealth() {
|
|
super("tps");
|
|
- this.setUsage("/<command> [server/region] [lowest regions to display]");
|
|
+ this.setUsage("/<command> [server/region] [lowest regions to display|all]"); // Shiroha - document "all" option
|
|
this.setDescription("Reports information about server health.");
|
|
this.setPermission("bukkit.command.tps");
|
|
}
|
|
|
|
+ // Shiroha start - prettier /tps output helpers
|
|
+ private static Component divider() {
|
|
+ // strikethrough spaces render as a solid flat line on every client/font, unlike box-drawing glyphs
|
|
+ return Component.text(" ".repeat(DIVIDER_WIDTH), MUTED, TextDecoration.STRIKETHROUGH);
|
|
+ }
|
|
+
|
|
+ private static Component sectionHeader(final String title) {
|
|
+ return Component.text()
|
|
+ .append(Component.text("» ", HEADER, TextDecoration.BOLD))
|
|
+ .append(Component.text(title + "\n", HEADER, TextDecoration.BOLD))
|
|
+ .build();
|
|
+ }
|
|
+
|
|
+ private static String rankLabel(final int index) {
|
|
+ return index < RANK_ICONS.length ? RANK_ICONS[index] : ("#" + (index + 1));
|
|
+ }
|
|
+
|
|
+ private static Component progressBar(final double fraction) {
|
|
+ // same strikethrough-space trick as divider() so the bar is a smooth flat two-tone line, not a
|
|
+ // row of block glyphs that may render as tiny/misaligned dots depending on the client's font
|
|
+ final double clamped = Math.max(0.0, Math.min(1.0, fraction));
|
|
+ final int filled = (int) Math.round(clamped * BAR_SEGMENTS);
|
|
+ final TextColor barColour = CommandUtil.getUtilisationColourRegion(clamped);
|
|
+ return Component.text()
|
|
+ .append(Component.text(" ".repeat(filled), barColour, TextDecoration.STRIKETHROUGH))
|
|
+ .append(Component.text(" ".repeat(BAR_SEGMENTS - filled), MUTED, TextDecoration.STRIKETHROUGH))
|
|
+ .build();
|
|
+ }
|
|
+ // Shiroha end
|
|
+
|
|
private static Component formatRegionInfo(final String prefix, final double util, final double mspt, final double tps,
|
|
final boolean newline) {
|
|
+ // Shiroha start - use progress bar + dot separators instead of plain "util at ... MSPT at ..." text
|
|
return Component.text()
|
|
- .append(Component.text(prefix, PRIMARY, TextDecoration.BOLD))
|
|
- .append(Component.text(ONE_DECIMAL_PLACES.get().format(util * 100.0), CommandUtil.getUtilisationColourRegion(util)))
|
|
- .append(Component.text("% util at ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(mspt), CommandUtil.getColourForMSPT(mspt)))
|
|
- .append(Component.text(" MSPT at ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(tps), CommandUtil.getColourForTPS(tps)))
|
|
- .append(Component.text(" TPS" + (newline ? "\n" : ""), PRIMARY))
|
|
- .build();
|
|
+ .append(Component.text(prefix, PRIMARY, TextDecoration.BOLD))
|
|
+ .append(progressBar(util))
|
|
+ .append(Component.text(" "))
|
|
+ .append(Component.text(ONE_DECIMAL_PLACES.get().format(util * 100.0) + "%", CommandUtil.getUtilisationColourRegion(util)))
|
|
+ .append(Component.text(" · ", MUTED))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(mspt) + " ms", CommandUtil.getColourForMSPT(mspt)))
|
|
+ .append(Component.text(" · ", MUTED))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(tps) + " tps", CommandUtil.getColourForTPS(tps)))
|
|
+ .append(Component.text(newline ? "\n" : "", PRIMARY))
|
|
+ .build();
|
|
+ // Shiroha end
|
|
}
|
|
|
|
private static Component formatRegionStats(final TickRegions.RegionStats stats, final boolean newline) {
|
|
+ // Shiroha start - add "·" separators for readability
|
|
return Component.text()
|
|
- .append(Component.text("Chunks: ", PRIMARY))
|
|
- .append(Component.text(NO_DECIMAL_PLACES.get().format((long)stats.getChunkCount()), INFORMATION))
|
|
- .append(Component.text(" Players: ", PRIMARY))
|
|
- .append(Component.text(NO_DECIMAL_PLACES.get().format((long)stats.getPlayerCount()), INFORMATION))
|
|
- .append(Component.text(" Entities: ", PRIMARY))
|
|
- .append(Component.text(NO_DECIMAL_PLACES.get().format((long)stats.getEntityCount()) + (newline ? "\n" : ""), INFORMATION))
|
|
- .build();
|
|
+ .append(Component.text("Chunks: ", PRIMARY))
|
|
+ .append(Component.text(NO_DECIMAL_PLACES.get().format((long)stats.getChunkCount()), INFORMATION))
|
|
+ .append(Component.text(" · Players: ", PRIMARY))
|
|
+ .append(Component.text(NO_DECIMAL_PLACES.get().format((long)stats.getPlayerCount()), INFORMATION))
|
|
+ .append(Component.text(" · Entities: ", PRIMARY))
|
|
+ .append(Component.text(NO_DECIMAL_PLACES.get().format((long)stats.getEntityCount()) + (newline ? "\n" : ""), INFORMATION))
|
|
+ .build();
|
|
+ // Shiroha end
|
|
}
|
|
|
|
private static boolean executeRegion(final CommandSender sender, final String commandLabel, final String[] args) {
|
|
final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region =
|
|
- TickRegionScheduler.getCurrentRegion();
|
|
+ TickRegionScheduler.getCurrentRegion();
|
|
if (region == null) {
|
|
sender.sendMessage(Component.text("You are not in a region currently", NamedTextColor.RED));
|
|
return true;
|
|
@@ -108,22 +150,24 @@ public final class CommandServerHealth extends Command {
|
|
final int yLoc = 80;
|
|
final String location = "[w:'" + world.getWorld().getName() + "'," + centerBlockX + "," + yLoc + "," + centerBlockZ + "]";
|
|
|
|
+ // Shiroha start - prettier /tps region output
|
|
final Component line = Component.text()
|
|
- .append(Component.text("Region around block ", PRIMARY))
|
|
- .append(Component.text(location, INFORMATION))
|
|
- .append(Component.text(":\n", PRIMARY))
|
|
-
|
|
- .append(
|
|
- formatRegionInfo("15s: ", util15s, mspt15s, tps15s, true)
|
|
- )
|
|
- .append(
|
|
- formatRegionInfo("1m: ", util1m, mspt1m, tps1m, true)
|
|
- )
|
|
- .append(
|
|
- formatRegionStats(region.getData().getRegionStats(), false)
|
|
- )
|
|
-
|
|
- .build();
|
|
+ .append(sectionHeader("Region around " + location))
|
|
+ .append(divider())
|
|
+ .append(Component.text("\n"))
|
|
+
|
|
+ .append(
|
|
+ formatRegionInfo("15s: ", util15s, mspt15s, tps15s, true)
|
|
+ )
|
|
+ .append(
|
|
+ formatRegionInfo("1m: ", util1m, mspt1m, tps1m, true)
|
|
+ )
|
|
+ .append(
|
|
+ formatRegionStats(region.getData().getRegionStats(), false)
|
|
+ )
|
|
+
|
|
+ .build();
|
|
+ // Shiroha end
|
|
|
|
sender.sendMessage(line);
|
|
|
|
@@ -131,9 +175,13 @@ public final class CommandServerHealth extends Command {
|
|
}
|
|
|
|
private static boolean executeServer(final CommandSender sender, final String commandLabel, final String[] args) {
|
|
+ // Shiroha start - "all" lists every tick region instead of just the top N by utilisation
|
|
+ final boolean showAllRegions = args.length >= 2 && args[1].equalsIgnoreCase("all");
|
|
final int lowestRegionsCount;
|
|
- if (args.length < 2) {
|
|
- lowestRegionsCount = 3;
|
|
+ if (showAllRegions) {
|
|
+ lowestRegionsCount = Integer.MAX_VALUE; // unused when showAllRegions is true, kept for definite assignment
|
|
+ } else if (args.length < 2) {
|
|
+ lowestRegionsCount = 5; // default to top 5 regions
|
|
} else {
|
|
try {
|
|
lowestRegionsCount = Integer.parseInt(args[1]);
|
|
@@ -142,9 +190,10 @@ public final class CommandServerHealth extends Command {
|
|
return true;
|
|
}
|
|
}
|
|
+ // Shiroha end
|
|
|
|
final List<ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>> regions =
|
|
- new ArrayList<>();
|
|
+ new ArrayList<>();
|
|
|
|
for (final World bukkitWorld : Bukkit.getWorlds()) {
|
|
final ServerLevel world = ((CraftWorld)bukkitWorld).getHandle();
|
|
@@ -174,6 +223,7 @@ public final class CommandServerHealth extends Command {
|
|
final double loadRate = ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkFullTask.loadRate(currTime);
|
|
|
|
totalUtil += globalTickReport.utilisation();
|
|
+ final double overallFraction = maxThreadCount > 0 ? (totalUtil / maxThreadCount) : 0.0; // Shiroha - overall load fraction for progress bar
|
|
|
|
tpsByRegion.sort(null);
|
|
if (!tpsByRegion.isEmpty()) {
|
|
@@ -194,7 +244,7 @@ public final class CommandServerHealth extends Command {
|
|
}
|
|
|
|
final List<ObjectObjectImmutablePair<ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>, TickData.TickReportData>>
|
|
- regionsBelowThreshold = new ArrayList<>();
|
|
+ regionsBelowThreshold = new ArrayList<>();
|
|
|
|
for (int i = 0, len = regions.size(); i < len; ++i) {
|
|
final TickData.TickReportData report = reportsByRegion.get(i);
|
|
@@ -215,15 +265,15 @@ public final class CommandServerHealth extends Command {
|
|
final TextComponent.Builder lowestRegionsBuilder = Component.text();
|
|
|
|
if (sender instanceof Player) {
|
|
- lowestRegionsBuilder.append(Component.text(" Click to teleport\n", SECONDARY));
|
|
+ lowestRegionsBuilder.append(Component.text(" Click to teleport\n", SECONDARY, TextDecoration.ITALIC)); // Shiroha - restyle hint text
|
|
}
|
|
- for (int i = 0, len = Math.min(lowestRegionsCount, regionsBelowThreshold.size()); i < len; ++i) {
|
|
+ for (int i = 0, len = showAllRegions ? regionsBelowThreshold.size() : Math.min(lowestRegionsCount, regionsBelowThreshold.size()); i < len; ++i) { // Shiroha - support "all"
|
|
final ObjectObjectImmutablePair<ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>, TickData.TickReportData>
|
|
- pair = regionsBelowThreshold.get(i);
|
|
+ pair = regionsBelowThreshold.get(i);
|
|
|
|
final TickData.TickReportData report = pair.right();
|
|
final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData> region =
|
|
- pair.left();
|
|
+ pair.left();
|
|
|
|
if (report == null) {
|
|
// skip regions with no data
|
|
@@ -244,74 +294,76 @@ public final class CommandServerHealth extends Command {
|
|
|
|
final int yLoc = 80;
|
|
final String location = "[w:'" + world.getWorld().getName() + "'," + centerBlockX + "," + yLoc + "," + centerBlockZ + "]";
|
|
+ // Shiroha start - prettier /tps region list entries
|
|
final Component line = Component.text()
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Region around block ", PRIMARY))
|
|
- .append(Component.text(location, INFORMATION))
|
|
- .append(Component.text(":\n", PRIMARY))
|
|
-
|
|
- .append(Component.text(" ", PRIMARY))
|
|
- .append(Component.text(ONE_DECIMAL_PLACES.get().format(util * 100.0), CommandUtil.getUtilisationColourRegion(util)))
|
|
- .append(Component.text("% util at ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(mspt), CommandUtil.getColourForMSPT(mspt)))
|
|
- .append(Component.text(" MSPT at ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(tps), CommandUtil.getColourForTPS(tps)))
|
|
- .append(Component.text(" TPS\n", PRIMARY))
|
|
-
|
|
- .append(Component.text(" ", PRIMARY))
|
|
- .append(formatRegionStats(region.getData().getRegionStats(), (i + 1) != len))
|
|
- .build()
|
|
-
|
|
- .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, Payload.string("/minecraft:execute as @s in " + world.getWorld().getKey().toString() + " run tp " + centerBlockX + ".5 " + yLoc + " " + centerBlockZ + ".5")))
|
|
- .hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("Click to teleport to " + location, SECONDARY)));
|
|
+ .append(Component.text(" " + rankLabel(i) + " ", LIST, TextDecoration.BOLD)) // Shiroha - Catppuccin Mocha: Sapphire rank marker
|
|
+ .append(Component.text(location + "\n", INFORMATION))
|
|
+
|
|
+ .append(Component.text(" "))
|
|
+ .append(progressBar(util))
|
|
+ .append(Component.text(" "))
|
|
+ .append(Component.text(ONE_DECIMAL_PLACES.get().format(util * 100.0) + "%", CommandUtil.getUtilisationColourRegion(util)))
|
|
+ .append(Component.text(" · ", MUTED))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(mspt) + " ms", CommandUtil.getColourForMSPT(mspt)))
|
|
+ .append(Component.text(" · ", MUTED))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(tps) + " tps\n", CommandUtil.getColourForTPS(tps)))
|
|
+
|
|
+ .append(Component.text(" "))
|
|
+ .append(formatRegionStats(region.getData().getRegionStats(), (i + 1) != len))
|
|
+ .build()
|
|
+
|
|
+ .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, Payload.string("/minecraft:execute as @s in " + world.getWorld().getKey().toString() + " run tp " + centerBlockX + ".5 " + yLoc + " " + centerBlockZ + ".5")))
|
|
+ .hoverEvent(HoverEvent.hoverEvent(HoverEvent.Action.SHOW_TEXT, Component.text("Click to teleport to " + location, SECONDARY)));
|
|
+ // Shiroha end
|
|
|
|
lowestRegionsBuilder.append(line);
|
|
}
|
|
|
|
sender.sendMessage(
|
|
- Component.text()
|
|
- .append(Component.text("Server Health Report\n", HEADER, TextDecoration.BOLD))
|
|
-
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Online Players: ", PRIMARY))
|
|
- .append(Component.text(Bukkit.getOnlinePlayers().size() + "\n", INFORMATION))
|
|
-
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Total regions: ", PRIMARY))
|
|
- .append(Component.text(regions.size() + "\n", INFORMATION))
|
|
-
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Utilisation: ", PRIMARY))
|
|
- .append(Component.text(ONE_DECIMAL_PLACES.get().format(totalUtil * 100.0), CommandUtil.getUtilisationColourRegion(totalUtil / (double)maxThreadCount)))
|
|
- .append(Component.text("% / ", PRIMARY))
|
|
- .append(Component.text(ONE_DECIMAL_PLACES.get().format(maxThreadCount * 100.0), INFORMATION))
|
|
- .append(Component.text("%\n", PRIMARY))
|
|
-
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Load rate: ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(loadRate) + ", ", INFORMATION))
|
|
- .append(Component.text("Gen rate: ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(genRate) + "\n", INFORMATION))
|
|
-
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Lowest Region TPS: ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(minTps) + "\n", CommandUtil.getColourForTPS(minTps)))
|
|
-
|
|
-
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Median Region TPS: ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(medianTps) + "\n", CommandUtil.getColourForTPS(medianTps)))
|
|
-
|
|
- .append(Component.text(" - ", LIST, TextDecoration.BOLD))
|
|
- .append(Component.text("Highest Region TPS: ", PRIMARY))
|
|
- .append(Component.text(TWO_DECIMAL_PLACES.get().format(maxTps) + "\n", CommandUtil.getColourForTPS(maxTps)))
|
|
-
|
|
- .append(Component.text("Highest ", HEADER, TextDecoration.BOLD))
|
|
- .append(Component.text(Integer.toString(lowestRegionsCount), INFORMATION, TextDecoration.BOLD))
|
|
- .append(Component.text(" utilisation regions\n", HEADER, TextDecoration.BOLD))
|
|
-
|
|
- .append(lowestRegionsBuilder.build())
|
|
- .build()
|
|
+ // Shiroha start - prettier /tps server output
|
|
+ Component.text()
|
|
+ .append(sectionHeader("Server Health Report"))
|
|
+ .append(divider())
|
|
+ .append(Component.text("\n"))
|
|
+
|
|
+ .append(Component.text(" Summary\n", HEADER, TextDecoration.BOLD))
|
|
+ .append(Component.text(" Players ", PRIMARY))
|
|
+ .append(Component.text(Bukkit.getOnlinePlayers().size() + " ", INFORMATION))
|
|
+ .append(Component.text("Regions ", PRIMARY))
|
|
+ .append(Component.text(regions.size() + "\n", INFORMATION))
|
|
+
|
|
+ .append(Component.text(" Chunk system load\n", HEADER, TextDecoration.BOLD))
|
|
+ .append(Component.text(" Load rate ", PRIMARY))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(loadRate) + " ", INFORMATION))
|
|
+ .append(Component.text("Gen rate ", PRIMARY))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(genRate) + "\n", INFORMATION))
|
|
+
|
|
+ .append(Component.text(" Overall load\n", HEADER, TextDecoration.BOLD))
|
|
+ .append(Component.text(" "))
|
|
+ .append(progressBar(overallFraction))
|
|
+ .append(Component.text(" "))
|
|
+ .append(Component.text(ONE_DECIMAL_PLACES.get().format(overallFraction * 100.0) + "%", CommandUtil.getUtilisationColourRegion(overallFraction)))
|
|
+ .append(Component.text(" (", MUTED))
|
|
+ .append(Component.text(ONE_DECIMAL_PLACES.get().format(totalUtil * 100.0) + "%", INFORMATION))
|
|
+ .append(Component.text(" / ", MUTED))
|
|
+ .append(Component.text(maxThreadCount + " threads", INFORMATION))
|
|
+ .append(Component.text(")\n", MUTED))
|
|
+
|
|
+ .append(Component.text(" TPS\n", HEADER, TextDecoration.BOLD))
|
|
+ .append(Component.text(" min ", PRIMARY))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(minTps) + " ", CommandUtil.getColourForTPS(minTps)))
|
|
+ .append(Component.text("med ", PRIMARY))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(medianTps) + " ", CommandUtil.getColourForTPS(medianTps)))
|
|
+ .append(Component.text("max ", PRIMARY))
|
|
+ .append(Component.text(TWO_DECIMAL_PLACES.get().format(maxTps) + "\n", CommandUtil.getColourForTPS(maxTps)))
|
|
+
|
|
+ .append(divider())
|
|
+ .append(Component.text("\n"))
|
|
+ .append(sectionHeader(showAllRegions ? "All " + regions.size() + " regions by utilisation" : "Top " + lowestRegionsCount + " regions by utilisation")) // Shiroha - "all" heading
|
|
+
|
|
+ .append(lowestRegionsBuilder.build())
|
|
+ .build()
|
|
+ // Shiroha end
|
|
);
|
|
|
|
return true;
|