New data system.

This commit is contained in:
Brianna 2019-08-02 09:59:10 -04:00
parent 237117dd1f
commit 17e4c6709a
15 changed files with 635 additions and 122 deletions

View File

@ -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
View File

@ -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>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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 " +
")");
}
}
}

View File

@ -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"))

View File

@ -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);
}
}

View File

@ -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:{"

View File

@ -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) {

View File

@ -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;