Newer
Older
TreasureChest / src / main / java / de / iani / treasurechest / TreasureChest.java
package de.iani.treasurechest;

import de.iani.cubesideutils.bukkit.commands.CommandRouter;
import de.iani.playerUUIDCache.CachedPlayer;
import de.iani.playerUUIDCache.PlayerUUIDCache;
import de.iani.treasurechest.PlayerTreasureChestContent.LoadState;
import de.iani.treasurechest.commands.AddItemCommand;
import de.iani.treasurechest.commands.AddMoneyCommand;
import de.iani.treasurechest.commands.CreateCommand;
import de.iani.treasurechest.commands.GiveCommand;
import de.iani.treasurechest.commands.HelpCommand;
import de.iani.treasurechest.commands.ListCommand;
import de.iani.treasurechest.commands.RemoveCommand;
import de.iani.treasurechest.commands.SetChestCommand;
import de.iani.treasurechest.database.DatabaseTreasureChestItem;
import de.iani.treasurechest.database.SQLConfig;
import de.iani.treasurechest.database.TreasureChestDatabase;
import de.iani.treasurechest.listener.ChestInventoryListener;
import de.iani.treasurechest.listener.PlayerEventListener;
import de.iani.treasurechest.worker.WorkerThread;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;
import java.util.logging.Level;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.ChatColor;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;

public class TreasureChest extends JavaPlugin implements TreasureChestAPI {
    private TreasureChestData data;

    private Location chestLocation;

    private Random random;

    private boolean hasEconomy;

    private Economy economy;

    private PlayerUUIDCache playerUUIDCache;

    private SQLConfig sqlConfig;

    private TreasureChestDatabase database;
    private WorkerThread workerThread;

    @Override
    public void onEnable() {
        saveDefaultConfig();

        random = new Random();
        setupEconomy();
        playerUUIDCache = (PlayerUUIDCache) getServer().getPluginManager().getPlugin("PlayerUUIDCache");
        readConfig();
        try {
            database = new TreasureChestDatabase(this, sqlConfig);
        } catch (SQLException e) {
            getLogger().log(Level.SEVERE, "Could not connect to database: " + e.getMessage(), e);
            setEnabled(false);
            return;
        }

        workerThread = new WorkerThread(this);
        data = new TreasureChestData(this);

        CommandRouter treasurechestCommand = new CommandRouter(getCommand("treasurechest"));
        treasurechestCommand.addCommandMapping(new HelpCommand(this));
        treasurechestCommand.addCommandMapping(new HelpCommand(this), "help");
        treasurechestCommand.addCommandMapping(new SetChestCommand(this), "setchest");
        treasurechestCommand.addCommandMapping(new CreateCommand(this), "create");
        treasurechestCommand.addCommandMapping(new AddItemCommand(this), "additem");
        treasurechestCommand.addCommandMapping(new AddMoneyCommand(this), "addmoney");
        treasurechestCommand.addCommandMapping(new GiveCommand(this), "give");
        treasurechestCommand.addCommandMapping(new ListCommand(this), "list");
        treasurechestCommand.addCommandMapping(new RemoveCommand(this), "remove");

        getServer().getPluginManager().registerEvents(new ChestInventoryListener(this), this);
        getServer().getPluginManager().registerEvents(new PlayerEventListener(this), this);

        getServer().getScheduler().runTaskTimer(this, this::createParticles, 1, 1);
        getServer().getScheduler().runTaskTimer(this, data::doGC, 8456, 140000);
    }

    @Override
    public void onDisable() {
        if (workerThread != null) {
            workerThread.shutdown();
            workerThread = null;
        }
        if (database != null) {
            database.disconnect();
            database = null;
        }
    }

    public PlayerUUIDCache getPlayerUUIDCache() {
        return playerUUIDCache;
    }

    @Override
    public boolean addItem(String player, ItemStack displayItem, ItemStack[] items, int money) {
        if (!getServer().isPrimaryThread()) {
            return false;
        }
        CachedPlayer id = playerUUIDCache.getPlayerFromNameOrUUID(player, true);
        if (id == null) {
            return false;
        }
        return addItem(id.getUUID(), displayItem, items, money);
    }

    @Override
    public boolean addItem(OfflinePlayer player, ItemStack displayItem, ItemStack[] items, int money) {
        if (!getServer().isPrimaryThread()) {
            return false;
        }
        return addItem(player.getUniqueId(), displayItem, items, money);
    }

    private boolean addItem(UUID player, ItemStack displayItem, ItemStack[] items, int money) {
        if (displayItem == null || displayItem.getAmount() == 0 || displayItem.getType() == Material.AIR) {
            return false;
        }
        ArrayList<ItemStack> copied = new ArrayList<>();
        if (items != null) {
            for (ItemStack is : items) {
                if (is != null && is.getAmount() > 0 && is.getType() != Material.AIR) {
                    copied.add(is.clone());
                }
            }
            items = copied.toArray(new ItemStack[copied.size()]);
        }
        TreasureChestItem item = new TreasureChestItem(displayItem, items, money);
        workerThread.addWork(database -> {
            try {
                DatabaseTreasureChestItem added = database.addItem(player, item);
                if (added != null) {
                    new BukkitRunnable() {
                        @Override
                        public void run() {
                            PlayerTreasureChestContent cc = getData().getChestContent(player);
                            if (cc != null && cc.getLoadState() == LoadState.LOADED) {
                                cc.addItem(added);
                            }
                        }
                    }.runTask(TreasureChest.this);
                }
            } catch (SQLException e) {
                getLogger().log(Level.SEVERE, "Could not add treasure chest item to database: " + e.getMessage(), e);
            }
        });
        return true;
    }

    private void readConfig() {
        // saveDefaultConfig();
        FileConfiguration config = getConfig();
        ConfigurationSection section = config.getConfigurationSection("chestLocation");
        if (section != null) {
            String worldName = section.getString("world");
            int x = section.getInt("x");
            int y = section.getInt("y");
            int z = section.getInt("z");
            if (worldName != null) {
                World world = getServer().getWorld(worldName);
                if (world != null) {
                    chestLocation = new Location(world, x, y, z);
                }
            }
        }
        sqlConfig = new SQLConfig(config.getConfigurationSection("database"));
    }

    @Override
    public void saveConfig() {
        FileConfiguration config = getConfig();
        if (chestLocation == null || chestLocation.getWorld() == null) {
            config.set("chestLocation", null);
        } else {
            ConfigurationSection section = config.getConfigurationSection("chestLocation");
            if (section == null) {
                section = config.createSection("chestLocation");
            }
            section.set("world", chestLocation.getWorld().getName());
            section.set("x", chestLocation.getBlockX());
            section.set("y", chestLocation.getBlockY());
            section.set("z", chestLocation.getBlockZ());
        }
        super.saveConfig();
    }

    public TreasureChestData getData() {
        return data;
    }

    public Location getChestLocation() {
        return chestLocation;
    }

    protected void createParticles() {
        if (random.nextInt(10) == 0 && chestLocation != null && chestLocation.getWorld() != null) {
            Location playerLocation = new Location(null, 0, 0, 0);
            for (Player player : getServer().getOnlinePlayers()) {
                if (player.getWorld() == chestLocation.getWorld()) {
                    player.getLocation(playerLocation);
                    double dx = playerLocation.getX() - chestLocation.getX();
                    double dy = playerLocation.getY() - chestLocation.getY();
                    double dz = playerLocation.getZ() - chestLocation.getZ();
                    double dsquared = dx * dx + dy * dy + dz * dz;
                    if (dsquared < 24 * 24) {
                        PlayerTreasureChestContent playerData = data.getChestContent(player.getUniqueId());
                        if (playerData != null) {
                            playerData.loadAsync();
                            if (!playerData.isEmpty()) {
                                player.playEffect(chestLocation, Effect.MOBSPAWNER_FLAMES, null);
                            }
                        }
                    }
                }
            }
        }
    }

    public void sendMessage(CommandSender p, String text) {
        sendMessage(p, text, false);
    }

    public void sendMessage(CommandSender p, String text, boolean error) {
        p.sendMessage(ChatColor.BLUE + "[TC] " + (error ? ChatColor.DARK_RED : ChatColor.YELLOW) + text);
    }

    public void setChestLocation(Location location) {
        chestLocation = location;
        saveConfig();
    }

    public SQLConfig getSqlConfig() {
        return sqlConfig;
    }

    private void setupEconomy() {
        try {
            RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
            if (economyProvider != null && economyProvider.getProvider() != null) {
                economy = economyProvider.getProvider();
                hasEconomy = true;
            } else {
                getLogger().warning("Kein Economy-Plugin! Es können keine Preisgelder ausgezahlt werden!");
            }
        } catch (Throwable e) {
            getLogger().warning("Vault nicht gefunden! Es können keine Preisgelder ausgezahlt werden!");
        }
    }

    public boolean hasEconomy() {
        return hasEconomy;
    }

    public void giveMoney(Player player, int amount) {
        if (hasEconomy) {
            try {
                economy.depositPlayer(player, amount);
            } catch (Throwable e) {
                getLogger().log(Level.SEVERE, "Error paying money", e);
            }
        }
    }

    public String formatMoney(int amount) {
        if (hasEconomy) {
            try {
                return economy.format(amount);
            } catch (Throwable e) {
                getLogger().log(Level.SEVERE, "Error formating money", e);
            }
        }
        return Integer.toString(amount);
    }

    public TreasureChestDatabase getDatabase() {
        return database;
    }

    public WorkerThread getWorkerThread() {
        return workerThread;
    }
}