### Handle Exceptions in SignGUI Java Usage Source: https://context7.com/rapha149/signgui/llms.txt This Java example demonstrates robust exception handling for SignGUI operations. It covers `SignGUIVersionException` for unsupported server versions, `SignGUIException` for runtime packet sending failures, and `IllegalArgumentException` for invalid configurations or conflicting actions returned by handlers. Proper handling ensures a smoother user experience and provides informative error messages to the player. ```java import de.rapha149.signgui.*; import de.rapha149.signgui.exception.*; import org.bukkit.entity.Player; import java.util.Collections; public class SafeSignGUIUsage { public void openSignSafely(Player player) { try { SignGUI gui = SignGUI.builder() .setLines("", "Enter text:", "", "") .setHandler((p, result) -> { String text = result.getLineWithoutColor(0); p.sendMessage("Text: " + text); return Collections.emptyList(); }) .build(); gui.open(player); } catch (SignGUIVersionException e) { // Thrown by builder() if server version is unsupported player.sendMessage("§cYour server version is not supported by SignGUI."); player.sendMessage("§cSupported versions: 1.8 - 1.21"); e.printStackTrace(); } catch (SignGUIException e) { // Thrown by open() if packet sending fails player.sendMessage("§cFailed to open sign editor. Please try again."); e.printStackTrace(); } catch (IllegalArgumentException e) { // Thrown if conflicting actions are returned player.sendMessage("§cInternal error: conflicting actions detected."); e.printStackTrace(); } } public void handleConflictingActions(Player player) { try { SignGUI gui = SignGUI.builder() .setHandler((p, result) -> { // WRONG: Cannot both re-display AND open inventory return java.util.List.of( SignGUIAction.displayNewLines("", "New text", "", ""), SignGUIAction.openInventory(null, null) // Conflict! ); }) .build(); gui.open(player); } catch (SignGUIVersionException | IllegalArgumentException e) { player.sendMessage("§cError: " + e.getMessage()); } } } ``` -------------------------------- ### Share SignGUI Instance Across Multiple Players in Java Source: https://context7.com/rapha149/signgui/llms.txt This example shows how to reuse a single SignGUI instance for multiple players. The `SignGUI.builder()` creates one instance, which is then opened for each player individually using `gui.open(player)`. The handler for the GUI executes independently for each player, allowing them to interact with the same GUI without conflict. This is useful for scenarios where multiple players need to input data into a shared interface. ```java import de.rapha149.signgui.*; import org.bukkit.entity.Player; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class MultiPlayerExample { private Map scores = new HashMap<>(); public void requestScores(Player player1, Player player2, Player player3) { try { // Single SignGUI instance shared across multiple players SignGUI gui = SignGUI.builder() .setLines("", "Enter your score:", "", "") .setHandler((p, result) -> { try { int score = Integer.parseInt(result.getLineWithoutColor(0)); scores.put(p.getName(), score); p.sendMessage("§aScore recorded: " + score); } catch (NumberFormatException e) { p.sendMessage("§cInvalid score!"); } return Collections.emptyList(); }) .build(); // Open same GUI for multiple players gui.open(player1); gui.open(player2); gui.open(player3); // Each player sees independent sign editor // Handler executes separately for each player } catch (SignGUIVersionException e) { e.printStackTrace(); } } } ``` -------------------------------- ### Open and Configure Sign Editor GUI (Java) Source: https://github.com/rapha149/signgui/blob/main/README.md Demonstrates how to build and open a SignGUI for a player, including setting initial lines, sign type, color, and a handler for player input. The handler allows processing player input, displaying new lines, or opening inventories. It also shows basic error handling for version compatibility. ```java try { SignGUI gui = SignGUI.builder() // set lines .setLines("§6Line 1", null, "§6Line 3") // set specific line, starting index is 0 .setLine(3, "Line 4") // set the sign type .setType(Material.DARK_OAK_SIGN) // set the sign color .setColor(DyeColor.YELLOW) // set the handler/listener (called when the player finishes editing) .setHandler((p, result) -> { // get a speficic line, starting index is 0 String line0 = result.getLine(0); // get a specific line without color codes String line1 = result.getLineWithoutColor(1); // get all lines String[] lines = result.getLines(); // get all lines without color codes String[] linesWithoutColor = result.getLinesWithoutColor(); if (line1.isEmpty()) { // The user has not entered anything on line 2, so we open the sign again return List.of(SignGUIAction.displayNewLines("§6Line 1", null, "§6Line 3", "Line 4")); } if (line1.equals("inv")) { // close the sign and open an inventory return List.of( // "this" = your JavaPlugin instance SignGUIAction.openInventory(this, Bukkit.createInventory(player, 27)), SignGUIAction.run(() -> player.sendMessage("Inventory opened!")) ); } // Just close the sign by not returning any actions return Collections.emptyList(); }) // build the SignGUI .build(); // open the sign gui.open(player); // you can also open the sign for multiple players gui.open(player2); } catch (SignGUIVersionException e) { // This error is thrown if SignGUI does not support this server version (yet). } ``` -------------------------------- ### Gradle Integration: Add SignGUI Dependency and Relocate Source: https://context7.com/rapha149/signgui/llms.txt Integrates SignGUI into a Gradle project using the Shadow plugin for dependency management and relocation. This configuration ensures SignGUI is bundled with your plugin, preventing conflicts with other plugins that might also use SignGUI. ```groovy plugins { id 'com.github.johnrengelman.shadow' version '8.1.1' } dependencies { implementation 'de.rapha149.signgui:signgui:2.5.4' } shadowJar { relocate 'de.rapha149.signgui', 'com.yourplugin.libs.signgui' // For Gradle minimize() users - exclude SignGUI from minimization minimize { exclude(dependency('de.rapha149.signgui:signgui:.*')) } } // Alternatively, if plugin only supports one MC version: dependencies { implementation 'de.rapha149.signgui:signgui:2.5.4' } shadowJar { relocate 'de.rapha149.signgui', 'com.yourplugin.libs.signgui' minimize() } // In your code, explicitly reference wrapper class to prevent removal: // Wrapper1_21_R5.class.getName(); // For Spigot/CraftBukkit // MojangWrapper1_21_R5.class.getName(); // For mojang-mapped Paper ``` -------------------------------- ### Chaining Actions with SignGUI in Java Source: https://context7.com/rapha149/signgui/llms.txt This snippet demonstrates how to chain multiple actions sequentially after a player interacts with a sign. It includes handling user input, validating quantities, opening an inventory, and displaying messages. This functionality requires the Bukkit API and the SignGUI library. ```java import de.rapha149.signgui.*; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import java.util.Collections; import java.util.List; public class ShopPlugin extends JavaPlugin { public void openShopWithQuantity(Player player) { try { SignGUI gui = SignGUI.builder() .setLines("", "How many items?", "", "") .callHandlerSynchronously(this) // Required for inventory operations .setHandler((p, result) -> { String input = result.getLineWithoutColor(0).trim(); if (input.equalsIgnoreCase("cancel")) { return Collections.emptyList(); // Just close } try { int quantity = Integer.parseInt(input); if (quantity < 1 || quantity > 64) { return List.of(SignGUIAction.displayNewLines( "", "§cQuantity must be", "§cbetween 1 and 64", "" )); } Inventory shop = Bukkit.createInventory(null, 27, "Shop - " + quantity + " items"); shop.setItem(13, new ItemStack(Material.DIAMOND, quantity)); return List.of( SignGUIAction.runSync(this, () -> p.sendMessage("§aOpening shop with " + quantity + " items...")), SignGUIAction.openInventory(this, shop), SignGUIAction.runSync(this, () -> p.sendMessage("§aShop opened!")) ); } catch (NumberFormatException e) { return List.of(SignGUIAction.displayNewLines( "", "§c'" + input + "' is not", "§ca valid number", "" )); } }) .build(); gui.open(player); } catch (SignGUIVersionException e) { player.sendMessage("§cSign GUI not supported."); } } } // Expected flow: // 1. Player sees sign "How many items?" // 2. Player types "16" // 3. Player receives: "Opening shop with 16 items..." // 4. Inventory opens with 16 diamonds in center slot // 5. Player receives: "Shop opened!" ``` -------------------------------- ### Maven Integration: Add SignGUI Dependency and Relocate Source: https://context7.com/rapha149/signgui/llms.txt Integrates SignGUI into a Maven project by adding the dependency and configuring the Maven Shade Plugin to relocate the package. This ensures SignGUI is bundled with your plugin and avoids potential conflicts with other plugins using the same library. ```xml de.rapha149.signgui signgui 2.5.4 org.apache.maven.plugins maven-shade-plugin 3.5.0 package shade de.rapha149.signgui com.yourplugin.libs.signgui ``` -------------------------------- ### Basic Sign Input Collection with SignGUI Source: https://context7.com/rapha149/signgui/llms.txt Collects player input using a default sign GUI. The handler processes the input from the first line and sends a confirmation message. It handles potential `SignGUIVersionException` for unsupported server versions. ```java import de.rapha149.signgui.*; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.Collections; public class MyPlugin extends JavaPlugin { public void requestPlayerName(Player player) { try { SignGUI gui = SignGUI.builder() .setHandler((p, result) -> { String name = result.getLineWithoutColor(0); p.sendMessage("You entered: " + name); return Collections.emptyList(); // Close the sign }) .build(); gui.open(player); } catch (SignGUIVersionException e) { player.sendMessage("§cSign GUI is not supported on this server version."); } } } // Expected output: // - Player sees blank sign editor // - Player types "Steve" on first line // - Player clicks "Done" // - Player receives message: "You entered: Steve" ``` -------------------------------- ### Adventure Component Support with SignGUI in Java Source: https://context7.com/rapha149/signgui/llms.txt This snippet illustrates how to use Adventure components for rich text formatting with SignGUI on mojang-mapped Paper 1.20.5+ servers. It also includes a fallback mechanism for servers that do not support Adventure components, using plain strings. Dependencies include the SignGUI library and Adventure API. ```java import de.rapha149.signgui.*; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.entity.Player; import java.util.Collections; import java.util.List; public void requestWithAdventure(Player player) { try { Component line1 = Component.text("Enter name", NamedTextColor.GOLD, TextDecoration.BOLD); Component line2 = Component.text("Required", NamedTextColor.RED, TextDecoration.ITALIC); SignGUI gui = SignGUI.builder() .setAdventureLines(Component.empty(), line1, line2, Component.empty()) .setLines("", "Enter name", "Required", "") // Fallback for non-Paper servers .setHandler((p, result) -> { String name = result.getLineWithoutColor(0).trim(); if (name.isEmpty()) { Component error1 = Component.text("Name cannot", NamedTextColor.RED); Component error2 = Component.text("be empty!", NamedTextColor.RED); return List.of(SignGUIAction.displayNewAdventureLines( new Object[]{Component.empty(), error1, error2, Component.empty()}, new String[]{"", "Name cannot", "be empty!", ""} // Fallback )); } p.sendMessage("§aName set to: " + name); return Collections.emptyList(); }) .build(); gui.open(player); } catch (SignGUIVersionException e) { e.printStackTrace(); } } // On mojang-mapped Paper 1.20.5+: // - Rich Adventure components displayed with full formatting // On other servers: // - Falls back to string-based lines ``` -------------------------------- ### Maven Shade Plugin Relocation for SignGUI Source: https://github.com/rapha149/signgui/blob/main/README.md This configuration for the Maven Shade Plugin relocates the SignGUI package to prevent conflicts with other plugins. Replace '[YOUR_PLUGIN_PACKAGE]' with your plugin's actual package name. The plugin version must be 3.5.0 or higher. ```xml org.apache.maven.plugins maven-shade-plugin SHADE_VERSION package shade de.rapha149.signgui [YOUR_PLUGIN_PACKAGE].signgui ``` -------------------------------- ### Maven Dependency for SignGUI Source: https://github.com/rapha149/signgui/blob/main/README.md This XML snippet shows how to add the SignGUI API as a dependency in a Maven project. Ensure you use the latest version available for compatibility and features. ```xml de.rapha149.signgui signgui 2.5.4 ``` -------------------------------- ### Process Sign Result with Color Stripping (Java) Source: https://context7.com/rapha149/signgui/llms.txt Demonstrates how to open a SignGUI, process the player's input, and retrieve lines with or without color codes. This method is useful for custom sign interactions in Bukkit plugins. It requires the SignGUI library and Bukkit API. ```java import de.rapha149.signgui.*; import org.bukkit.entity.Player; import java.util.Collections; public void processSignResult(Player player) { try { SignGUI gui = SignGUI.builder() .setLines("§aLine 1", "§bLine 2", "§cLine 3", "§dLine 4") .setHandler((p, result) -> { // Get all lines (with color codes) String[] lines = result.getLines(); // lines = ["§aLine 1", "§bLine 2", "§cLine 3", "§dLine 4"] // Get specific line (with color codes) String line2 = result.getLine(1); // line2 = "§bLine 2" // Get all lines without color codes String[] linesNoColor = result.getLinesWithoutColor(); // linesNoColor = ["Line 1", "Line 2", "Line 3", "Line 4"] // Get specific line without color codes String line3NoColor = result.getLineWithoutColor(2); // line3NoColor = "Line 3" p.sendMessage("You entered:"); for (int i = 0; i < lines.length; i++) { p.sendMessage(" Line " + i + " (raw): " + lines[i]); p.sendMessage(" Line " + i + " (clean): " + linesNoColor[i]); } return Collections.emptyList(); }) .build(); gui.open(player); } catch (SignGUIVersionException e) { e.printStackTrace(); } } ``` -------------------------------- ### Configured Sign Input with SignGUI: Pre-filled, Type, Color, Glow Source: https://context7.com/rapha149/signgui/llms.txt Configures a sign GUI with pre-filled lines, a specific sign material (dark oak), a custom color (yellow), and enables glowing text (requires Minecraft 1.17+). The handler displays the entered age with a formatted message and handles `SignGUIVersionException`. ```java import de.rapha149.signgui.*; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.entity.Player; import java.util.Collections; public void requestAge(Player player) { try { SignGUI gui = SignGUI.builder() .setLines("", "Enter your age:", "", "") .setType(Material.DARK_OAK_SIGN) .setColor(DyeColor.YELLOW) .setGlow(true) // 1.17+ only .setHandler((p, result) -> { String age = result.getLineWithoutColor(0); p.sendMessage("§eAge entered: " + age); return Collections.emptyList(); }) .build(); gui.open(player); } catch (SignGUIVersionException e) { e.printStackTrace(); } } // Expected output: // - Dark oak sign with yellow glowing text appears // - Line 2 shows "Enter your age:" // - Player types "25" on line 1 // - Player receives message: "Age entered: 25" ``` -------------------------------- ### Control Handler Execution (Async/Sync) with Java Source: https://context7.com/rapha149/signgui/llms.txt Demonstrates how to manage the execution thread for the SignGUI handler. By default, handlers run asynchronously, suitable for I/O operations. The `callHandlerSynchronously` method forces execution on the main server thread, which is necessary for Bukkit API calls. ```java import de.rapha149.signgui.*; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.Collections; public class DatabasePlugin extends JavaPlugin { // Async handler (default) - safe for database operations public void saveToDatabase(Player player) { try { SignGUI gui = SignGUI.builder() .setLines("", "Enter username:", "", "") .setHandler((p, result) -> { String username = result.getLineWithoutColor(0); // Safe to do blocking I/O here - runs async by default boolean saved = performDatabaseInsert(username); if (saved) { p.sendMessage("§aUsername saved to database!"); } else { p.sendMessage("§cDatabase error occurred."); } return Collections.emptyList(); }) .build(); gui.open(player); } catch (SignGUIVersionException e) { e.printStackTrace(); } } // Sync handler - required for Bukkit API calls public void givePotionEffect(Player player) { try { SignGUI gui = SignGUI.builder() .setLines("", "Duration (seconds)", "", "") .callHandlerSynchronously(this) // MUST be called for Bukkit API .setHandler((p, result) -> { try { int seconds = Integer.parseInt(result.getLineWithoutColor(0)); // Safe to call Bukkit API - runs on main thread p.addPotionEffect(new org.bukkit.potion.PotionEffect( org.bukkit.potion.PotionEffectType.SPEED, seconds * 20, 1 )); p.sendMessage("§aSpeed effect applied for " + seconds + " seconds!"); } catch (NumberFormatException e) { p.sendMessage("§cInvalid number!"); } return Collections.emptyList(); }) .build(); gui.open(player); } catch (SignGUIVersionException e) { e.printStackTrace(); } } private boolean performDatabaseInsert(String username) { // Simulated blocking database operation return true; } } // Default behavior (async): // - Handler runs on separate thread // - Safe for I/O operations, database queries, web requests // - Do NOT use Bukkit API directly // With callHandlerSynchronously(): // - Handler runs on main server thread // - Safe for all Bukkit API calls // - Avoid blocking operations ``` -------------------------------- ### Gradle Exclusion for SignGUI minimize() Method Source: https://github.com/rapha149/signgui/blob/main/README.md This Gradle snippet demonstrates how to exclude the SignGUI dependency from Gradle's minimize() method to avoid compilation issues related to reflection-based version wrappers. This ensures all wrapper classes are compiled. ```gradle minimize() { // exclude every version of the SignGUI dependency using a Regex string exclude(dependency("de\.rapha149\.signgui:signgui:.*")) } ``` -------------------------------- ### Java SignGUI Input Validation and Re-display Source: https://context7.com/rapha149/signgui/llms.txt This Java code snippet demonstrates how to create a SignGUI that validates player input. It handles cases for empty input, non-numeric input, and numbers that are not positive. If the input is invalid, the GUI is re-displayed with specific error messages. Valid input is acknowledged, and the GUI closes. This utilizes the SignGUI library for Bukkit plugins. ```java import de.rapha149.signgui.*; import org.bukkit.entity.Player; import java.util.Collections; import java.util.List; public void requestPositiveNumber(Player player) { try { SignGUI gui = SignGUI.builder() .setLines("", "Enter a number:", "Must be > 0", "") .setHandler((p, result) -> { String input = result.getLineWithoutColor(0).trim(); if (input.isEmpty()) { return List.of(SignGUIAction.displayNewLines( "", "§cYou didn't enter", "§canything!", "" )); } try { int number = Integer.parseInt(input); if (number <= 0) { return List.of(SignGUIAction.displayNewLines( "", "§cMust be positive!", "§cTry again", "" )); } p.sendMessage("§aValid number: " + number); return Collections.emptyList(); } catch (NumberFormatException e) { return List.of(SignGUIAction.displayNewLines( "", "§c'" + input + "'", "§cis not a number!", "" )); } }) .build(); gui.open(player); } catch (SignGUIVersionException e) { e.printStackTrace(); } } ``` -------------------------------- ### Specify Custom Sign Location with Java Source: https://context7.com/rapha149/signgui/llms.txt Allows setting a specific location for the sign GUI, overriding the default placement. The sign is positioned relative to the player's current location. This is useful for custom UI designs. ```java import de.rapha149.signgui.*; import org.bukkit.Location; import org.bukkit.entity.Player; import java.util.Collections; public void requestWithCustomLocation(Player player) { try { // Place sign 10 blocks above player Location signLocation = player.getLocation().clone().add(0, 10, 0); SignGUI gui = SignGUI.builder() .setLines("", "Enter password:", "", "") .setLocation(signLocation) .setHandler((p, result) -> { String password = result.getLine(0); // Preserve color codes p.sendMessage("§7Password entered: " + password); return Collections.emptyList(); }) .build(); gui.open(player); } catch (SignGUIVersionException e) { e.printStackTrace(); } } // Expected output: // - Sign appears 10 blocks above player's current position // - Default behavior: sign appears 3 blocks behind player ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.