/*******************************************************************************
* Copyright 2014 stuntguy3000 (Luke Anderson) and coasterman10.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
******************************************************************************/
package org.eodsteven.CrafterNexus;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.potion.PotionEffect;
import org.bukkit.scoreboard.Team;
import static org.eodsteven.CrafterNexus.Translation._;
import org.eodsteven.CrafterNexus.api.GameStartEvent;
import org.eodsteven.CrafterNexus.api.PhaseChangeEvent;
import org.eodsteven.CrafterNexus.bar.ActionAPI;
import org.eodsteven.CrafterNexus.chat.ChatListener;
import org.eodsteven.CrafterNexus.chat.ChatUtil;
import org.eodsteven.CrafterNexus.commands.ClassCommand;
import org.eodsteven.CrafterNexus.commands.CrafterNexusCommand;
import org.eodsteven.CrafterNexus.commands.DistanceCommand;
import org.eodsteven.CrafterNexus.commands.MapCommand;
import org.eodsteven.CrafterNexus.commands.StatsCommand;
import org.eodsteven.CrafterNexus.commands.TeamCommand;
import org.eodsteven.CrafterNexus.commands.TeamShortcutCommand;
import org.eodsteven.CrafterNexus.commands.VoteCommand;
import org.eodsteven.CrafterNexus.listeners.ClassAbilityListener;
import org.eodsteven.CrafterNexus.listeners.CraftingListener;
import org.eodsteven.CrafterNexus.listeners.EnderBrewingStandListener;
import org.eodsteven.CrafterNexus.listeners.EnderChestListener;
import org.eodsteven.CrafterNexus.listeners.EnderFurnaceListener;
import org.eodsteven.CrafterNexus.listeners.GolemListener;
import org.eodsteven.CrafterNexus.listeners.PlayerListener;
import org.eodsteven.CrafterNexus.listeners.ResourceListener;
import org.eodsteven.CrafterNexus.listeners.SoulboundListener;
import org.eodsteven.CrafterNexus.listeners.WandListener;
import org.eodsteven.CrafterNexus.listeners.WorldListener;
import org.eodsteven.CrafterNexus.manager.ConfigManager;
import org.eodsteven.CrafterNexus.manager.DatabaseManager;
import org.eodsteven.CrafterNexus.manager.GolemManager;
import org.eodsteven.CrafterNexus.manager.MapManager;
import org.eodsteven.CrafterNexus.manager.PhaseManager;
import org.eodsteven.CrafterNexus.manager.RestartHandler;
import org.eodsteven.CrafterNexus.manager.ScoreboardManager;
import org.eodsteven.CrafterNexus.manager.SignManager;
import org.eodsteven.CrafterNexus.manager.VotingManager;
import org.eodsteven.CrafterNexus.maps.MapRollback;
import org.eodsteven.CrafterNexus.object.GameTeam;
import org.eodsteven.CrafterNexus.object.Golem;
import org.eodsteven.CrafterNexus.object.Kit;
import org.eodsteven.CrafterNexus.object.PlayerMeta;
import org.eodsteven.CrafterNexus.object.Shop;
import org.eodsteven.CrafterNexus.stats.StatType;
import org.eodsteven.CrafterNexus.stats.StatsManager;
public final class CrafterNexus extends JavaPlugin {
private ConfigManager configManager;
private VotingManager voting;
private MapManager maps;
private PhaseManager timer;
private ResourceListener resources;
private EnderFurnaceListener enderFurnaces;
private EnderBrewingStandListener enderBrewingStands;
private EnderChestListener enderChests;
private StatsManager stats;
private SignManager sign;
private ScoreboardManager sb;
private DatabaseManager db;
private GolemManager boss;
public static HashMap<String, String> messages = new HashMap<>();
public boolean useMysql = false;
public boolean updateAvailable = false;
public boolean motd = true;
public String newVersion;
public int build = 1;
public int lastJoinPhase = 2;
public int respawn = 10;
public boolean runCommand = false;
public List<String> commands = new ArrayList<>();
public String mysqlName = "annihilation";
@Override
public void onEnable() {
configManager = new ConfigManager(this);
configManager.loadConfigFiles("config.yml", "maps.yml", "shops.yml",
"stats.yml", "messages.yml");
MapRollback mapLoader = new MapRollback(getLogger(), getDataFolder());
runCommand = getConfig().contains("commandsToRunAtEndGame");
if (runCommand) {
commands = getConfig().getStringList("commandsToRunAtEndGame");
} else commands = null;
maps = new MapManager(this, mapLoader,
configManager.getConfig("maps.yml"));
Configuration shops = configManager.getConfig("shops.yml");
new Shop(this, "Weapon", shops);
new Shop(this, "Brewing", shops);
stats = new StatsManager(this, configManager);
resources = new ResourceListener(this);
enderFurnaces = new EnderFurnaceListener(this);
enderBrewingStands = new EnderBrewingStandListener(this);
enderChests = new EnderChestListener();
sign = new SignManager(this);
Configuration config = configManager.getConfig("config.yml");
timer = new PhaseManager(this, config.getInt("start-delay"),
config.getInt("phase-period"));
voting = new VotingManager(this);
sb = new ScoreboardManager();
boss = new GolemManager(this);
PluginManager pm = getServer().getPluginManager();
File messagesFile = new File("plugins/" + getDescription().getName() + "/messages.yml");
YamlConfiguration yml = YamlConfiguration.loadConfiguration(messagesFile);
for (String id : yml.getKeys(false))
messages.put(id, yml.getString(id));
sign.loadSigns();
sb.resetScoreboard(ChatColor.DARK_AQUA + "Voting" + ChatColor.WHITE
+ " | " + ChatColor.GOLD + "/vote <name>");
build = this.getConfig().getInt("build", 5);
lastJoinPhase = this.getConfig().getInt("lastJoinPhase", 2);
respawn = this.getConfig().getInt("bossRespawnDelay", 10);
pm.registerEvents(resources, this);
pm.registerEvents(enderFurnaces, this);
pm.registerEvents(enderBrewingStands, this);
pm.registerEvents(enderChests, this);
pm.registerEvents(new ChatListener(this), this);
pm.registerEvents(new PlayerListener(this), this);
pm.registerEvents(new WorldListener(), this);
pm.registerEvents(new SoulboundListener(), this);
pm.registerEvents(new WandListener(this), this);
pm.registerEvents(new CraftingListener(), this);
pm.registerEvents(new ClassAbilityListener(this), this);
pm.registerEvents(new GolemListener(this), this);
getCommand("crafternexus").setExecutor(new CrafterNexusCommand(this));
getCommand("class").setExecutor(new ClassCommand());
getCommand("stats").setExecutor(new StatsCommand(stats));
getCommand("team").setExecutor(new TeamCommand(this));
getCommand("vote").setExecutor(new VoteCommand(voting));
getCommand("red").setExecutor(new TeamShortcutCommand());
getCommand("green").setExecutor(new TeamShortcutCommand());
getCommand("yellow").setExecutor(new TeamShortcutCommand());
getCommand("blue").setExecutor(new TeamShortcutCommand());
getCommand("distance").setExecutor(new DistanceCommand(this));
getCommand("map").setExecutor(new MapCommand(this, mapLoader));
if (config.getString("stats").equalsIgnoreCase("sql"))
useMysql = true;
motd = config.getBoolean("enableMotd", true);
if (useMysql) {
String host = config.getString("MySQL.host");
Integer port = config.getInt("MySQL.port");
String name = config.getString("MySQL.name");
String user = config.getString("MySQL.user");
String pass = config.getString("MySQL.pass");
db = new DatabaseManager(host, port, name, user, pass, this);
db.query("CREATE TABLE IF NOT EXISTS `" + mysqlName + "` ( `username` varchar(16) NOT NULL, "
+ "`kills` int(16) NOT NULL, `deaths` int(16) NOT NULL, `wins` int(16) NOT NULL, "
+ "`losses` int(16) NOT NULL, `nexus_damage` int(16) NOT NULL, "
+ "UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;");
} else
db = new DatabaseManager(this);
if (getServer().getPluginManager().isPluginEnabled("Vault")) {
VaultHooks.vault = true;
if (!VaultHooks.instance().setupPermissions()) {
VaultHooks.vault = false;
getLogger().warning("Unable to load Vault: No permission plugin found.");
} else {
if (!VaultHooks.instance().setupChat()) {
VaultHooks.vault = false;
getLogger().warning("Unable to load Vault: No chat plugin found.");
} else {
getLogger().info("Vault hook initalized!");
}
}
} else {
getLogger().warning("Vault not found! Permissions features disabled.");
}
reset();
ChatUtil.setRoman(getConfig().getBoolean("roman", false));
}
public boolean startTimer() {
if (timer.isRunning())
return false;
timer.start();
return true;
}
public void loadMap(final String map) {
FileConfiguration config = configManager.getConfig("maps.yml");
ConfigurationSection section = config.getConfigurationSection(map);
World w = getServer().getWorld(map);
for (GameTeam team : GameTeam.teams()) {
String name = team.name().toLowerCase();
if (section.contains("spawns." + name)) {
for (String s : section.getStringList("spawns." + name))
team.addSpawn(Util.parseLocation(getServer().getWorld(map),
s));
}
if (section.contains("nexuses." + name)) {
Location loc = Util.parseLocation(w,
section.getString("nexuses." + name));
team.loadNexus(loc, 75);
}
if (section.contains("furnaces." + name)) {
Location loc = Util.parseLocation(w,
section.getString("furnaces." + name));
enderFurnaces.setFurnaceLocation(team, loc);
loc.getBlock().setType(Material.BURNING_FURNACE);
}
if (section.contains("brewingstands." + name)) {
Location loc = Util.parseLocation(w,
section.getString("brewingstands." + name));
enderBrewingStands.setBrewingStandLocation(team, loc);
loc.getBlock().setType(Material.BREWING_STAND);
}
if (section.contains("enderchests." + name)) {
Location loc = Util.parseLocation(w,
section.getString("enderchests." + name));
enderChests.setEnderChestLocation(team, loc);
loc.getBlock().setType(Material.ENDER_CHEST);
}
}
if (section.contains("bosses")) {
HashMap<String, Golem> bosses = new HashMap<>();
ConfigurationSection sec = section
.getConfigurationSection("bosses");
for (String boss : sec.getKeys(false))
bosses.put(boss,
new Golem(boss, sec.getInt(boss + ".hearts") * 2, sec
.getString(boss + ".name"), Util.parseLocation(
w, sec.getString(boss + ".spawn")), Util
.parseLocation(w,
sec.getString(boss + ".chest"))));
boss.loadBosses(bosses);
}
if (section.contains("diamonds")) {
Set<Location> diamonds = new HashSet<>();
for (String s : section.getStringList("diamonds"))
diamonds.add(Util.parseLocation(w, s));
resources.loadDiamonds(diamonds);
}
}
public void startGame() {
for (Player p : Bukkit.getOnlinePlayers()) {
for (Player pp : Bukkit.getOnlinePlayers()) {
p.showPlayer(pp);
pp.showPlayer(p);
}
}
Bukkit.getPluginManager().callEvent(
new GameStartEvent(maps.getCurrentMap()));
sb.scores.clear();
for (OfflinePlayer score : sb.sb.getPlayers())
sb.sb.resetScores(score);
sb.obj.setDisplayName(ChatColor.DARK_AQUA + "Map: "
+ WordUtils.capitalize(voting.getWinner()));
for (GameTeam t : GameTeam.teams()) {
sb.scores.put(t.name(), sb.obj.getScore(Bukkit
.getOfflinePlayer(WordUtils.capitalize(t.name()
.toLowerCase() + " Nexus"))));
sb.scores.get(t.name()).setScore(t.getNexus().getHealth());
Team sbt = sb.sb.registerNewTeam(t.name() + "SB");
sbt.addPlayer(Bukkit.getOfflinePlayer(WordUtils
.capitalize(WordUtils.capitalize(t.name().toLowerCase()
+ " Nexus"))));
sbt.setPrefix(t.color().toString());
}
sb.obj.setDisplayName(ChatColor.DARK_AQUA + "Map: "
+ WordUtils.capitalize(voting.getWinner()));
for (Player p : getServer().getOnlinePlayers())
if (PlayerMeta.getMeta(p).getTeam() != GameTeam.NONE)
Util.sendPlayerToGame(p, this);
sb.update();
getServer().getScheduler().runTaskTimer(this, new Runnable() {
@Override
public void run() {
for (Player p : getServer().getOnlinePlayers()) {
if (PlayerMeta.getMeta(p).getKit() == Kit.SCOUT) {
PlayerMeta.getMeta(p).getKit().addScoutParticles(p);
}
}
}
}, 0L, 1200L);
getServer().getScheduler().runTaskTimer(this, new Runnable() {
@Override
public void run() {
for (GameTeam t : GameTeam.values()) {
if (t != GameTeam.NONE && t.getNexus().isAlive()) {
Location nexus = t.getNexus().getLocation().clone();
nexus.add(0.5, 0, 0.5);
Util.ParticleEffect.PORTAL.getName();
Util.ParticleEffect.ENCHANTMENT_TABLE.getName();
}
}
}
}, 100L, 5L);
}
public void advancePhase() {
ChatUtil.phaseMessage(timer.getPhase());
if (timer.getPhase() == 2)
boss.spawnBosses();
if (timer.getPhase() == 3)
resources.spawnDiamonds();
Bukkit.getPluginManager().callEvent(
new PhaseChangeEvent(timer.getPhase()));
getSignHandler().updateSigns(GameTeam.RED);
getSignHandler().updateSigns(GameTeam.BLUE);
getSignHandler().updateSigns(GameTeam.GREEN);
getSignHandler().updateSigns(GameTeam.YELLOW);
}
public void onSecond() {
long time = timer.getTime();
if (time == -5L) {
String winner = voting.getWinner();
voting.end();
getServer().broadcastMessage(ChatColor.GOLD + "Voting is now closed!");
maps.selectMap(winner);
getServer().broadcastMessage(
ChatColor.GREEN + WordUtils.capitalize(winner)
+ " was chosen!");
loadMap(winner);
for (Player p : Bukkit.getOnlinePlayers()) {
p.playSound(p.getLocation(), Sound.ENDERDRAGON_WINGS, 10, 1);
p.playSound(p.getLocation(), Sound.ENDERDRAGON_GROWL, 10, 1);
}
}
if (time <= -5L) {
for (Player p : Bukkit.getOnlinePlayers()) {
//p.playSound(p.getLocation(), Sound.ENDERDRAGON_WINGS, 10, 1);
//p.playSound(p.getLocation(), Sound.ENDERDRAGON_GROWL, 10, 1);
p.playSound(p.getLocation(), Sound.NOTE_PLING, 10, 2F);
p.playSound(p.getLocation(), Sound.NOTE_BASS_GUITAR, 10, 2F);
p.playSound(p.getLocation(), Sound.NOTE_PIANO, 10, 2F);
}
}
if (time == 0L)
startGame();
}
public int getPhase() {
return timer.getPhase();
}
public MapManager getMapManager() {
return maps;
}
public StatsManager getStatsManager() {
return stats;
}
public DatabaseManager getDatabaseHandler() {
return db;
}
public ConfigManager getConfigManager() {
return configManager;
}
public int getPhaseDelay() {
return configManager.getConfig("config.yml").getInt("phase-period");
}
public void log(String m, Level l) {
getLogger().log(l, m);
}
public VotingManager getVotingManager() {
return voting;
}
public ScoreboardManager getScoreboardHandler() {
return sb;
}
public void endGame(GameTeam winner) {
if (winner == null)
return;
ChatUtil.winMessage(winner);
timer.stop();
for (Player p : getServer().getOnlinePlayers()) {
if (PlayerMeta.getMeta(p).getTeam() == winner)
stats.incrementStat(StatType.WINS, p);
}
long restartDelay = configManager.getConfig("config.yml").getLong(
"restart-delay");
RestartHandler rs = new RestartHandler(this, restartDelay);
rs.start(timer.getTime(), winner.getColor(winner));
}
public void reset() {
sb.resetScoreboard(ChatColor.DARK_AQUA + "Voting" + ChatColor.WHITE
+ " | " + ChatColor.GOLD + "/vote <name>");
maps.reset();
timer.reset();
PlayerMeta.reset();
for (Player p : getServer().getOnlinePlayers()) {
PlayerMeta.getMeta(p).setTeam(GameTeam.NONE);
p.teleport(maps.getLobbySpawnPoint());
ActionAPI.sendPlayerAnnouncement(p, ChatColor.DARK_AQUA
+ "Welcome to Crafter's Nexus!");
p.setMaxHealth(20D);
p.setHealth(20D);
p.setFoodLevel(20);
p.setSaturation(20F);
}
voting.start();
sb.update();
for (Player p : Bukkit.getOnlinePlayers()) {
for (Player pp : Bukkit.getOnlinePlayers()) {
p.showPlayer(pp);
pp.showPlayer(p);
}
}
Bukkit.getScheduler().runTaskLater(this, new Runnable() {
@SuppressWarnings("deprecation")
@Override
public void run() {
for (Player p : getServer().getOnlinePlayers()) {
PlayerInventory inv = p.getInventory();
inv.setHelmet(null);
inv.setChestplate(null);
inv.setLeggings(null);
inv.setBoots(null);
p.getInventory().clear();
for (PotionEffect effect : p.getActivePotionEffects())
p.removePotionEffect(effect.getType());
p.setLevel(0);
p.setExp(0);
p.setSaturation(20F);
ItemStack selector = new ItemStack(Material.FEATHER);
ItemMeta itemMeta = selector.getItemMeta();
itemMeta.setDisplayName(ChatColor.AQUA
+ "Right click to select class");
selector.setItemMeta(itemMeta);
p.getInventory().setItem(0, selector);
p.updateInventory();
}
for (GameTeam t : GameTeam.values())
if (t != GameTeam.NONE)
sign.updateSigns(t);
checkStarting();
}
}, 2L);
}
public void checkWin() {
int alive = 0;
GameTeam aliveTeam = null;
for (GameTeam t : GameTeam.teams()) {
if (t.getNexus().isAlive()) {
alive++;
aliveTeam = t;
}
}
if (alive == 1) {
endGame(aliveTeam);
}
}
public SignManager getSignHandler() {
return sign;
}
public void setSignHandler(SignManager sign) {
this.sign = sign;
}
public void checkStarting() {
if (!timer.isRunning()) {
if (Bukkit.getOnlinePlayers().size() >= getConfig().getInt(
"requiredToStart"))
timer.start();
}
}
public GolemManager getBossManager() {
return boss;
}
public PhaseManager getPhaseManager() {
return timer;
}
public void listTeams(CommandSender sender) {
sender.sendMessage(ChatColor.GRAY + "============[ "
+ ChatColor.DARK_AQUA + "Teams" + ChatColor.GRAY
+ " ]============");
for (GameTeam t : GameTeam.teams()) {
int size = 0;
for (Player p : Bukkit.getOnlinePlayers()) {
PlayerMeta meta = PlayerMeta.getMeta(p);
if (meta.getTeam() == t)
size++;
}
if (size != 1) {
sender.sendMessage(t.coloredName() + " - " + size + " " + _("INFO_TEAM_LIST_PLAYERS") + _("DYNAMIC_S"));
} else {
sender.sendMessage(t.coloredName() + " - " + size + " " + _("INFO_TEAM_LIST_PLAYERS"));
}
}
sender.sendMessage(ChatColor.GRAY + "===============================");
}
public void joinTeam(Player player, String team) {
PlayerMeta meta = PlayerMeta.getMeta(player);
if (meta.getTeam() != GameTeam.NONE && !player.hasPermission("crafternexus.bypass.teamlimitor")) {
player.sendMessage(ChatColor.GOLD + _("CRAFTERNEXUS_PREFIX") + ChatColor.DARK_AQUA + _("ERROR_PLAYER_NOSWITCHTEAM"));
return;
}
GameTeam target;
try {
target = GameTeam.valueOf(team.toUpperCase());
} catch (IllegalArgumentException e) {
player.sendMessage(ChatColor.GOLD + _("CRAFTERNEXUS_PREFIX") + ChatColor.RED + _("ERROR_GAME_INVALIDTEAM"));
listTeams(player);
return;
}
if (Util.isTeamTooBig(target)
&& !player.hasPermission("crafternexus.bypass.teamlimit")) {
player.sendMessage(ChatColor.GOLD + _("CRAFTERNEXUS_PREFIX") + ChatColor.RED + _("ERROR_GAME_TEAMFULL"));
return;
}
if (target.getNexus() != null) {
if (target.getNexus().getHealth() == 0 && getPhase() > 1) {
player.sendMessage(ChatColor.GOLD + _("CRAFTERNEXUS_PREFIX") + ChatColor.RED + _("ERROR_GAME_TEAMNONEXUS"));
return;
}
}
if (getPhase() > lastJoinPhase
&& !player.hasPermission("crafternexus.bypass.phaselimiter")) {
player.kickPlayer(ChatColor.GOLD + _("CRAFTERNEXUS_PREFIX") + ChatColor.RED
+ "You cannot join the game in this phase!");
return;
}
player.sendMessage(ChatColor.GOLD + _("CRAFTERNEXUS_PREFIX") + ChatColor.DARK_AQUA + "You joined "
+ target.coloredName());
meta.setTeam(target);
getScoreboardHandler().teams.get(team.toUpperCase()).addPlayer(
player);
if (getPhase() > 0) {
Util.sendPlayerToGame(player, this);
}
getSignHandler().updateSigns(GameTeam.RED);
getSignHandler().updateSigns(GameTeam.BLUE);
getSignHandler().updateSigns(GameTeam.GREEN);
getSignHandler().updateSigns(GameTeam.YELLOW);
}
}