mirror of
https://github.com/songoda/UltimateStacker.git
synced 2024-09-28 06:27:28 +02:00
New data system.
This commit is contained in:
parent
237117dd1f
commit
17e4c6709a
@ -4,7 +4,7 @@ stages:
|
||||
variables:
|
||||
name: "UltimateStacker"
|
||||
path: "/builds/$CI_PROJECT_PATH"
|
||||
version: "1.8.7"
|
||||
version: "1.8.8"
|
||||
|
||||
build:
|
||||
stage: build
|
||||
|
17
pom.xml
17
pom.xml
@ -34,6 +34,9 @@
|
||||
<includes>
|
||||
<include>com.songoda:songodaupdater</include>
|
||||
<include>com.songoda:Lootables</include>
|
||||
<include>com.zaxxer:HikariCP</include>
|
||||
<include>org.slf4j:slf4j-api</include>
|
||||
<include>org.slf4j:slf4j-nop</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<filters>
|
||||
@ -57,6 +60,10 @@
|
||||
<id>private</id>
|
||||
<url>http://repo.songoda.com/artifactory/private/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>CodeMC</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@ -109,5 +116,15 @@
|
||||
<artifactId>Clearlag</artifactId>
|
||||
<version>3.0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.23.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.songoda.ultimatestacker;
|
||||
|
||||
import com.songoda.ultimatestacker.command.CommandManager;
|
||||
import com.songoda.ultimatestacker.database.*;
|
||||
import com.songoda.ultimatestacker.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.hologram.Hologram;
|
||||
@ -13,7 +14,6 @@ import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStackManager;
|
||||
import com.songoda.ultimatestacker.storage.Storage;
|
||||
import com.songoda.ultimatestacker.storage.StorageRow;
|
||||
import com.songoda.ultimatestacker.storage.types.StorageMysql;
|
||||
import com.songoda.ultimatestacker.storage.types.StorageYaml;
|
||||
import com.songoda.ultimatestacker.tasks.StackingTask;
|
||||
import com.songoda.ultimatestacker.utils.*;
|
||||
@ -33,6 +33,7 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -53,22 +54,22 @@ public class UltimateStacker extends JavaPlugin {
|
||||
private StackingTask stackingTask;
|
||||
private Hologram hologram;
|
||||
|
||||
private DatabaseConnector databaseConnector;
|
||||
private DataMigrationManager dataMigrationManager;
|
||||
private DataManager dataManager;
|
||||
|
||||
private EntityUtils entityUtils;
|
||||
|
||||
private List<StackerHook> stackerHooks = new ArrayList<>();
|
||||
|
||||
private ServerVersion serverVersion = ServerVersion.fromPackageName(Bukkit.getServer().getClass().getPackage().getName());
|
||||
private Storage storage;
|
||||
|
||||
public static UltimateStacker getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
this.saveToFile();
|
||||
this.storage.closeConnection();
|
||||
if (hologram != null)
|
||||
this.hologram.unloadHolograms();
|
||||
this.dataManager.bulkUpdateSpawners(this.spawnerStackManager.getStacks());
|
||||
|
||||
ConsoleCommandSender console = Bukkit.getConsoleSender();
|
||||
console.sendMessage(Methods.formatText("&a============================="));
|
||||
@ -137,31 +138,6 @@ public class UltimateStacker extends JavaPlugin {
|
||||
this.entityStackManager = new EntityStackManager();
|
||||
this.stackingTask = new StackingTask(this);
|
||||
|
||||
checkStorage();
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> {
|
||||
if (storage.containsGroup("spawners")) {
|
||||
for (StorageRow row : storage.getRowsByGroup("spawners")) {
|
||||
try {
|
||||
Location location = Methods.unserializeLocation(row.getKey());
|
||||
|
||||
SpawnerStack stack = new SpawnerStack(
|
||||
location,
|
||||
row.get("amount").asInt());
|
||||
|
||||
this.spawnerStackManager.addSpawner(stack);
|
||||
} catch (Exception e) {
|
||||
console.sendMessage("Failed to load spawner.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save data initially so that if the person reloads again fast they don't lose all their data.
|
||||
this.saveToFile();
|
||||
if (hologram != null)
|
||||
hologram.loadHolograms();
|
||||
}, 10);
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
if (isServerVersionAtLeast(ServerVersion.V1_10))
|
||||
pluginManager.registerEvents(new BreedListeners(this), this);
|
||||
@ -189,11 +165,68 @@ public class UltimateStacker extends JavaPlugin {
|
||||
stackerHooks.add(new JobsHook());
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskTimerAsynchronously(this, this::saveToFile, 6000, 6000);
|
||||
|
||||
// Starting Metrics
|
||||
new Metrics(this);
|
||||
|
||||
// Legacy Data
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> {
|
||||
File folder = getDataFolder();
|
||||
File dataFile = new File(folder, "data.yml");
|
||||
|
||||
if (dataFile.exists()) {
|
||||
Storage storage = new StorageYaml(this);
|
||||
if (storage.containsGroup("spawners")) {
|
||||
for (StorageRow row : storage.getRowsByGroup("spawners")) {
|
||||
try {
|
||||
Location location = Methods.unserializeLocation(row.getKey());
|
||||
|
||||
SpawnerStack stack = new SpawnerStack(
|
||||
location,
|
||||
row.get("amount").asInt());
|
||||
|
||||
getDataManager().createSpawner(stack);
|
||||
} catch (Exception e) {
|
||||
console.sendMessage("Failed to load spawner.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
dataFile.delete();
|
||||
}
|
||||
}, 10);
|
||||
|
||||
// Database stuff, go!
|
||||
try {
|
||||
if (Setting.MYSQL_ENABLED.getBoolean()) {
|
||||
String hostname = Setting.MYSQL_HOSTNAME.getString();
|
||||
int port = Setting.MYSQL_PORT.getInt();
|
||||
String database = Setting.MYSQL_DATABASE.getString();
|
||||
String username = Setting.MYSQL_USERNAME.getString();
|
||||
String password = Setting.MYSQL_PASSWORD.getString();
|
||||
boolean useSSL = Setting.MYSQL_USE_SSL.getBoolean();
|
||||
|
||||
this.databaseConnector = new MySQLConnector(this, hostname, port, database, username, password, useSSL);
|
||||
this.getLogger().info("Data handler connected using MySQL.");
|
||||
} else {
|
||||
this.databaseConnector = new SQLiteConnector(this);
|
||||
this.getLogger().info("Data handler connected using SQLite.");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
this.getLogger().severe("Fatal error trying to connect to database. Please make sure all your connection settings are correct and try again. Plugin has been disabled.");
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
this.dataManager = new DataManager(this.databaseConnector, this);
|
||||
this.dataMigrationManager = new DataMigrationManager(this.databaseConnector, this.dataManager);
|
||||
this.dataMigrationManager.runMigrations();
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> {
|
||||
this.dataManager.getSpawners((spawners) -> {
|
||||
this.spawnerStackManager.addSpawners(spawners);
|
||||
this.hologram.loadHolograms();
|
||||
});
|
||||
}, 20L);
|
||||
|
||||
console.sendMessage(Methods.formatText("&a============================="));
|
||||
}
|
||||
|
||||
@ -203,21 +236,6 @@ public class UltimateStacker extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkStorage() {
|
||||
if (getConfig().getBoolean("Database.Activate Mysql Support")) {
|
||||
this.storage = new StorageMysql(this);
|
||||
} else {
|
||||
this.storage = new StorageYaml(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveToFile() {
|
||||
this.storage.closeConnection();
|
||||
checkStorage();
|
||||
|
||||
storage.doSave();
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
this.locale = Locale.getLocale(getConfig().getString("System.Language Mode"));
|
||||
this.locale.reloadMessages();
|
||||
@ -301,4 +319,12 @@ public class UltimateStacker extends JavaPlugin {
|
||||
public EntityUtils getEntityUtils() {
|
||||
return entityUtils;
|
||||
}
|
||||
|
||||
public DatabaseConnector getDatabaseConnector() {
|
||||
return databaseConnector;
|
||||
}
|
||||
|
||||
public DataManager getDataManager() {
|
||||
return dataManager;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,149 @@
|
||||
package com.songoda.ultimatestacker.database;
|
||||
|
||||
import com.songoda.ultimatestacker.spawner.SpawnerStack;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class DataManager {
|
||||
|
||||
private final DatabaseConnector databaseConnector;
|
||||
private final Plugin plugin;
|
||||
|
||||
public DataManager(DatabaseConnector databaseConnector, Plugin plugin) {
|
||||
this.databaseConnector = databaseConnector;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the prefix to be used by all table names
|
||||
*/
|
||||
public String getTablePrefix() {
|
||||
return this.plugin.getDescription().getName().toLowerCase() + '_';
|
||||
}
|
||||
|
||||
public void bulkUpdateSpawners(Collection<SpawnerStack> spawnerStacks) {
|
||||
this.databaseConnector.connect(connection -> {
|
||||
String updateSpawner = "UPDATE " + this.getTablePrefix() + "spawners SET amount = ? WHERE world = ? AND x = ? AND y = ? and z = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(updateSpawner)) {
|
||||
for (SpawnerStack spawnerStack : spawnerStacks) {
|
||||
statement.setInt(1, spawnerStack.getAmount());
|
||||
|
||||
statement.setString(5, spawnerStack.getWorld().getName());
|
||||
statement.setInt(6, spawnerStack.getX());
|
||||
statement.setInt(7, spawnerStack.getY());
|
||||
statement.setInt(8, spawnerStack.getZ());
|
||||
statement.executeUpdate();
|
||||
statement.addBatch();
|
||||
}
|
||||
|
||||
statement.executeBatch();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void updateSpawner(SpawnerStack spawnerStack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String updateSpawner = "UPDATE " + this.getTablePrefix() + "spawners SET amount = ? WHERE world = ? AND x = ? AND y = ? and z = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(updateSpawner)) {
|
||||
statement.setInt(1, spawnerStack.getAmount());
|
||||
|
||||
statement.setString(2, spawnerStack.getWorld().getName());
|
||||
statement.setInt(3, spawnerStack.getX());
|
||||
statement.setInt(4, spawnerStack.getY());
|
||||
statement.setInt(5, spawnerStack.getZ());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
public void createSpawner(SpawnerStack spawnerStack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String createSpawner = "INSERT INTO " + this.getTablePrefix() + "spawners (amount, world, x, y, z) VALUES (?, ?, ?, ? , ?)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(createSpawner)) {
|
||||
statement.setInt(1, spawnerStack.getAmount());
|
||||
|
||||
statement.setString(2, spawnerStack.getWorld().getName());
|
||||
statement.setInt(3, spawnerStack.getX());
|
||||
statement.setInt(4, spawnerStack.getY());
|
||||
statement.setInt(5, spawnerStack.getZ());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void deleteSpawner(SpawnerStack spawnerStack) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String deleteSpawner = "DELETE FROM " + this.getTablePrefix() + "spawners WHERE world = ? AND x = ? AND y = ? and z = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(deleteSpawner)) {
|
||||
statement.setString(1, spawnerStack.getWorld().getName());
|
||||
statement.setInt(2, spawnerStack.getX());
|
||||
statement.setInt(3, spawnerStack.getY());
|
||||
statement.setInt(4, spawnerStack.getZ());
|
||||
statement.executeUpdate();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void getSpawners(Consumer<Map<Location, SpawnerStack>> callback) {
|
||||
this.async(() -> this.databaseConnector.connect(connection -> {
|
||||
String selectSpawners = "SELECT * FROM " + this.getTablePrefix() + "spawners";
|
||||
|
||||
Map<Location, SpawnerStack> spawners = new HashMap<>();
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
ResultSet result = statement.executeQuery(selectSpawners);
|
||||
while (result.next()) {
|
||||
|
||||
int amount = result.getInt("amount");
|
||||
|
||||
String world = result.getString("world");
|
||||
int x = result.getInt("x");
|
||||
int y = result.getInt("y");
|
||||
int z = result.getInt("z");
|
||||
Location location = new Location(Bukkit.getWorld(world), x, y, z);
|
||||
|
||||
SpawnerStack spawnerStack = new SpawnerStack(location, amount);
|
||||
spawners.put(location, spawnerStack);
|
||||
}
|
||||
}
|
||||
|
||||
this.sync(() -> callback.accept(spawners));
|
||||
}));
|
||||
}
|
||||
|
||||
private int lastInsertedId(Connection connection) {
|
||||
String query;
|
||||
if (this.databaseConnector instanceof SQLiteConnector) {
|
||||
query = "SELECT last_insert_rowid()";
|
||||
} else {
|
||||
query = "SELECT LAST_INSERT_ID()";
|
||||
}
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
ResultSet result = statement.executeQuery(query);
|
||||
result.next();
|
||||
return result.getInt(1);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void async(Runnable runnable) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, runnable);
|
||||
}
|
||||
|
||||
public void sync(Runnable runnable) {
|
||||
Bukkit.getScheduler().runTask(this.plugin, runnable);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.songoda.ultimatestacker.database;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public abstract class DataMigration {
|
||||
|
||||
private final int revision;
|
||||
|
||||
public DataMigration(int revision) {
|
||||
this.revision = revision;
|
||||
}
|
||||
|
||||
public abstract void migrate(Connection connection, String tablePrefix) throws SQLException;
|
||||
|
||||
/**
|
||||
* @return the revision number of this migration
|
||||
*/
|
||||
public int getRevision() {
|
||||
return this.revision;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.songoda.ultimatestacker.database;
|
||||
|
||||
import com.songoda.ultimatestacker.database.migrations._1_InitialMigration;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DataMigrationManager {
|
||||
|
||||
private List<DataMigration> migrations;
|
||||
private DatabaseConnector databaseConnector;
|
||||
private DataManager dataManager;
|
||||
|
||||
public DataMigrationManager(DatabaseConnector databaseConnector, DataManager dataManager) {
|
||||
this.databaseConnector = databaseConnector;
|
||||
this.dataManager = dataManager;
|
||||
|
||||
this.migrations = Arrays.asList(
|
||||
new _1_InitialMigration()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs any needed data migrations
|
||||
*/
|
||||
public void runMigrations() {
|
||||
this.databaseConnector.connect((connection -> {
|
||||
int currentMigration = -1;
|
||||
boolean migrationsExist;
|
||||
|
||||
String query;
|
||||
if (this.databaseConnector instanceof SQLiteConnector) {
|
||||
query = "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?";
|
||||
} else {
|
||||
query = "SHOW TABLES LIKE ?";
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
statement.setString(1, this.getMigrationsTableName());
|
||||
migrationsExist = statement.executeQuery().next();
|
||||
}
|
||||
|
||||
if (!migrationsExist) {
|
||||
// No migration table exists, create one
|
||||
String createTable = "CREATE TABLE " + this.getMigrationsTableName() + " (migration_version INT NOT NULL)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(createTable)) {
|
||||
statement.execute();
|
||||
}
|
||||
|
||||
// Insert primary row into migration table
|
||||
String insertRow = "INSERT INTO " + this.getMigrationsTableName() + " VALUES (?)";
|
||||
try (PreparedStatement statement = connection.prepareStatement(insertRow)) {
|
||||
statement.setInt(1, -1);
|
||||
statement.execute();
|
||||
}
|
||||
} else {
|
||||
// Grab the current migration version
|
||||
String selectVersion = "SELECT migration_version FROM " + this.getMigrationsTableName();
|
||||
try (PreparedStatement statement = connection.prepareStatement(selectVersion)) {
|
||||
ResultSet result = statement.executeQuery();
|
||||
result.next();
|
||||
currentMigration = result.getInt("migration_version");
|
||||
}
|
||||
}
|
||||
|
||||
// Grab required migrations
|
||||
int finalCurrentMigration = currentMigration;
|
||||
List<DataMigration> requiredMigrations = this.migrations
|
||||
.stream()
|
||||
.filter(x -> x.getRevision() > finalCurrentMigration)
|
||||
.sorted(Comparator.comparingInt(DataMigration::getRevision))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// Nothing to migrate, abort
|
||||
if (requiredMigrations.isEmpty())
|
||||
return;
|
||||
|
||||
// Migrate the data
|
||||
for (DataMigration dataMigration : requiredMigrations)
|
||||
dataMigration.migrate(connection, this.dataManager.getTablePrefix());
|
||||
|
||||
// Set the new current migration to be the highest migrated to
|
||||
currentMigration = requiredMigrations
|
||||
.stream()
|
||||
.map(DataMigration::getRevision)
|
||||
.max(Integer::compareTo)
|
||||
.orElse(-1);
|
||||
|
||||
String updateVersion = "UPDATE " + this.getMigrationsTableName() + " SET migration_version = ?";
|
||||
try (PreparedStatement statement = connection.prepareStatement(updateVersion)) {
|
||||
statement.setInt(1, currentMigration);
|
||||
statement.execute();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the migrations table
|
||||
*/
|
||||
private String getMigrationsTableName() {
|
||||
return this.dataManager.getTablePrefix() + "migrations";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.songoda.ultimatestacker.database;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public interface DatabaseConnector {
|
||||
|
||||
/**
|
||||
* Checks if the connection to the database has been created
|
||||
*
|
||||
* @return true if the connection is created, otherwise false
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Closes all open connections to the database
|
||||
*/
|
||||
void closeConnection();
|
||||
|
||||
/**
|
||||
* Executes a callback with a Connection passed and automatically closes it when finished
|
||||
*
|
||||
* @param callback The callback to execute once the connection is retrieved
|
||||
*/
|
||||
void connect(ConnectionCallback callback);
|
||||
|
||||
/**
|
||||
* Wraps a connection in a callback which will automagically handle catching sql errors
|
||||
*/
|
||||
interface ConnectionCallback {
|
||||
void accept(Connection connection) throws SQLException;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.songoda.ultimatestacker.database;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class MySQLConnector implements DatabaseConnector {
|
||||
|
||||
private final Plugin plugin;
|
||||
private HikariDataSource hikari;
|
||||
private boolean initializedSuccessfully;
|
||||
|
||||
public MySQLConnector(Plugin plugin, String hostname, int port, String database, String username, String password, boolean useSSL) {
|
||||
this.plugin = plugin;
|
||||
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database + "?useSSL=" + useSSL);
|
||||
config.setUsername(username);
|
||||
config.setPassword(password);
|
||||
config.setMaximumPoolSize(3);
|
||||
|
||||
try {
|
||||
this.hikari = new HikariDataSource(config);
|
||||
this.initializedSuccessfully = true;
|
||||
} catch (Exception ex) {
|
||||
this.initializedSuccessfully = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return this.initializedSuccessfully;
|
||||
}
|
||||
|
||||
public void closeConnection() {
|
||||
this.hikari.close();
|
||||
}
|
||||
|
||||
public void connect(ConnectionCallback callback) {
|
||||
try (Connection connection = this.hikari.getConnection()) {
|
||||
callback.accept(connection);
|
||||
} catch (SQLException ex) {
|
||||
this.plugin.getLogger().severe("An error occurred executing a MySQL query: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.songoda.ultimatestacker.database;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class SQLiteConnector implements DatabaseConnector {
|
||||
|
||||
private final Plugin plugin;
|
||||
private final String connectionString;
|
||||
private Connection connection;
|
||||
|
||||
public SQLiteConnector(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
this.connectionString = "jdbc:sqlite:" + plugin.getDataFolder() + File.separator + plugin.getDescription().getName().toLowerCase() + ".db";
|
||||
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC"); // This is required to put here for Spigot 1.10 and below for some reason
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return true; // Always available
|
||||
}
|
||||
|
||||
public void closeConnection() {
|
||||
try {
|
||||
if (this.connection != null) {
|
||||
this.connection.close();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
this.plugin.getLogger().severe("An error occurred closing the SQLite database connection: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void connect(ConnectionCallback callback) {
|
||||
if (this.connection == null) {
|
||||
try {
|
||||
this.connection = DriverManager.getConnection(this.connectionString);
|
||||
} catch (SQLException ex) {
|
||||
this.plugin.getLogger().severe("An error occurred retrieving the SQLite database connection: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
callback.accept(this.connection);
|
||||
} catch (Exception ex) {
|
||||
this.plugin.getLogger().severe("An error occurred executing an SQLite query: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.songoda.ultimatestacker.database.migrations;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import com.songoda.ultimatestacker.database.DataMigration;
|
||||
import com.songoda.ultimatestacker.database.MySQLConnector;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class _1_InitialMigration extends DataMigration {
|
||||
|
||||
public _1_InitialMigration() {
|
||||
super(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(Connection connection, String tablePrefix) throws SQLException {
|
||||
String autoIncrement = UltimateStacker.getInstance().getDatabaseConnector() instanceof MySQLConnector ? " AUTO_INCREMENT" : "";
|
||||
|
||||
// Create plugin settings table
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
statement.execute("CREATE TABLE " + tablePrefix + "spawners (" +
|
||||
"amount INTEGER NOT NULL," +
|
||||
"world TEXT NOT NULL, " +
|
||||
"x DOUBLE NOT NULL, " +
|
||||
"y DOUBLE NOT NULL, " +
|
||||
"z DOUBLE NOT NULL " +
|
||||
")");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -29,10 +29,10 @@ import java.util.List;
|
||||
|
||||
public class BlockListeners implements Listener {
|
||||
|
||||
private final UltimateStacker instance;
|
||||
private final UltimateStacker plugin;
|
||||
|
||||
public BlockListeners(UltimateStacker instance) {
|
||||
this.instance = instance;
|
||||
public BlockListeners(UltimateStacker plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
@ -42,14 +42,14 @@ public class BlockListeners implements Listener {
|
||||
ItemStack item = event.getPlayer().getInventory().getItemInHand();
|
||||
|
||||
if (block == null
|
||||
|| block.getType() != (instance.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))
|
||||
|| item.getType() != (instance.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))
|
||||
|| block.getType() != (plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))
|
||||
|| item.getType() != (plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))
|
||||
|| event.getAction() == Action.LEFT_CLICK_BLOCK) return;
|
||||
|
||||
List<String> disabledWorlds = Setting.DISABLED_WORLDS.getStringList();
|
||||
if (disabledWorlds.stream().anyMatch(worldStr -> event.getPlayer().getWorld().getName().equalsIgnoreCase(worldStr))) return;
|
||||
|
||||
if (!instance.spawnersEnabled()) return;
|
||||
if (!plugin.spawnersEnabled()) return;
|
||||
|
||||
BlockStateMeta bsm = (BlockStateMeta) item.getItemMeta();
|
||||
CreatureSpawner cs = (CreatureSpawner) bsm.getBlockState();
|
||||
@ -57,7 +57,7 @@ public class BlockListeners implements Listener {
|
||||
EntityType itemType = cs.getSpawnedType();
|
||||
|
||||
int itemAmount = getSpawnerAmount(item);
|
||||
int specific = instance.getSpawnerFile().getConfig().getInt("Spawners." + cs.getSpawnedType().name() + ".Max Stack Size");
|
||||
int specific = plugin.getSpawnerFile().getConfig().getInt("Spawners." + cs.getSpawnedType().name() + ".Max Stack Size");
|
||||
int maxStackSize = specific == -1 ? Setting.MAX_STACK_SPAWNERS.getInt() : specific;
|
||||
|
||||
cs = (CreatureSpawner) block.getState();
|
||||
@ -67,7 +67,7 @@ public class BlockListeners implements Listener {
|
||||
event.setCancelled(true);
|
||||
|
||||
if (itemType == blockType) {
|
||||
SpawnerStack stack = instance.getSpawnerStackManager().getSpawner(block);
|
||||
SpawnerStack stack = plugin.getSpawnerStackManager().getSpawner(block);
|
||||
if (player.isSneaking()) return;
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||
if (stack.getAmount() == maxStackSize) return;
|
||||
@ -93,15 +93,15 @@ public class BlockListeners implements Listener {
|
||||
}
|
||||
|
||||
stack.setAmount(stack.getAmount() + itemAmount);
|
||||
if (instance.getHologram() != null) {
|
||||
instance.getHologram().update(stack);
|
||||
if (plugin.getHologram() != null) {
|
||||
plugin.getHologram().update(stack);
|
||||
}
|
||||
Methods.takeItem(player, itemAmount);
|
||||
}
|
||||
}
|
||||
|
||||
if (instance.getHologram() != null)
|
||||
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(instance, () -> instance.getHologram().processChange(block), 10L);
|
||||
if (plugin.getHologram() != null)
|
||||
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> plugin.getHologram().processChange(block), 10L);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
@ -110,8 +110,8 @@ public class BlockListeners implements Listener {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
if (block.getType() != (instance.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))
|
||||
|| !instance.spawnersEnabled())
|
||||
if (block.getType() != (plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))
|
||||
|| !plugin.spawnersEnabled())
|
||||
return;
|
||||
|
||||
CreatureSpawner cs = (CreatureSpawner) block.getState();
|
||||
@ -125,25 +125,26 @@ public class BlockListeners implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnerStack stack = instance.getSpawnerStackManager().addSpawner(new SpawnerStack(block.getLocation(), amount));
|
||||
SpawnerStack stack = plugin.getSpawnerStackManager().addSpawner(new SpawnerStack(block.getLocation(), amount));
|
||||
plugin.getDataManager().createSpawner(stack);
|
||||
|
||||
cs.setSpawnedType(cs2.getSpawnedType());
|
||||
cs.update();
|
||||
|
||||
if (instance.getHologram() != null)
|
||||
instance.getHologram().add(stack);
|
||||
if (plugin.getHologram() != null)
|
||||
plugin.getHologram().add(stack);
|
||||
}
|
||||
|
||||
if (instance.getHologram() != null)
|
||||
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(instance, () -> instance.getHologram().processChange(block), 1L);
|
||||
if (plugin.getHologram() != null)
|
||||
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> plugin.getHologram().processChange(block), 1L);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onBlockBreak(BlockBreakEvent event) {
|
||||
Block block = event.getBlock();
|
||||
if (block.getType() != (instance.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))) return;
|
||||
if (block.getType() != (plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER"))) return;
|
||||
|
||||
if (!instance.spawnersEnabled()) return;
|
||||
if (!plugin.spawnersEnabled()) return;
|
||||
event.setExpToDrop(0);
|
||||
|
||||
CreatureSpawner cs = (CreatureSpawner) block.getState();
|
||||
@ -153,7 +154,7 @@ public class BlockListeners implements Listener {
|
||||
Player player = event.getPlayer();
|
||||
ItemStack item = player.getInventory().getItemInHand();
|
||||
|
||||
SpawnerStack stack = instance.getSpawnerStackManager().getSpawner(block);
|
||||
SpawnerStack stack = plugin.getSpawnerStackManager().getSpawner(block);
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
@ -174,13 +175,14 @@ public class BlockListeners implements Listener {
|
||||
|
||||
if (remove) {
|
||||
event.setCancelled(false);
|
||||
if (instance.getHologram() != null)
|
||||
instance.getHologram().remove(stack);
|
||||
instance.getSpawnerStackManager().removeSpawner(block.getLocation());
|
||||
if (plugin.getHologram() != null)
|
||||
plugin.getHologram().remove(stack);
|
||||
SpawnerStack spawnerStack = plugin.getSpawnerStackManager().removeSpawner(block.getLocation());
|
||||
plugin.getDataManager().deleteSpawner(spawnerStack);
|
||||
} else {
|
||||
stack.setAmount(stack.getAmount() - 1);
|
||||
if (instance.getHologram() != null)
|
||||
instance.getHologram().update(stack);
|
||||
if (plugin.getHologram() != null)
|
||||
plugin.getHologram().update(stack);
|
||||
}
|
||||
|
||||
if (player.hasPermission("ultimatestacker.spawner.nosilkdrop") || item != null && item.getEnchantments().containsKey(Enchantment.SILK_TOUCH) && player.hasPermission("ultimatestacker.spawner.silktouch"))
|
||||
|
@ -28,22 +28,22 @@ import java.util.List;
|
||||
|
||||
public class EntityListeners implements Listener {
|
||||
|
||||
private final UltimateStacker instance;
|
||||
private final UltimateStacker plugin;
|
||||
|
||||
public EntityListeners(UltimateStacker instance) {
|
||||
this.instance = instance;
|
||||
public EntityListeners(UltimateStacker plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onSpawn(CreatureSpawnEvent event) {
|
||||
LivingEntity entity = event.getEntity();
|
||||
entity.setMetadata("US_REASON", new FixedMetadataValue(instance, event.getSpawnReason().name()));
|
||||
entity.setMetadata("US_REASON", new FixedMetadataValue(plugin, event.getSpawnReason().name()));
|
||||
|
||||
if (event.getSpawnReason().name().equals("DROWNED")
|
||||
|| event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.LIGHTNING) {
|
||||
String name = event.getEntity().getCustomName();
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(instance,
|
||||
() -> instance.getEntityStackManager().addSerializedStack(entity, name), 1L);
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin,
|
||||
() -> plugin.getEntityStackManager().addSerializedStack(entity, name), 1L);
|
||||
}
|
||||
|
||||
}
|
||||
@ -60,7 +60,7 @@ public class EntityListeners implements Listener {
|
||||
|
||||
Entity entity = entities.get(0);
|
||||
|
||||
EntityStackManager stackManager = instance.getEntityStackManager();
|
||||
EntityStackManager stackManager = plugin.getEntityStackManager();
|
||||
|
||||
if (!stackManager.isStacked(entity)) return;
|
||||
|
||||
@ -74,19 +74,19 @@ public class EntityListeners implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onBlow(EntityExplodeEvent event) {
|
||||
if (!instance.spawnersEnabled()) return;
|
||||
if (!plugin.spawnersEnabled()) return;
|
||||
|
||||
List<Block> destroyed = event.blockList();
|
||||
Iterator<Block> it = destroyed.iterator();
|
||||
List<Block> toCancel = new ArrayList<>();
|
||||
while (it.hasNext()) {
|
||||
Block block = it.next();
|
||||
if (block.getType() != (instance.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER")))
|
||||
if (block.getType() != (plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.SPAWNER : Material.valueOf("MOB_SPAWNER")))
|
||||
continue;
|
||||
|
||||
Location spawnLocation = block.getLocation();
|
||||
|
||||
SpawnerStack spawner = instance.getSpawnerStackManager().getSpawner(block);
|
||||
SpawnerStack spawner = plugin.getSpawnerStackManager().getSpawner(block);
|
||||
|
||||
if (Setting.SPAWNERS_DONT_EXPLODE.getBoolean())
|
||||
toCancel.add(block);
|
||||
@ -104,9 +104,10 @@ public class EntityListeners implements Listener {
|
||||
ItemStack item = Methods.getSpawnerItem(blockType, spawner.getAmount());
|
||||
spawnLocation.getWorld().dropItemNaturally(spawnLocation.clone().add(.5, 0, .5), item);
|
||||
|
||||
instance.getSpawnerStackManager().removeSpawner(spawnLocation);
|
||||
if (instance.getHologram() != null)
|
||||
instance.getHologram().remove(spawner);
|
||||
SpawnerStack spawnerStack = plugin.getSpawnerStackManager().removeSpawner(spawnLocation);
|
||||
plugin.getDataManager().deleteSpawner(spawnerStack);
|
||||
if (plugin.getHologram() != null)
|
||||
plugin.getHologram().remove(spawner);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import com.songoda.ultimatestacker.utils.ServerVersion;
|
||||
import com.songoda.ultimatestacker.utils.settings.Setting;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
|
||||
import java.util.Random;
|
||||
@ -20,10 +21,6 @@ public class SpawnerStack {
|
||||
setAmount(amount);
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location.clone();
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
@ -31,6 +28,7 @@ public class SpawnerStack {
|
||||
public void setAmount(int amount) {
|
||||
UltimateStacker plugin = UltimateStacker.getInstance();
|
||||
this.amount = amount;
|
||||
plugin.getDataManager().updateSpawner(this);
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
if (!(location.getBlock().getState() instanceof CreatureSpawner)) return;
|
||||
@ -48,6 +46,26 @@ public class SpawnerStack {
|
||||
}, 1L);
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location.clone();
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return location.getBlockX();
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return location.getBlockY();
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return location.getBlockZ();
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return location.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SpawnerStack:{"
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.songoda.ultimatestacker.spawner;
|
||||
|
||||
import com.songoda.ultimatestacker.UltimateStacker;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
@ -10,10 +11,14 @@ import java.util.Map;
|
||||
|
||||
public class SpawnerStackManager {
|
||||
|
||||
private static final Map<Location, SpawnerStack> registeredSpawners = new HashMap<>();
|
||||
private final Map<Location, SpawnerStack> registeredSpawners = new HashMap<>();
|
||||
|
||||
public void addSpawners(Map<Location, SpawnerStack> spawners) {
|
||||
this.registeredSpawners.putAll(spawners);
|
||||
}
|
||||
|
||||
public SpawnerStack addSpawner(SpawnerStack spawnerStack) {
|
||||
registeredSpawners.put(roundLocation(spawnerStack.getLocation()), spawnerStack);
|
||||
this.registeredSpawners.put(roundLocation(spawnerStack.getLocation()), spawnerStack);
|
||||
return spawnerStack;
|
||||
}
|
||||
|
||||
@ -22,10 +27,12 @@ public class SpawnerStackManager {
|
||||
}
|
||||
|
||||
public SpawnerStack getSpawner(Location location) {
|
||||
if (!registeredSpawners.containsKey(roundLocation(location))) {
|
||||
return addSpawner(new SpawnerStack(roundLocation(location), 1));
|
||||
if (!this.registeredSpawners.containsKey(roundLocation(location))) {
|
||||
SpawnerStack spawnerStack = addSpawner(new SpawnerStack(roundLocation(location), 1));
|
||||
UltimateStacker.getInstance().getDataManager().createSpawner(spawnerStack);
|
||||
return spawnerStack;
|
||||
}
|
||||
return registeredSpawners.get(location);
|
||||
return this.registeredSpawners.get(location);
|
||||
}
|
||||
|
||||
public SpawnerStack getSpawner(Block block) {
|
||||
@ -33,11 +40,11 @@ public class SpawnerStackManager {
|
||||
}
|
||||
|
||||
public boolean isSpawner(Location location) {
|
||||
return registeredSpawners.get(location) != null;
|
||||
return this.registeredSpawners.get(location) != null;
|
||||
}
|
||||
|
||||
public Collection<SpawnerStack> getStacks() {
|
||||
return Collections.unmodifiableCollection(registeredSpawners.values());
|
||||
return Collections.unmodifiableCollection(this.registeredSpawners.values());
|
||||
}
|
||||
|
||||
private Location roundLocation(Location location) {
|
||||
|
@ -174,30 +174,17 @@ public enum Setting {
|
||||
"The text displayed above a stacked spawner where {TYPE} refers to",
|
||||
"The entities type and {AMT} is the amount currently stacked."),
|
||||
|
||||
DATABASE_SUPPORT("Database.Activate Mysql Support", false,
|
||||
"Should MySQL be used for data storage?"),
|
||||
|
||||
DATABASE_IP("Database.IP", "127.0.0.1",
|
||||
"MySQL IP"),
|
||||
|
||||
DATABASE_PORT("Database.Port", 3306,
|
||||
"MySQL Port"),
|
||||
|
||||
DATABASE_NAME("Database.Database Name", "UltimateStacker",
|
||||
"The database you are inserting data into."),
|
||||
|
||||
DATABASE_PREFIX("Database.Prefix", "US-",
|
||||
"The prefix for tables inserted into the database."),
|
||||
|
||||
DATABASE_USERNAME("Database.Username", "PUT_USERNAME_HERE",
|
||||
"MySQL Username"),
|
||||
|
||||
DATABASE_PASSWORD("Database.Password", "PUT_PASSWORD_HERE",
|
||||
"MySQL Password"),
|
||||
|
||||
LANGUGE_MODE("System.Language Mode", "en_US",
|
||||
"The enabled language file.",
|
||||
"More language files (if available) can be found in the plugins data folder.");
|
||||
"More language files (if available) can be found in the plugins data folder."),
|
||||
|
||||
MYSQL_ENABLED("MySQL.Enabled", false, "Set to 'true' to use MySQL instead of SQLite for data storage."),
|
||||
MYSQL_HOSTNAME("MySQL.Hostname", "localhost"),
|
||||
MYSQL_PORT("MySQL.Port", 3306),
|
||||
MYSQL_DATABASE("MySQL.Database", "your-database"),
|
||||
MYSQL_USERNAME("MySQL.Username", "user"),
|
||||
MYSQL_PASSWORD("MySQL.Password", "pass"),
|
||||
MYSQL_USE_SSL("MySQL.Use SSL", false);
|
||||
|
||||
private String setting;
|
||||
private Object option;
|
||||
|
Loading…
Reference in New Issue
Block a user