Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/BG-Software-LLC/SuperiorSkyblock2/llms.txt

Use this file to discover all available pages before exploring further.

Database Bridge System

The Database Bridge system provides an abstraction layer for database operations in SuperiorSkyblock2. It supports multiple database backends (MySQL, SQLite) and handles data persistence for islands, players, and custom data.

Database Bridge Interface

The DatabaseBridge interface provides methods for CRUD operations:
import com.bgsoftware.superiorskyblock.api.data.DatabaseBridge;
import com.bgsoftware.superiorskyblock.api.data.DatabaseBridgeMode;
import com.bgsoftware.superiorskyblock.api.data.DatabaseFilter;
import com.bgsoftware.superiorskyblock.api.objects.Pair;

import java.util.Map;
import java.util.function.Consumer;

public class MyDataHandler {
    
    private final DatabaseBridge databaseBridge;
    
    public MyDataHandler(DatabaseBridge databaseBridge) {
        this.databaseBridge = databaseBridge;
        // Enable saving data
        databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.SAVE_DATA);
    }
}

Database Bridge Modes

Control when the bridge saves data:
public enum DatabaseBridgeMode {
    SAVE_DATA,  // Execute database updates
    IDLE        // Skip updates, only allow reads
}

Mode Usage

// Enable data saving
databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.SAVE_DATA);

// Disable data saving (useful during bulk operations)
databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.IDLE);

// Check current mode
DatabaseBridgeMode currentMode = databaseBridge.getDatabaseBridgeMode();
Set mode to IDLE when loading data to prevent unnecessary write operations.

CRUD Operations

Insert Data

Insert new records into the database:
import com.bgsoftware.superiorskyblock.api.objects.Pair;

public void insertPlayer(UUID playerId, String playerName, int score) {
    databaseBridge.insertObject(
        "custom_players",
        new Pair<>("uuid", playerId.toString()),
        new Pair<>("name", playerName),
        new Pair<>("score", score),
        new Pair<>("created_at", System.currentTimeMillis())
    );
}

Update Data

Update existing records with filters:
import com.bgsoftware.superiorskyblock.api.data.DatabaseFilter;

public void updatePlayerScore(UUID playerId, int newScore) {
    DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
    
    databaseBridge.updateObject(
        "custom_players",
        filter,
        new Pair<>("score", newScore),
        new Pair<>("updated_at", System.currentTimeMillis())
    );
}

Delete Data

Remove records from the database:
public void deletePlayer(UUID playerId) {
    DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
    databaseBridge.deleteObject("custom_players", filter);
}

// Delete all records (use with caution)
public void clearAllData() {
    databaseBridge.deleteObject("custom_players", null);
}

Load Data

Query and load data from the database:
public void loadPlayer(UUID playerId) {
    DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
    
    databaseBridge.loadObject("custom_players", filter, result -> {
        String name = (String) result.get("name");
        int score = (int) result.get("score");
        long createdAt = (long) result.get("created_at");
        
        // Process loaded data
        System.out.println("Loaded player: " + name + " with score: " + score);
    });
}

// Load all records
public void loadAllPlayers() {
    databaseBridge.loadAllObjects("custom_players", result -> {
        String uuid = (String) result.get("uuid");
        String name = (String) result.get("name");
        int score = (int) result.get("score");
        
        // Process each record
        players.put(UUID.fromString(uuid), new PlayerData(name, score));
    });
}

Database Filters

Create filters for precise queries:
1

Single Filter

Filter by a single column:
DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
2

Multiple Filters

Filter by multiple columns:
List<Pair<String, Object>> filters = Arrays.asList(
    new Pair<>("island_owner", ownerId.toString()),
    new Pair<>("status", "active")
);
DatabaseFilter filter = DatabaseFilter.fromFilters(filters);
3

Iterate Filters

Process filter conditions:
filter.forEach((column, value) -> {
    System.out.println("Filter: " + column + " = " + value);
});

Batch Operations

Optimize performance with batch operations:
public void saveBulkData(List<PlayerData> players) {
    // Enable batch mode
    databaseBridge.batchOperations(true);
    
    try {
        for (PlayerData player : players) {
            databaseBridge.insertObject(
                "custom_players",
                new Pair<>("uuid", player.getUuid().toString()),
                new Pair<>("name", player.getName()),
                new Pair<>("score", player.getScore())
            );
        }
    } finally {
        // Disable batch mode and flush
        databaseBridge.batchOperations(false);
    }
}
Always disable batch operations after bulk inserts to ensure data is flushed to the database.

Creating Custom Database Bridges

Extend database bridges for custom entities using DatabaseBridgeFactory:
import com.bgsoftware.superiorskyblock.api.factory.DatabaseBridgeFactory;
import com.bgsoftware.superiorskyblock.api.SuperiorSkyblock;

public class CustomDatabaseBridge implements DatabaseBridge {
    
    private final DatabaseBridge original;
    private final MyCustomObject object;
    
    public CustomDatabaseBridge(MyCustomObject object, DatabaseBridge original) {
        this.object = object;
        this.original = original;
    }
    
    @Override
    public void updateObject(String table, DatabaseFilter filter, Pair<String, Object>... columns) {
        // Add custom logic before/after update
        original.updateObject(table, filter, columns);
    }
    
    @Override
    public void insertObject(String table, Pair<String, Object>... columns) {
        // Add custom logic before/after insert
        original.insertObject(table, columns);
    }
    
    @Override
    public void deleteObject(String table, DatabaseFilter filter) {
        // Add custom logic before/after delete
        original.deleteObject(table, filter);
    }
    
    @Override
    public void loadObject(String table, DatabaseFilter filter, Consumer<Map<String, Object>> resultConsumer) {
        original.loadObject(table, filter, resultConsumer);
    }
    
    @Override
    public void loadAllObjects(String table, Consumer<Map<String, Object>> resultConsumer) {
        original.loadAllObjects(table, resultConsumer);
    }
    
    @Override
    public void batchOperations(boolean batchOperations) {
        original.batchOperations(batchOperations);
    }
    
    @Override
    public void setDatabaseBridgeMode(DatabaseBridgeMode mode) {
        original.setDatabaseBridgeMode(mode);
    }
    
    @Override
    public DatabaseBridgeMode getDatabaseBridgeMode() {
        return original.getDatabaseBridgeMode();
    }
}

Practical Example: Player Stats System

public class PlayerStatsManager {
    
    private final DatabaseBridge databaseBridge;
    private final Map<UUID, PlayerStats> cachedStats;
    
    public PlayerStatsManager(SuperiorSkyblock plugin) {
        this.databaseBridge = plugin.getFactory().createPlayersDatabaseBridge(null, null);
        this.cachedStats = new HashMap<>();
        
        loadAllStats();
    }
    
    private void loadAllStats() {
        // Set to IDLE mode during loading
        databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.IDLE);
        
        databaseBridge.loadAllObjects("player_stats", result -> {
            UUID uuid = UUID.fromString((String) result.get("uuid"));
            int kills = (int) result.get("kills");
            int deaths = (int) result.get("deaths");
            int blocksPlaced = (int) result.get("blocks_placed");
            
            PlayerStats stats = new PlayerStats(uuid, kills, deaths, blocksPlaced);
            cachedStats.put(uuid, stats);
        });
        
        // Enable saving after loading
        databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.SAVE_DATA);
    }
    
    public void incrementKills(UUID playerId) {
        PlayerStats stats = cachedStats.computeIfAbsent(playerId, PlayerStats::new);
        stats.incrementKills();
        
        // Save to database
        DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
        databaseBridge.updateObject(
            "player_stats",
            filter,
            new Pair<>("kills", stats.getKills())
        );
    }
    
    public void createPlayerStats(UUID playerId) {
        PlayerStats stats = new PlayerStats(playerId, 0, 0, 0);
        cachedStats.put(playerId, stats);
        
        databaseBridge.insertObject(
            "player_stats",
            new Pair<>("uuid", playerId.toString()),
            new Pair<>("kills", 0),
            new Pair<>("deaths", 0),
            new Pair<>("blocks_placed", 0)
        );
    }
    
    public void deletePlayerStats(UUID playerId) {
        cachedStats.remove(playerId);
        
        DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
        databaseBridge.deleteObject("player_stats", filter);
    }
    
    public PlayerStats getStats(UUID playerId) {
        return cachedStats.get(playerId);
    }
}

Factory Methods

Use factory methods to create specialized database bridges:
SuperiorSkyblock plugin = ...; // Get plugin instance
DatabaseBridgeFactory factory = plugin.getFactory();

// Island database bridge
Island island = ...;
DatabaseBridge islandBridge = factory.createIslandsDatabaseBridge(island, null);

// Player database bridge
SuperiorPlayer player = ...;
DatabaseBridge playerBridge = factory.createPlayersDatabaseBridge(player, null);

// Grid database bridge
GridManager grid = plugin.getGrid();
DatabaseBridge gridBridge = factory.createGridDatabaseBridge(grid, null);

// Stacked blocks database bridge
StackedBlocksManager stackedBlocks = plugin.getStackedBlocks();
DatabaseBridge stackedBridge = factory.createStackedBlocksDatabaseBridge(stackedBlocks, null);

Best Practices

  • Use IDLE mode when loading data to prevent write operations
  • Enable SAVE_DATA mode only when ready to persist changes
  • Use batch operations for bulk inserts/updates
  • Always disable batch mode after operations complete
  • Cache frequently accessed data to minimize database queries
  • Use database filters for precise queries
  • Handle null results when loading data
  • Clean up resources in module’s onDisable() method
  • Use appropriate data types for column values
  • Create indexes on frequently queried columns

Build docs developers (and LLMs) love