mirror of
https://github.com/KoopaCode/Lockage.git
synced 2025-04-05 15:47:31 +00:00
227 lines
8.9 KiB
Java
227 lines
8.9 KiB
Java
package com.koopalabs.lockage.database;
|
|
|
|
import com.koopalabs.lockage.Lockage;
|
|
import org.bukkit.Location;
|
|
|
|
import java.io.File;
|
|
import java.sql.*;
|
|
import java.util.UUID;
|
|
|
|
public class DatabaseManager {
|
|
private final Lockage plugin;
|
|
private Connection connection;
|
|
|
|
public DatabaseManager(Lockage plugin) {
|
|
this.plugin = plugin;
|
|
}
|
|
|
|
public void initialize() {
|
|
File dataFolder = new File(plugin.getDataFolder(), "database.db");
|
|
boolean needsInit = !dataFolder.exists();
|
|
|
|
try {
|
|
if (needsInit) {
|
|
dataFolder.getParentFile().mkdirs();
|
|
dataFolder.createNewFile();
|
|
}
|
|
|
|
Class.forName("org.sqlite.JDBC");
|
|
connection = DriverManager.getConnection("jdbc:sqlite:" + dataFolder);
|
|
|
|
// Create or verify tables
|
|
verifyDatabase();
|
|
|
|
if (needsInit) {
|
|
plugin.getLogger().info("Database created successfully!");
|
|
}
|
|
} catch (Exception e) {
|
|
plugin.getLogger().severe("Failed to initialize database: " + e.getMessage());
|
|
plugin.getLogger().severe("Attempting to repair database...");
|
|
repairDatabase();
|
|
}
|
|
}
|
|
|
|
private void verifyDatabase() {
|
|
try (Statement stmt = connection.createStatement()) {
|
|
// Check if tables exist and have correct structure
|
|
DatabaseMetaData meta = connection.getMetaData();
|
|
boolean hasLockedChests = false;
|
|
boolean hasKeys = false;
|
|
|
|
ResultSet tables = meta.getTables(null, null, "locked_chests", null);
|
|
hasLockedChests = tables.next();
|
|
tables.close();
|
|
|
|
tables = meta.getTables(null, null, "keys", null);
|
|
hasKeys = tables.next();
|
|
tables.close();
|
|
|
|
if (!hasLockedChests || !hasKeys) {
|
|
createTables();
|
|
}
|
|
|
|
// Verify data integrity
|
|
cleanupInvalidEntries();
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Database verification failed: " + e.getMessage());
|
|
repairDatabase();
|
|
}
|
|
}
|
|
|
|
private void cleanupInvalidEntries() {
|
|
try {
|
|
// Remove entries with invalid worlds
|
|
String sql = "DELETE FROM locked_chests WHERE world NOT IN (SELECT name FROM worlds)";
|
|
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
|
|
int removed = pstmt.executeUpdate();
|
|
if (removed > 0) {
|
|
plugin.getLogger().warning("Removed " + removed + " chest locks from invalid worlds");
|
|
}
|
|
}
|
|
|
|
// Remove orphaned keys
|
|
sql = "DELETE FROM keys WHERE key_id NOT IN (SELECT key_id FROM locked_chests)";
|
|
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
|
|
int removed = pstmt.executeUpdate();
|
|
if (removed > 0) {
|
|
plugin.getLogger().warning("Removed " + removed + " orphaned keys");
|
|
}
|
|
}
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Failed to clean up invalid entries: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private void repairDatabase() {
|
|
try {
|
|
// Close existing connection
|
|
if (connection != null && !connection.isClosed()) {
|
|
connection.close();
|
|
}
|
|
|
|
// Backup existing database if it exists
|
|
File dbFile = new File(plugin.getDataFolder(), "database.db");
|
|
if (dbFile.exists()) {
|
|
File backupFile = new File(plugin.getDataFolder(), "database.db.backup");
|
|
if (backupFile.exists()) {
|
|
backupFile.delete();
|
|
}
|
|
dbFile.renameTo(backupFile);
|
|
plugin.getLogger().warning("Created database backup: database.db.backup");
|
|
}
|
|
|
|
// Create new database
|
|
dbFile.createNewFile();
|
|
connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile);
|
|
createTables();
|
|
plugin.getLogger().info("Database repaired successfully!");
|
|
} catch (Exception e) {
|
|
plugin.getLogger().severe("Failed to repair database: " + e.getMessage());
|
|
plugin.getLogger().severe("Please contact an administrator!");
|
|
}
|
|
}
|
|
|
|
private void createTables() {
|
|
try (Statement stmt = connection.createStatement()) {
|
|
// Table for locked chests
|
|
stmt.execute("CREATE TABLE IF NOT EXISTS locked_chests (" +
|
|
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
|
"world TEXT NOT NULL," +
|
|
"x INTEGER NOT NULL," +
|
|
"y INTEGER NOT NULL," +
|
|
"z INTEGER NOT NULL," +
|
|
"owner UUID NOT NULL," +
|
|
"key_id TEXT NOT NULL," +
|
|
"created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP" +
|
|
")");
|
|
|
|
// Table for keys
|
|
stmt.execute("CREATE TABLE IF NOT EXISTS keys (" +
|
|
"key_id TEXT PRIMARY KEY," +
|
|
"owner UUID NOT NULL," +
|
|
"created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP" +
|
|
")");
|
|
|
|
// Create indices for better performance
|
|
stmt.execute("CREATE INDEX IF NOT EXISTS idx_chest_location ON locked_chests(world, x, y, z)");
|
|
stmt.execute("CREATE INDEX IF NOT EXISTS idx_chest_key ON locked_chests(key_id)");
|
|
|
|
// Create worlds table to track valid worlds
|
|
stmt.execute("CREATE TABLE IF NOT EXISTS worlds (" +
|
|
"name TEXT PRIMARY KEY," +
|
|
"last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP" +
|
|
")");
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Failed to create tables: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
public void close() {
|
|
try {
|
|
if (connection != null && !connection.isClosed()) {
|
|
connection.close();
|
|
}
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Error closing database connection: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
public void addLockedChest(Location location, UUID owner, String keyId) {
|
|
String sql = "INSERT INTO locked_chests (world, x, y, z, owner, key_id) VALUES (?, ?, ?, ?, ?, ?)";
|
|
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
|
|
pstmt.setString(1, location.getWorld().getName());
|
|
pstmt.setInt(2, location.getBlockX());
|
|
pstmt.setInt(3, location.getBlockY());
|
|
pstmt.setInt(4, location.getBlockZ());
|
|
pstmt.setString(5, owner.toString());
|
|
pstmt.setString(6, keyId);
|
|
pstmt.executeUpdate();
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Failed to add locked chest: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
public boolean isChestLocked(Location location) {
|
|
String sql = "SELECT * FROM locked_chests WHERE world = ? AND x = ? AND y = ? AND z = ?";
|
|
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
|
|
pstmt.setString(1, location.getWorld().getName());
|
|
pstmt.setInt(2, location.getBlockX());
|
|
pstmt.setInt(3, location.getBlockY());
|
|
pstmt.setInt(4, location.getBlockZ());
|
|
ResultSet rs = pstmt.executeQuery();
|
|
return rs.next();
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Failed to check locked chest: " + e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public boolean isKeyValidForChest(Location location, String keyId) {
|
|
String sql = "SELECT * FROM locked_chests WHERE world = ? AND x = ? AND y = ? AND z = ? AND key_id = ?";
|
|
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
|
|
pstmt.setString(1, location.getWorld().getName());
|
|
pstmt.setInt(2, location.getBlockX());
|
|
pstmt.setInt(3, location.getBlockY());
|
|
pstmt.setInt(4, location.getBlockZ());
|
|
pstmt.setString(5, keyId);
|
|
ResultSet rs = pstmt.executeQuery();
|
|
return rs.next();
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Failed to check key validity: " + e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void removeLock(Location location) {
|
|
String sql = "DELETE FROM locked_chests WHERE world = ? AND x = ? AND y = ? AND z = ?";
|
|
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
|
|
pstmt.setString(1, location.getWorld().getName());
|
|
pstmt.setInt(2, location.getBlockX());
|
|
pstmt.setInt(3, location.getBlockY());
|
|
pstmt.setInt(4, location.getBlockZ());
|
|
pstmt.executeUpdate();
|
|
} catch (SQLException e) {
|
|
plugin.getLogger().severe("Failed to remove lock: " + e.getMessage());
|
|
}
|
|
}
|
|
} |