Skip to main content

Overview

Modules are the official extension system for SuperiorSkyblock2. Unlike regular Bukkit plugins, modules are loaded and managed by SuperiorSkyblock itself, providing tighter integration and hot-reload capabilities.

Why Use Modules?

Hot Reload

Enable, disable, and reload modules without restarting the server.

Managed Lifecycle

SuperiorSkyblock handles listener and command registration automatically.

Integrated API

Direct access to SuperiorSkyblock’s internal systems and data.

Organized Structure

Dedicated folders for module code and data storage.

Module vs Plugin

  • Loaded by SuperiorSkyblock
  • Can be reloaded without server restart
  • Automatic listener/command management
  • Direct API access
  • Managed through /is admin modules

Creating a Module

Basic Structure

import com.bgsoftware.superiorskyblock.api.SuperiorSkyblock;
import com.bgsoftware.superiorskyblock.api.modules.PluginModule;
import com.bgsoftware.superiorskyblock.api.commands.SuperiorCommand;
import org.bukkit.event.Listener;

public class MyModule extends PluginModule {
    
    public MyModule() {
        super("MyModule", "AuthorName");
    }
    
    @Override
    public void onEnable(SuperiorSkyblock plugin) {
        // Module initialization
        getLogger().info("Module enabled!");
    }
    
    @Override
    public void onReload(SuperiorSkyblock plugin) {
        // Reload configuration/data
        getLogger().info("Module reloaded!");
    }
    
    @Override
    public void onDisable(SuperiorSkyblock plugin) {
        // Cleanup resources
        getLogger().info("Module disabled!");
    }
    
    @Override
    public Listener[] getModuleListeners(SuperiorSkyblock plugin) {
        // Return event listeners
        return new Listener[] {
            new MyListener()
        };
    }
    
    @Override
    public SuperiorCommand[] getSuperiorCommands(SuperiorSkyblock plugin) {
        // Return player commands
        return new SuperiorCommand[] {
            new MyCommand()
        };
    }
    
    @Override
    public SuperiorCommand[] getSuperiorAdminCommands(SuperiorSkyblock plugin) {
        // Return admin commands
        return null; // or return admin commands
    }
}

Module Properties

// Get module name
String getName();

// Get module author  
String getAuthor();

Module Lifecycle

Load Stages

Modules can specify when they should be loaded:
@Override
public ModuleLoadTime getLoadTime() {
    return ModuleLoadTime.NORMAL;
}
1

BEFORE_WORLD_CREATION

Loaded before worlds are created. Use if you need to override the WorldsProvider.

NORMAL

Default loading stage. Most modules should use this.

AFTER_HANDLERS_LOADING

Loaded after all plugin handlers are ready. Use if interacting with handlers in onEnable().

Lifecycle Methods

@Override
public void onEnable(SuperiorSkyblock plugin) {
    // Module initialization
    // Register custom handlers
    // Load configuration
    // Initialize data structures
}
Called when the module is loaded/enabled.

Event Listeners

Modules return event listeners that are automatically managed:
@Override
public Listener[] getModuleListeners(SuperiorSkyblock plugin) {
    return new Listener[] {
        new IslandListener(this),
        new PlayerListener(this),
        new CustomEventListener(this)
    };
}
Listeners are automatically registered when the module enables and unregistered when it disables.

Example Listener

public class IslandListener implements Listener {
    private final MyModule module;
    
    public IslandListener(MyModule module) {
        this.module = module;
    }
    
    @EventHandler
    public void onIslandCreate(IslandCreateEvent event) {
        Island island = event.getIsland();
        SuperiorPlayer player = event.getPlayer();
        
        module.getLogger().info(
            player.getName() + " created island " + island.getUniqueId()
        );
    }
}

Commands

Modules can provide both player and admin commands:

Player Commands

@Override
public SuperiorCommand[] getSuperiorCommands(SuperiorSkyblock plugin) {
    return new SuperiorCommand[] {
        new InfoCommand(),
        new ListCommand()
    };
}

Admin Commands

@Override
public SuperiorCommand[] getSuperiorAdminCommands(SuperiorSkyblock plugin) {
    return new SuperiorCommand[] {
        new GiveCommand(),
        new SetCommand()
    };
}
Return null if your module doesn’t provide commands of that type.

File Management

Module Folders

// plugins/SuperiorSkyblock2/modules/{module-name}/
File moduleFolder = getModuleFolder();

// Store configuration files, resources
File config = new File(moduleFolder, "config.yml");

Resource Management

// Save embedded resource from jar
saveResource("config.yml");
saveResource("lang/en-US.yml");

// Read resource from jar
InputStream stream = getResource("defaults.yml");

Configuration Example

public class MyModule extends PluginModule {
    private FileConfiguration config;
    
    @Override
    public void onEnable(SuperiorSkyblock plugin) {
        // Save default config if not exists
        File configFile = new File(getModuleFolder(), "config.yml");
        if (!configFile.exists()) {
            saveResource("config.yml");
        }
        
        // Load config
        config = YamlConfiguration.loadConfiguration(configFile);
        
        getLogger().info("Loaded configuration!");
    }
    
    @Override
    public void onReload(SuperiorSkyblock plugin) {
        // Reload config
        File configFile = new File(getModuleFolder(), "config.yml");
        config = YamlConfiguration.loadConfiguration(configFile);
        
        getLogger().info("Reloaded configuration!");
    }
    
    public FileConfiguration getConfig() {
        return config;
    }
}

Accessing SuperiorSkyblock API

Modules have direct access to the SuperiorSkyblock API:
@Override
public void onEnable(SuperiorSkyblock plugin) {
    // Get managers
    GridManager gridManager = plugin.getGrid();
    PlayersManager playersManager = plugin.getPlayers();
    
    // Access islands
    for (Island island : gridManager.getIslands()) {
        getLogger().info("Island: " + island.getName());
    }
    
    // Access players
    for (SuperiorPlayer player : playersManager.getAllPlayers()) {
        getLogger().info("Player: " + player.getName());
    }
}

Module Logger

// Get module-specific logger
Logger logger = getLogger();

logger.info("Information message");
logger.warning("Warning message");
logger.severe("Error message");
Log messages are prefixed with [SuperiorSkyblock2] [ModuleName].

Advanced: Module Initialization

These methods are for advanced usage. SuperiorSkyblock calls them automatically.
// Initialize module (called by SuperiorSkyblock)
void initModule(SuperiorSkyblock plugin, ModuleInitializeData context);

// Initialize loader settings
void initModuleLoader(File moduleFile, ClassLoader classLoader);

// Disable module
void disableModule();

Complete Module Example

public class RewardsModule extends PluginModule {
    private FileConfiguration config;
    private Map<UUID, Integer> dailyRewards = new HashMap<>();
    
    public RewardsModule() {
        super("DailyRewards", "YourName");
    }
    
    @Override
    public void onEnable(SuperiorSkyblock plugin) {
        // Load config
        File configFile = new File(getModuleFolder(), "config.yml");
        if (!configFile.exists()) {
            saveResource("config.yml");
        }
        config = YamlConfiguration.loadConfiguration(configFile);
        
        // Load data
        loadRewardsData();
        
        // Start daily reset task
        startResetTask(plugin);
        
        getLogger().info("Daily rewards module enabled!");
    }
    
    @Override
    public void onReload(SuperiorSkyblock plugin) {
        File configFile = new File(getModuleFolder(), "config.yml");
        config = YamlConfiguration.loadConfiguration(configFile);
        getLogger().info("Configuration reloaded!");
    }
    
    @Override
    public void onDisable(SuperiorSkyblock plugin) {
        // Save data
        saveRewardsData();
        getLogger().info("Daily rewards module disabled!");
    }
    
    @Override
    public void loadData(SuperiorSkyblock plugin) {
        // Load player-specific reward data
        loadRewardsData();
    }
    
    @Override
    public Listener[] getModuleListeners(SuperiorSkyblock plugin) {
        return new Listener[] {
            new RewardListener(this)
        };
    }
    
    @Override
    public SuperiorCommand[] getSuperiorCommands(SuperiorSkyblock plugin) {
        return new SuperiorCommand[] {
            new DailyCommand(this)
        };
    }
    
    @Override
    public SuperiorCommand[] getSuperiorAdminCommands(SuperiorSkyblock plugin) {
        return new SuperiorCommand[] {
            new ResetCommand(this)
        };
    }
    
    private void loadRewardsData() {
        File dataFile = new File(getDataStoreFolder(), "rewards.yml");
        if (dataFile.exists()) {
            FileConfiguration data = YamlConfiguration.loadConfiguration(dataFile);
            for (String key : data.getKeys(false)) {
                UUID uuid = UUID.fromString(key);
                int count = data.getInt(key);
                dailyRewards.put(uuid, count);
            }
        }
    }
    
    private void saveRewardsData() {
        File dataFile = new File(getDataStoreFolder(), "rewards.yml");
        FileConfiguration data = new YamlConfiguration();
        for (Map.Entry<UUID, Integer> entry : dailyRewards.entrySet()) {
            data.set(entry.getKey().toString(), entry.getValue());
        }
        try {
            data.save(dataFile);
        } catch (IOException e) {
            getLogger().severe("Failed to save rewards data!");
        }
    }
    
    private void startResetTask(SuperiorSkyblock plugin) {
        // Reset daily rewards at midnight
        // Implementation details...
    }
    
    public int getRewardCount(UUID player) {
        return dailyRewards.getOrDefault(player, 0);
    }
    
    public void incrementReward(UUID player) {
        dailyRewards.put(player, getRewardCount(player) + 1);
    }
}

Module Commands Management

Commands are managed through /is admin modules:
/is admin modules list          - List all modules
/is admin modules load <name>   - Load a module
/is admin modules unload <name> - Unload a module  
/is admin modules reload <name> - Reload a module

Best Practices

Save on Disable

Always save data in onDisable() to prevent data loss.

Handle Reload

Implement onReload() properly to support runtime changes.

Use Separate Data Folder

Store databases in getDataStoreFolder(), not getModuleFolder().

Check Initialization

Use isInitialized() before accessing module resources.

Return Null for No Commands

If your module has no commands, return null instead of empty array.

Log Important Events

Use getLogger() to log initialization, errors, and important events.

Packaging a Module

1

Create module.yml

name: MyModule
main: com.example.MyModule
version: 1.0.0
author: YourName
2

Build JAR file

Compile your module into a JAR with dependencies.
3

Place in modules folder

Put the JAR in plugins/SuperiorSkyblock2/modules/
4

Load module

Use /is admin modules load MyModule or restart server.

See Also

API Reference

Complete API documentation

Events

SuperiorSkyblock events

Commands

Creating custom commands

Examples

Module examples and templates