From c423793fc8ff97cb255e973e44f7bfa0aad5a28c Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Tue, 17 Oct 2023 15:41:11 +0530 Subject: [PATCH 1/2] fix logger methods again, lol --- .../main/java/lol/pyr/znpcsplus/storage/sqlite/SQLite.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLite.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLite.java index 344e038..f44944c 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLite.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLite.java @@ -5,7 +5,6 @@ import lol.pyr.znpcsplus.storage.database.Database; import java.io.File; import java.io.IOException; import java.sql.*; -import java.util.logging.Level; import java.util.logging.Logger; public class SQLite extends Database{ @@ -20,7 +19,7 @@ public class SQLite extends Database{ try { dbFile.createNewFile(); } catch (IOException e) { - logger.log(Level.SEVERE, "File write error: "+dbFile.getName()); + logger.severe("File write error: "+dbFile.getName()); } } try { @@ -31,9 +30,9 @@ public class SQLite extends Database{ connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath()); return connection; } catch (SQLException ex) { - logger.log(Level.SEVERE,"SQLite exception on initialize", ex); + logger.severe("SQLite exception on initialize" + ex); } catch (ClassNotFoundException ex) { - logger.log(Level.SEVERE, "SQLite JDBC library not found", ex); + logger.severe("SQLite JDBC library not found" + ex); } return null; } From 788e962d37b20e386ce302171a396b6158578fda Mon Sep 17 00:00:00 2001 From: D3v1s0m Date: Tue, 17 Oct 2023 21:13:48 +0530 Subject: [PATCH 2/2] Added MySQL Storage option --- .../pyr/znpcsplus/config/DatabaseConfig.java | 41 +++ .../lol/pyr/znpcsplus/config/MainConfig.java | 8 +- .../pyr/znpcsplus/storage/NpcStorageType.java | 12 + .../pyr/znpcsplus/storage/mysql/MySQL.java | 115 +++++++ .../znpcsplus/storage/mysql/MySQLStorage.java | 316 ++++++++++++++++++ .../storage/sqlite/SQLiteStorage.java | 6 +- 6 files changed, 494 insertions(+), 4 deletions(-) create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/config/DatabaseConfig.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQL.java create mode 100644 plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQLStorage.java diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/config/DatabaseConfig.java b/plugin/src/main/java/lol/pyr/znpcsplus/config/DatabaseConfig.java new file mode 100644 index 0000000..16b110e --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/config/DatabaseConfig.java @@ -0,0 +1,41 @@ +package lol.pyr.znpcsplus.config; + +import space.arim.dazzleconf.annote.ConfComments; +import space.arim.dazzleconf.annote.ConfDefault.*; +import space.arim.dazzleconf.annote.ConfKey; + +public interface DatabaseConfig { + @ConfKey("host") + @ConfComments("The host of the database") + @DefaultString("localhost") + String host(); + + @ConfKey("port") + @ConfComments("The port of the database") + @DefaultInteger(3306) + int port(); + + @ConfKey("username") + @ConfComments("The username to use to connect to the database") + @DefaultString("znpcsplus") + String username(); + + @ConfKey("password") + @ConfComments("The password to use to connect to the database") + @DefaultString("password") + String password(); + + @ConfKey("database-name") + @ConfComments("The name of the database to use") + @DefaultString("znpcsplus") + String databaseName(); + + default String createConnectionURL(String dbType) { + if (dbType.equalsIgnoreCase("mysql")) { + return "jdbc:mysql://" + host() + ":" + port() + "/" + databaseName() + "?useSSL=false&user=" + username() + "&password=" + password(); + } else { + throw new IllegalArgumentException("Unsupported database type: " + dbType); + } + } +} + diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java b/plugin/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java index 1b19a22..619a727 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java @@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.config; import lol.pyr.znpcsplus.storage.NpcStorageType; import space.arim.dazzleconf.annote.ConfComments; import space.arim.dazzleconf.annote.ConfKey; +import space.arim.dazzleconf.annote.SubSection; import static space.arim.dazzleconf.annote.ConfDefault.*; @@ -28,10 +29,15 @@ public interface MainConfig { boolean debugEnabled(); @ConfKey("storage-type") - @ConfComments("The storage type to use. Available storage types: YAML, SQLITE") + @ConfComments("The storage type to use. Available storage types: YAML, SQLITE, MYSQL") @DefaultString("YAML") NpcStorageType storageType(); + @ConfKey("database-config") + @ConfComments("The database config. Only used if storage-type is MYSQL") + @SubSection + DatabaseConfig databaseConfig(); + @ConfKey("disable-skin-fetcher-warnings") @ConfComments("Set this to true if you don't want to be warned in the console when a skin fails to resolve") @DefaultBoolean(false) diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java index 341767d..93c421b 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/NpcStorageType.java @@ -6,6 +6,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; import lol.pyr.znpcsplus.interaction.ActionRegistry; import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.storage.mysql.MySQLStorage; import lol.pyr.znpcsplus.storage.sqlite.SQLiteStorage; import lol.pyr.znpcsplus.storage.yaml.YamlStorage; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -29,6 +30,17 @@ public enum NpcStorageType { return null; } } + }, + MYSQL { + @Override + public NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + try { + return new MySQLStorage(packetFactory, configManager, actionRegistry, typeRegistry, propertyRegistry, textSerializer); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } }; public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer); diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQL.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQL.java new file mode 100644 index 0000000..7ffd709 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQL.java @@ -0,0 +1,115 @@ +package lol.pyr.znpcsplus.storage.mysql; + +import lol.pyr.znpcsplus.storage.database.Database; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.logging.Logger; + +public class MySQL extends Database { + private final String connectionURL; + + public MySQL(String connectionURL, Logger logger) { + super(logger); + this.connectionURL = connectionURL; + } + + @Override + public Connection getSQLConnection() { + validateConnectionUrl(); + + try { + if (connection != null && !connection.isClosed()) { + return connection; + } + Class.forName("com.mysql.jdbc.Driver"); + connection = java.sql.DriverManager.getConnection(connectionURL); + return connection; + } catch (ClassNotFoundException ex) { + logger.severe("MySQL JDBC library not found" + ex); + } catch (SQLException ex) { + if (ex.getSQLState().equals("08006")) { + logger.severe("Could not connect to MySQL server. Check your connection settings and make sure the server is online."); + } else if (ex.getSQLState().equals("08002")) { + logger.severe("A connection already exists." + ex); + } else { + logger.severe("MySQL exception on initialize" + ex); + } + } + return null; + } + + private void validateConnectionUrl() { + if (connectionURL == null || connectionURL.isEmpty()) { + throw new IllegalArgumentException("Connection URL cannot be null or empty"); + } + if (!connectionURL.startsWith("jdbc:mysql://")) { + throw new IllegalArgumentException("Connection URL must start with 'jdbc:mysql://'"); + } + // TODO: Validate the rest of the URL + } + + @Override + public void load() { + connection = getSQLConnection(); + } + + public boolean tableExists(String tableName) { + try { + Statement s = connection.createStatement(); + s.executeQuery("SELECT * FROM " + tableName + ";"); + s.close(); + return true; + } catch (SQLException e) { + return false; + } + } + + public boolean columnExists(String tableName, String columnName) { + try { + Statement s = connection.createStatement(); + s.executeQuery("SELECT " + columnName + " FROM " + tableName + ";"); + s.close(); + return true; + } catch (SQLException e) { + return false; + } + } + + public boolean addColumn(String tableName, String columnName, String type) { + if (columnExists(tableName, columnName)) return false; + try { + Statement s = connection.createStatement(); + s.executeQuery("ALTER TABLE " + tableName + " ADD COLUMN " + columnName + " " + type + ";"); + s.close(); + } catch (SQLException e) { + return false; + } + return true; + } + + public ResultSet executeQuery(String query) { + try { + Statement s = connection.createStatement(); + ResultSet rs = s.executeQuery(query); + s.close(); + return rs; + } catch (SQLException e) { + return null; + } + } + + public int executeUpdate(String sql) { + try { + Statement s = connection.createStatement(); + int rowCount = s.executeUpdate(sql); + s.close(); + return rowCount; + } catch (SQLException e) { + e.printStackTrace(); + return -1; + } + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQLStorage.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQLStorage.java new file mode 100644 index 0000000..190b6b3 --- /dev/null +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQLStorage.java @@ -0,0 +1,316 @@ +package lol.pyr.znpcsplus.storage.mysql; + +import lol.pyr.znpcsplus.api.entity.EntityProperty; +import lol.pyr.znpcsplus.config.ConfigManager; +import lol.pyr.znpcsplus.entity.EntityPropertyImpl; +import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl; +import lol.pyr.znpcsplus.entity.PropertySerializer; +import lol.pyr.znpcsplus.hologram.HologramImpl; +import lol.pyr.znpcsplus.interaction.ActionRegistry; +import lol.pyr.znpcsplus.npc.NpcEntryImpl; +import lol.pyr.znpcsplus.npc.NpcImpl; +import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl; +import lol.pyr.znpcsplus.packets.PacketFactory; +import lol.pyr.znpcsplus.storage.NpcStorage; +import lol.pyr.znpcsplus.util.NpcLocation; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; + +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class MySQLStorage implements NpcStorage { + private final static Logger logger = Logger.getLogger("MySQLStorage"); + + private final PacketFactory packetFactory; + private final ConfigManager configManager; + private final ActionRegistry actionRegistry; + private final NpcTypeRegistryImpl typeRegistry; + private final EntityPropertyRegistryImpl propertyRegistry; + private final LegacyComponentSerializer textSerializer; + private final MySQL database; + + private final String TABLE_NPCS; + private final String TABLE_NPCS_PROPERTIES; + private final String TABLE_NPCS_HOLOGRAMS; + private final String TABLE_NPCS_ACTIONS; + + public MySQLStorage(PacketFactory packetFactory, ConfigManager configManager, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer) { + this.packetFactory = packetFactory; + this.configManager = configManager; + this.actionRegistry = actionRegistry; + this.typeRegistry = typeRegistry; + this.propertyRegistry = propertyRegistry; + this.textSerializer = textSerializer; + this.database = new MySQL(configManager.getConfig().databaseConfig().createConnectionURL("mysql"), logger); + database.load(); + if (database.getSQLConnection() == null) { + throw new RuntimeException("Failed to initialize MySQL Storage"); + } + TABLE_NPCS = "npcs"; + TABLE_NPCS_PROPERTIES = "npcs_properties"; + TABLE_NPCS_HOLOGRAMS = "npcs_holograms"; + TABLE_NPCS_ACTIONS = "npcs_actions"; + validateTables(); + } + + private void validateTables() { + if (!database.tableExists(TABLE_NPCS)) { + logger.info("Creating table " + TABLE_NPCS + "..."); + createNpcsTable(); + } + if (!database.tableExists(TABLE_NPCS_PROPERTIES)) { + logger.info("Creating table " + TABLE_NPCS_PROPERTIES + "..."); + createNpcsPropertiesTable(); + } + if (!database.tableExists(TABLE_NPCS_HOLOGRAMS)) { + logger.info("Creating table " + TABLE_NPCS_HOLOGRAMS + "..."); + createNpcsHologramsTable(); + } + if (!database.tableExists(TABLE_NPCS_ACTIONS)) { + logger.info("Creating table " + TABLE_NPCS_ACTIONS + "..."); + createNpcsActionsTable(); + } + updateTables(); + } + + private void createNpcsTable() { + if (database.executeUpdate("CREATE TABLE " + TABLE_NPCS + + " (id VARCHAR(256) PRIMARY KEY, isProcessed BOOLEAN, allowCommands BOOLEAN, enabled BOOLEAN, " + + "uuid VARCHAR(36), world VARCHAR(128), x DOUBLE, y DOUBLE, z DOUBLE, yaw DOUBLE, pitch DOUBLE, type VARCHAR(128), hologramOffset DOUBLE, hologramRefreshDelay BIGINT)") != -1) { + logger.info("Table " + TABLE_NPCS + " created."); + } else { + logger.severe("Failed to create table " + TABLE_NPCS + "."); + } + } + + private void createNpcsPropertiesTable() { + if (database.executeUpdate("CREATE TABLE " + TABLE_NPCS_PROPERTIES + + " (npc_id VARCHAR(256), property VARCHAR(128), value TEXT, PRIMARY KEY (npc_id, property))") != -1) { + logger.info("Table " + TABLE_NPCS_PROPERTIES + " created."); + } else { + logger.severe("Failed to create table " + TABLE_NPCS_PROPERTIES + "."); + } + } + + private void createNpcsHologramsTable() { + if (database.executeUpdate("CREATE TABLE " + TABLE_NPCS_HOLOGRAMS + + " (npc_id VARCHAR(256), line INT, text TEXT, PRIMARY KEY (npc_id, line))") != -1) { + logger.info("Table " + TABLE_NPCS_HOLOGRAMS + " created."); + } else { + logger.severe("Failed to create table " + TABLE_NPCS_HOLOGRAMS + "."); + } + } + + private void createNpcsActionsTable() { + if (database.executeUpdate("CREATE TABLE " + TABLE_NPCS_ACTIONS + + " (npc_id VARCHAR(256), action_id INT, action_data TEXT, PRIMARY KEY (npc_id, action_id))") != -1) { + logger.info("Table " + TABLE_NPCS_ACTIONS + " created."); + } else { + logger.severe("Failed to create table " + TABLE_NPCS_ACTIONS + "."); + } + } + + private void updateTables() { + // Any table updates go here + } + + @Override + public Collection loadNpcs() { + Map npcMap = new HashMap<>(); + try { + PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS); + ResultSet rs = st.executeQuery(); + while (rs.next()) { + NpcImpl npc = new NpcImpl(UUID.fromString(rs.getString("uuid")), propertyRegistry, configManager, packetFactory, textSerializer, + rs.getString("world"), typeRegistry.getByName(rs.getString("type")), + new NpcLocation(rs.getDouble("x"), rs.getDouble("y"), rs.getDouble("z"), rs.getFloat("yaw"), rs.getFloat("pitch"))); + + if (!rs.getBoolean("enabled")) npc.setEnabled(false); + + npc.getHologram().setOffset(rs.getDouble("hologramOffset")); + if (rs.getBigDecimal("hologramRefreshDelay") != null) npc.getHologram().setRefreshDelay(rs.getBigDecimal("hologramRefreshDelay").longValue()); + + NpcEntryImpl entry = new NpcEntryImpl(rs.getString("id"), npc); + entry.setProcessed(rs.getBoolean("isProcessed")); + entry.setAllowCommandModification(rs.getBoolean("allowCommands")); + entry.setSave(true); + npcMap.put(rs.getString("id"), entry); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + try { + PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS_PROPERTIES); + ResultSet rs = st.executeQuery(); + while (rs.next()) { + NpcEntryImpl entry = npcMap.get(rs.getString("npc_id")); + String key = rs.getString("property"); + if (entry != null) { + EntityPropertyImpl property = propertyRegistry.getByName(key); + if (property == null) { + logger.warning("Unknown property '" + key + "' for npc '" + rs.getString("npc_id") + "'. skipping ..."); + continue; + } + PropertySerializer serializer = propertyRegistry.getSerializer(property.getType()); + if (serializer == null) { + logger.warning("Unknown serializer for property '" + key + "' for npc '" + rs.getString("npc_id") + "'. skipping ..."); + continue; + } + Object value = serializer.deserialize(rs.getString("value")); + if (value == null) { + logger.warning("Failed to deserialize property '" + key + "' for npc '" + rs.getString("npc_id") + "'. Resetting to default ..."); + value = property.getDefaultValue(); + } + entry.getNpc().UNSAFE_setProperty(property, value); + npcMap.put(rs.getString("npc_id"), entry); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + + try { + PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS_HOLOGRAMS + " ORDER BY line"); + ResultSet rs = st.executeQuery(); + + while (rs.next()) { + NpcEntryImpl entry = npcMap.get(rs.getString("npc_id")); + if (entry != null) { + entry.getNpc().getHologram().insertLine(rs.getInt("line"), rs.getString("text")); + } + npcMap.put(rs.getString("npc_id"), entry); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + + try { + PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS_ACTIONS + " ORDER BY action_id"); + ResultSet rs = st.executeQuery(); + + while (rs.next()) { + NpcEntryImpl entry = npcMap.get(rs.getString("npc_id")); + if (entry != null) { + entry.getNpc().addAction(actionRegistry.deserialize(rs.getString("action_data"))); + } + npcMap.put(rs.getString("npc_id"), entry); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + return npcMap.values().stream().filter(Objects::nonNull).collect(Collectors.toList()); + } + + @Override + public void saveNpcs(Collection npcs) { + long start = System.currentTimeMillis(); + for (NpcEntryImpl entry : npcs) try { + + PreparedStatement ps; + ps = database.getSQLConnection().prepareStatement("REPLACE INTO " + TABLE_NPCS + " (id, isProcessed, allowCommands, enabled, uuid, world, x, y, z, yaw, pitch, type, hologramOffset, hologramRefreshDelay) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); + ps.setString(1, entry.getId()); + ps.setBoolean(2, entry.isProcessed()); + ps.setBoolean(3, entry.isAllowCommandModification()); + NpcImpl npc = entry.getNpc(); + ps.setBoolean(4, npc.isEnabled()); + ps.setString(5, npc.getUuid().toString()); + ps.setString(6, npc.getWorldName()); + ps.setDouble(7, npc.getLocation().getX()); + ps.setDouble(8, npc.getLocation().getY()); + ps.setDouble(9, npc.getLocation().getZ()); + ps.setFloat(10, npc.getLocation().getYaw()); + ps.setFloat(11, npc.getLocation().getPitch()); + ps.setString(12, npc.getType().getName()); + HologramImpl hologram = npc.getHologram(); + ps.setDouble(13, hologram.getOffset()); + ps.setBigDecimal(14, new BigDecimal(hologram.getRefreshDelay())); + + ps.executeUpdate(); + + ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_PROPERTIES + " WHERE npc_id = ?"); + ps.setString(1, entry.getId()); + ps.executeUpdate(); + + for (EntityProperty property : npc.getAllProperties()) try { + PropertySerializer serializer = propertyRegistry.getSerializer(((EntityPropertyImpl) property).getType()); + if (serializer == null) { + logger.warning("Unknown serializer for property '" + property.getName() + "' for npc '" + entry.getId() + "'. skipping ..."); + continue; + } + ps = database.getSQLConnection().prepareStatement("REPLACE INTO " + TABLE_NPCS_PROPERTIES + " (npc_id, property, value) VALUES(?,?,?)"); + ps.setString(1, entry.getId()); + ps.setString(2, property.getName()); + ps.setString(3, serializer.UNSAFE_serialize(npc.getProperty(property))); + ps.executeUpdate(); + } catch (Exception exception) { + logger.severe("Failed to serialize property " + property.getName() + " for npc with id " + entry.getId()); + exception.printStackTrace(); + } + + ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_HOLOGRAMS + " WHERE npc_id = ? AND line > ?"); + ps.setString(1, entry.getId()); + ps.setInt(2, hologram.getLines().size() - 1); + ps.executeUpdate(); + + for (int i = 0; i < hologram.getLines().size(); i++) { + ps = database.getSQLConnection().prepareStatement("REPLACE INTO " + TABLE_NPCS_HOLOGRAMS + " (npc_id, line, text) VALUES(?,?,?)"); + ps.setString(1, entry.getId()); + ps.setInt(2, i); + ps.setString(3, hologram.getLine(i)); + ps.executeUpdate(); + } + + ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_ACTIONS + " WHERE npc_id = ? AND action_id > ?"); + ps.setString(1, entry.getId()); + ps.setInt(2, npc.getActions().size() - 1); + ps.executeUpdate(); + + for (int i = 0; i < npc.getActions().size(); i++) { + ps = database.getSQLConnection().prepareStatement("REPLACE INTO " + TABLE_NPCS_ACTIONS + " (npc_id, action_id, action_data) VALUES(?,?,?)"); + ps.setString(1, entry.getId()); + ps.setInt(2, i); + String action = actionRegistry.serialize(npc.getActions().get(i)); + if (action == null) continue; + ps.setString(3, action); + ps.executeUpdate(); + } + } catch (SQLException exception) { + logger.severe("Failed to save npc with id " + entry.getId()); + exception.printStackTrace(); + } + if (configManager.getConfig().debugEnabled()) { + logger.info("Saved " + npcs.size() + " npcs in " + (System.currentTimeMillis() - start) + "ms"); + } + } + + @Override + public void deleteNpc(NpcEntryImpl entry) { + try { + PreparedStatement ps; + ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS + " WHERE id = ?"); + ps.setString(1, entry.getId()); + ps.executeUpdate(); + + ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_PROPERTIES + " WHERE npc_id = ?"); + ps.setString(1, entry.getId()); + ps.executeUpdate(); + + ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_HOLOGRAMS + " WHERE npc_id = ?"); + ps.setString(1, entry.getId()); + ps.executeUpdate(); + + ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_ACTIONS + " WHERE npc_id = ?"); + ps.setString(1, entry.getId()); + ps.executeUpdate(); + } catch (SQLException exception) { + logger.severe("Failed to delete npc with id " + entry.getId()); + exception.printStackTrace(); + } + } +} diff --git a/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLiteStorage.java b/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLiteStorage.java index 0519236..005169a 100644 --- a/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLiteStorage.java +++ b/plugin/src/main/java/lol/pyr/znpcsplus/storage/sqlite/SQLiteStorage.java @@ -177,7 +177,7 @@ public class SQLiteStorage implements NpcStorage { } try { - PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS_HOLOGRAMS + " ORDER BY line ASC"); + PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS_HOLOGRAMS + " ORDER BY line"); ResultSet rs = st.executeQuery(); while (rs.next()) { @@ -192,7 +192,7 @@ public class SQLiteStorage implements NpcStorage { } try { - PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS_ACTIONS + " ORDER BY action_id ASC"); + PreparedStatement st = database.getSQLConnection().prepareStatement("SELECT * FROM " + TABLE_NPCS_ACTIONS + " ORDER BY action_id"); ResultSet rs = st.executeQuery(); while (rs.next()) { @@ -229,7 +229,7 @@ public class SQLiteStorage implements NpcStorage { ps.setString(12, npc.getType().getName()); HologramImpl hologram = npc.getHologram(); ps.setDouble(13, hologram.getOffset()); - if(hologram.getRefreshDelay() != -1) ps.setBigDecimal(14, new BigDecimal(hologram.getRefreshDelay())); + ps.setBigDecimal(14, new BigDecimal(hologram.getRefreshDelay())); ps.executeUpdate(); ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_PROPERTIES + " WHERE npc_id = ?");