UltimateStacker/src/main/java/com/songoda/ultimatestacker/UltimateStacker.java

520 lines
20 KiB
Java
Raw Normal View History

2018-11-06 04:33:10 +01:00
package com.songoda.ultimatestacker;
2019-09-03 22:38:00 +02:00
import com.songoda.core.SongodaCore;
import com.songoda.core.SongodaPlugin;
import com.songoda.core.commands.CommandManager;
2019-09-09 18:08:04 +02:00
import com.songoda.core.compatibility.CompatibleMaterial;
2019-09-03 22:38:00 +02:00
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.configuration.Config;
import com.songoda.core.database.DataMigrationManager;
import com.songoda.core.database.DatabaseConnector;
import com.songoda.core.database.MySQLConnector;
import com.songoda.core.database.SQLiteConnector;
import com.songoda.core.gui.GuiManager;
import com.songoda.core.hooks.HologramManager;
2019-09-18 18:02:35 +02:00
import com.songoda.core.hooks.WorldGuardHook;
2019-09-03 22:38:00 +02:00
import com.songoda.core.utils.TextUtils;
import com.songoda.ultimatestacker.commands.*;
2019-09-03 22:38:00 +02:00
import com.songoda.ultimatestacker.database.DataManager;
import com.songoda.ultimatestacker.database.migrations._1_InitialMigration;
2018-11-06 04:33:10 +01:00
import com.songoda.ultimatestacker.entity.EntityStack;
2018-11-06 06:09:40 +01:00
import com.songoda.ultimatestacker.entity.EntityStackManager;
import com.songoda.ultimatestacker.hook.StackerHook;
import com.songoda.ultimatestacker.hook.hooks.JobsHook;
import com.songoda.ultimatestacker.listeners.*;
import com.songoda.ultimatestacker.listeners.item.ItemCurrentListener;
import com.songoda.ultimatestacker.listeners.item.ItemLegacyListener;
import com.songoda.ultimatestacker.listeners.item.ItemListeners;
2019-07-23 16:55:49 +02:00
import com.songoda.ultimatestacker.lootables.LootablesManager;
2019-09-07 23:55:16 +02:00
import com.songoda.ultimatestacker.settings.Settings;
2018-11-06 04:33:10 +01:00
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.StorageYaml;
import com.songoda.ultimatestacker.tasks.StackingTask;
2019-09-03 22:38:00 +02:00
import com.songoda.ultimatestacker.utils.EntityUtils;
import com.songoda.ultimatestacker.utils.Methods;
2019-12-27 18:42:02 +01:00
import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
2019-09-03 22:38:00 +02:00
import org.bukkit.block.Block;
import org.bukkit.block.CreatureSpawner;
2018-11-06 04:33:10 +01:00
import org.bukkit.entity.EntityType;
2019-09-03 22:38:00 +02:00
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
2019-09-03 22:38:00 +02:00
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
2019-01-23 19:01:31 +01:00
import org.bukkit.plugin.PluginManager;
2018-11-06 04:33:10 +01:00
2020-04-26 14:42:18 +02:00
import java.io.File;
import java.util.*;
2019-09-03 22:38:00 +02:00
public class UltimateStacker extends SongodaPlugin {
2018-11-06 04:33:10 +01:00
private static UltimateStacker INSTANCE;
private final static Set<String> whitelist = new HashSet();
2020-04-26 14:42:18 +02:00
private final static Set<String> blacklist = new HashSet();
2018-11-06 04:33:10 +01:00
2019-09-03 22:38:00 +02:00
private final Config mobFile = new Config(this, "mobs.yml");
private final Config itemFile = new Config(this, "items.yml");
private final Config spawnerFile = new Config(this, "spawners.yml");
2018-11-06 04:33:10 +01:00
2019-09-03 22:38:00 +02:00
private final GuiManager guiManager = new GuiManager(this);
private final List<StackerHook> stackerHooks = new ArrayList<>();
2018-11-06 04:33:10 +01:00
private EntityStackManager entityStackManager;
private SpawnerStackManager spawnerStackManager;
2019-07-23 16:55:49 +02:00
private LootablesManager lootablesManager;
2018-11-06 04:33:10 +01:00
private CommandManager commandManager;
private StackingTask stackingTask;
2018-11-06 05:41:58 +01:00
2019-08-02 15:59:10 +02:00
private DatabaseConnector databaseConnector;
private DataMigrationManager dataMigrationManager;
private DataManager dataManager;
2019-07-31 06:29:10 +02:00
private EntityUtils entityUtils;
2018-11-06 06:09:40 +01:00
public static UltimateStacker getInstance() {
return INSTANCE;
}
2019-09-03 22:38:00 +02:00
@Override
public void onPluginLoad() {
INSTANCE = this;
2019-09-18 18:02:35 +02:00
// Register WorldGuard
WorldGuardHook.addHook("mob-stacking", true);
2019-09-03 22:38:00 +02:00
}
2020-04-26 14:42:18 +02:00
2019-09-03 22:38:00 +02:00
@Override
public void onPluginDisable() {
2019-08-02 15:59:10 +02:00
this.dataManager.bulkUpdateSpawners(this.spawnerStackManager.getStacks());
2019-09-03 22:38:00 +02:00
HologramManager.removeAllHolograms();
2018-11-06 04:33:10 +01:00
}
2018-11-09 05:11:49 +01:00
@Override
2019-09-03 22:38:00 +02:00
public void onPluginEnable() {
// Run Songoda Updater
2019-09-09 18:08:04 +02:00
SongodaCore.registerPlugin(this, 16, CompatibleMaterial.IRON_INGOT);
2019-09-03 22:38:00 +02:00
// Setup Config
2019-09-07 23:55:16 +02:00
Settings.setupConfig();
2020-04-26 14:42:18 +02:00
this.setLocale(Settings.LANGUGE_MODE.getString(), false);
blacklist.clear();
whitelist.clear();
whitelist.addAll(Settings.ITEM_WHITELIST.getStringList());
blacklist.addAll(Settings.ITEM_BLACKLIST.getStringList());
2020-04-26 14:42:18 +02:00
2019-09-03 22:38:00 +02:00
// Setup plugin commands
this.commandManager = new CommandManager(this);
2020-06-28 04:12:13 +02:00
this.commandManager.addMainCommand("us")
.addSubCommands(new CommandSettings(guiManager),
new CommandRemoveAll(),
new CommandReload(),
new CommandGiveSpawner(),
new CommandSpawn(),
new CommandLootables(),
new CommandConvert(guiManager)
);
2018-11-06 04:33:10 +01:00
2019-07-31 06:29:10 +02:00
this.entityUtils = new EntityUtils();
2019-07-23 16:55:49 +02:00
this.lootablesManager = new LootablesManager();
this.lootablesManager.createDefaultLootables();
this.getLootablesManager().getLootManager().loadLootables();
2019-07-08 18:39:57 +02:00
2018-11-06 04:33:10 +01:00
for (EntityType value : EntityType.values()) {
2018-11-06 05:53:27 +01:00
if (value.isSpawnable() && value.isAlive() && !value.toString().contains("ARMOR")) {
2019-09-03 22:38:00 +02:00
mobFile.addDefault("Mobs." + value.name() + ".Enabled", true);
mobFile.addDefault("Mobs." + value.name() + ".Display Name", Methods.formatText(value.name().toLowerCase().replace("_", " "), true));
mobFile.addDefault("Mobs." + value.name() + ".Max Stack Size", -1);
mobFile.addDefault("Mobs." + value.name() + ".Kill Whole Stack", false);
2018-11-06 04:33:10 +01:00
}
}
2019-09-03 22:38:00 +02:00
mobFile.load();
mobFile.saveChanges();
2018-11-06 04:33:10 +01:00
for (Material value : Material.values()) {
2019-09-03 22:38:00 +02:00
itemFile.addDefault("Items." + value.name() + ".Has Hologram", true);
itemFile.addDefault("Items." + value.name() + ".Max Stack Size", -1);
2019-12-27 18:42:02 +01:00
itemFile.addDefault("Items." + value.name() + ".Display Name", WordUtils.capitalizeFully(value.name().toLowerCase().replace("_", " ")));
2018-11-06 04:33:10 +01:00
}
2019-09-03 22:38:00 +02:00
itemFile.load();
itemFile.saveChanges();
2018-11-06 04:33:10 +01:00
for (EntityType value : EntityType.values()) {
2018-11-06 05:53:27 +01:00
if (value.isSpawnable() && value.isAlive() && !value.toString().contains("ARMOR")) {
2019-09-03 22:38:00 +02:00
spawnerFile.addDefault("Spawners." + value.name() + ".Max Stack Size", -1);
spawnerFile.addDefault("Spawners." + value.name() + ".Display Name", Methods.formatText(value.name().toLowerCase().replace("_", " "), true));
2018-11-06 04:33:10 +01:00
}
}
2019-09-03 22:38:00 +02:00
spawnerFile.load();
spawnerFile.saveChanges();
2018-11-06 04:33:10 +01:00
this.spawnerStackManager = new SpawnerStackManager();
this.entityStackManager = new EntityStackManager();
this.stackingTask = new StackingTask(this);
2019-09-03 22:38:00 +02:00
guiManager.init();
2019-01-23 19:01:31 +01:00
PluginManager pluginManager = Bukkit.getPluginManager();
2019-09-03 22:38:00 +02:00
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_10))
pluginManager.registerEvents(new BreedListeners(this), this);
pluginManager.registerEvents(new BlockListeners(this), this);
pluginManager.registerEvents(new DeathListeners(this), this);
pluginManager.registerEvents(new ShearListeners(this), this);
pluginManager.registerEvents(new InteractListeners(this), this);
pluginManager.registerEvents(new EntityListeners(this), this);
pluginManager.registerEvents(new ItemListeners(this), this);
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_12))
pluginManager.registerEvents(new ItemCurrentListener(), this);
else
pluginManager.registerEvents(new ItemLegacyListener(), this);
pluginManager.registerEvents(new TameListeners(this), this);
pluginManager.registerEvents(new SpawnerListeners(this), this);
pluginManager.registerEvents(new SheepDyeListeners(this), this);
2018-11-06 04:33:10 +01:00
2019-09-07 23:55:16 +02:00
if (Settings.CLEAR_LAG.getBoolean() && pluginManager.isPluginEnabled("ClearLag"))
2019-06-20 09:33:29 +02:00
pluginManager.registerEvents(new ClearLagListeners(this), this);
// Register Hooks
if (pluginManager.isPluginEnabled("Jobs")) {
stackerHooks.add(new JobsHook());
}
2019-09-04 15:17:45 +02:00
HologramManager.load(this);
2019-08-02 15:59:10 +02:00
// 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 {
2019-09-07 23:55:16 +02:00
if (Settings.MYSQL_ENABLED.getBoolean()) {
String hostname = Settings.MYSQL_HOSTNAME.getString();
int port = Settings.MYSQL_PORT.getInt();
String database = Settings.MYSQL_DATABASE.getString();
String username = Settings.MYSQL_USERNAME.getString();
String password = Settings.MYSQL_PASSWORD.getString();
boolean useSSL = Settings.MYSQL_USE_SSL.getBoolean();
2019-08-02 15:59:10 +02:00
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);
2019-09-03 22:38:00 +02:00
this.dataMigrationManager = new DataMigrationManager(this.databaseConnector, this.dataManager,
new _1_InitialMigration());
2019-08-02 15:59:10 +02:00
this.dataMigrationManager.runMigrations();
Bukkit.getScheduler().runTaskLater(this, () -> {
2019-09-07 23:55:16 +02:00
final boolean useHolo = Settings.SPAWNER_HOLOGRAMS.getBoolean();
2019-08-02 15:59:10 +02:00
this.dataManager.getSpawners((spawners) -> {
this.spawnerStackManager.addSpawners(spawners);
2019-09-03 22:38:00 +02:00
if (useHolo)
loadHolograms();
2019-08-02 15:59:10 +02:00
});
}, 20L);
2018-11-06 04:33:10 +01:00
}
public void addExp(Player player, EntityStack stack) {
for (StackerHook stackerHook : stackerHooks) {
stackerHook.applyExperience(player, stack);
}
}
2019-09-03 22:38:00 +02:00
@Override
public List<Config> getExtraConfig() {
return Arrays.asList(mobFile, itemFile, spawnerFile);
}
2020-04-26 14:42:18 +02:00
2019-09-03 22:38:00 +02:00
@Override
public void onConfigReload() {
blacklist.clear();
whitelist.clear();
whitelist.addAll(Settings.ITEM_WHITELIST.getStringList());
blacklist.addAll(Settings.ITEM_BLACKLIST.getStringList());
2020-04-26 14:42:18 +02:00
this.setLocale(getConfig().getString("System.Language Mode"), true);
2018-11-06 04:33:10 +01:00
this.locale.reloadMessages();
2019-07-31 06:29:10 +02:00
this.entityUtils = new EntityUtils();
this.stackingTask.cancel();
this.stackingTask = new StackingTask(this);
2019-09-03 22:38:00 +02:00
this.mobFile.load();
this.itemFile.load();
this.spawnerFile.load();
2019-07-23 16:55:49 +02:00
this.getLootablesManager().getLootManager().loadLootables();
2018-11-06 04:33:10 +01:00
}
public boolean spawnersEnabled() {
2019-09-07 23:55:16 +02:00
return !this.getServer().getPluginManager().isPluginEnabled("EpicSpawners") && Settings.SPAWNERS_ENABLED.getBoolean();
}
2018-11-06 04:33:10 +01:00
public CommandManager getCommandManager() {
return commandManager;
}
2019-07-23 16:55:49 +02:00
public LootablesManager getLootablesManager() {
return lootablesManager;
2019-07-08 18:39:57 +02:00
}
2018-11-06 04:33:10 +01:00
public EntityStackManager getEntityStackManager() {
return entityStackManager;
}
public SpawnerStackManager getSpawnerStackManager() {
return spawnerStackManager;
}
public StackingTask getStackingTask() {
return stackingTask;
}
2019-09-03 22:38:00 +02:00
public Config getMobFile() {
2018-11-06 04:33:10 +01:00
return mobFile;
}
2019-09-03 22:38:00 +02:00
public Config getItemFile() {
2018-11-06 04:33:10 +01:00
return itemFile;
}
2019-09-03 22:38:00 +02:00
public Config getSpawnerFile() {
2018-11-06 05:53:27 +01:00
return spawnerFile;
}
2019-07-31 06:29:10 +02:00
public EntityUtils getEntityUtils() {
return entityUtils;
}
2019-08-02 15:59:10 +02:00
public DatabaseConnector getDatabaseConnector() {
return databaseConnector;
}
public DataManager getDataManager() {
return dataManager;
}
2019-09-03 22:38:00 +02:00
2020-06-03 15:44:12 +02:00
public GuiManager getGuiManager() {
return guiManager;
}
2019-09-03 22:38:00 +02:00
void loadHolograms() {
Collection<SpawnerStack> spawners = getSpawnerStackManager().getStacks();
if (spawners.isEmpty()) return;
for (SpawnerStack spawner : spawners) {
if (spawner.getLocation().getWorld() != null) {
updateHologram(spawner);
}
}
}
public void clearHologram(SpawnerStack stack) {
HologramManager.removeHologram(stack.getLocation());
}
public void updateHologram(SpawnerStack stack) {
// are holograms enabled?
2020-04-26 14:42:18 +02:00
if (!Settings.SPAWNER_HOLOGRAMS.getBoolean() || !HologramManager.getManager().isEnabled()) return;
Block block = stack.getLocation().getBlock();
if (block.getType() != CompatibleMaterial.SPAWNER.getBlockMaterial()) return;
2019-09-03 22:38:00 +02:00
// grab the spawner block
CreatureSpawner creatureSpawner = (CreatureSpawner) block.getState();
2019-09-03 22:38:00 +02:00
String name = Methods.compileSpawnerName(creatureSpawner.getSpawnedType(), stack.getAmount());
// create the hologram
HologramManager.updateHologram(stack.getLocation(), name);
}
2019-09-10 23:50:41 +02:00
public void removeHologram(Block block) {
HologramManager.removeHologram(block.getLocation());
}
2019-09-03 22:38:00 +02:00
public void updateHologram(Block block) {
// verify that this is a spawner
2019-09-09 18:08:04 +02:00
if (block.getType() != CompatibleMaterial.SPAWNER.getMaterial()) return;
2019-09-03 22:38:00 +02:00
// are holograms enabled?
2020-04-26 14:42:18 +02:00
if (!Settings.SPAWNER_HOLOGRAMS.getBoolean() || !HologramManager.getManager().isEnabled()) return;
2019-09-03 22:38:00 +02:00
// update this hologram in a tick
SpawnerStack spawner = getSpawnerStackManager().getSpawner(block);
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, () -> updateHologram(spawner), 10L);
}
//////// Convenient API //////////
2020-04-26 14:42:18 +02:00
2019-09-03 22:38:00 +02:00
/**
* Change the stacked amount for this item
2020-04-26 14:42:18 +02:00
*
* @param item item entity to update
2019-09-03 22:38:00 +02:00
* @param newAmount number of items this item represents
*/
public static void updateItemAmount(Item item, int newAmount) {
updateItemAmount(item, item.getItemStack(), newAmount);
}
/**
* Change the stacked amount for this item
*
2020-06-28 04:12:13 +02:00
* @param item item entity to update
2019-09-03 22:38:00 +02:00
* @param itemStack ItemStack that will represent this item
* @param newAmount number of items this item represents
*/
public static void updateItemAmount(Item item, ItemStack itemStack, int newAmount) {
boolean blacklisted = isMaterialBlacklisted(itemStack);
if (newAmount > (itemStack.getMaxStackSize() / 2) && !blacklisted)
itemStack.setAmount(Math.max(1, itemStack.getMaxStackSize() / 2));
else
itemStack.setAmount(newAmount);
// If amount is 0, Minecraft change the type to AIR
if (itemStack.getType() == Material.AIR)
return;
updateItemMeta(item, itemStack, newAmount);
}
public static void updateItemMeta(Item item, ItemStack itemStack, int newAmount) {
2019-09-03 22:38:00 +02:00
Material material = itemStack.getType();
String name = TextUtils.convertToInvisibleString("IS") + Methods.compileItemName(itemStack, newAmount);
boolean blacklisted = isMaterialBlacklisted(itemStack);
if (newAmount > (itemStack.getMaxStackSize() / 2) && !blacklisted) {
2019-09-03 22:38:00 +02:00
item.setMetadata("US_AMT", new FixedMetadataValue(INSTANCE, newAmount));
} else {
item.removeMetadata("US_AMT", INSTANCE);
}
item.setItemStack(itemStack);
2019-09-07 23:55:16 +02:00
if ((blacklisted && !Settings.ITEM_HOLOGRAM_BLACKLIST.getBoolean())
2019-09-03 22:38:00 +02:00
|| !INSTANCE.getItemFile().getBoolean("Items." + material + ".Has Hologram")
2019-09-07 23:55:16 +02:00
|| !Settings.ITEM_HOLOGRAMS.getBoolean()
2019-09-19 22:14:22 +02:00
|| newAmount < Settings.ITEM_MIN_HOLOGRAM_SIZE.getInt())
2019-09-03 22:38:00 +02:00
return;
item.setCustomName(name);
item.setCustomNameVisible(true);
}
/**
* Lookup the stacked size of this item
*
* @param item item to check
* @return stacker-corrected value for the stack size
*/
public static int getActualItemAmount(Item item) {
ItemStack itemStack = item.getItemStack();
int amount = itemStack.getAmount();
if (/*amount >= (itemStack.getMaxStackSize() / 2) && */item.hasMetadata("US_AMT")) {
2019-09-03 22:38:00 +02:00
return item.getMetadata("US_AMT").get(0).asInt();
} else {
return amount;
}
}
/**
* Check to see if the amount stored in this itemstack is not the stacked
* amount
*
* @param item item to check
* @return true if Item.getItemStack().getAmount() is different from the
* stacked amount
*/
public static boolean hasCustomAmount(Item item) {
if (item.hasMetadata("US_AMT")) {
return item.getItemStack().getAmount() != item.getMetadata("US_AMT").get(0).asInt();
}
return false;
}
/**
* Check to see if this material is not permitted to stack
*
* @param item Item material to check
* @return true if this material will not stack
*/
public static boolean isMaterialBlacklisted(ItemStack item) {
CompatibleMaterial mat = CompatibleMaterial.getMaterial(item);
2020-04-26 14:42:18 +02:00
if (mat == null) {
2019-09-10 20:25:48 +02:00
// this shouldn't happen, but just in case?
return item == null ? false : (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)
2020-04-26 14:42:18 +02:00
? isMaterialBlacklisted(item.getType()) : isMaterialBlacklisted(item.getType(), item.getData().getData()));
} else if (mat.usesData()) {
return isMaterialBlacklisted(mat.name()) || isMaterialBlacklisted(mat.getMaterial(), mat.getData());
} else {
return isMaterialBlacklisted(mat.name()) || isMaterialBlacklisted(mat.getMaterial());
}
}
2019-09-03 22:38:00 +02:00
/**
* Check to see if this material is not permitted to stack
*
* @param type Material to check
* @return true if this material will not stack
*/
public static boolean isMaterialBlacklisted(String type) {
return !whitelist.isEmpty() && !whitelist.contains(type)
|| !blacklist.isEmpty() && blacklist.contains(type);
2019-09-03 22:38:00 +02:00
}
/**
* Check to see if this material is not permitted to stack
*
* @param type Material to check
2019-09-03 22:38:00 +02:00
* @return true if this material will not stack
*/
public static boolean isMaterialBlacklisted(Material type) {
return !whitelist.isEmpty() && !whitelist.contains(type.name())
|| !blacklist.isEmpty() && blacklist.contains(type.name());
2019-09-03 22:38:00 +02:00
}
/**
* Check to see if this material is not permitted to stack
*
* @param type Material to check
* @param data data value for this item (for 1.12 and older servers)
2019-09-03 22:38:00 +02:00
* @return true if this material will not stack
*/
public static boolean isMaterialBlacklisted(Material type, byte data) {
String combined = type.toString() + ":" + data;
return !whitelist.isEmpty() && !whitelist.contains(combined)
|| !blacklist.isEmpty() && blacklist.contains(combined);
}
2018-11-06 04:33:10 +01:00
}