package de.iani.treasurechest;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;
import java.util.logging.Level;
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;
import de.iani.playerUUIDCache.CachedPlayer;
import de.iani.playerUUIDCache.PlayerUUIDCache;
import de.iani.treasurechest.PlayerTreasureChestContent.LoadState;
import de.iani.treasurechest.database.DatabaseTreasureChestItem;
import de.iani.treasurechest.database.SQLConfig;
import de.iani.treasurechest.database.TreasureChestDatabase;
import de.iani.treasurechest.worker.WorkEntry;
import de.iani.treasurechest.worker.WorkerThread;
import net.milkbowl.vault.economy.Economy;
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(sqlConfig);
} catch (SQLException e) {
getLogger().log(Level.SEVERE, "Could not connect to database: " + e.getMessage(), e);
setEnabled(false);
return;
}
new Converter(this).convertAll();
workerThread = new WorkerThread(this);
data = new TreasureChestData(this);
getCommand("treasurechest").setExecutor(new TreasureChestCommandExecutor(this));
getServer().getPluginManager().registerEvents(new ChestInventoryListener(this), this);
getServer().getPluginManager().registerEvents(new PlayerEventListener(this), this);
getServer().getScheduler().runTaskTimer(this, new Runnable() {
@Override
public void run() {
createParticles();
}
}, 1, 1);
getServer().getScheduler().runTaskTimer(this, new Runnable() {
@Override
public void run() {
data.doGC();
}
}, 8456, 140000);
}
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<>();
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(new WorkEntry() {
@Override
public void process(TreasureChestDatabase 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 static String capitalize(String s, boolean replaceUnderscores) {
char[] cap = s.toCharArray();
boolean lastSpace = true;
for (int i = 0; i < cap.length; i++) {
if (cap[i] == '_') {
if (replaceUnderscores) {
cap[i] = ' ';
}
lastSpace = true;
} else if (cap[i] >= '0' && cap[i] <= '9') {
lastSpace = true;
} else {
if (lastSpace) {
cap[i] = Character.toUpperCase(cap[i]);
} else {
cap[i] = Character.toLowerCase(cap[i]);
}
lastSpace = false;
}
}
return new String(cap);
}
public TreasureChestDatabase getDatabase() {
return database;
}
public WorkerThread getWorkerThread() {
return workerThread;
}
}