package uk.codingbadgers.brewarded;
import com.vexsoftware.votifier.model.Vote;
import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import uk.codingbadgers.bFundamentals.DatabaseSettings;
import uk.codingbadgers.bFundamentals.bFundamentals;
import uk.codingbadgers.bFundamentals.module.Module;
import uk.thecodingbadgers.bDatabaseManager.Database.BukkitDatabase;
import uk.thecodingbadgers.bDatabaseManager.DatabaseTable.DatabaseTable;
import uk.thecodingbadgers.bDatabaseManager.bDatabaseManager;
import uk.thecodingbadgers.bDatabaseManager.bDatabaseManager.DatabaseType;
/**
* The Class bRewarded.
* Main entry point to the module
*/
public class bRewarded extends Module {
/**
* The economy instance
*/
private Economy economy = null;
/**
* The amount to reward players every time they vote
*/
private double voteRewardAmount = 10000.0f;
/**
* The amount to reward players for voting on 10 different services in a day
*/
private double voteRewardBonusAmount = 100000.0f;
/**
*
*/
private List<Integer> voteRewardBonusLevels = new ArrayList<Integer>();
/**
*
*/
private List<ItemStack> rewardItemsCommon = new ArrayList<ItemStack>();
/**
*
*/
private List<ItemStack> rewardItemsRare = new ArrayList<ItemStack>();
/**
*
*/
private List<ItemStack> rewardItemsSuperRare = new ArrayList<ItemStack>();
/**
*
*/
private Double rewardItemsCommonChance = 0.9;
/**
*
*/
private Double rewardItemsRareChance = 0.09;
/**
*
*/
private Double rewardItemsSuperRareChance = 0.01;
/**
*
*/
private BukkitDatabase database = null;
/**
*
*/
private DatabaseTable voteTable = null;
/**
*
*/
final private OutputMessages message = new OutputMessages();
/**
* This is called when the module is unloaded
*/
@Override
public void onDisable() {
log(Level.INFO, getName() + " version " + getVersion() + " disabled.");
}
/**
* Called when the module is loaded.
* Allowing us to register the player and block listeners
*/
@Override
public void onEnable() {
loadLanguageFile();
loadConfig();
this.economy = bFundamentals.getEconomy();
this.database = bDatabaseManager.createDatabase("BadgerNetwork", bFundamentals.getInstance(), DatabaseType.SQL);
DatabaseSettings settings = bFundamentals.getConfigurationManager().getDatabaseSettings();
if (!this.database.login(settings.host, settings.user, settings.password, settings.port)) {
// disable logging
this.database = null;
this.voteTable = null;
}
else {
this.voteTable = this.database.createTable("bRewarded-Votes", VoteTableData.class);
}
register(new RewardedVotifierListener(this));
this.message.messageAnnounceOther = this.getLanguageValue("ANNOUNCE-VOTE-OTHERS");
this.message.messageAnnounce = this.getLanguageValue("ANNOUNCE-VOTE-TO-PLAYER");
this.message.messageAnnounceOtherRewardAmount = this.getLanguageValue("ANNOUNCE-VOTE-REWARD-AMOUNT-OTHERS");
this.message.messageAnnounceRewardAmount = this.getLanguageValue("ANNOUNCE-VOTE-REWARD-AMOUNT");
this.message.messageAnnounceOtherRewardBonus = this.getLanguageValue("ANNOUNCE-VOTE-REWARD-BONUS-OTHERS");
this.message.messageAnnounceRewardBonus = this.getLanguageValue("ANNOUNCE-VOTE-REWARD-BONUS");
this.message.messageAnnounceRandomReward = this.getLanguageValue("ANNOUNCE-REWARD-REWARD");
log(Level.INFO, getName() + " version " + getVersion() + " enabled.");
}
/**
*
*/
public void loadConfig() {
File confFile = new File(getDataFolder(), "config.yml");
if (!confFile.exists()) {
createDefaultConfig(confFile);
}
FileConfiguration config = this.getConfig();
this.voteRewardAmount = config.getDouble("vote.reward.amount");
this.voteRewardBonusAmount = config.getDouble("vote.reward.bonus.amount");
this.voteRewardBonusLevels = config.getIntegerList("vote.reward.bonus.levels");
List<String> commonRewards = config.getStringList("vote.bonus.items.common.items");
List<String> rareRewards = config.getStringList("vote.bonus.items.rare.items");
List<String> superRareRewards = config.getStringList("vote.bonus.items.superrare.items");
for (String reward : commonRewards) {
ItemStack material = parseMaterial(reward);
if (material != null) {
this.rewardItemsCommon.add(material);
this.log(Level.INFO, "Loaded: " + reward);
}
}
for (String reward : rareRewards) {
ItemStack material = parseMaterial(reward);
if (material != null) {
this.rewardItemsRare.add(material);
this.log(Level.INFO, "Loaded: " + reward);
}
}
for (String reward : superRareRewards) {
ItemStack material = parseMaterial(reward);
if (material != null) {
this.rewardItemsSuperRare.add(material);
this.log(Level.INFO, "Loaded: " + reward);
}
}
this.rewardItemsCommonChance = config.getDouble("vote.bonus.items.common.chance");
this.rewardItemsRareChance = config.getDouble("vote.bonus.items.rare.chance");
this.rewardItemsSuperRareChance = config.getDouble("vote.bonus.items.superrare.chance");
}
/**
*
*/
private void createDefaultConfig(File file) {
FileConfiguration config = this.getConfig();
config.set("vote.reward.amount", 25000);
config.set("vote.reward.bonus.amount", 50000);
List<Integer> bonusLevels = new ArrayList<Integer>();
bonusLevels.add(4); bonusLevels.add(8); bonusLevels.add(12);
config.set("vote.reward.bonus.levels", bonusLevels);
// common items
List<String> commonRewards = new ArrayList<String>();
commonRewards.add(Material.IRON_CHESTPLATE.name());
commonRewards.add(Material.IRON_INGOT.name() + ":" + 16);
commonRewards.add(Material.COAL.name() + ":" + 64);
config.set("vote.bonus.items.common.items", commonRewards);
config.set("vote.bonus.items.common.chance", 0.9);
// rare items
List<String> rareRewards = new ArrayList<String>();
rareRewards.add(Material.DIAMOND.name());
rareRewards.add(Material.GOLD_INGOT.name() + ":" + 64);
config.set("vote.bonus.items.rare.items", rareRewards);
config.set("vote.bonus.items.rare.chance", 0.09);
// superrare items
List<String> superRareRewards = new ArrayList<String>();
superRareRewards.add(Material.DIAMOND_CHESTPLATE.name());
config.set("vote.bonus.items.superrare.items", superRareRewards);
config.set("vote.bonus.items.superrare.chance", 0.01);
try {
config.save(file);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
*
* @param materialName
* @return
*/
private ItemStack parseMaterial(String materialName) {
// Format: <id>
// Format: <id>:<quantity>
// Format: <id>:<quantity>:<data>
// Format: <id>:<quantity>:<data>:<name>
String[] parts = materialName.split(":");
Material material = null;
try {
material = Material.getMaterial(parts[0]);
} catch (Exception ex) {
try {
material = Material.valueOf(parts[0]);
} catch (Exception ex2) {
return null;
}
}
if (parts.length == 1) {
return new ItemStack(material);
}
int quantity = 1;
try {
quantity = Integer.parseInt(parts[1]);
}
catch (Exception ex) {
return null;
}
if (parts.length == 2) {
ItemStack item = new ItemStack(material);
item.setAmount(quantity);
return item;
}
byte data = 0;
try {
data = Byte.parseByte(parts[2]);
}
catch (Exception ex) {
return null;
}
if (parts.length == 3) {
ItemStack item = new ItemStack(material);
item.setAmount(quantity);
MaterialData matData = item.getData();
matData.setData(data);
item.setData(matData);
return item;
}
String name = parts[3];
if (parts.length == 4) {
ItemStack item = new ItemStack(material);
item.setAmount(quantity);
MaterialData matData = item.getData();
matData.setData(data);
item.setData(matData);
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(name);
item.setItemMeta(itemMeta);
return item;
}
return null;
}
/**
* Log a vote to a database
* @param vote The vote to log
*/
public void logVote(final Vote vote) {
if (this.voteTable != null) {
VoteTableData newVote = new VoteTableData();
newVote.server = Bukkit.getServerName();
newVote.service = vote.getServiceName();
newVote.username = vote.getUsername();
newVote.timestamp = System.currentTimeMillis();
this.voteTable.insert(newVote, VoteTableData.class, true);
}
}
/**
* Pay the person who voted
* @param vote The vote to process
*/
public void payVotee(final Vote vote) {
if (this.economy != null) {
final String user = vote.getUsername();
this.economy.depositPlayer(user, this.voteRewardAmount);
output(
vote,
formatMessage(this.message.messageAnnounceOtherRewardAmount, vote, this.voteRewardAmount),
formatMessage(this.message.messageAnnounceRewardAmount, vote, this.voteRewardAmount)
);
int votesToday = getNumberOfServicesToday(user);
final OfflinePlayer player = Bukkit.getOfflinePlayer(user);
if (player.isOnline()) {
String site = votesToday == 1 ? "site" : "sites";
Module.sendMessage(this.getName(), player.getPlayer(), "You have voted on " + votesToday + " " + site + " in the past 24 hours...");
}
for (int bonusLevel : voteRewardBonusLevels) {
if (votesToday == bonusLevel) {
this.economy.depositPlayer(user, this.voteRewardBonusAmount);
output(
vote,
formatMessage(this.message.messageAnnounceOtherRewardBonus, vote, this.voteRewardBonusAmount),
formatMessage(this.message.messageAnnounceRewardBonus, vote, this.voteRewardBonusAmount)
);
break;
}
}
}
}
/**
* Give the person who voted a random reward
* @param vote The vote to process
*/
public void rewardVotee(final Vote vote) {
Double[] tiers = new Double[]
{
this.rewardItemsCommonChance,
this.rewardItemsRareChance,
this.rewardItemsSuperRareChance
};
Double totalChance = 0.0;
for (Double tier : tiers) {
totalChance += tier;
}
Random random = new Random();
Double randomTier = random.nextDouble() * totalChance;
Double currentTierLevel = 0.0;
int tierIndex = 0;
for (Double tier : tiers) {
if (randomTier < tier) {
break;
}
currentTierLevel += tier;
tierIndex++;
}
List<ItemStack> items = null;
// Common
if (tierIndex == 0) {
items = this.rewardItemsCommon;
}
// Rare
else if (tierIndex == 1) {
items = this.rewardItemsRare;
}
// Super Rare
else if (tierIndex == 2) {
items = this.rewardItemsSuperRare;
}
if (items == null) {
items = this.rewardItemsCommon;
}
if (items.isEmpty()) {
return;
}
int itemIndex = random.nextInt(items.size());
ItemStack item = items.get(itemIndex).clone();
OfflinePlayer player = Bukkit.getOfflinePlayer(vote.getUsername());
if (player.isOnline()) {
Player onlinePlayer = player.getPlayer();
onlinePlayer.getInventory().addItem(item);
onlinePlayer.updateInventory();
Module.sendMessage(this.getName(), player.getPlayer(), formatRandomReward(item, vote));
}
}
/**
* Announce a vote to the server network
* @param vote The vote to process
*/
public void announceVote(final Vote vote) {
output(vote, formatMessage(this.message.messageAnnounceOther, vote, 0.0), formatMessage(this.message.messageAnnounce, vote, 0.0));
}
/**
*
* @param vote
* @param othersMessage
* @param playerMessage
*/
private void output(final Vote vote, String othersMessage, String playerMessage) {
final OfflinePlayer player = Bukkit.getOfflinePlayer(vote.getUsername());
// Tell the server
for (Player otherPlayer : Bukkit.getOnlinePlayers()) {
if (otherPlayer.getName().equalsIgnoreCase(player.getName())) {
continue;
}
Module.sendMessage(this.getName(), otherPlayer, othersMessage);
}
// Tell the player if they are online
if (player.isOnline()) {
Module.sendMessage(this.getName(), player.getPlayer(), playerMessage);
}
}
/**
*
* @param playerName
* @return
*/
private int getNumberOfServicesToday(String playerName) {
if (this.voteTable != null) {
final long time24h = 86400000;
final long minTime = System.currentTimeMillis() - time24h;
ResultSet result = this.database.queryResult(
"SELECT * FROM `bRewarded-Votes` WHERE `username`='"
+ playerName + "' AND `server`='"
+ Bukkit.getServerName()
+ "' AND `timestamp`>=" + minTime
);
if (result != null) {
int votesToday = 0;
try {
while (result.next()) {
votesToday++;
}
}
catch (SQLException ex) {
bFundamentals.log(Level.WARNING, "Failed to count todays votes for '" + playerName + "'.", ex);
}
return votesToday;
}
}
return 0;
}
/**
*
* @param item
* @return
*/
private String formatRandomReward(ItemStack item, Vote vote) {
String message = formatMessage(this.message.messageAnnounceRandomReward, vote, 0.0);
String itemName = item.getAmount() + "x ";
if (item.getItemMeta().hasDisplayName()) {
itemName += item.getItemMeta().getDisplayName();
}
else {
itemName += item.getType().name();
}
message = message.replaceAll("<<item>>", itemName);
return message;
}
/**
*
* @param message
* @param vote
* @param amount
* @return
*/
private String formatMessage(String message, Vote vote, Double amount) {
message = message.replaceAll("<<player>>", vote.getUsername());
message = message.replaceAll("<<servername>>", Bukkit.getServerName());
message = message.replaceAll("<<service>>", vote.getServiceName());
message = message.replaceAll("<<amount>>", formatAmount(amount));
return message;
}
/**
*
* @param amount
* @return
*/
private String formatAmount(double amount) {
DecimalFormat format = new DecimalFormat("##0.00");
String formatted = format.format(amount);
if (formatted.endsWith(".")) {
formatted = formatted.substring(0, formatted.length() - 1);
}
return formatted;
}
}