-
Notifications
You must be signed in to change notification settings - Fork 13
interface styling configuration #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Caution Review failedThe pull request is closed. WalkthroughAdds a StyleManager singleton and config keys, initializes it during plugin startup, and refactors GUI, commands, and listeners to use StyleManager for title colors and glass-pane material; adds ItemUtil.createGlassPane(). No public API signatures changed; control flow is largely unchanged. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Srv as Server
participant P as PerPlayerKit
participant Cfg as ConfigManager
participant SM as StyleManager
participant UI as GUI/Commands/Listeners
Srv->>P: onEnable()
P->>Cfg: loadConfig()
P->>SM: new StyleManager(plugin)
activate SM
SM->>SM: loadConfig() (read interface.glass-material, interface.main-color)
deactivate SM
P->>UI: register/init remaining components
note right of UI: Components now call StyleManager.get() for colors/materials
sequenceDiagram
autonumber
participant Player
participant Cmd as Command Executor
participant SM as StyleManager
participant UI as GUI
participant It as ItemUtil
Player->>Cmd: execute command (e.g., /ec, /rg)
Cmd->>SM: getPrimaryColor()
Cmd->>UI: open inventory(title with primary color)
UI->>It: createGlassPane()
It->>SM: getGlassMaterial()
It-->>UI: ItemStack pane
UI-->>Player: show inventory with styled title and panes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (6)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/main/java/dev/noah/perplayerkit/PerPlayerKit.java (1)
21-45: StaticStyleManager.get()Calls Occurring at Class Initialization Must Be DeferredThe only early calls to
StyleManager.get()happen in static field initializers inRegearCommand.java, which will run as soon as the class is loaded—potentially before your plugin’sonEnable()guard is in place. All otherStyleManager.get()invocations occur inside methods or event handlers (i.e., afteronEnable()).• src/main/java/dev/noah/perplayerkit/commands/RegearCommand.java
– Lines 29–30:
java public static final ItemStack REGEAR_SHULKER_ITEM = ItemUtil.createItem( Material.WHITE_SHULKER_BOX, 1, StyleManager.get().getMainColor() + "Regear Shulker", …); public static final ItemStack REGEAR_SHELL_ITEM = ItemUtil.createItem( Material.SHULKER_SHELL, 1, StyleManager.get().getMainColor() + "Regear Shell", …);
These run at class‐load time, beforeonEnable().Recommendation: Move these static
ItemStackinitializations into a setup method—e.g., inside your plugin’sonEnable()or lazily in the command constructor—so thatStyleManager.get()is only invoked after the guard is active.
🧹 Nitpick comments (10)
src/main/java/dev/noah/perplayerkit/util/StyleManager.java (3)
33-38: Harden material parsing (null-safety, case-insensitive, and log fallback).
Material.valueOf(...)throws on null or invalid input; onlyIllegalArgumentExceptionis caught. Make parsing null-safe, accept lowercase config, and log the fallback so admins know why defaults were used.@@ - public void loadConfig() { - try { - this.glassMaterial = Material.valueOf(plugin.getConfig().getString("interface.glass-material", "BLUE_STAINED_GLASS_PANE")); - } catch (IllegalArgumentException e) { - this.glassMaterial = Material.BLUE_STAINED_GLASS_PANE; - } + public void loadConfig() { + String raw = plugin.getConfig().getString("interface.glass-material", "BLUE_STAINED_GLASS_PANE"); + try { + this.glassMaterial = Material.valueOf(raw.toUpperCase(java.util.Locale.ROOT)); + } catch (RuntimeException e) { + plugin.getLogger().warning("[StyleManager] Invalid interface.glass-material: '" + raw + + "'. Falling back to BLUE_STAINED_GLASS_PANE"); + this.glassMaterial = Material.BLUE_STAINED_GLASS_PANE; + }
29-31: Guard the singleton accessor to fail fast on misuse.If any code calls
StyleManager.get()beforeonEnable()initializes it, you'll hit a null dereference elsewhere. A defensive guard improves diagnostics.- public static StyleManager get() { - return instance; - } + public static StyleManager get() { + if (instance == null) { + throw new IllegalStateException("StyleManager not initialized yet. Initialize it in onEnable()."); + } + return instance; + }
16-26: Minor: consider preventing re-initialization.Reassigning
instanceon each constructor call can mask accidental multiple instantiations. Optionally reject subsequent constructions or provide a staticinit(Plugin)to enforce one-time init.src/main/java/dev/noah/perplayerkit/gui/ItemUtil.java (1)
58-60: Graceful fallback if StyleManager is unavailable.If
createGlassPane()is called too early orStyleManagerinitialization fails, this will NPE. Use a safe fallback to a default material.- public static ItemStack createGlassPane() { - return createItem(StyleManager.get().getGlassMaterial(), 1, " "); - } + public static ItemStack createGlassPane() { + Material mat; + try { + mat = StyleManager.get().getGlassMaterial(); + } catch (IllegalStateException ex) { + mat = Material.BLUE_STAINED_GLASS_PANE; // safe default + } + return createItem(mat, 1, " "); + }src/main/java/dev/noah/perplayerkit/PerPlayerKit.java (1)
55-67: Wire style reload into your existing reload flow.If you support config reloads, also call
StyleManager.get().loadConfig()so style changes apply without a full restart.Would you like me to add a reload hook in your reload command to call
StyleManager.get().loadConfig()?src/main/java/dev/noah/perplayerkit/listeners/KitRoomSaveListener.java (1)
44-44: Make title matching color-agnostic to support any configured color.Relying on the exact legacy color prefix is brittle (and breaks if color parsing fails or is changed). Strip colors before the contains check.
- if (view.getTitle().contains(StyleManager.get().getMainColor() + p.getName() + "'s Kits")) { + if (net.md_5.bungee.api.ChatColor.stripColor(view.getTitle()).contains(p.getName() + "'s Kits")) {src/main/resources/config.yml (1)
56-58: Config keys look good; add a brief hint for valid values.A short note can reduce misconfigurations (e.g., lowercase materials, hex colors). Optional doc improvement.
interface: - glass-material: BLUE_STAINED_GLASS_PANE - main-color: "<blue>" # Plugin main color (MiniMessage format: <blue>, <red>, <green>, etc.) + glass-material: BLUE_STAINED_GLASS_PANE # Bukkit Material enum (e.g., BLUE_STAINED_GLASS_PANE). Case-insensitive. + main-color: "<blue>" # MiniMessage color (e.g., <blue>, <red>, <green>, hex: <#AA66FF>)src/main/java/dev/noah/perplayerkit/commands/EnderchestCommand.java (1)
55-55: Title now honors theme color; consider resilience to config reloads.Using StyleManager for the title is correct. Note that if interface.main-color is reloaded while a menu is open, listeners that parse titles should not depend on the live color value to match (see my comment on KitMenuCloseListener for a robust approach using ChatColor.stripColor).
Would you like me to wire a lightweight “/ppk style reload” that safely refreshes open menus or at least warns players?
src/main/java/dev/noah/perplayerkit/gui/GUI.java (2)
87-88: Micro-optimization: reuse a single filler ItemStack per menu render.Repeatedly calling createGlassPane() in tight loops allocates many identical ItemStacks. Cache one per method and reuse in the loop; it’s cheaper and reduces allocations.
Example pattern you can apply to these loops:
- for (int i = 41; i < 54; i++) { - menu.getSlot(i).setItem(ItemUtil.createGlassPane()); - } + final ItemStack fill = ItemUtil.createGlassPane(); + for (int i = 41; i < 54; i++) { + menu.getSlot(i).setItem(fill); + }Repeat similarly in the other loops in this file.
Also applies to: 120-121, 144-145, 148-149, 183-184, 216-217, 220-221, 254-255, 279-280, 308-309, 355-356, 382-383
25-26: Consistency nit: mix of static import vs. qualified call for createGlassPane.You use both
createGlassPane()(static import) andItemUtil.createGlassPane(). Prefer one style across the file for consistency; static import reduces verbosity.Also applies to: 46-47
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
src/main/java/dev/noah/perplayerkit/PerPlayerKit.java(2 hunks)src/main/java/dev/noah/perplayerkit/commands/EnderchestCommand.java(2 hunks)src/main/java/dev/noah/perplayerkit/commands/RegearCommand.java(3 hunks)src/main/java/dev/noah/perplayerkit/gui/GUI.java(14 hunks)src/main/java/dev/noah/perplayerkit/gui/ItemUtil.java(2 hunks)src/main/java/dev/noah/perplayerkit/listeners/KitMenuCloseListener.java(6 hunks)src/main/java/dev/noah/perplayerkit/listeners/KitRoomSaveListener.java(2 hunks)src/main/java/dev/noah/perplayerkit/util/StyleManager.java(1 hunks)src/main/resources/config.yml(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
src/main/java/dev/noah/perplayerkit/listeners/KitRoomSaveListener.java (1)
src/main/java/dev/noah/perplayerkit/util/StyleManager.java (1)
StyleManager(16-60)
src/main/java/dev/noah/perplayerkit/listeners/KitMenuCloseListener.java (1)
src/main/java/dev/noah/perplayerkit/util/StyleManager.java (1)
StyleManager(16-60)
src/main/java/dev/noah/perplayerkit/PerPlayerKit.java (1)
src/main/java/dev/noah/perplayerkit/util/StyleManager.java (1)
StyleManager(16-60)
src/main/java/dev/noah/perplayerkit/commands/EnderchestCommand.java (2)
src/main/java/dev/noah/perplayerkit/util/StyleManager.java (1)
StyleManager(16-60)src/main/java/dev/noah/perplayerkit/gui/ItemUtil.java (1)
ItemUtil(33-93)
src/main/java/dev/noah/perplayerkit/commands/RegearCommand.java (2)
src/main/java/dev/noah/perplayerkit/util/StyleManager.java (1)
StyleManager(16-60)src/main/java/dev/noah/perplayerkit/gui/ItemUtil.java (1)
ItemUtil(33-93)
src/main/java/dev/noah/perplayerkit/gui/ItemUtil.java (1)
src/main/java/dev/noah/perplayerkit/util/StyleManager.java (1)
StyleManager(16-60)
src/main/java/dev/noah/perplayerkit/gui/GUI.java (2)
src/main/java/dev/noah/perplayerkit/gui/ItemUtil.java (1)
ItemUtil(33-93)src/main/java/dev/noah/perplayerkit/util/StyleManager.java (1)
StyleManager(16-60)
🔇 Additional comments (6)
src/main/java/dev/noah/perplayerkit/gui/ItemUtil.java (1)
21-21: Nice addition; reduces duplication and centralizes theming.The new helper cleanly routes filler panes through config. LGTM.
Also applies to: 58-60
src/main/java/dev/noah/perplayerkit/PerPlayerKit.java (1)
66-67: Good placement of StyleManager initialization.Initialized after config load and before GUI/commands use it. This ordering is correct.
src/main/java/dev/noah/perplayerkit/listeners/KitRoomSaveListener.java (1)
44-44: Dependent on StyleManager’s legacy output.If you keep the current approach, it depends on
StyleManager.get().getMainColor()returning a legacy (§) code. The fix in StyleManager ensures this.After updating StyleManager, please verify this flow by opening the Kit Room and confirming saves trigger as expected with a non-default color (e.g., "<dark_purple>").
src/main/java/dev/noah/perplayerkit/commands/EnderchestCommand.java (1)
53-53: Good move: centralize filler panes via ItemUtil.createGlassPane().This keeps visuals consistent with the configured glass material and avoids hard-coding.
src/main/java/dev/noah/perplayerkit/commands/RegearCommand.java (1)
196-196: LGTM: inventory title now reflects the configured main color.This keeps the regear UI aligned with the rest of the themed menus.
src/main/java/dev/noah/perplayerkit/gui/GUI.java (1)
66-68: Titles now consistently use StyleManager — good alignment with the theming system.
- Public kit room, per-kit, EC, inspect, main, and kit-room titles all honor the configured color.
- This pairs well with the listener changes once title parsing is made color-agnostic (see my comment on KitMenuCloseListener).
No functional issues spotted here.
After you update the listeners to strip colors, please sanity-check that opening/closing each menu works after a color change without restarting the server.
Also applies to: 652-678
| public static final ItemStack REGEAR_SHULKER_ITEM = ItemUtil.createItem(Material.WHITE_SHULKER_BOX, 1, StyleManager.get().getMainColor() + "Regear Shulker", "&7● Restocks Your Kit", "&7● Use " + StyleManager.get().getMainColor() + "/rg &7to get another regear shulker"); | ||
| public static final ItemStack REGEAR_SHELL_ITEM = ItemUtil.createItem(Material.SHULKER_SHELL, 1, StyleManager.get().getMainColor() + "Regear Shell", "&7● Restocks Your Kit", "&7● Click to use!"); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid static, config-dependent ItemStack constants; tag items with PDC and build on demand.
Problems:
- Class-load order risk: StyleManager.get() may be null when these static fields initialize.
- Stale config: after changing interface.main-color, equals() comparisons against REGEAR_SHULKER_ITEM/REGEAR_SHELL_ITEM will fail for old/new items.
- equals(ItemStack) is brittle (meta or minor changes break equality).
Refactor to:
- Build the items on demand using the current StyleManager color, and
- Identify them via a PersistentDataContainer tag instead of equals().
Apply this local change (replacing the static fields with helpers):
- public static final ItemStack REGEAR_SHULKER_ITEM = ItemUtil.createItem(Material.WHITE_SHULKER_BOX, 1, StyleManager.get().getMainColor() + "Regear Shulker", "&7● Restocks Your Kit", "&7● Use " + StyleManager.get().getMainColor() + "/rg &7to get another regear shulker");
- public static final ItemStack REGEAR_SHELL_ITEM = ItemUtil.createItem(Material.SHULKER_SHELL, 1, StyleManager.get().getMainColor() + "Regear Shell", "&7● Restocks Your Kit", "&7● Click to use!");
+ // Build items using current theme; identify via PDC
+ private ItemStack buildRegearShulkerItem() {
+ ItemStack item = ItemUtil.createItem(
+ Material.WHITE_SHULKER_BOX,
+ 1,
+ StyleManager.get().getMainColor() + "Regear Shulker",
+ "&7● Restocks Your Kit",
+ "&7● Use " + StyleManager.get().getMainColor() + "/rg &7to get another regear shulker");
+ org.bukkit.inventory.meta.ItemMeta meta = item.getItemMeta();
+ if (meta != null) {
+ meta.getPersistentDataContainer().set(new org.bukkit.NamespacedKey(plugin, "ppk-regear-type"),
+ org.bukkit.persistence.PersistentDataType.STRING, "shulker");
+ item.setItemMeta(meta);
+ }
+ return item;
+ }
+
+ private ItemStack buildRegearShellItem() {
+ ItemStack item = ItemUtil.createItem(
+ Material.SHULKER_SHELL,
+ 1,
+ StyleManager.get().getMainColor() + "Regear Shell",
+ "&7● Restocks Your Kit",
+ "&7● Click to use!");
+ org.bukkit.inventory.meta.ItemMeta meta = item.getItemMeta();
+ if (meta != null) {
+ meta.getPersistentDataContainer().set(new org.bukkit.NamespacedKey(plugin, "ppk-regear-type"),
+ org.bukkit.persistence.PersistentDataType.STRING, "shell");
+ item.setItemMeta(meta);
+ }
+ return item;
+ }
+
+ private boolean isRegearItemOfType(ItemStack item, String type) {
+ if (item == null) return false;
+ org.bukkit.inventory.meta.ItemMeta meta = item.getItemMeta();
+ if (meta == null) return false;
+ String val = meta.getPersistentDataContainer().get(new org.bukkit.NamespacedKey(plugin, "ppk-regear-type"),
+ org.bukkit.persistence.PersistentDataType.STRING);
+ return type.equals(val);
+ }And update usages elsewhere in this class (outside this hunk):
- Give item: replace player.getInventory().setItem(slot, REGEAR_SHULKER_ITEM) with buildRegearShulkerItem().
- Open shulker GUI: inventory.setItem(13, buildRegearShellItem()).
- Placement guard: replace if (!event.getItemInHand().equals(REGEAR_SHULKER_ITEM)) with if (!isRegearItemOfType(event.getItemInHand(), "shulker")) return;.
- Click guard: replace if (!currentItem.equals(REGEAR_SHELL_ITEM)) with if (!isRegearItemOfType(currentItem, "shell")) { ... }.
Result: no NPE risk at class load; items survive theme changes; identification is reliable.
I can push a follow-up commit with these changes if you’d like.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public static final ItemStack REGEAR_SHULKER_ITEM = ItemUtil.createItem(Material.WHITE_SHULKER_BOX, 1, StyleManager.get().getMainColor() + "Regear Shulker", "&7● Restocks Your Kit", "&7● Use " + StyleManager.get().getMainColor() + "/rg &7to get another regear shulker"); | |
| public static final ItemStack REGEAR_SHELL_ITEM = ItemUtil.createItem(Material.SHULKER_SHELL, 1, StyleManager.get().getMainColor() + "Regear Shell", "&7● Restocks Your Kit", "&7● Click to use!"); | |
| // Build items using current theme; identify via PDC | |
| private ItemStack buildRegearShulkerItem() { | |
| ItemStack item = ItemUtil.createItem( | |
| Material.WHITE_SHULKER_BOX, | |
| 1, | |
| StyleManager.get().getMainColor() + "Regear Shulker", | |
| "&7● Restocks Your Kit", | |
| "&7● Use " + StyleManager.get().getMainColor() + "/rg &7to get another regear shulker"); | |
| org.bukkit.inventory.meta.ItemMeta meta = item.getItemMeta(); | |
| if (meta != null) { | |
| meta.getPersistentDataContainer().set( | |
| new org.bukkit.NamespacedKey(plugin, "ppk-regear-type"), | |
| org.bukkit.persistence.PersistentDataType.STRING, | |
| "shulker" | |
| ); | |
| item.setItemMeta(meta); | |
| } | |
| return item; | |
| } | |
| private ItemStack buildRegearShellItem() { | |
| ItemStack item = ItemUtil.createItem( | |
| Material.SHULKER_SHELL, | |
| 1, | |
| StyleManager.get().getMainColor() + "Regear Shell", | |
| "&7● Restocks Your Kit", | |
| "&7● Click to use!"); | |
| org.bukkit.inventory.meta.ItemMeta meta = item.getItemMeta(); | |
| if (meta != null) { | |
| meta.getPersistentDataContainer().set( | |
| new org.bukkit.NamespacedKey(plugin, "ppk-regear-type"), | |
| org.bukkit.persistence.PersistentDataType.STRING, | |
| "shell" | |
| ); | |
| item.setItemMeta(meta); | |
| } | |
| return item; | |
| } | |
| private boolean isRegearItemOfType(ItemStack item, String type) { | |
| if (item == null) return false; | |
| org.bukkit.inventory.meta.ItemMeta meta = item.getItemMeta(); | |
| if (meta == null) return false; | |
| String val = meta.getPersistentDataContainer().get( | |
| new org.bukkit.NamespacedKey(plugin, "ppk-regear-type"), | |
| org.bukkit.persistence.PersistentDataType.STRING | |
| ); | |
| return type.equals(val); | |
| } |
🤖 Prompt for AI Agents
In src/main/java/dev/noah/perplayerkit/commands/RegearCommand.java around lines
29-31, remove the static config-dependent ItemStack constants and replace them
with on-demand builder methods that construct the regear shulker and shell using
StyleManager.get() at call time; tag the built items with a
PersistentDataContainer key/value (e.g., type="shulker" or "shell") for reliable
identity instead of equals(), then update usages in this class: replace
inventory setItem calls with buildRegearShulkerItem()/buildRegearShellItem(),
replace equality checks like event.getItemInHand().equals(REGEAR_SHULKER_ITEM)
with a helper isRegearItemOfType(item,"shulker"), and replace
currentItem.equals(REGEAR_SHELL_ITEM) with
isRegearItemOfType(currentItem,"shell"); ensure null checks for ItemStack and
ItemMeta before reading PDC.
| if (view.getTitle().contains(StyleManager.get().getMainColor() + "Kit: ")) { | ||
| Player p = (Player) e.getPlayer(); | ||
| UUID uuid = p.getUniqueId(); | ||
| int slot = Integer.parseInt(view.getTitle().replace(ChatColor.BLUE + "Kit: ", "")); | ||
| int slot = Integer.parseInt(view.getTitle().replace(StyleManager.get().getMainColor() + "Kit: ", "")); | ||
| ItemStack[] kit = new ItemStack[41]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Make title parsing color-agnostic to survive theme changes and formatting variance.
Right now the code matches and extracts data using StyleManager.get().getMainColor() + "...". If interface.main-color is changed (or MiniMessage returns multi-code sequences), open menus will close with titles that no longer match the new prefix, and saves will silently skip. Strip colors before matching and parse based on plain-text prefixes.
Apply these diffs to the affected blocks:
@@
- if (view.getTitle().contains(StyleManager.get().getMainColor() + "Kit: ")) {
+ String stripped = ChatColor.stripColor(view.getTitle());
+ if (stripped.startsWith("Kit: ")) {
Player p = (Player) e.getPlayer();
UUID uuid = p.getUniqueId();
- int slot = Integer.parseInt(view.getTitle().replace(StyleManager.get().getMainColor() + "Kit: ", ""));
+ int slot = Integer.parseInt(stripped.substring("Kit: ".length()));@@
- if (view.getTitle().contains(StyleManager.get().getMainColor() + "Public Kit: ")) {
+ String stripped = ChatColor.stripColor(view.getTitle());
+ if (stripped.startsWith("Public Kit: ")) {
Player player = (Player) e.getPlayer();
- String publickit = view.getTitle().replace(StyleManager.get().getMainColor() + "Public Kit: ", "");
+ String publickit = stripped.substring("Public Kit: ".length());@@
- if (view.getTitle().contains(StyleManager.get().getMainColor() + "Enderchest: ")) {
+ String stripped = ChatColor.stripColor(view.getTitle());
+ if (stripped.startsWith("Enderchest: ")) {
Player p = (Player) e.getPlayer();
UUID uuid = p.getUniqueId();
- int slot = Integer.parseInt(view.getTitle().replace(StyleManager.get().getMainColor() + "Enderchest: ", ""));
+ int slot = Integer.parseInt(stripped.substring("Enderchest: ".length()));@@
- if (view.getTitle().contains(StyleManager.get().getMainColor() + "Inspecting ") && view.getTitle().contains("'s kit ")) {
+ String stripped = ChatColor.stripColor(view.getTitle());
+ if (stripped.startsWith("Inspecting ") && stripped.contains("'s kit ")) {
Player p = (Player) e.getPlayer();
@@
- String title = view.getTitle();
- String[] parts = title.replace(StyleManager.get().getMainColor() + "Inspecting ", "").split("'s kit ");
+ String[] parts = stripped.substring("Inspecting ".length()).split("'s kit ");@@
- if (view.getTitle().contains(StyleManager.get().getMainColor() + "Inspecting ") && view.getTitle().contains("'s enderchest ")) {
+ String stripped = ChatColor.stripColor(view.getTitle());
+ if (stripped.startsWith("Inspecting ") && stripped.contains("'s enderchest ")) {
Player p = (Player) e.getPlayer();
@@
- String title = view.getTitle();
- String[] parts = title.replace(StyleManager.get().getMainColor() + "Inspecting ", "").split("'s enderchest ");
+ String[] parts = stripped.substring("Inspecting ".length()).split("'s enderchest ");This makes the logic robust to any color code (legacy, hex, gradient) and to runtime theme reloads.
If you prefer not to parse titles at all, I can convert these menus to use a custom InventoryHolder per menu carrying the slot/id, which is the most reliable approach.
Also applies to: 71-74, 96-100, 122-129, 189-196
| String colorTag = plugin.getConfig().getString("interface.main-color", "<blue>"); | ||
| this.titleColor = miniMessageToLegacy(colorTag); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix legacy color fallback; current "" fallback breaks string comparisons.
miniMessageToLegacy returns legacy §-codes, but on error it returns "" (MiniMessage tag), which will not match callers that expect legacy (e.g., Inventory title contains checks). Return a legacy code and validate conversion.
@@
- String colorTag = plugin.getConfig().getString("interface.main-color", "<blue>");
- this.titleColor = miniMessageToLegacy(colorTag);
+ String colorTag = plugin.getConfig().getString("interface.main-color", "<blue>");
+ this.titleColor = miniMessageToLegacy(colorTag);
@@
- private String miniMessageToLegacy(String miniMessage) {
- try {
- Component component = MiniMessage.miniMessage().deserialize(miniMessage + "test");
- return LegacyComponentSerializer.legacySection().serialize(component).replace("test", "");
- } catch (Exception e) {
- return "<blue>";
- }
- }
+ private String miniMessageToLegacy(String miniMessage) {
+ final String defaultLegacyBlue = "§9";
+ try {
+ Component component = MiniMessage.miniMessage().deserialize(miniMessage + "test");
+ String out = LegacyComponentSerializer.legacySection().serialize(component).replace("test", "");
+ // If conversion produced no legacy codes (misconfigured value), use default.
+ if (!out.contains("§")) {
+ plugin.getLogger().warning("[StyleManager] Invalid interface.main-color: '" + miniMessage
+ + "'. Falling back to blue.");
+ return defaultLegacyBlue;
+ }
+ return out;
+ } catch (Exception e) {
+ plugin.getLogger().warning("[StyleManager] Failed to parse interface.main-color: '" + miniMessage
+ + "'. Falling back to blue. Cause: " + e.getClass().getSimpleName());
+ return defaultLegacyBlue;
+ }
+ }Also applies to: 44-51
🤖 Prompt for AI Agents
In src/main/java/dev/noah/perplayerkit/util/StyleManager.java around lines 40-42
and also 44-51, the fallback string "<blue>" is a MiniMessage tag while
miniMessageToLegacy() returns legacy §-codes — causing mismatches in callers
that expect legacy codes; change the fallback to the legacy blue code (e.g.,
"§9"), call miniMessageToLegacy(plugin.getConfig().getString(..., "<blue>")) and
then validate the result (check for null/empty or that it does not start with
'<') and if validation fails use the legacy fallback "§9" (and optionally log a
warning) so titleColor and other fields always contain a legacy color code.
Usage example:
Summary by CodeRabbit