package com.spaceshipproject; import org.bukkit.entity.Player; import java.io.File; import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * Gestionnaire de la base de données SQLite. * * Tables : * - players(uuid, name, settings, created_at, updated_at) * - spaceships(id, owner_uuid, name, size_x/y/z, spawn_x/y/z, schematic, settings, created_at, updated_at) * - spaceships_loaded(spaceship_id, world, origin_x/y/z, loaded_at) */ public class DatabaseManager { private final SpaceShipProject plugin; private Connection connection; public DatabaseManager(SpaceShipProject plugin) { this.plugin = plugin; } public void initialize() { try { File dataFolder = plugin.getDataFolder(); if (!dataFolder.exists()) { dataFolder.mkdirs(); } File dbFile = new File(dataFolder, "spaceships.db"); connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath()); try (Statement stmt = connection.createStatement()) { stmt.execute("PRAGMA foreign_keys = ON;"); } createTables(); plugin.getLogger().info("Base de donnees SpaceShipProject initialisee."); } catch (SQLException e) { plugin.getLogger().severe("Erreur a l'initialisation de la base : " + e.getMessage()); } } public void close() { try { if (connection != null && !connection.isClosed()) { connection.close(); } } catch (SQLException e) { plugin.getLogger().severe("Erreur a la fermeture de la base : " + e.getMessage()); } } private void createTables() throws SQLException { String players = """ CREATE TABLE IF NOT EXISTS players ( uuid TEXT PRIMARY KEY, name TEXT, settings TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """; String spaceships = """ CREATE TABLE IF NOT EXISTS spaceships ( id INTEGER PRIMARY KEY AUTOINCREMENT, owner_uuid TEXT NOT NULL, name TEXT NOT NULL, size_x INTEGER NOT NULL, size_y INTEGER NOT NULL, size_z INTEGER NOT NULL, spawn_x INTEGER NOT NULL, spawn_y INTEGER NOT NULL, spawn_z INTEGER NOT NULL, schematic TEXT, settings TEXT, level INTEGER NOT NULL DEFAULT 1, money INTEGER NOT NULL DEFAULT 0, last_loaded_level INTEGER NOT NULL DEFAULT 1, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (owner_uuid) REFERENCES players(uuid) ON DELETE CASCADE ) """; String loaded = """ CREATE TABLE IF NOT EXISTS spaceships_loaded ( spaceship_id INTEGER PRIMARY KEY, world TEXT NOT NULL, origin_x INTEGER NOT NULL, origin_y INTEGER NOT NULL, origin_z INTEGER NOT NULL, loaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (spaceship_id) REFERENCES spaceships(id) ON DELETE CASCADE ) """; try (Statement stmt = connection.createStatement()) { stmt.execute(players); stmt.execute(spaceships); stmt.execute(loaded); // Migrations (idempotentes) pour les bases creees avant l'ajout de level/money. tryAlter(stmt, "ALTER TABLE spaceships ADD COLUMN level INTEGER NOT NULL DEFAULT 1"); tryAlter(stmt, "ALTER TABLE spaceships ADD COLUMN money INTEGER NOT NULL DEFAULT 0"); tryAlter(stmt, "ALTER TABLE spaceships ADD COLUMN last_loaded_level INTEGER NOT NULL DEFAULT 1"); } } private void tryAlter(Statement stmt, String sql) { try { stmt.execute(sql); } catch (SQLException ignored) { /* colonne deja presente */ } } /* ========================= PLAYERS ========================= */ public void upsertPlayer(Player player) { String sql = """ INSERT INTO players(uuid, name, updated_at) VALUES(?, ?, CURRENT_TIMESTAMP) ON CONFLICT(uuid) DO UPDATE SET name = excluded.name, updated_at = CURRENT_TIMESTAMP """; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setString(1, player.getUniqueId().toString()); stmt.setString(2, player.getName()); stmt.executeUpdate(); } catch (SQLException e) { plugin.getLogger().severe("Erreur upsertPlayer : " + e.getMessage()); } } public void setPlayerSettings(UUID uuid, String settingsJson) { String sql = "UPDATE players SET settings = ?, updated_at = CURRENT_TIMESTAMP WHERE uuid = ?"; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setString(1, settingsJson); stmt.setString(2, uuid.toString()); stmt.executeUpdate(); } catch (SQLException e) { plugin.getLogger().severe("Erreur setPlayerSettings : " + e.getMessage()); } } public String getPlayerSettings(UUID uuid) { String sql = "SELECT settings FROM players WHERE uuid = ?"; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setString(1, uuid.toString()); try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) return rs.getString("settings"); } } catch (SQLException e) { plugin.getLogger().severe("Erreur getPlayerSettings : " + e.getMessage()); } return null; } /* ========================= SPACESHIPS ========================= */ public long createSpaceship(UUID owner, String name, int sizeX, int sizeY, int sizeZ, int spawnX, int spawnY, int spawnZ, String schematicJson, String settingsJson) { String sql = """ INSERT INTO spaceships(owner_uuid, name, size_x, size_y, size_z, spawn_x, spawn_y, spawn_z, schematic, settings, level, money, last_loaded_level) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0, 1) """; try (PreparedStatement stmt = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { stmt.setString(1, owner.toString()); stmt.setString(2, name); stmt.setInt(3, sizeX); stmt.setInt(4, sizeY); stmt.setInt(5, sizeZ); stmt.setInt(6, spawnX); stmt.setInt(7, spawnY); stmt.setInt(8, spawnZ); stmt.setString(9, schematicJson); stmt.setString(10, settingsJson); stmt.executeUpdate(); try (ResultSet keys = stmt.getGeneratedKeys()) { if (keys.next()) return keys.getLong(1); } } catch (SQLException e) { plugin.getLogger().severe("Erreur createSpaceship : " + e.getMessage()); } return -1; } public Spaceship getSpaceship(long id) { String sql = "SELECT * FROM spaceships WHERE id = ?"; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setLong(1, id); try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) return rowToSpaceship(rs); } } catch (SQLException e) { plugin.getLogger().severe("Erreur getSpaceship : " + e.getMessage()); } return null; } public List getSpaceshipsByOwner(UUID owner) { List list = new ArrayList<>(); String sql = "SELECT * FROM spaceships WHERE owner_uuid = ? ORDER BY id ASC"; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setString(1, owner.toString()); try (ResultSet rs = stmt.executeQuery()) { while (rs.next()) list.add(rowToSpaceship(rs)); } } catch (SQLException e) { plugin.getLogger().severe("Erreur getSpaceshipsByOwner : " + e.getMessage()); } return list; } public int countSpaceshipsByOwner(UUID owner) { String sql = "SELECT COUNT(*) FROM spaceships WHERE owner_uuid = ?"; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setString(1, owner.toString()); try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) return rs.getInt(1); } } catch (SQLException e) { plugin.getLogger().severe("Erreur countSpaceshipsByOwner : " + e.getMessage()); } return 0; } @SuppressWarnings("deprecation") public void updateSpaceship(Spaceship ship) { String sql = """ UPDATE spaceships SET name = ?, size_x = ?, size_y = ?, size_z = ?, spawn_x = ?, spawn_y = ?, spawn_z = ?, schematic = ?, settings = ?, level = ?, money = ?, last_loaded_level = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? """; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setString(1, ship.getName()); stmt.setInt(2, ship.getSizeX()); stmt.setInt(3, ship.getSizeY()); stmt.setInt(4, ship.getSizeZ()); stmt.setInt(5, ship.getSpawnX()); stmt.setInt(6, ship.getSpawnY()); stmt.setInt(7, ship.getSpawnZ()); stmt.setString(8, ship.getSchematicJson()); stmt.setString(9, ship.getSettingsJson()); stmt.setInt(10, ship.getLevel()); stmt.setInt(11, ship.getMoney()); stmt.setInt(12, ship.getLastLoadedLevel()); stmt.setLong(13, ship.getId()); stmt.executeUpdate(); } catch (SQLException e) { plugin.getLogger().severe("Erreur updateSpaceship : " + e.getMessage()); } } public void deleteSpaceship(long id) { try (PreparedStatement st1 = connection.prepareStatement("DELETE FROM spaceships_loaded WHERE spaceship_id = ?"); PreparedStatement st2 = connection.prepareStatement("DELETE FROM spaceships WHERE id = ?")) { st1.setLong(1, id); st1.executeUpdate(); st2.setLong(1, id); st2.executeUpdate(); } catch (SQLException e) { plugin.getLogger().severe("Erreur deleteSpaceship : " + e.getMessage()); } } private Spaceship rowToSpaceship(ResultSet rs) throws SQLException { int level = 1, money = 0, lastLoadedLevel = 1; try { level = rs.getInt("level"); if (rs.wasNull()) level = 1; } catch (SQLException ignored) {} try { money = rs.getInt("money"); } catch (SQLException ignored) {} try { lastLoadedLevel = rs.getInt("last_loaded_level"); if (rs.wasNull()) lastLoadedLevel = 1; } catch (SQLException ignored) {} return new Spaceship( rs.getLong("id"), UUID.fromString(rs.getString("owner_uuid")), rs.getString("name"), rs.getInt("size_x"), rs.getInt("size_y"), rs.getInt("size_z"), rs.getInt("spawn_x"), rs.getInt("spawn_y"), rs.getInt("spawn_z"), rs.getString("schematic"), rs.getString("settings"), level, money, lastLoadedLevel ); } /* ========================= SPACESHIPS_LOADED ========================= */ public void markLoaded(long spaceshipId, String world, int x, int y, int z) { String sql = """ INSERT INTO spaceships_loaded(spaceship_id, world, origin_x, origin_y, origin_z, loaded_at) VALUES(?, ?, ?, ?, ?, CURRENT_TIMESTAMP) ON CONFLICT(spaceship_id) DO UPDATE SET world = excluded.world, origin_x = excluded.origin_x, origin_y = excluded.origin_y, origin_z = excluded.origin_z, loaded_at = CURRENT_TIMESTAMP """; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setLong(1, spaceshipId); stmt.setString(2, world); stmt.setInt(3, x); stmt.setInt(4, y); stmt.setInt(5, z); stmt.executeUpdate(); } catch (SQLException e) { plugin.getLogger().severe("Erreur markLoaded : " + e.getMessage()); } } public void markUnloaded(long spaceshipId) { String sql = "DELETE FROM spaceships_loaded WHERE spaceship_id = ?"; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setLong(1, spaceshipId); stmt.executeUpdate(); } catch (SQLException e) { plugin.getLogger().severe("Erreur markUnloaded : " + e.getMessage()); } } public LoadedSpaceship getLoaded(long spaceshipId) { String sql = """ SELECT l.spaceship_id, l.world, l.origin_x, l.origin_y, l.origin_z, s.size_x, s.size_y, s.size_z FROM spaceships_loaded l JOIN spaceships s ON s.id = l.spaceship_id WHERE l.spaceship_id = ? """; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setLong(1, spaceshipId); try (ResultSet rs = stmt.executeQuery()) { if (rs.next()) { return new LoadedSpaceship( rs.getLong("spaceship_id"), rs.getString("world"), rs.getInt("origin_x"), rs.getInt("origin_y"), rs.getInt("origin_z"), rs.getInt("size_x"), rs.getInt("size_y"), rs.getInt("size_z") ); } } } catch (SQLException e) { plugin.getLogger().severe("Erreur getLoaded : " + e.getMessage()); } return null; } public List getLoadedByOwner(UUID owner) { List list = new ArrayList<>(); String sql = """ SELECT l.spaceship_id, l.world, l.origin_x, l.origin_y, l.origin_z, s.size_x, s.size_y, s.size_z FROM spaceships_loaded l JOIN spaceships s ON s.id = l.spaceship_id WHERE s.owner_uuid = ? """; try (PreparedStatement stmt = connection.prepareStatement(sql)) { stmt.setString(1, owner.toString()); try (ResultSet rs = stmt.executeQuery()) { while (rs.next()) { list.add(new LoadedSpaceship( rs.getLong("spaceship_id"), rs.getString("world"), rs.getInt("origin_x"), rs.getInt("origin_y"), rs.getInt("origin_z"), rs.getInt("size_x"), rs.getInt("size_y"), rs.getInt("size_z") )); } } } catch (SQLException e) { plugin.getLogger().severe("Erreur getLoadedByOwner : " + e.getMessage()); } return list; } public List getAllLoaded() { List list = new ArrayList<>(); String sql = """ SELECT l.spaceship_id, l.world, l.origin_x, l.origin_y, l.origin_z, s.size_x, s.size_y, s.size_z FROM spaceships_loaded l JOIN spaceships s ON s.id = l.spaceship_id """; try (PreparedStatement stmt = connection.prepareStatement(sql); ResultSet rs = stmt.executeQuery()) { while (rs.next()) { list.add(new LoadedSpaceship( rs.getLong("spaceship_id"), rs.getString("world"), rs.getInt("origin_x"), rs.getInt("origin_y"), rs.getInt("origin_z"), rs.getInt("size_x"), rs.getInt("size_y"), rs.getInt("size_z") )); } } catch (SQLException e) { plugin.getLogger().severe("Erreur getAllLoaded : " + e.getMessage()); } return list; } }