package in.twizmwaz.cardinal;
import com.sk89q.bukkit.util.CommandsManagerRegistration;
import com.sk89q.minecraft.util.commands.ChatColor;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
import com.sk89q.minecraft.util.commands.CommandUsageException;
import com.sk89q.minecraft.util.commands.CommandsManager;
import com.sk89q.minecraft.util.commands.MissingNestedCommandException;
import com.sk89q.minecraft.util.commands.WrappedCommandException;
import in.twizmwaz.cardinal.chat.ChatConstant;
import in.twizmwaz.cardinal.chat.LocaleHandler;
import in.twizmwaz.cardinal.chat.LocalizedChatMessage;
import in.twizmwaz.cardinal.command.BroadcastCommands;
import in.twizmwaz.cardinal.command.CancelCommand;
import in.twizmwaz.cardinal.command.CardinalCommand;
import in.twizmwaz.cardinal.command.ChatCommands;
import in.twizmwaz.cardinal.command.ClassCommands;
import in.twizmwaz.cardinal.command.CycleCommand;
import in.twizmwaz.cardinal.command.InventoryCommand;
import in.twizmwaz.cardinal.command.JoinCommand;
import in.twizmwaz.cardinal.command.ListCommand;
import in.twizmwaz.cardinal.command.MapCommands;
import in.twizmwaz.cardinal.command.MatchCommand;
import in.twizmwaz.cardinal.command.ModesCommand;
import in.twizmwaz.cardinal.command.PollCommands;
import in.twizmwaz.cardinal.command.PrivateMessageCommands;
import in.twizmwaz.cardinal.command.ProximityCommand;
import in.twizmwaz.cardinal.command.PunishmentCommands;
import in.twizmwaz.cardinal.command.RankCommands;
import in.twizmwaz.cardinal.command.ReadyCommand;
import in.twizmwaz.cardinal.command.RepositoryCommands;
import in.twizmwaz.cardinal.command.ScoreCommand;
import in.twizmwaz.cardinal.command.SettingCommands;
import in.twizmwaz.cardinal.command.SnowflakesCommand;
import in.twizmwaz.cardinal.command.StartAndEndCommand;
import in.twizmwaz.cardinal.command.TeamCommands;
import in.twizmwaz.cardinal.command.TeleportCommands;
import in.twizmwaz.cardinal.command.TimeLimitCommand;
import in.twizmwaz.cardinal.command.WhitelistCommands;
import in.twizmwaz.cardinal.rank.Rank;
import in.twizmwaz.cardinal.repository.RepositoryManager;
import in.twizmwaz.cardinal.repository.exception.RotationLoadException;
import in.twizmwaz.cardinal.settings.Setting;
import in.twizmwaz.cardinal.settings.SettingValue;
import in.twizmwaz.cardinal.util.ChatUtil;
import in.twizmwaz.cardinal.util.Config;
import in.twizmwaz.cardinal.util.DomUtil;
import in.twizmwaz.cardinal.util.NonModuleFactory;
import in.twizmwaz.cardinal.util.Numbers;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
public class Cardinal extends JavaPlugin {
private final static String CRAFTBUKKIT_VERSION = "1.11.1-R0.1-SNAPSHOT";
private final static String MINECRAFT_VERSION = "1.11.1";
private static Cardinal instance;
private static GameHandler gameHandler;
private static LocaleHandler localeHandler;
private static Database database;
private CommandsManager<CommandSender> commands;
private File databaseFile;
// Used to store objects that are not modules, like utils that need listeners, or the TabList
private NonModuleFactory nonModules;
public static LocaleHandler getLocaleHandler() {
return localeHandler;
}
public static Cardinal getInstance() {
return instance;
}
public static Database getCardinalDatabase() {
return database;
}
public static <T> T getNonModule(Class<T> clazz) {
return instance.nonModules.getNonModule(clazz);
}
public String getPluginFileName() {
return this.getFile().getName();
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
String locale = ChatUtil.getLocale(sender);
try {
this.commands.execute(cmd.getName(), args, sender, sender);
} catch (CommandPermissionsException e) {
sender.sendMessage(ChatUtil.getWarningMessage(new LocalizedChatMessage(ChatConstant.ERROR_NO_PERMISSION).getMessage(locale)));
} catch (MissingNestedCommandException e) {
sender.sendMessage(ChatUtil.getWarningMessage(e.getUsage().replace("{cmd}", cmd.getName())));
} catch (CommandUsageException e) {
sender.sendMessage(ChatUtil.getWarningMessage(e.getMessage()));
sender.sendMessage(ChatUtil.getWarningMessage(e.getUsage()));
} catch (WrappedCommandException e) {
if (e.getCause() instanceof NumberFormatException) {
sender.sendMessage(ChatUtil.getWarningMessage(new LocalizedChatMessage(ChatConstant.ERROR_NUMBER_STRING).getMessage(locale)));
} else {
sender.sendMessage(ChatUtil.getWarningMessage(new LocalizedChatMessage(ChatConstant.ERROR_UNKNOWN_ERROR).getMessage(locale)));
e.printStackTrace();
}
} catch (CommandException e) {
sender.sendMessage(ChatUtil.getWarningMessage(ChatColor.RED + e.getMessage()));
}
return true;
}
private void setupCommands() {
this.commands = new CommandsManager<CommandSender>() {
@Override
public boolean hasPermission(CommandSender sender, String perm) {
return sender instanceof ConsoleCommandSender || sender.hasPermission(perm);
}
};
CommandsManagerRegistration cmdRegister = new CommandsManagerRegistration(this, this.commands);
cmdRegister.register(BroadcastCommands.class);
cmdRegister.register(CancelCommand.class);
cmdRegister.register(CardinalCommand.class);
cmdRegister.register(ChatCommands.class);
cmdRegister.register(ClassCommands.class);
cmdRegister.register(CycleCommand.class);
cmdRegister.register(InventoryCommand.class);
cmdRegister.register(JoinCommand.class);
cmdRegister.register(ListCommand.class);
cmdRegister.register(MapCommands.class);
cmdRegister.register(MatchCommand.class);
cmdRegister.register(ModesCommand.ModesParentCommand.class);
cmdRegister.register(PrivateMessageCommands.class);
cmdRegister.register(ProximityCommand.class);
cmdRegister.register(PunishmentCommands.class);
cmdRegister.register(RankCommands.RankParentCommand.class);
cmdRegister.register(ReadyCommand.class);
cmdRegister.register(RepositoryCommands.class);
cmdRegister.register(ScoreCommand.class);
cmdRegister.register(SettingCommands.class);
cmdRegister.register(SnowflakesCommand.class);
cmdRegister.register(StartAndEndCommand.class);
cmdRegister.register(TeamCommands.TeamParentCommand.class);
cmdRegister.register(TeamCommands.class);
cmdRegister.register(TeleportCommands.class);
cmdRegister.register(TimeLimitCommand.class);
cmdRegister.register(WhitelistCommands.WhitelistParentCommand.class);
cmdRegister.register(PollCommands.class);
}
private void checkCraftVersion() {
if (!Bukkit.getServer().getBukkitVersion().equals(CRAFTBUKKIT_VERSION)) {
getLogger().warning("########################################");
getLogger().warning("##### YOUR VERSION OF SPORTBUKKIT #####");
getLogger().warning("##### IS NOT SUPPORTED. PLEASE #####");
getLogger().warning("##### USE SPORTBUKKIT " + MINECRAFT_VERSION + " #####");
getLogger().warning("########################################");
}
}
private void deleteMatches() {
if (Config.deleteMatches) {
getLogger().info("Deleting match files, this can be disabled via the configuration");
File matches = new File("matches/");
try {
FileUtils.deleteDirectory(matches);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void reloadConfig() {
super.reloadConfig();
Config.reload(getConfig());
saveConfig();
}
private void registerSettings() {
FileConfiguration config = YamlConfiguration.loadConfiguration(new InputStreamReader(this.getResource("settings.yml"), Charsets.UTF_8));
if (config.contains("settings")) {
for (String settingName : config.getStringList("settings")) {
List<String> names = new ArrayList<>();
String description = "No description.";
List<SettingValue> values = new ArrayList<>();
names.add(settingName.trim());
if (config.contains("setting." + settingName + ".aliases")) {
for (String alias : config.getStringList("setting." + settingName + ".aliases")) {
names.add(alias.trim());
}
}
if (config.contains("setting." + settingName + ".description"))
description = config.getString("setting." + settingName + ".description");
if (config.contains("setting." + settingName + ".values")) {
for (String valueName : config.getStringList("setting." + settingName + ".values")) {
if (valueName.endsWith("[default]"))
values.add(new SettingValue(valueName.trim().substring(0, valueName.length() - 9), true));
else values.add(new SettingValue(valueName.trim(), false));
}
}
new Setting(names, description, values);
}
}
new Setting(Arrays.asList("ChatChannel"), "Choose a default chat channel.", Arrays.asList(new SettingValue("global", false), new SettingValue("team", true), new SettingValue("admin", false)));
}
public void registerRanks() {
File file = new File(getDataFolder(), "ranks.xml");
if (!file.exists()) {
try {
FileUtils.copyInputStreamToFile(getResource("ranks.xml"), file);
} catch (IOException e) {
e.printStackTrace();
getLogger().warning("Could not copy default ranks file to 'ranks.xml'.");
}
}
try {
Rank.clearRanks();
Document document = DomUtil.parse(file);
for (Element rank : document.getRootElement().getChildren("rank")) {
String name = rank.getAttributeValue("name");
boolean defaultRank = rank.getAttributeValue("default") != null && Numbers.parseBoolean(rank.getAttributeValue("default"));
boolean staffRank = false;
String parent = rank.getAttributeValue("parent");
if (parent != null) {
for (Element element : document.getRootElement().getChildren("rank")) {
String elementName = element.getAttributeValue("name");
if (elementName.equalsIgnoreCase(parent) || elementName.toLowerCase().startsWith(parent.toLowerCase())) {
staffRank = element.getAttributeValue("staff") != null && Numbers.parseBoolean(element.getAttributeValue("staff"));
}
}
if (rank.getAttributeValue("staff") != null) {
staffRank = Numbers.parseBoolean(rank.getAttributeValue("staff"));
}
} else {
staffRank = rank.getAttributeValue("staff") != null && Numbers.parseBoolean(rank.getAttributeValue("staff"));
}
String flair = rank.getAttributeValue("flair") != null ? ChatColor.translateAlternateColorCodes('`', rank.getAttributeValue("flair")) : "";
List<String> permissions = new ArrayList<>(), disabledPermissions = new ArrayList<>();
for (Element permission : rank.getChildren("permission")) {
if (permission.getText().startsWith("-")) {
disabledPermissions.add(permission.getText().substring(1));
} else {
permissions.add(permission.getText());
}
}
new Rank(name, defaultRank, staffRank, flair, permissions, disabledPermissions, parent);
}
for (Rank rank : Rank.getRanks()) {
if (rank.getParent() != null &&
Rank.getRank(rank.getParent()) != null &&
Rank.getRank(rank.getParent()).getParent() != null &&
Rank.getRank(Rank.getRank(rank.getParent()).getParent()) != null &&
Rank.getRank(Rank.getRank(rank.getParent()).getParent()).equals(rank)) {
getLogger().warning("Rank inheritance processes were terminated because " + rank.getName() + " and " + Rank.getRank(rank.getParent()).getName() + " are parents of each other, which cannot occur.");
return;
}
}
List<Rank> completed = new ArrayList<>();
for (Rank rank : Rank.getRanks()) {
if (rank.getParent() == null) {
completed.add(rank);
}
}
while (!completed.containsAll(Rank.getRanks())) {
Rank inheriting = null;
for (Rank rank : Rank.getRanks()) {
if (!completed.contains(rank) && rank.getParent() != null && completed.contains(Rank.getRank(rank.getParent()))) {
inheriting = rank;
}
}
for (String permission : Rank.getRank(inheriting.getParent()).getPermissions()) {
inheriting.addPermission(permission);
}
completed.add(inheriting);
}
} catch (JDOMException | IOException e) {
e.printStackTrace();
getLogger().warning("Could not parse file 'ranks.xml' for ranks.");
}
}
@Override
public void onEnable() {
instance = this;
checkCraftVersion();
try {
localeHandler = new LocaleHandler(this);
} catch (IOException | JDOMException e) {
e.printStackTrace();
getLogger().severe("Failed to initialize because of invalid language files. Please make sure all language files in the plugin are present.");
setEnabled(false);
return;
}
getDataFolder().mkdir();
databaseFile = new File(getDataFolder(), "database.xml");
if (databaseFile.exists()) {
try {
database = Database.loadFromFile(databaseFile);
} catch (JDOMException | IOException e) {
e.printStackTrace();
getLogger().severe("Failed to initialize because of an IOException. Please try restarting your server.");
setEnabled(false);
return;
}
} else {
database = Database.newInstance(databaseFile);
}
Config.reload(getConfig());
saveConfig();
deleteMatches();
registerSettings();
registerRanks();
setupCommands();
nonModules = new NonModuleFactory();
try {
gameHandler = new GameHandler();
gameHandler.load();
} catch (RotationLoadException e) {
e.printStackTrace();
getLogger().severe(new LocalizedChatMessage(ChatConstant.GENERIC_REPO_RELOAD_FAIL, "" + RepositoryManager.get().getMapSize()).getMessage(Locale.getDefault().toString()));
setEnabled(false);
return;
}
if (Config.resetSpawnProtection && Bukkit.getServer().getSpawnRadius() != 0) {
Bukkit.getServer().setSpawnRadius(0);
}
}
@Override
public void onDisable() {
database.save(databaseFile);
saveConfig();
}
public GameHandler getGameHandler() {
return gameHandler;
}
public JavaPlugin getPlugin() {
return this;
}
public static String getNewRepoPath(String repoName) {
String reposPath = Cardinal.getInstance().getDataFolder().getAbsolutePath() +
File.separator + "repositories" + File.separator + repoName;
File repo = new File(reposPath);
if (!repo.exists()) repo.mkdirs();
return reposPath;
}
}