### Check for Plugin Updates using Modrinth API (Java) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt This snippet shows how to use the ModrinthUpdateChecker from EternalCode Commons to query the Modrinth API for newer plugin versions. It includes checking for updates, handling the results, and an example of asynchronous integration within a Bukkit plugin. Requires EternalCode Commons and a Modrinth project ID. ```java import com.eternalcode.commons.updater.UpdateChecker; import com.eternalcode.commons.updater.UpdateResult; import com.eternalcode.commons.updater.Version; import com.eternalcode.commons.updater.impl.ModrinthUpdateChecker; // Create update checker UpdateChecker checker = new ModrinthUpdateChecker(); // Check for updates Version currentVersion = new Version("1.2.0"); UpdateResult result = checker.check("EternalCombat", currentVersion); // Use Modrinth project ID/slug // Handle result if (result.isUpdateAvailable()) { System.out.println("New version available: " + result.latestVersion()); System.out.println("Download: " + result.downloadUrl()); System.out.println("Release page: " + result.releaseUrl()); } else { System.out.println("You are running the latest version!"); } // Access version info System.out.println("Current: " + result.currentVersion()); // 1.2.0 System.out.println("Latest: " + result.latestVersion()); // 1.3.0 // Example Bukkit plugin integration public class MyPlugin extends JavaPlugin { @Override public void onEnable() { // Check for updates asynchronously getServer().getScheduler().runTaskAsynchronously(this, () -> { try { UpdateChecker checker = new ModrinthUpdateChecker(); Version current = new Version(getDescription().getVersion()); UpdateResult result = checker.check("my-plugin-slug", current); if (result.isUpdateAvailable()) { getLogger().info("Update available! " + result.latestVersion()); getLogger().info("Download: " + result.downloadUrl()); } } catch (Exception e) { getLogger().warning("Failed to check for updates: " + e.getMessage()); } }); } } ``` -------------------------------- ### Safely Get Random Element from Collection with RandomElementUtil Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The `RandomElementUtil` class provides a utility method to safely retrieve a random element from any Java `Collection`. It returns an `Optional` to handle cases where the collection might be empty, preventing `NullPointerException`s. ```java import com.eternalcode.commons.RandomElementUtil; import java.util.List; import java.util.Set; import java.util.Optional; List messages = List.of("Hello!", "Welcome!", "Hi there!", "Greetings!"); // Get random element (returns Optional) Optional randomMessage = RandomElementUtil.randomElement(messages); randomMessage.ifPresent(msg -> System.out.println("Random: " + msg)); // Handle empty collections safely List empty = List.of(); Optional noResult = RandomElementUtil.randomElement(empty); System.out.println(noResult.isPresent()); // false // Works with any Collection Set numbers = Set.of(1, 2, 3, 4, 5); Optional randomNum = RandomElementUtil.randomElement(numbers); int value = randomNum.orElse(0); // Use orElse for default value ``` -------------------------------- ### AdventureUtil: Work with Text Components (Java) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt AdventureUtil simplifies interactions with Kyori Adventure text components, including parsing legacy color codes and hex colors, resetting text decorations, and converting components to raw strings. Dependencies include Kyori Adventure library. ```java import com.eternalcode.commons.adventure.AdventureUtil; import net.kyori.adventure.text.Component; // Parse legacy color codes (&) to Component Component message = AdventureUtil.component("&aHello &bWorld!"); // Creates green "Hello " + aqua "World!" // Parse hex colors Component hex = AdventureUtil.component("&x&F&F&5&5&0&0Gradient text"); // Reset italic decoration (useful for item lore) Component lore = AdventureUtil.component("&7Item description"); Component resetLore = AdventureUtil.resetItalic(lore); // Prevents Minecraft's default italic on lore // Extract raw text from Component (strips formatting) Component formatted = AdventureUtil.component("&c&lBold Red Text"); String raw = AdventureUtil.componentToRawString(formatted); // Returns: "Bold Red Text" // Use section serializer for vanilla format String vanilla = AdventureUtil.SECTION_SERIALIZER.serialize(message); // Returns string with section symbols ``` -------------------------------- ### Semantic Version Comparison with Java Version Class Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt Demonstrates how to create and compare semantic version strings using the Version class. It covers basic comparison, handling prefixes and suffixes, checking for snapshot versions, and equality checks. This class is useful for managing software versions and update checks. ```java import com.eternalcode.commons.updater.Version; // Create versions Version v1 = new Version("1.0.0"); Version v2 = new Version("1.2.0"); Version v3 = new Version("2.0.0"); Version snapshot = new Version("1.3.0-SNAPSHOT"); // Compare versions System.out.println(v2.isNewerThan(v1)); // true System.out.println(v1.isNewerThan(v2)); // false System.out.println(v3.isNewerThan(v2)); // true // Using Comparable interface int comparison = v1.compareTo(v2); // negative: v1 < v2 // zero: v1 == v2 // positive: v1 > v2 // Handle prefixed versions Version prefixed = new Version("v1.5.0"); // 'v' prefix is stripped System.out.println(prefixed.isNewerThan(v2)); // true (1.5.0 > 1.2.0) // Handle suffix versions Version suffixed = new Version("1.2.0-beta"); // suffix stripped for comparison System.out.println(suffixed.compareTo(v2)); // 0 (equal: 1.2.0) // Check for snapshot System.out.println(snapshot.isSnapshot()); // true System.out.println(v1.isSnapshot()); // false // Equality Version v1Copy = new Version("1.0.0"); System.out.println(v1.equals(v1Copy)); // true System.out.println(v1.equals(new Version("1.0"))); // true (1.0 == 1.0.0) // String representation System.out.println(snapshot.toString()); // "1.3.0-SNAPSHOT" ``` -------------------------------- ### BukkitSchedulerImpl Task Scheduling with Java Duration - Java Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt Demonstrates how to use BukkitSchedulerImpl to schedule various types of tasks, including immediate, asynchronous, delayed, and repeating tasks, using Java Duration for time specifications. It also shows how to manage tasks by checking their status and canceling them. This API is useful for handling background operations and time-based events in Bukkit plugins. ```java import com.eternalcode.commons.bukkit.scheduler.BukkitSchedulerImpl; import com.eternalcode.commons.scheduler.Task; import org.bukkit.plugin.Plugin; import java.time.Duration; public class MyPlugin extends JavaPlugin { private BukkitSchedulerImpl scheduler; @Override public void onEnable() { this.scheduler = new BukkitSchedulerImpl(this); // Run task on main thread immediately scheduler.run(() -> { getLogger().info("Running on main thread!"); }); // Run task asynchronously scheduler.runAsync(() -> { // Database operations, HTTP requests, etc. loadDataFromDatabase(); }); // Run task after delay Task delayedTask = scheduler.runLater(() -> { getLogger().info("5 seconds have passed!"); }, Duration.ofSeconds(5)); // Run async task after delay scheduler.runLaterAsync(() -> { saveDataToDatabase(); }, Duration.ofMinutes(1)); // Create repeating timer Task repeatingTask = scheduler.timer(() -> { broadcastMessage("Server announcement!"); }, Duration.ofMinutes(5), Duration.ofMinutes(10)); // Start after 5min, repeat every 10min // Async repeating timer Task asyncTimer = scheduler.timerAsync(() -> { checkForUpdates(); }, Duration.ZERO, Duration.ofHours(1)); // Start immediately, repeat hourly // Complete a value on main thread scheduler.complete(() -> { return getServer().getOnlinePlayers().size(); }).thenAccept(count -> { getLogger().info("Online players: " + count); }); // Complete async and handle result scheduler.completeAsync(() -> fetchDataFromAPI()) .thenAccept(data -> { scheduler.run(() -> processDataOnMainThread(data)); }); // Task management System.out.println(delayedTask.isCanceled()); // false System.out.println(delayedTask.isAsync()); // false System.out.println(repeatingTask.isRepeating()); // true // Cancel a task repeatingTask.cancel(); System.out.println(repeatingTask.isCanceled()); // true } // Dummy methods for demonstration private void loadDataFromDatabase() {} private void saveDataToDatabase() {} private void broadcastMessage(String message) {} private void checkForUpdates() {} private String fetchDataFromAPI() { return ""; } private void processDataOnMainThread(String data) {} } ``` -------------------------------- ### Transform Adventure Components with Legacy Color and URL Processors (Java) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt This snippet demonstrates how to use Adventure post-processors to handle legacy color codes and make URLs clickable. It shows direct usage of processors and integration with MiniMessage for deserialization. Dependencies include Kyori Adventure and EternalCode Commons. ```java import com.eternalcode.commons.adventure.AdventureLegacyColorPostProcessor; import com.eternalcode.commons.adventure.AdventureLegacyColorPreProcessor; import com.eternalcode.commons.adventure.AdventureUrlPostProcessor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; // Pre-processor: Convert section symbols to ampersand AdventureLegacyColorPreProcessor preProcessor = new AdventureLegacyColorPreProcessor(); String converted = preProcessor.apply("Hello world!"); // Converts section to & // Post-processor: Parse legacy colors in existing components AdventureLegacyColorPostProcessor colorProcessor = new AdventureLegacyColorPostProcessor(); Component base = Component.text("&aGreen &cRed"); Component colored = colorProcessor.apply(base); // Parses legacy codes // URL post-processor: Make URLs clickable AdventureUrlPostProcessor urlProcessor = new AdventureUrlPostProcessor(); Component withUrl = Component.text("Visit https://example.com for more info!"); Component clickableUrl = urlProcessor.apply(withUrl); // URLs are now clickable (opens in browser) // Use with MiniMessage MiniMessage miniMessage = MiniMessage.builder() .preProcessor(preProcessor) // Handle section symbols in input .postProcessor(colorProcessor) // Handle legacy codes after MiniMessage .postProcessor(urlProcessor) // Make URLs clickable .build(); Component result = miniMessage.deserialize("&aClick https://example.com here!"); // Creates: Green "Click " + clickable URL + " here!" // Use URL config directly Component manualUrl = Component.text("Link: https://github.com/EternalCodeTeam") .replaceText(AdventureUrlPostProcessor.CLICKABLE_URL_CONFIG); ``` -------------------------------- ### Batch Processing with BatchProcessor in Java Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The BatchProcessor class allows for efficient processing of large collections by dividing them into smaller, manageable batches. This is useful for preventing timeouts and distributing workload. It provides methods to control batch size, track progress, and reset the processing state. ```java import com.eternalcode.commons.algorithm.BatchProcessor; import java.util.List; import java.util.ArrayList; List players = List.of("Player1", "Player2", "Player3", "Player4", "Player5", "Player6", "Player7", "Player8", "Player9", "Player10"); // Create processor with batch size of 3 BatchProcessor processor = new BatchProcessor<>(players, 3); // Process batches until complete while (!processor.isComplete()) { boolean hasMore = processor.processNext(player -> { System.out.println("Processing: " + player); // Send message, save data, etc. }); System.out.println("More batches remaining: " + hasMore); } // Output: Processes 3 players at a time (3, 3, 3, 1) // Track progress BatchProcessor numbered = new BatchProcessor<>(List.of(1,2,3,4,5,6,7,8,9,10), 4); System.out.println("Total: " + numbered.getTotalSize()); // 10 System.out.println("Batch size: " + numbered.getBatchSize()); // 4 System.out.println("Total batches: " + numbered.getTotalBatchCount()); // 3 numbered.processNext(n -> {}); // Process first batch System.out.println("Progress: " + (numbered.getProgress() * 100) + "%"); // 40.0% System.out.println("Remaining: " + numbered.getRemainingCount()); // 6 System.out.println("Processed batches: " + numbered.getProcessedBatchCount()); // 1 // Reset to start over numbered.reset(); System.out.println("Position after reset: " + numbered.getPosition()); // 0 ``` -------------------------------- ### Add EternalCode Commons Dependencies (Kotlin) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt Configures Gradle build scripts to include EternalCode Commons modules from the EternalCode Maven repository. Supports release and snapshot versions. Requires Java 17+. ```kotlin repositories { maven("https://repo.eternalcode.pl/releases") // For snapshot versions: maven("https://repo.eternalcode.pl/snapshots") } dependencies { // Core utilities (no external dependencies) implementation("com.eternalcode:eternalcode-commons-shared:1.3.3-SNAPSHOT") // Bukkit integration (requires Spigot API) implementation("com.eternalcode:eternalcode-commons-bukkit:1.3.3-SNAPSHOT") // Folia support (requires Folia API) implementation("com.eternalcode:eternalcode-commons-folia:1.3.3-SNAPSHOT") // Adventure text utilities (includes Adventure dependencies) implementation("com.eternalcode:eternalcode-commons-adventure:1.3.3-SNAPSHOT") // Update checker (includes Gson) implementation("com.eternalcode:eternalcode-commons-updater:1.3.3-SNAPSHOT") } ``` -------------------------------- ### ItemUtil: Manage Player Inventory Items (Java) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The ItemUtil class provides methods for safely adding and removing items from a player's inventory. It handles cases where the inventory might be full by dropping excess items. Dependencies include Bukkit API. ```java import com.eternalcode.commons.bukkit.ItemUtil; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; // Remove items from player inventory Player player = event.getPlayer(); ItemUtil.removeItem(player, Material.DIAMOND, 5); // Remove up to 5 diamonds // Give items safely (drops if inventory full) ItemStack reward = new ItemStack(Material.GOLDEN_APPLE, 3); ItemUtil.giveItem(player, reward); // If inventory has space: adds to inventory // If inventory is full: drops at player's location // Example usage in shop plugin public void purchaseItem(Player buyer, Material currency, int cost, ItemStack product) { // Remove payment ItemUtil.removeItem(buyer, currency, cost); // Give product (safely handles full inventory) ItemUtil.giveItem(buyer, product); } ``` -------------------------------- ### FoliaSchedulerImpl: Region-Based Task Scheduling in Java Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The FoliaSchedulerImpl allows scheduling tasks within specific regions of a Folia server, tied to locations or entities. It ensures tasks run on the correct thread, preventing concurrency issues and memory leaks associated with Bukkit's global scheduler. Dependencies include Folia and Bukkit APIs. ```java import com.eternalcode.commons.folia.scheduler.FoliaSchedulerImpl; import com.eternalcode.commons.bukkit.scheduler.MinecraftScheduler; import com.eternalcode.commons.scheduler.Task; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import java.time.Duration; public class FoliaPlugin extends JavaPlugin { private MinecraftScheduler scheduler; @Override public void onEnable() { this.scheduler = new FoliaSchedulerImpl(this); // Check thread context if (scheduler.isGlobalTickThread()) { // Running on global tick thread } // Run on global region scheduler scheduler.run(() -> { getLogger().info("Global region task"); }); // Run in specific location's region Location spawnLoc = getServer().getWorlds().get(0).getSpawnLocation(); scheduler.run(spawnLoc, () -> { // This runs in the region owning spawnLoc spawnLoc.getWorld().spawnParticle(Particle.FLAME, spawnLoc, 10); }); // Run for specific entity for (Player player : getServer().getOnlinePlayers()) { scheduler.run(player, () -> { // This runs in the region owning the player player.sendMessage("Hello from your region!"); }); } // Delayed task in location's region scheduler.runLater(spawnLoc, () -> { // Executes in spawn region after 5 seconds }, Duration.ofSeconds(5)); // Repeating timer for entity Entity entity = spawnLoc.getWorld().getEntities().get(0); Task entityTimer = scheduler.timer(entity, () -> { // Updates entity every second in its region entity.setGlowing(true); }, Duration.ZERO, Duration.ofSeconds(1)); // Complete value in entity's region scheduler.complete(entity, () -> { return entity.getLocation(); }).thenAccept(loc -> { getLogger().info("Entity at: " + loc); }); // Check if current thread owns entity/location if (scheduler.isRegionThread(entity)) { // Safe to modify entity directly } if (scheduler.isRegionThread(spawnLoc)) { // Safe to modify blocks at location } } } ``` -------------------------------- ### Customizable Text Progress Bars with ProgressBar in Java Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The ProgressBar class enables the creation of customizable ASCII progress bars for visual feedback on task completion. It supports configuration of length, fill/empty characters, brackets, and colors, making it adaptable for various console applications. ```java import com.eternalcode.commons.progressbar.ProgressBar; // Create basic progress bar ProgressBar bar = ProgressBar.builder() .length(20) .build(); // Render with progress (0.0 to 1.0) System.out.println(bar.render(0.0)); // [░░░░░░░░░░░░░░░░░░░░] System.out.println(bar.render(0.5)); // [██████████░░░░░░░░░░] System.out.println(bar.render(1.0)); // [████████████████████] // Render with current/max values System.out.println(bar.render(25, 100)); // [█████░░░░░░░░░░░░░░░] System.out.println(bar.render(75, 100)); // [███████████████░░░░░] // Customized progress bar ProgressBar custom = ProgressBar.builder() .length(15) .filledChar("=") .emptyChar("-") .brackets("<", ">") .build(); System.out.println(custom.render(0.6)); // <=========>--------> // With Minecraft color codes (for chat messages) ProgressBar colored = ProgressBar.builder() .length(10) .filledChar("|") .emptyChar("|") .filledColor("&a") // Green for filled .emptyColor("&7") // Gray for empty .bracketColor("&f") // White brackets .build(); String progress = colored.render(0.7); // &f[&a|||||||&7|||&f] // Without brackets ProgressBar noBrackets = ProgressBar.builder() .length(10) .hideBrackets() .build(); System.out.println(noBrackets.render(0.5)); // █████░░░░░ ``` -------------------------------- ### Convert Java Duration to Minecraft Ticks with DurationTickUtil Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The `DurationTickUtil` class converts Java `Duration` objects into Minecraft server ticks. One Minecraft tick is equivalent to 50 milliseconds (20 ticks per second). This utility is useful for scheduling tasks in Minecraft plugins. ```java import com.eternalcode.commons.time.DurationTickUtil; import java.time.Duration; // Convert Duration to ticks (1 tick = 50ms) int oneSecond = DurationTickUtil.durationToTicks(Duration.ofSeconds(1)); // 20 int fiveSeconds = DurationTickUtil.durationToTicks(Duration.ofSeconds(5)); // 100 int halfSecond = DurationTickUtil.durationToTicks(Duration.ofMillis(500)); // 10 int tenMinutes = DurationTickUtil.durationToTicks(Duration.ofMinutes(10)); // 12000 // Use with Bukkit scheduler // scheduler.runTaskLater(plugin, task, DurationTickUtil.durationToTicks(Duration.ofSeconds(5))); ``` -------------------------------- ### Thread-Safe Lazy Initialization with Lazy Class Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The `Lazy` class implements thread-safe lazy initialization. It defers the computation of an expensive object until it's first accessed, caching the result for subsequent calls. This improves performance by avoiding unnecessary computations. ```java import com.eternalcode.commons.Lazy; import java.util.function.Supplier; // Create lazy value with supplier Lazy lazyConnection = new Lazy<>(() -> { System.out.println("Initializing connection..."); return new DatabaseConnection("localhost:5432"); }); // Value is not computed yet System.out.println(lazyConnection.isInitialized()); // false // First access triggers computation DatabaseConnection conn = lazyConnection.get(); // Prints "Initializing connection..." System.out.println(lazyConnection.isInitialized()); // true // Subsequent accesses return cached value DatabaseConnection same = lazyConnection.get(); // No print, returns cached value // Create lazy value with immediate initialization Lazy immediate = new Lazy<>("pre-computed value"); System.out.println(immediate.isInitialized()); // true // Wrap Runnable for lazy execution Lazy lazyTask = Lazy.ofRunnable(() -> { System.out.println("Task executed!"); }); lazyTask.get(); // Prints "Task executed!" (only once) // Handle initialization failures Lazy failing = new Lazy<>(() -> { throw new RuntimeException("Init failed"); }); try { failing.get(); } catch (RuntimeException e) { System.out.println(failing.hasFailed()); // true } ``` -------------------------------- ### Position and PositionAdapter: Memory-Safe Location Storage in Java Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The Position record and PositionAdapter class provide a way to store Bukkit Location data without holding direct World references, thus preventing memory leaks. This is ideal for saving locations to configurations or databases. They handle conversion to and from Bukkit's Location object. ```java import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.commons.bukkit.position.PositionAdapter; import org.bukkit.Location; import org.bukkit.entity.Player; // Create Position from coordinates Position spawn = new Position(100.5, 64.0, -200.5, 90.0f, 0.0f, "world"); Position simple = new Position(0.0, 100.0, 0.0, "world_nether"); // No yaw/pitch Position flat = new Position(50.0, 75.0, "world_the_end"); // Only x, z // Convert Bukkit Location to Position (safe for storage) Player player = event.getPlayer(); Location playerLoc = player.getLocation(); Position savedPosition = PositionAdapter.convert(playerLoc); // Store in config, database, etc. String serialized = savedPosition.toString(); // "Position{x=100.5, y=64.0, z=-200.5, yaw=90.0, pitch=0.0, world='world'}" // Parse back from string Position parsed = Position.parse(serialized); // Convert Position back to Location when needed Location bukkitLoc = PositionAdapter.convert(savedPosition); player.teleport(bukkitLoc); // Access Position data double x = spawn.x(); double y = spawn.y(); double z = spawn.z(); float yaw = spawn.yaw(); float pitch = spawn.pitch(); String worldName = spawn.world(); // Check for unset world Position noWorld = new Position(0, 0, 0, Position.NONE_WORLD); if (noWorld.isNoneWorld()) { System.out.println("World not set"); } ``` -------------------------------- ### Parse Human-Readable Time Strings to Duration (Java) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt Utilizes DurationParser to convert human-readable time strings (e.g., '5m', '1d2h30m') into Java Duration objects. Supports various time units, negative durations, and custom parsing configurations. Includes formatting Duration back to strings. ```java import com.eternalcode.commons.time.DurationParser; import com.eternalcode.commons.time.TemporalAmountParser; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.math.RoundingMode; // Use pre-configured parsers for common use cases TemporalAmountParser parser = DurationParser.DATE_TIME_UNITS; // Parse time strings to Duration Duration fiveMinutes = parser.parse("5m"); // PT5M Duration complex = parser.parse("1d2h30m15s"); // PT26H30M15S Duration withMillis = parser.parse("500ms"); // PT0.5S Duration negative = parser.parse("-1h30m"); // PT-1H-30M // Format Duration back to string String formatted = parser.format(Duration.ofSeconds(90)); // "1m30s" String days = parser.format(Duration.ofHours(25)); // "1d1h" String negFmt = parser.format(Duration.ofMinutes(-90)); // "-1h30m" // Use TIME_UNITS for time-only parsing (ms, s, m, h) TemporalAmountParser timeOnly = DurationParser.TIME_UNITS; Duration hourOnly = timeOnly.parse("2h30m"); // Works // timeOnly.parse("1d"); // Throws IllegalArgumentException - 'd' not configured // Create custom parser with specific units TemporalAmountParser custom = new DurationParser() .withUnit("sec", ChronoUnit.SECONDS) .withUnit("min", ChronoUnit.MINUTES) .withUnit("hr", ChronoUnit.HOURS); Duration customParsed = custom.parse("2hr30min"); // PT2H30M // Add rounding for formatting output TemporalAmountParser rounded = new DurationParser() .withUnit("s", ChronoUnit.SECONDS) .withUnit("m", ChronoUnit.MINUTES) .withRounded(ChronoUnit.SECONDS, RoundingMode.UP); Duration withMilliseconds = Duration.ofSeconds(90).plusMillis(500); String roundedFormat = rounded.format(withMilliseconds); // "1m31s" (rounded up) ``` -------------------------------- ### Asynchronous Result Handling with FutureHandler in Java Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt FutureHandler simplifies the management of CompletableFuture results, including automatic logging of exceptions. It can be used with `whenComplete` for general handling or as a static method for `exceptionally` chains, ensuring robust asynchronous operation management. ```java import com.eternalcode.commons.concurrent.FutureHandler; import java.util.concurrent.CompletableFuture; // Create handler for successful results FutureHandler handler = FutureHandler.whenSuccess(result -> { System.out.println("Got result: " + result); }); // Use with CompletableFuture.whenComplete() CompletableFuture.supplyAsync(() -> "Hello, World!") .whenComplete(handler); // Output: "Got result: Hello, World!" // Exceptions are automatically logged CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Something went wrong"); return "Never reached"; }).whenComplete(handler); // Logs: SEVERE: Caught an exception in future execution: Something went wrong // Static exception handler for exceptionally() chains CompletableFuture future = CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Database error"); return "data"; }).exceptionally(FutureHandler::handleException); // Logs exception and returns null ``` -------------------------------- ### Use Exception-Throwing Functions in Streams with ThrowingFunction Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt The `ThrowingFunction` interface allows the use of lambda expressions or method references that throw checked exceptions within Java Streams and other functional programming constructs. It provides a way to convert these throwing functions into standard `Function` interfaces with error handling. ```java import com.eternalcode.commons.ThrowingFunction; import java.util.List; import java.util.function.Function; import java.io.IOException; // Define a function that throws checked exceptions ThrowingFunction parseFile = (path) -> { // Simulated file parsing that might throw IOException if (path.isEmpty()) { throw new IOException("Empty path"); } return path.length(); }; // Convert to standard Function with exception handling Function safeParser = ThrowingFunction.asFunction( parseFile, exception -> { System.err.println("Error: " + exception.getMessage()); return -1; // Default value on error } ); // Use in streams List paths = List.of("file1.txt", "", "file2.txt"); List results = paths.stream() .map(safeParser) .toList(); // Results: [9, -1, 9] - empty path returns -1 // Identity function ThrowingFunction identity = ThrowingFunction.identity(); String same = identity.apply("test"); // "test" ``` -------------------------------- ### Parse Date-Based Durations to Period (Java) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt Employs PeriodParser to convert date-based time strings (e.g., '1w', '1mo', '1y') into Java Period objects. Supports parsing and formatting of periods, including complex combinations. ```java import com.eternalcode.commons.time.PeriodParser; import com.eternalcode.commons.time.TemporalAmountParser; import java.time.Period; // Use pre-configured date units parser TemporalAmountParser parser = PeriodParser.DATE_UNITS; // Parse period strings Period oneWeek = parser.parse("1w"); // P7D Period oneMonth = parser.parse("1mo"); // P1M Period oneYear = parser.parse("1y"); // P1Y Period complex = parser.parse("1y2mo1w"); // P1Y2M7D // Format Period back to string String formatted = parser.format(Period.ofDays(14)); // "2w" String months = parser.format(Period.ofMonths(3)); // "3mo" ``` -------------------------------- ### OnlinePlayersRunnable: Iterate Online Players Safely (Java) Source: https://context7.com/eternalcodeteam/eternalcodecommons/llms.txt OnlinePlayersRunnable offers a safe way to iterate over all online players, with built-in exception handling for individual player processing. It can be used directly or extended for custom logic. Requires Bukkit API. ```java import com.eternalcode.commons.bukkit.runnable.OnlinePlayersRunnable; import org.bukkit.entity.Player; // Create runnable using Consumer Runnable broadcastRunnable = OnlinePlayersRunnable.asRunnable(player -> { player.sendMessage("Server restarting in 5 minutes!"); }); // Use with Bukkit scheduler getServer().getScheduler().runTask(this, broadcastRunnable); // Extend for custom behavior with exception handling OnlinePlayersRunnable customRunnable = new OnlinePlayersRunnable() { @Override public void runFor(Player player) { // Process each player player.setHealth(player.getMaxHealth()); player.setFoodLevel(20); player.sendMessage("You have been healed!"); } @Override protected void handlePlayerException(Player player, Exception exception) { // Custom exception handling getLogger().warning("Failed to heal " + player.getName() + ": " + exception.getMessage()); } }; // Schedule as repeating task getServer().getScheduler().runTaskTimer(this, customRunnable, 0L, 20L * 60); // Every minute // Create using static factory OnlinePlayersRunnable scoreboard = OnlinePlayersRunnable.consuming(player -> { updatePlayerScoreboard(player); }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.