Added MySQL Storage option
This commit is contained in:
parent
c423793fc8
commit
788e962d37
6 changed files with 494 additions and 4 deletions
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package lol.pyr.znpcsplus.config;
|
||||||
import lol.pyr.znpcsplus.storage.NpcStorageType;
|
import lol.pyr.znpcsplus.storage.NpcStorageType;
|
||||||
import space.arim.dazzleconf.annote.ConfComments;
|
import space.arim.dazzleconf.annote.ConfComments;
|
||||||
import space.arim.dazzleconf.annote.ConfKey;
|
import space.arim.dazzleconf.annote.ConfKey;
|
||||||
|
import space.arim.dazzleconf.annote.SubSection;
|
||||||
|
|
||||||
import static space.arim.dazzleconf.annote.ConfDefault.*;
|
import static space.arim.dazzleconf.annote.ConfDefault.*;
|
||||||
|
|
||||||
|
@ -28,10 +29,15 @@ public interface MainConfig {
|
||||||
boolean debugEnabled();
|
boolean debugEnabled();
|
||||||
|
|
||||||
@ConfKey("storage-type")
|
@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")
|
@DefaultString("YAML")
|
||||||
NpcStorageType storageType();
|
NpcStorageType storageType();
|
||||||
|
|
||||||
|
@ConfKey("database-config")
|
||||||
|
@ConfComments("The database config. Only used if storage-type is MYSQL")
|
||||||
|
@SubSection
|
||||||
|
DatabaseConfig databaseConfig();
|
||||||
|
|
||||||
@ConfKey("disable-skin-fetcher-warnings")
|
@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")
|
@ConfComments("Set this to true if you don't want to be warned in the console when a skin fails to resolve")
|
||||||
@DefaultBoolean(false)
|
@DefaultBoolean(false)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
||||||
import lol.pyr.znpcsplus.interaction.ActionRegistry;
|
import lol.pyr.znpcsplus.interaction.ActionRegistry;
|
||||||
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
|
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
|
||||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
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.sqlite.SQLiteStorage;
|
||||||
import lol.pyr.znpcsplus.storage.yaml.YamlStorage;
|
import lol.pyr.znpcsplus.storage.yaml.YamlStorage;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
|
@ -29,6 +30,17 @@ public enum NpcStorageType {
|
||||||
return null;
|
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);
|
public abstract NpcStorage create(ConfigManager configManager, ZNpcsPlus plugin, PacketFactory packetFactory, ActionRegistry actionRegistry, NpcTypeRegistryImpl typeRegistry, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer);
|
||||||
|
|
115
plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQL.java
Normal file
115
plugin/src/main/java/lol/pyr/znpcsplus/storage/mysql/MySQL.java
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<NpcEntryImpl> loadNpcs() {
|
||||||
|
Map<String, NpcEntryImpl> 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<NpcEntryImpl> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -177,7 +177,7 @@ public class SQLiteStorage implements NpcStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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();
|
ResultSet rs = st.executeQuery();
|
||||||
|
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
|
@ -192,7 +192,7 @@ public class SQLiteStorage implements NpcStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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();
|
ResultSet rs = st.executeQuery();
|
||||||
|
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
|
@ -229,7 +229,7 @@ public class SQLiteStorage implements NpcStorage {
|
||||||
ps.setString(12, npc.getType().getName());
|
ps.setString(12, npc.getType().getName());
|
||||||
HologramImpl hologram = npc.getHologram();
|
HologramImpl hologram = npc.getHologram();
|
||||||
ps.setDouble(13, hologram.getOffset());
|
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.executeUpdate();
|
||||||
|
|
||||||
ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_PROPERTIES + " WHERE npc_id = ?");
|
ps = database.getSQLConnection().prepareStatement("DELETE FROM " + TABLE_NPCS_PROPERTIES + " WHERE npc_id = ?");
|
||||||
|
|
Loading…
Reference in a new issue