|
| 1 | +# Command Output Formatting Style Guide |
| 2 | + |
| 3 | +This document describes the command output formatting conventions used in this project. Follow this guide to maintain consistency across all commands, or to reproduce this style in other Bukkit/Spigot plugin projects. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +All command output uses Unicode box-drawing characters for structure, Minecraft `ChatColor` codes for color, and Unicode block characters for visual progress bars. |
| 8 | + |
| 9 | +``` |
| 10 | +┌─ Title ─ Subtitle |
| 11 | +│ Label: Value |
| 12 | +│ Label: Value [██████░░░░] |
| 13 | +└───────────────────────── |
| 14 | +``` |
| 15 | + |
| 16 | +## Structure |
| 17 | + |
| 18 | +### Layout |
| 19 | + |
| 20 | +Every command output block follows this structure: |
| 21 | + |
| 22 | +1. **Empty line** — send an empty `""` message for visual separation from prior chat |
| 23 | +2. **Header** — top border with title using `┌─` |
| 24 | +3. **Body lines** — content rows prefixed with `│ ` |
| 25 | +4. **Footer** — bottom border using `└─────────────────────────` |
| 26 | + |
| 27 | +### Box-Drawing Characters |
| 28 | + |
| 29 | +| Character | Unicode | Usage | |
| 30 | +|-----------|---------|-------| |
| 31 | +| `┌` | U+250C | Top-left corner (header start) | |
| 32 | +| `│` | U+2502 | Left border (body lines) | |
| 33 | +| `└` | U+2514 | Bottom-left corner (footer start) | |
| 34 | +| `─` | U+2500 | Horizontal line (header/footer fill) | |
| 35 | + |
| 36 | +## Color Scheme |
| 37 | + |
| 38 | +All colors use Bukkit's `org.bukkit.ChatColor` enum. |
| 39 | + |
| 40 | +### Borders and Structure |
| 41 | + |
| 42 | +| Element | Color | ChatColor | |
| 43 | +|---------|-------|-----------| |
| 44 | +| Box-drawing borders (`┌│└─`) | Gold | `ChatColor.GOLD` | |
| 45 | + |
| 46 | +### Header |
| 47 | + |
| 48 | +| Element | Color | ChatColor | |
| 49 | +|---------|-------|-----------| |
| 50 | +| Plugin/player name | Yellow + Bold | `ChatColor.YELLOW` + `ChatColor.BOLD` | |
| 51 | +| Subtitle text | Gold | `ChatColor.GOLD` | |
| 52 | + |
| 53 | +**Important:** After using `ChatColor.BOLD`, always insert `ChatColor.RESET` before continuing with other colors to prevent bold from bleeding into subsequent text. |
| 54 | + |
| 55 | +### Body Content |
| 56 | + |
| 57 | +| Element | Color | ChatColor | |
| 58 | +|---------|-------|-----------| |
| 59 | +| Labels (e.g., "Logins:", "Status:") | Gray | `ChatColor.GRAY` | |
| 60 | +| General data values | White | `ChatColor.WHITE` | |
| 61 | +| Positive numeric values (hours, counts) | Green | `ChatColor.GREEN` | |
| 62 | +| Averages, rankings, commands | Aqua | `ChatColor.AQUA` | |
| 63 | +| Negative states (Offline, Ended) | Red | `ChatColor.RED` | |
| 64 | +| Positive states (Online, Active) | Green | `ChatColor.GREEN` | |
| 65 | +| Visual bars | Dark Gray | `ChatColor.DARK_GRAY` | |
| 66 | + |
| 67 | +### Error Messages |
| 68 | + |
| 69 | +| Element | Color | ChatColor | |
| 70 | +|---------|-------|-----------| |
| 71 | +| Error messages | Red | `ChatColor.RED` | |
| 72 | + |
| 73 | +## Visual Progress Bars |
| 74 | + |
| 75 | +Use Unicode block characters to create visual indicators for metrics: |
| 76 | + |
| 77 | +| Character | Unicode | Usage | |
| 78 | +|-----------|---------|-------| |
| 79 | +| `█` | U+2588 | Filled portion | |
| 80 | +| `░` | U+2591 | Empty portion | |
| 81 | + |
| 82 | +### Bar Format |
| 83 | + |
| 84 | +``` |
| 85 | +[██████░░░░] |
| 86 | +``` |
| 87 | + |
| 88 | +- Default bar length: **10 characters** |
| 89 | +- Enclosed in square brackets `[` and `]` |
| 90 | +- Colored with `ChatColor.DARK_GRAY` |
| 91 | + |
| 92 | +### Scaling |
| 93 | + |
| 94 | +Calculate the filled portion based on the value relative to its maximum: |
| 95 | + |
| 96 | +```java |
| 97 | +private String createBar(double value, double max) { |
| 98 | + int barLength = 10; |
| 99 | + int filled = (int) Math.min(barLength, (value / max) * barLength); |
| 100 | + StringBuilder bar = new StringBuilder("["); |
| 101 | + for (int i = 0; i < barLength; i++) { |
| 102 | + bar.append(i < filled ? "\u2588" : "\u2591"); |
| 103 | + } |
| 104 | + bar.append("]"); |
| 105 | + return bar.toString(); |
| 106 | +} |
| 107 | +``` |
| 108 | + |
| 109 | +For ranking bars (where rank 1 = best), invert the scale: |
| 110 | + |
| 111 | +```java |
| 112 | +private String createRankBar(int rank, int totalPlayers) { |
| 113 | + int barLength = 10; |
| 114 | + int filled = (int) Math.round(((double)(totalPlayers - rank + 1) / totalPlayers) * barLength); |
| 115 | + filled = Math.max(0, Math.min(barLength, filled)); |
| 116 | + StringBuilder bar = new StringBuilder("["); |
| 117 | + for (int i = 0; i < barLength; i++) { |
| 118 | + bar.append(i < filled ? "\u2588" : "\u2591"); |
| 119 | + } |
| 120 | + bar.append("]"); |
| 121 | + return bar.toString(); |
| 122 | +} |
| 123 | +``` |
| 124 | + |
| 125 | +## Code Patterns |
| 126 | + |
| 127 | +### Header Pattern |
| 128 | + |
| 129 | +```java |
| 130 | +sender.sendMessage(""); |
| 131 | +sender.sendMessage(ChatColor.GOLD + "┌─ " + ChatColor.YELLOW + ChatColor.BOLD + "Title" + |
| 132 | + ChatColor.RESET + ChatColor.GOLD + " ─ Subtitle"); |
| 133 | +``` |
| 134 | + |
| 135 | +### Label-Value Line Pattern |
| 136 | + |
| 137 | +```java |
| 138 | +// Simple value |
| 139 | +sender.sendMessage(ChatColor.GOLD + "│ " + ChatColor.GRAY + "Label: " + |
| 140 | + ChatColor.WHITE + value); |
| 141 | + |
| 142 | +// Numeric value (positive) |
| 143 | +sender.sendMessage(ChatColor.GOLD + "│ " + ChatColor.GRAY + "Hours: " + |
| 144 | + ChatColor.GREEN + String.format("%.2f", hours) + "h"); |
| 145 | + |
| 146 | +// Value with visual bar |
| 147 | +sender.sendMessage(ChatColor.GOLD + "│ " + ChatColor.GRAY + "Progress: " + |
| 148 | + ChatColor.GREEN + String.format("%.2f", value) + "h " + |
| 149 | + ChatColor.DARK_GRAY + createBar(value, maxValue)); |
| 150 | +``` |
| 151 | + |
| 152 | +### Numbered List Entry Pattern |
| 153 | + |
| 154 | +```java |
| 155 | +sender.sendMessage(ChatColor.GOLD + "│ " + ChatColor.AQUA + "#" + count + " " + |
| 156 | + ChatColor.WHITE + itemName + " " + |
| 157 | + ChatColor.GREEN + String.format("%.2f", value) + "h " + |
| 158 | + ChatColor.DARK_GRAY + createBar(value, maxValue)); |
| 159 | +``` |
| 160 | + |
| 161 | +### Command List Entry Pattern |
| 162 | + |
| 163 | +```java |
| 164 | +sender.sendMessage(ChatColor.GOLD + "│ " + ChatColor.AQUA + "/command args " + |
| 165 | + ChatColor.GRAY + "- Description text."); |
| 166 | +``` |
| 167 | + |
| 168 | +### Status Indicator Pattern |
| 169 | + |
| 170 | +```java |
| 171 | +// Online/Active status |
| 172 | +String status = isActive ? ChatColor.GREEN + "Active" : ChatColor.RED + "Ended"; |
| 173 | +``` |
| 174 | + |
| 175 | +### Footer Pattern |
| 176 | + |
| 177 | +```java |
| 178 | +sender.sendMessage(ChatColor.GOLD + "└─────────────────────────"); |
| 179 | +``` |
| 180 | + |
| 181 | +The footer uses 25 horizontal line characters (`─`) after the corner character. |
| 182 | + |
| 183 | +## Command Output Examples |
| 184 | + |
| 185 | +### Info/Detail View |
| 186 | + |
| 187 | +``` |
| 188 | +┌─ PlayerName ─ Activity Info |
| 189 | +│ Logins: 42 |
| 190 | +│ Play Time: 156.30h |
| 191 | +│ Ranking: 3/15 [███████░░░] |
| 192 | +│ Status: Online |
| 193 | +│ Session: 1.25h since login |
| 194 | +│ First Login: 2025-01-15T10:30:00 |
| 195 | +└───────────────────────── |
| 196 | +``` |
| 197 | + |
| 198 | +### Statistics View |
| 199 | + |
| 200 | +``` |
| 201 | +┌─ Activity Tracker ─ Statistics |
| 202 | +│ Unique Players: 42 |
| 203 | +│ Total Logins: 156 |
| 204 | +└───────────────────────── |
| 205 | +``` |
| 206 | + |
| 207 | +### Leaderboard View |
| 208 | + |
| 209 | +``` |
| 210 | +┌─ Activity Tracker ─ Top Players |
| 211 | +│ #1 PlayerA 156.30h [██████████] |
| 212 | +│ #2 PlayerB 98.50h [██████░░░░] |
| 213 | +│ #3 PlayerC 45.20h [██░░░░░░░░] |
| 214 | +└───────────────────────── |
| 215 | +``` |
| 216 | + |
| 217 | +### Help/Command List View |
| 218 | + |
| 219 | +``` |
| 220 | +┌─ Activity Tracker ─ Commands |
| 221 | +│ /at help - View a list of helpful commands. |
| 222 | +│ /at info - View your activity record. |
| 223 | +│ /at top - View the most active players. |
| 224 | +└───────────────────────── |
| 225 | +``` |
| 226 | + |
| 227 | +### Config View |
| 228 | + |
| 229 | +``` |
| 230 | +┌─ Activity Tracker ─ Config |
| 231 | +│ version: 1.3.0 |
| 232 | +│ debugMode: false |
| 233 | +│ restApiEnabled: false |
| 234 | +│ restApiPort: 8080 |
| 235 | +└───────────────────────── |
| 236 | +``` |
| 237 | + |
| 238 | +### Session List View |
| 239 | + |
| 240 | +``` |
| 241 | +┌─ Activity Tracker ─ Recent Sessions (5) |
| 242 | +│ #1 PlayerA - 2025-03-07 10:30:00 (Active) |
| 243 | +│ #2 PlayerB - 2025-03-07 09:15:00 (Ended - 45.0 min) |
| 244 | +└───────────────────────── |
| 245 | +``` |
| 246 | + |
| 247 | +## Label Alignment |
| 248 | + |
| 249 | +When multiple labels appear in a block, right-pad shorter labels with spaces to align values: |
| 250 | + |
| 251 | +``` |
| 252 | +│ Logins: 42 |
| 253 | +│ Play Time: 156.30h |
| 254 | +│ Ranking: 3/15 |
| 255 | +│ Status: Online |
| 256 | +``` |
| 257 | + |
| 258 | +For config options, use consistent padding: |
| 259 | + |
| 260 | +``` |
| 261 | +│ version: 1.3.0 |
| 262 | +│ debugMode: false |
| 263 | +│ restApiEnabled: false |
| 264 | +│ restApiPort: 8080 |
| 265 | +``` |
| 266 | + |
| 267 | +## Adapting for Other Projects |
| 268 | + |
| 269 | +To use this style in another Bukkit/Spigot project: |
| 270 | + |
| 271 | +1. Copy the color scheme table above as your reference |
| 272 | +2. Use the code patterns section as templates for building output |
| 273 | +3. Include the `createBar()` helper method in any command that displays metrics |
| 274 | +4. Keep the footer length consistent at 25 `─` characters |
| 275 | +5. Always prefix output with an empty line for visual separation from chat |
| 276 | +6. Always use `ChatColor.RESET` after `ChatColor.BOLD` to prevent bleed |
0 commit comments