Utilities - litjisz/Astra GitHub Wiki

Utilities

The Astra framework provides several utility classes to help with common tasks in plugin development. These utilities make it easier to work with text formatting, logging, and more.

Text Utility

The Text class provides methods for formatting and colorizing text in Minecraft.

import lol.jisz.astra.utils.Text;

Text Colorization

// Colorize text using Minecraft color codes
String coloredText = Text.colorize("&aThis text is green &cand this is red");

// Colorize a list of strings
List<String> coloredLines = Text.colorize(Arrays.asList(
    "&aThis is green",
    "&bThis is aqua"
));

Gradient Text

// Create text with a color gradient
String gradientText = Text.gradient("Astra Framework", "9863E7", "C69FFF");

Example Usage

// Example from AstraCommand
private void sendGithubMessage(CommandSender sender) {
    List<String> githubMessages = Arrays.asList(
            Text.colorize(" "),
            Text.gradient("☽ Astra", "9863E7", "C69FFF") +
            Text.colorize(" &8| &fFramwork built with &c❤ &fby &aAstra Team"),
            Text.colorize(" "),
            Text.colorize("&8 ⏩ &fRepository: &bhttps://github.com/litjisz/Astra"),
            Text.colorize("&8 ⚠ &fReport issues: &chttps://github.com/litjisz/Astra/issues"),
            Text.colorize("&8 ✎ &fWiki: &dhttps://github.com/litjisz/Astra/wiki"),
            Text.colorize(" ")
    );

    githubMessages.forEach(sender::sendMessage);
}

Logger Utility

The Logger class provides enhanced logging capabilities with color support and different log levels.

import lol.jisz.astra.utils.Logger;

Creating a Logger

// Create a logger with the plugin instance
Logger logger = new Logger(plugin);

// Create a logger with a custom prefix
Logger logger = new Logger(plugin, Text.gradient("AstraTask", "9863E7", "C69FFF") + " &8| &r");

Logging Messages

// Log at different levels
logger.info("This is an info message");
logger.warning("This is a warning message");
logger.error("This is an error message");
logger.debug("This is a debug message");

// Log an error with an exception
try {
    // Some code that might throw an exception
} catch (Exception e) {
    logger.error("An error occurred", e);
}

Example Usage

// Example from TaskManager
logger.info("Task system initialized with limit of " + maxConcurrentAsyncTasks + " concurrent async tasks");
logger.debug("Task " + task.getId() + " added to queue with priority " + task.getPriority());
logger.error("Task " + task.getId() + " failed with error: " + throwable.getMessage(), throwable);

ConfigManager Utility

The ConfigManager class provides methods for managing YAML configuration files.

import lol.jisz.astra.utils.ConfigManager;

Loading Configurations

// Load a configuration file (creates it if it doesn't exist)
FileConfiguration config = configManager.loadConfig("settings");

// Load without creating if it doesn't exist
FileConfiguration config = configManager.loadConfig("settings", false);

Getting and Setting Values

// Get values with defaults
String serverName = configManager.getString("config", "server.name", "My Server");
int maxPlayers = configManager.getInt("config", "server.max-players", 20);
double moneyMultiplier = configManager.getDouble("config", "economy.multiplier", 1.0);
Boolean enableFeature = configManager.get("config", "features.new-feature", false);

// Set values
configManager.set("config", "server.name", "New Server Name");

Working with Sections

// Create a configuration section
ConfigurationSection section = configManager.createSection("config", "new-feature");

// Get keys from a configuration
Set<String> topLevelKeys = configManager.getKeys("config");
Set<String> featureKeys = configManager.getKeys("config", "features", true);

Managing Configuration Files

// Check if a configuration exists
boolean exists = configManager.exists("settings");

// Save a configuration
configManager.saveConfig("settings");

// Reload a configuration
configManager.reloadConfig("settings");

// Delete a configuration
configManager.deleteConfig("temporary");

// Save all configurations
configManager.saveAllConfigs();

// Reload all configurations
configManager.reloadAllConfigs();

Getting Lists

// Get a string list
List<String> allowedCommands = configManager.getStringList("config", "commands.allowed");

Accessing Utilities in Modules

In an AbstractModule, you can access these utilities directly:

public class MyModule extends AbstractModule {
    @Override
    public void enable() {
        // Access the logger
        getLogger().info("Module enabled");
        
        // Access the config manager
        ConfigManager configManager = getConfig();
        String value = configManager.getString("config", "my.setting", "default");
    }
}

Class Scanner

The ClassScanner is a powerful utility in the Astra framework that automatically discovers and registers classes with specific annotations. This eliminates the need for manual registration of modules, commands, listeners, and tasks.

Overview

The ClassScanner uses the Reflections library to scan packages for classes with specific annotations and automatically registers them with the appropriate systems. This reduces boilerplate code and makes your plugin more maintainable.

Basic Usage

Creating a ClassScanner

// The ClassScanner is typically created in the Astra plugin's initialization
ClassScanner classScanner = new ClassScanner(plugin);

Scanning Packages

// Scan a specific package for annotated classes
classScanner.scanPackage("com.example.myplugin");

// In your main plugin class, you can scan your plugin's package
scanPackage(getClass().getPackage().getName());

What Gets Scanned

The ClassScanner looks for classes with the following annotations:

  1. @AutoRegisterModule - For automatic module registration
  2. @AutoRegisterCommand - For automatic command registration
  3. @AutoRegisterListener - For automatic event listener registration
  4. @AutoRegisterTask - For automatic task registration

Module Registration

@AutoRegisterModule(priority = 10)
public class MyModule extends AbstractModule {
    // Module implementation
}

The ClassScanner will:

  1. Find all classes annotated with @AutoRegisterModule
  2. Filter for classes that extend Module and are not interfaces or abstract
  3. Sort them by priority (higher numbers = higher priority)
  4. Instantiate each module using either:
    • A constructor that takes an Astra parameter
    • A default no-args constructor
  5. Register the module with the Implements system

Command Registration

@AutoRegisterCommand(
    name = "mycommand",
    permission = "myplugin.command.mycommand",
    playerOnly = false,
    aliases = {"mc", "mycmd"}
)
public class MyCommand extends CommandBase {
    // Command implementation
}

The ClassScanner will:

  1. Find all classes annotated with @AutoRegisterCommand
  2. Filter for classes that extend CommandBase and are not interfaces or abstract
  3. Extract command information from the annotation
  4. Instantiate each command using either:
    • A constructor that takes an Astra parameter
    • A default no-args constructor
    • A constructor that takes name, permission, playerOnly, and aliases parameters
  5. Register the command with the plugin's CommandManager

Listener Registration

@AutoRegisterListener(priority = 5)
public class MyListener implements Listener {
    // Event handlers
}

The ClassScanner will:

  1. Find all classes annotated with @AutoRegisterListener
  2. Filter for classes that implement Listener and are not interfaces or abstract
  3. Sort them by priority (higher numbers = higher priority)
  4. Instantiate each listener using either:
    • A constructor that takes an Astra parameter
    • A default no-args constructor
  5. Register the listener with Bukkit's event system

Task Registration

@AutoRegisterTask(
    id = "my-task",
    async = true,
    executeOnStartup = true,
    delay = 20,
    period = 100,
    priority = TaskPriority.HIGH
)
public class MyTask extends AsyncAstraTask {
    // Task implementation
}

The ClassScanner will:

  1. Find all classes annotated with @AutoRegisterTask
  2. Filter for non-interface, non-abstract classes
  3. Extract task information from the annotation
  4. Instantiate each task using either:
    • A constructor that takes an Astra parameter
    • A default no-args constructor
  5. Configure the task based on annotation parameters
  6. If executeOnStartup is true:
    • For repeating tasks (period > 0), schedule as repeating
    • For delayed tasks (delay > 0), schedule as delayed
    • For immediate tasks, execute immediately

Implementation Details

The ClassScanner uses the Reflections library to efficiently scan for annotated classes:

Reflections reflections = new Reflections(packageName, Scanners.TypesAnnotated, Scanners.SubTypes);

It handles errors gracefully, logging any issues that occur during scanning or registration:

try {
    // Registration code
} catch (Exception e) {
    plugin.logger().error("Could not register the module: " + clazz.getName(), e);
}

Benefits

  1. Reduced Boilerplate: No need to manually register each module, command, listener, or task
  2. Automatic Dependency Management: Modules are registered in the correct order based on priority
  3. Simplified Development: Just add annotations to your classes and they'll be registered automatically
  4. Improved Maintainability: Registration logic is centralized in the ClassScanner
  5. Flexible Configuration: Annotations provide fine-grained control over how classes are registered

By using the ClassScanner, you can focus on implementing your plugin's functionality rather than writing registration code, making your development process more efficient and your code more maintainable.

⚠️ **GitHub.com Fallback** ⚠️