package be.Balor.bukkit.AdminCmd;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import lib.SQL.PatPeter.SQLibrary.Database;
import lib.SQL.PatPeter.SQLibrary.DatabaseConfig.DatabaseType;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import be.Balor.Importer.IImport;
import be.Balor.Importer.ImportTools;
import be.Balor.Importer.Essentials.EssentialsImport;
import be.Balor.Manager.CommandManager;
import be.Balor.Manager.LocaleManager;
import be.Balor.Manager.Commands.CommandArgs;
import be.Balor.Manager.Exceptions.WorldNotLoaded;
import be.Balor.Manager.Permissions.PermissionManager;
import be.Balor.Player.ACPlayer;
import be.Balor.Player.Ban;
import be.Balor.Player.BannedIP;
import be.Balor.Player.FilePlayer;
import be.Balor.Player.FilePlayerFactory;
import be.Balor.Player.IBan;
import be.Balor.Player.ITempBan;
import be.Balor.Player.PlayerManager;
import be.Balor.Player.sql.SQLPlayer;
import be.Balor.Player.sql.SQLPlayerFactory;
import be.Balor.Tools.MaterialContainer;
import be.Balor.Tools.Type;
import be.Balor.Tools.Utils;
import be.Balor.Tools.Blocks.BlockRemanence;
import be.Balor.Tools.Configuration.ExConfigurationSection;
import be.Balor.Tools.Configuration.File.ExtendedConfiguration;
import be.Balor.Tools.Debug.ACLogger;
import be.Balor.Tools.Debug.DebugLog;
import be.Balor.Tools.Exceptions.InvalidInputException;
import be.Balor.Tools.Files.DataManager;
import be.Balor.Tools.Files.FileManager;
import be.Balor.Tools.Files.KitInstance;
import be.Balor.Tools.Help.HelpLister;
import be.Balor.Tools.Help.HelpLoader;
import be.Balor.Tools.Lister.Lister;
import be.Balor.Tools.Threads.SetTimeTask;
import be.Balor.Tools.Threads.UnBanTask;
import be.Balor.Tools.Threads.UndoBlockTask;
import be.Balor.World.ACWorld;
import be.Balor.World.FileWorldFactory;
import be.Balor.World.WorldManager;
import be.Balor.World.sql.SQLWorld;
import be.Balor.World.sql.SQLWorldFactory;
import belgium.Balor.Workers.AFKWorker;
import belgium.Balor.Workers.InvisibleWorker;
import com.google.common.collect.MapMaker;
private final static HashMap<Material, String[]> materialsColors;
private final static List<Integer> listOfPossibleRepair;
private static long mainThreadID;
return Utils.getElapsedTime(pluginStarted);
}
return instance;
}
final String dbWrap = ConfigEnum.DATA_WRAPPER.getString();
if (dbWrap.equalsIgnoreCase("mysql")
|| dbWrap.equalsIgnoreCase("sqlite")) {
Database.DATABASE.close();
}
instance = null;
}
return mainThreadID == Thread.currentThread().getId();
}
private FileManager fManager;
private final Set<MaterialContainer> itemBlacklist = new TreeSet<MaterialContainer>();
private List<Integer> blockBlacklist;
private List<String> groups;
private AdminCmd coreInstance;
private final ConcurrentMap<String, MaterialContainer> alias = new MapMaker()
.makeMap();
private Map<String, KitInstance> kits = new HashMap<String, KitInstance>();
private Map<String, String> deathMessages = new HashMap<String, String>();
private final ConcurrentMap<String, IBan> bannedPlayers = new MapMaker()
.makeMap();
private final ConcurrentMap<Player, Object> fakeQuitPlayers = new MapMaker()
.makeMap();
private final ConcurrentMap<Player, Object> spyPlayers = new MapMaker()
.makeMap();
private static ACHelper instance = new ACHelper();
private final ConcurrentMap<String, Stack<Stack<BlockRemanence>>> undoQueue = new MapMaker()
.makeMap();
private static long pluginStarted;
static {
materialsColors = new HashMap<Material, String[]>();
materialsColors.put(Material.WOOL, new String[] { "White", "Orange",
"Magenta", "LightBlue", "Yellow", "LimeGreen", "Pink", "Gray",
"LightGray", "Cyan", "Purple", "Blue", "Brown", "Green", "Red",
"Black" });
materialsColors.put(Material.INK_SACK, new String[] { "Black", "Red",
"Green", "Brown", "Blue", "Purple", "Cyan", "LightGray",
"Gray", "Pink", "LimeGreen", "Yellow", "LightBlue", "Magenta",
"Orange", "White" });
materialsColors.put(Material.LOG,
new String[] { "Oak", "Pine", "Birch" });
materialsColors.put(Material.STEP, new String[] { "Stone", "Sandstone",
"Wooden", "Cobblestone" });
materialsColors.put(Material.DOUBLE_STEP,
materialsColors.get(Material.STEP));
listOfPossibleRepair = new LinkedList<Integer>();
for (int i = 256; i <= 259; i++) {
listOfPossibleRepair.add(i);
}
for (int i = 267; i <= 279; i++) {
listOfPossibleRepair.add(i);
}
for (int i = 283; i <= 286; i++) {
listOfPossibleRepair.add(i);
}
for (int i = 290; i <= 294; i++) {
listOfPossibleRepair.add(i);
}
for (int i = 298; i <= 317; i++) {
listOfPossibleRepair.add(i);
}
listOfPossibleRepair.add(359);
listOfPossibleRepair.add(Material.BOW.getId());
listOfPossibleRepair.add(Material.FISHING_ROD.getId());
}
private ExtendedConfiguration pluginConfig;
private DataManager dataManager;
private boolean serverLocked = false;
private final ConcurrentMap<Player, Player> playersForReplyMessage = new MapMaker()
.makeMap();
bannedPlayers.put(ban.getPlayer(), ban);
dataManager.addBan(ban);
if (ban instanceof BannedIP) {
ACPluginManager.getServer().banIP(ban.getPlayer());
}
final Lister list = Lister.getLister(Lister.List.BAN, false);
if (list != null) {
list.update();
}
}
final String name) {
final MaterialContainer m = checkMaterial(sender, name);
if (!m.isNull()) {
final ExtendedConfiguration config = fManager.getYml("blacklist");
List<Integer> list = config.getIntList("BlackListedBlocks", null);
if (list == null) {
list = new ArrayList<Integer>();
}
list.add(m.getMaterial().getId());
config.set("BlackListedBlocks", list);
try {
config.save();
} catch (final IOException e) {
}
if (blockBlacklist == null) {
blockBlacklist = new ArrayList<Integer>();
}
blockBlacklist.add(m.getMaterial().getId());
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", m.getMaterial().toString());
Utils.sI18n(sender, "addBlacklistBlock", replace);
return true;
}
return false;
}
final String name) {
final MaterialContainer m = checkMaterial(sender, name);
return addBlackListedItem(sender, m);
}
final ItemStack item) {
final MaterialContainer m = new MaterialContainer(item);
return addBlackListedItem(sender, m);
}
final MaterialContainer mat) {
if (mat.isNull()) {
return false;
}
if (!itemBlacklist.add(mat)) {
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("item", mat.display());
LocaleHelper.BL_ITEM_ALREADY.sendLocale(sender, replace);
return false;
}
final ExtendedConfiguration config = fManager.getYml("blacklist");
config.set("BlackListedMaterial", itemBlacklist);
try {
config.save();
} catch (final IOException e) {
DebugLog.INSTANCE.log(Level.WARNING, "Can't save the blacklist", e);
LocaleHelper.BL_ITEM_PROBLEM.sendLocale(sender);
return false;
}
Utils.sI18n(sender, "addBlacklistItem", "material", mat.display());
return true;
}
fakeQuitPlayers.put(p, new Object());
}
final Stack<BlockRemanence> blocks) {
if (undoQueue.containsKey(player)) {
undoQueue.get(player).push(blocks);
} else {
final Stack<Stack<BlockRemanence>> blockQueue = new Stack<Stack<BlockRemanence>>();
blockQueue.push(blocks);
undoQueue.put(player, blockQueue);
}
}
String locale = fManager.getTextFile("motd.txt");
if (locale == null) {
ACLogger.info("Could not read motd.txt. Using default values for the MotD!");
Utils.addLocale("MOTD", ChatColor.GOLD + "Welcome "
+ ChatColor.WHITE + "%player" + ChatColor.GOLD
+ ", there is currently " + ChatColor.DARK_RED
+ "%nb players connected : //n" + ChatColor.GOLD
+ "%connected //n" + ChatColor.DARK_GREEN
+ "You've played so far : " + ChatColor.AQUA
+ "#elapsedTotalTime# //n" + ChatColor.DARK_GREEN
+ "Your last login was: " + ChatColor.AQUA + "%lastlogin",
true);
} else {
ACLogger.info("motd.txt loaded");
Utils.addLocale("MOTD", Utils.colorParser(locale), true);
}
locale = fManager.getTextFile("motdNewUser.txt");
if (locale == null) {
ACLogger.info("Could not read motdNewUser.txt. Using default values for the MotDNewUser!");
Utils.addLocale("MOTDNewUser", ChatColor.GOLD + "Welcome "
+ ChatColor.WHITE + "%player" + ChatColor.GOLD
+ ", there is currently " + ChatColor.DARK_RED
+ "%nb players connected : //n" + ChatColor.GOLD
+ "%connected //n" + ChatColor.DARK_GREEN
+ "You've played so far : " + ChatColor.AQUA
+ "#elapsedTotalTime#", true);
} else {
ACLogger.info("motdNewUser.txt loaded");
Utils.addLocale("MOTDNewUser", Utils.colorParser(locale), true);
}
locale = fManager.getTextFile("news.txt");
if (locale == null) {
ACLogger.info("Could not read news.txt. Using default values for the MotD!");
Utils.addLocale("NEWS", ChatColor.DARK_GREEN
+ "News : AdminCmd Plugin has been installed", true);
} else {
ACLogger.info("news.txt loaded");
Utils.addLocale("NEWS", Utils.colorParser(locale), true);
}
locale = fManager.getTextFile("rules.txt");
if (locale == null) {
ACLogger.info("Could not read motdNewUser.txt. Using default values for the MotD!");
Utils.addLocale("Rules", "1. Do not grief! //n"
+ "2. Do not use strong language! //n"
+ "3. Be friendly to other players!", true);
} else {
ACLogger.info("rules.txt loaded");
Utils.addLocale("Rules", Utils.colorParser(locale), true);
}
LocaleManager.getInstance().save();
}
public void addSpy(
final Player p) {
spyPlayers.put(p, new Object());
}
public boolean alias(
final CommandSender sender,
final CommandArgs args) {
final MaterialContainer m = checkMaterial(sender, args.getString(1));
if (m.isNull()) {
return true;
}
final String alias = args.getString(0);
this.alias.put(alias, m);
this.fManager.addAlias(alias, m);
sender.sendMessage(ChatColor.BLUE + "You can now use " + ChatColor.GOLD
+ alias + ChatColor.BLUE + " for the item " + ChatColor.GOLD
+ m.display());
return true;
}
private boolean checkBan(
final IBan player) {
if (player instanceof ITempBan) {
final ITempBan tempBan = (ITempBan) player;
final Long timeLeft = tempBan.timeLeft();
if (timeLeft <= 0) {
unBanPlayer(player);
return false;
} else {
ACPluginManager.getScheduler().scheduleAsyncDelayedTask(
coreInstance, new UnBanTask(tempBan, true),
timeLeft / Utils.secondInMillis * Utils.secInTick);
return true;
}
} else {
return true;
}
}
public MaterialContainer
checkMaterial(
final CommandSender sender,
final String mat) {
MaterialContainer m = null;
try {
m = Utils.checkMaterial(mat);
} catch (final InvalidInputException e) {
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", mat);
Utils.sI18n(sender, "unknownMat", replace);
return new MaterialContainer();
}
if (m.isNull()) {
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", mat);
Utils.sI18n(sender, "unknownMat", replace);
}
return m;
}
final File spawnFile = fManager.getFile("spawn", "spawnLocations.yml",
false);
if (spawnFile.exists()) {
final ExtendedConfiguration spawn = ExtendedConfiguration
.loadConfiguration(spawnFile);
final ConfigurationSection spawnPoints = spawn
.getConfigurationSection("spawn");
if (spawnPoints != null) {
for (final String key : spawnPoints.getKeys(false)) {
try {
ACWorld.getWorld(key).setSpawn(
fManager.getLocation("spawn." + key,
"spawnLocations", "spawn"));
} catch (final WorldNotLoaded e) {
}
}
}
spawnFile.delete();
spawnFile.getParentFile().delete();
}
final File warpFile = fManager.getFile("warp", "warpPoints.yml", false);
if (warpFile.exists()) {
for (final String key : fManager.getKeys("warp", "warpPoints",
"warp")) {
try {
final Location loc = fManager.getLocation("warp." + key,
"warpPoints", "warp");
ACWorld.getWorld(loc.getWorld().getName())
.addWarp(key, loc);
} catch (final WorldNotLoaded e) {
}
}
warpFile.delete();
warpFile.getParentFile().delete();
}
}
return bannedPlayers.size();
}
return itemBlacklist.size();
}
return bannedPlayers.values();
}
public MaterialContainer
getAlias(
final String name) {
return alias.get(name);
}
return fManager.getYml("blacklist").getIntList("BlackListedBlocks",
new ArrayList<Integer>());
}
@SuppressWarnings("unchecked")
return (Set<MaterialContainer>) fManager.getYml("blacklist").get(
"BlackListedMaterial", new TreeSet<MaterialContainer>());
}
private short getColor(
final String name,
final Material mat) {
short value = -1;
try {
value = Short.parseShort(name);
} catch (final Exception e) {
for (short i = 0; i < materialsColors.get(mat).length; ++i) {
if (materialsColors.get(mat)[i].equalsIgnoreCase(name)) {
value = i;
break;
}
}
}
if (value < 0 || value >= materialsColors.get(mat).length) {
return -1;
}
return value;
}
return coreInstance;
}
return fakeQuitPlayers.keySet();
}
return Collections.unmodifiableList(groups);
}
final List<String> gFileList = fManager.getYml("config").getStringList(
"groupNames", new ArrayList<String>());
final List<String> gNewList = new ArrayList<String>();
for (final String item : gFileList) {
gNewList.add(item.toLowerCase());
}
return gNewList;
}
public KitInstance
getKit(
final String kit) {
return kits.get(kit);
}
public String
getKitList(
final CommandSender sender) {
String kitList = "";
final HashSet<String> list = new HashSet<String>();
try {
list.addAll(kits.keySet());
if (Utils.oddItem != null) {
}
} catch (final Throwable e) {
}
for (final String kit : list) {
if (PermissionManager.hasPerm(sender, "admincmd.kit." + kit, false)) {
kitList += kit + ", ";
}
}
if (!kitList.equals("")) {
if (kitList.endsWith(", ")) {
kitList = kitList.substring(0, kitList.lastIndexOf(","));
}
}
return kitList.trim();
}
public int getLimit(
final CommandSender sender,
final Type.Limit type) {
if (sender instanceof ConsoleCommandSender) {
return Integer.MAX_VALUE;
}
return getLimit((Player) sender, type, type.toString());
}
public int getLimit(
final Player player,
final Type.Limit type) {
return getLimit(player, type, type.toString());
}
public int getLimit(
final Player player,
final Type.Limit type,
final String defaultLvl) {
Integer limit = null;
final String toParse = PermissionManager.getPermissionLimit(player,
type.toString());
limit = toParse != null && !toParse.isEmpty() ? Integer
.parseInt(toParse) : null;
if (limit == null || limit == -1) {
limit = pluginConfig.getInt(defaultLvl, 0);
}
if (limit == 0 && type != Type.Limit.IMMUNITY) {
limit = Integer.MAX_VALUE;
}
return limit;
}
return kits.size();
}
return playersForReplyMessage.get(key);
}
return spyPlayers.keySet();
}
final Location loc = getGroupSpawnLocation(player);
player.teleport(loc);
Utils.sI18n(player, "spawn");
}
Location loc = null;
final ACWorld acWorld = ACWorld.getWorld(player.getWorld());
if (groups.isEmpty()) {
loc = acWorld.getSpawn();
if (loc == null) {
loc = player.getWorld().getSpawnLocation();
}
return loc;
}
for (final String groupName : groups) {
if (PermissionManager.hasPerm(player, "admincmd.respawn."
+ groupName)) {
loc = acWorld.getGroupSpawn(groupName);
break;
}
}
if (loc == null) {
loc = player.getWorld().getSpawnLocation();
}
return loc;
}
final ItemStack mat) {
if (!PermissionManager.hasPerm(sender, "admincmd.spec.noblacklist",
false) && blockBlacklist.contains(mat.getTypeId())) {
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", mat.getType().toString());
Utils.sI18n(sender, "inBlacklistBlock", replace);
return true;
}
return false;
}
final MaterialContainer mat) {
if (!PermissionManager.hasPerm(sender, "admincmd.spec.noblacklist",
false) && blockBlacklist.contains(mat.getMaterial().getId())) {
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", mat.display());
Utils.sI18n(sender, "inBlacklistBlock", replace);
return true;
}
return false;
}
final ItemStack mat) {
return inBlackListItem(sender, new MaterialContainer(mat));
}
final MaterialContainer mat) {
if (PermissionManager.hasPerm(sender, "admincmd.spec.noblacklist",
false)) {
return false;
}
if (!itemBlacklist.contains(mat)) {
return false;
}
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", mat.display());
Utils.sI18n(sender, "inBlacklistItem", replace);
return true;
}
AFKWorker.createInstance();
if (pluginConfig.getBoolean("autoAfk", true)) {
AFKWorker.getInstance().setAfkTime(
pluginConfig.getInt("afkTimeInSecond", 60));
AFKWorker.getInstance().setKickTime(
pluginConfig.getInt("afkKickInMinutes", 3));
this.coreInstance
.getServer()
.getScheduler()
.scheduleAsyncRepeatingTask(this.coreInstance,
AFKWorker.getInstance().getAfkChecker(), 0,
pluginConfig.getInt("statutCheckInSec", 20) * 20);
if (pluginConfig.getBoolean("autoKickAfkPlayer", false)) {
this.coreInstance
.getServer()
.getScheduler()
.scheduleAsyncRepeatingTask(
this.coreInstance,
AFKWorker.getInstance().getKickChecker(),
0,
pluginConfig.getInt("statutCheckInSec", 20) * 20);
}
}
final ExtendedConfiguration localeFile = ExtendedConfiguration
.loadConfiguration(new File(coreInstance.getDataFolder(),
"locales" + File.separator
+ pluginConfig.getString("locale", "en_US")
+ ".yml"));
final ExtendedConfiguration defaultLocale = ExtendedConfiguration
.loadConfiguration(fManager.getInnerFile("default_locale.yml",
"locales", true));
final Properties props = new Properties();
try {
props.load(this.getClass().getResourceAsStream("/git.properties"));
} catch (final IOException e1) {
}
defaultLocale.options()
.header("version: " + props.getProperty("git.commit.id"))
.copyHeader(true);
localeFile.setDefaults(defaultLocale);
localeFile.options().copyHeader(false);
LocaleManager.getInstance().addLocaleFile(LocaleManager.DEFAULT_LOCALE,
defaultLocale);
LocaleManager.getInstance().addLocaleFile(LocaleManager.PRIMARY_LOCALE,
localeFile);
LocaleManager.getInstance().addLocaleFile(
"kickMessages",
ExtendedConfiguration.loadConfiguration(fManager.getInnerFile(
"kickMessages.yml", "locales", false)));
LocaleManager.getInstance().setNoMsg(
pluginConfig.getBoolean("noMessage", false));
HelpLoader.load(coreInstance.getDataFolder());
CommandManager.createInstance().setCorePlugin(coreInstance);
if (pluginConfig.get("pluginStarted") != null) {
pluginStarted = Long.parseLong(pluginConfig
.getString("pluginStarted"));
pluginConfig.remove("pluginStarted");
try {
pluginConfig.save();
} catch (final IOException e) {
}
} else {
pluginStarted = System.currentTimeMillis();
}
for (final Player p : coreInstance.getServer().getOnlinePlayers()) {
PlayerManager.getInstance().setOnline(p);
}
if (!isSqlWrapper()) {
FilePlayer.scheduleAsyncSave();
}
if (pluginConfig.getBoolean("tpRequestActivatedByDefault", false)) {
for (final Player p : coreInstance.getServer().getOnlinePlayers()) {
ACPlayer.getPlayer(p).setPower(Type.TP_REQUEST);
}
}
for (final World w : coreInstance.getServer().getWorlds()) {
final ACWorld world = ACWorld.getWorld(w);
int task = world.getInformation(Type.TIME_FREEZED.toString())
.getInt(-1);
if (task != -1) {
task = ACPluginManager.getScheduler()
.scheduleSyncRepeatingTask(
ACHelper.getInstance().getCoreInstance(),
new SetTimeTask(w), 0, 5L);
world.setInformation(Type.TIME_FREEZED.toString(), task);
}
}
}
public IBan
getBan(
final String player) {
return bannedPlayers.get(player);
}
return serverLocked;
}
public boolean itemColor(
final CommandSender sender,
final String color) {
if (Utils.isPlayer(sender)) {
if (color.equalsIgnoreCase("help")) {
sender.sendMessage(ChatColor.RED + "Wool: " + ChatColor.WHITE
+ printColors(Material.WOOL));
sender.sendMessage(ChatColor.RED + "Dyes: " + ChatColor.WHITE
+ printColors(Material.INK_SACK));
sender.sendMessage(ChatColor.RED + "Logs: " + ChatColor.WHITE
+ printColors(Material.LOG));
sender.sendMessage(ChatColor.RED + "Slab: " + ChatColor.WHITE
+ printColors(Material.STEP));
return true;
}
short value = -1;
final Material m = ((Player) sender).getItemInHand().getType();
if (materialsColors.containsKey(m)) {
value = getColor(color, m);
} else {
sender.sendMessage(ChatColor.RED
+ "You must hold a colorable material!");
return true;
}
if (value < 0) {
sender.sendMessage(ChatColor.RED + "Color " + ChatColor.WHITE
+ color + ChatColor.RED
+ " is not usable for what you're holding!");
return true;
}
final Player player = (Player) sender;
final short colorVal = value;
ACPluginManager.scheduleSyncTask(new Runnable() {
@Override
player.getItemInHand().setDurability(colorVal);
}
});
}
return true;
}
itemBlacklist.addAll(getBlackListedItems());
blockBlacklist = getBlackListedBlocks();
groups = getGroupNames();
alias.putAll(fManager.getAlias());
addLocaleFromFile();
kits = fManager.loadKits();
deathMessages = fManager.loadDeathMessages();
final Map<String, Ban> bans = dataManager.loadBan();
for (final Entry<String, Ban> ban : bans.entrySet()) {
if (checkBan(ban.getValue())) {
bannedPlayers.put(ban.getKey(), ban.getValue());
}
}
if (pluginConfig.getBoolean("verboseLog", true)) {
final Logger logger = coreInstance.getLogger();
logger.info(itemBlacklist.size() + " blacklisted items loaded.");
logger.info(blockBlacklist.size() + " blacklisted blocks loaded.");
logger.info(alias.size() + " alias loaded.");
logger.info(kits.size() + " kits loaded.");
logger.info(bannedPlayers.size() + " banned players loaded.");
logger.info(deathMessages.size() + " death messages loaded.");
}
}
String output = "";
for (int i = 0; i < materialsColors.get(mat).length; ++i) {
output += materialsColors.get(mat)[i] + ", ";
}
return output;
}
final String dWrapper = ConfigEnum.DATA_WRAPPER.getString();
return dWrapper.equalsIgnoreCase("mysql")
|| dWrapper.equalsIgnoreCase("sqlite");
}
public synchronized void reload() {
coreInstance.getServer().getScheduler().cancelTasks(coreInstance);
if (!isSqlWrapper()) {
FilePlayer.forceSaveList();
}
alias.clear();
itemBlacklist.clear();
blockBlacklist.clear();
groups.clear();
undoQueue.clear();
try {
pluginConfig.reload();
} catch (final FileNotFoundException e) {
ACLogger.severe("Config Reload Problem :", e);
} catch (final IOException e) {
ACLogger.severe("Config Reload Problem :", e);
} catch (final InvalidConfigurationException e) {
ACLogger.severe("Config Reload Problem :", e);
}
bannedPlayers.clear();
loadInfos();
for (final Player p : InvisibleWorker.getInstance()
.getAllInvisiblePlayers()) {
InvisibleWorker.getInstance().reappear(p);
}
InvisibleWorker.killInstance();
AFKWorker.killInstance();
CommandManager.killInstance();
HelpLister.killInstance();
System.gc();
init();
CommandManager.getInstance().registerACPlugin(coreInstance);
coreInstance.registerCmds();
CommandManager.getInstance().checkAlias(coreInstance);
if (ConfigEnum.H_ALLPLUGIN.getBoolean()) {
for (final Plugin plugin : coreInstance.getServer()
.getPluginManager().getPlugins()) {
HelpLister.getInstance().addPlugin(plugin);
}
}
if (pluginConfig.getBoolean("autoAfk", true)) {
for (final Player p : Utils.getOnlinePlayers()) {
AFKWorker.getInstance().updateTimeStamp(p);
}
}
}
final String name) {
final MaterialContainer m = checkMaterial(sender, name);
if (!m.isNull()) {
final ExtendedConfiguration config = fManager.getYml("blacklist");
final List<Integer> list = config.getIntList("BlackListedBlocks",
new ArrayList<Integer>());
if (!list.isEmpty() && list.contains(m.getMaterial().getId())) {
list.remove((Integer) m.getMaterial().getId());
config.set("BlackListedBlocks", list);
try {
config.save();
} catch (final IOException e) {
}
}
if (itemBlacklist != null && !itemBlacklist.isEmpty()
&& itemBlacklist.contains(m.getMaterial().getId())) {
itemBlacklist.remove(m.getMaterial().getId());
}
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", m.getMaterial().toString());
Utils.sI18n(sender, "rmBlacklistBlock", replace);
return true;
}
return false;
}
final String name) {
final MaterialContainer m = checkMaterial(sender, name);
return removeBlackListedItem(sender, m);
}
final ItemStack item) {
final MaterialContainer m = new MaterialContainer(item);
return removeBlackListedItem(sender, m);
}
final MaterialContainer mat) {
if (mat.isNull()) {
return false;
}
if (!itemBlacklist.remove(mat)) {
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("item", mat.display());
LocaleHelper.BL_ITEM_NOT_BLISTED.sendLocale(sender, replace);
return false;
}
final ExtendedConfiguration config = fManager.getYml("blacklist");
config.set("BlackListedMaterial", itemBlacklist);
try {
config.save();
} catch (final IOException e) {
DebugLog.INSTANCE.log(Level.WARNING, "Can't save the blacklist", e);
LocaleHelper.BL_ITEM_PROBLEM.sendLocale(sender);
return false;
}
final HashMap<String, String> replace = new HashMap<String, String>();
replace.put("material", mat.getMaterial().toString());
Utils.sI18n(sender, "rmBlacklistItem", replace);
return true;
}
AFKWorker.getInstance().removePlayer(player);
fakeQuitPlayers.remove(player);
playersForReplyMessage.remove(player);
spyPlayers.remove(player);
InvisibleWorker.getInstance().onQuitEvent(player);
}
fakeQuitPlayers.remove(p);
}
if (key == null) {
return;
}
playersForReplyMessage.remove(key);
}
if (p == null) {
return;
}
spyPlayers.remove(p);
}
return listOfPossibleRepair.contains(id);
}
public boolean rmAlias(
final CommandSender sender,
final String alias) {
this.fManager.removeAlias(alias);
this.alias.remove(alias);
sender.sendMessage(ChatColor.GOLD + alias + ChatColor.RED + " removed");
return true;
}
pluginConfig.set("pluginStarted", pluginStarted);
try {
pluginConfig.save();
} catch (final IOException e) {
}
}
mainThreadID = Thread.currentThread().getId();
ACPluginManager.setCorePlugin(pluginInstance);
this.coreInstance = pluginInstance;
fManager = FileManager.getInstance();
fManager.setPath(pluginInstance.getDataFolder().getPath());
dataManager = fManager;
convertSpawnWarp();
fManager.getInnerFile("kits.yml");
fManager.getInnerFile("deathMessages.yml");
fManager.getInnerFile("ReadMe.txt", null, true);
fManager.getInnerFile("LiesMich.txt", null, true);
fManager.getInnerFile("AdminCmd.yml", "HelpFiles" + File.separator
+ "AdminCmd", true);
pluginConfig = ExtendedConfiguration.loadConfiguration(new File(
coreInstance.getDataFolder(), "config.yml"));
TextLocale.setVersion(ExtendedConfiguration.loadConfiguration(new File(
new File(coreInstance.getDataFolder(), "locales"),
"textFile.yml")));
ConfigEnum.setPluginInfos(pluginInstance.getDescription());
ConfigEnum.setConfig(pluginConfig);
dataWrapperInit();
if (ConfigEnum.IMPORT_ESSENTIALS.getBoolean()) {
final IImport importer = new EssentialsImport(
ImportTools.getPluginsFolder(coreInstance.getDataFolder()));
importer.initImport();
}
List<String> disabled = new ArrayList<String>();
List<String> priority = new ArrayList<String>();
if (pluginConfig.get("disabledCommands") != null) {
disabled = pluginConfig.getStringList("disabledCommands", disabled);
pluginConfig.remove("disabledCommands");
}
if (pluginConfig.get("prioritizedCommands") != null) {
priority = pluginConfig.getStringList("prioritizedCommands",
priority);
pluginConfig.remove("prioritizedCommands");
}
if (pluginConfig.get("respawnAtSpawnPoint") != null) {
pluginConfig.remove("respawnAtSpawnPoint");
}
if (!pluginConfig.getBoolean("debug")) {
DebugLog.stopLogging();
}
final ExtendedConfiguration commands = ExtendedConfiguration
.loadConfiguration(new File(coreInstance.getDataFolder(),
"commands.yml"));
commands.add("disabledCommands", disabled);
commands.add("prioritizedCommands",
priority.isEmpty() ? Arrays.asList("reload", "/", "stop")
: priority);
final ExConfigurationSection aliases = commands.addSection("aliases");
final ExConfigurationSection god = aliases.addSection("god");
god.add("gg", "");
god.add("gd", "");
final ExConfigurationSection fly = aliases.addSection("fly");
fly.add("ofly", "-o");
final ExConfigurationSection egg = aliases.addSection("egg");
egg.add("grenade", "-E ExplosionEgg");
commands.add("onNewJoin", Arrays.asList("/kit dirt", "/motd"));
try {
commands.save();
} catch (final IOException e) {
}
init();
}
playersForReplyMessage.put(key, value);
}
this.serverLocked = serverLocked;
}
public void setSpawn(
final CommandSender sender) {
if (Utils.isPlayer(sender)) {
final Location loc = ((Player) sender).getLocation();
final World w = loc.getWorld();
ACPluginManager.scheduleSyncTask(new Runnable() {
@Override
w.setSpawnLocation(loc.getBlockX(), loc.getBlockY(),
loc.getBlockZ());
}
});
ACWorld.getWorld(w.getName()).setSpawn(loc);
Utils.sI18n(sender, "setSpawn");
}
}
public void spawn(
final Player player) {
spawn(player, null);
}
public void spawn(
final Player player,
final ACWorld world) {
Location loc = null;
if (world == null) {
final String worldName = player.getWorld().getName();
loc = ACWorld.getWorld(worldName).getSpawn();
} else {
loc = world.getSpawn();
}
if (loc == null) {
loc = player.getWorld().getSpawnLocation();
}
Utils.teleportWithChunkCheck(player, loc);
}
bannedPlayers.remove(ban.getPlayer());
dataManager.unBanPlayer(ban);
if (ban instanceof BannedIP) {
ACPluginManager.getServer().unbanIP(ban.getPlayer());
}
final Lister list = Lister.getLister(Lister.List.BAN, false);
if (list != null) {
list.update();
}
}
throws EmptyStackException {
if (!undoQueue.containsKey(player)) {
throw new EmptyStackException();
}
final Stack<Stack<BlockRemanence>> blockQueue = undoQueue.get(player);
if (blockQueue.isEmpty()) {
throw new EmptyStackException();
}
final Stack<BlockRemanence> undo = blockQueue.pop();
final Stack<BlockRemanence> undoCache = new Stack<BlockRemanence>();
int i = 0;
try {
while (!undo.isEmpty()) {
undoCache.push(undo.pop());
if (undoCache.size() == Utils.MAX_BLOCKS) {
ACPluginManager.getScheduler().scheduleSyncDelayedTask(
coreInstance, new UndoBlockTask(undoCache), 1);
}
i++;
}
} catch (final Exception e) {
ACLogger.severe(e.getMessage(), e);
return i;
} finally {
ACPluginManager.getScheduler().scheduleSyncDelayedTask(
coreInstance, new UndoBlockTask(undoCache), 1);
}
return i;
}
return deathMessages.get(reason);
}
if (isSqlWrapper()) {
try {
createTable();
PlayerManager.getInstance().setPlayerFactory(
new SQLPlayerFactory());
WorldManager.getInstance().setWorldFactory(
new SQLWorldFactory());
} catch (final SQLException e) {
PlayerManager.getInstance().setPlayerFactory(
new FilePlayerFactory(coreInstance.getDataFolder()
.getPath() + File.separator + "userData"));
WorldManager.getInstance().setWorldFactory(
new FileWorldFactory(coreInstance.getDataFolder()
.getPath() + File.separator + "worldData"));
return;
}
} else {
PlayerManager.getInstance().setPlayerFactory(
new FilePlayerFactory(coreInstance.getDataFolder()
.getPath() + File.separator + "userData"));
WorldManager.getInstance().setWorldFactory(
new FileWorldFactory(coreInstance.getDataFolder().getPath()
+ File.separator + "worldData"));
}
convertFactory();
}
try {
final Database db = Database.DATABASE;
db.open();
if (!db.checkTable("ac_players")) {
if (db.getType() == DatabaseType.MYSQL) {
db.createTable("CREATE TABLE IF NOT EXISTS `ac_homes` ("
+ " `name` varchar(64) NOT NULL,"
+ " `player_id` int(10) unsigned NOT NULL,"
+ " `world` varchar(64) NOT NULL,"
+ " `x` double NOT NULL,"
+ " `y` double NOT NULL,"
+ " `z` double NOT NULL,"
+ " `yaw` double NOT NULL,"
+ " `pitch` double NOT NULL,"
+ " PRIMARY KEY (`name`,`player_id`),"
+ " KEY `player_id` (`player_id`)"
+ ")ENGINE=InnoDB DEFAULT CHARSET=utf8;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_informations` ("
+ " `key` varchar(128) NOT NULL,"
+ " `player_id` int(10) unsigned NOT NULL,"
+ " `info` text NOT NULL,"
+ " PRIMARY KEY (`key`,`player_id`),"
+ " KEY `player_id` (`player_id`)"
+ ")ENGINE=InnoDB DEFAULT CHARSET=utf8;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_kit_uses` ("
+ " `kit` varchar(64) NOT NULL,"
+ " `player_id` int(10) unsigned NOT NULL,"
+ " `use` BIGINT unsigned NOT NULL,"
+ " PRIMARY KEY (`kit`,`player_id`),"
+ " KEY `player_id` (`player_id`)"
+ ")ENGINE=InnoDB DEFAULT CHARSET=utf8;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_players` ("
+ " `id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
+ " `name` varchar(64) NOT NULL,"
+ " `world` varchar(64) DEFAULT NULL,"
+ " `x` double DEFAULT NULL,"
+ " `y` double DEFAULT NULL,"
+ " `z` double DEFAULT NULL,"
+ " `yaw` double DEFAULT NULL,"
+ " `pitch` double DEFAULT NULL,"
+ " PRIMARY KEY (`id`),"
+ " UNIQUE KEY `name` (`name`)"
+ ")ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_powers` ("
+ " `key` varchar(128) NOT NULL,"
+ " `player_id` int(10) unsigned NOT NULL,"
+ " `info` text NOT NULL,"
+ " `category` varchar(64) NOT NULL,"
+ " PRIMARY KEY (`key`,`player_id`),"
+ " KEY `player_id` (`player_id`),"
+ " KEY `category` (`category`)"
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
db.createTable("ALTER TABLE `ac_homes`"
+ " ADD CONSTRAINT `ac_homes_ibfk_1` FOREIGN KEY (`player_id`) "
+ "REFERENCES `ac_players` (`id`) "
+ "ON DELETE CASCADE ON UPDATE CASCADE;");
db.createTable("ALTER TABLE `ac_informations`"
+ " ADD CONSTRAINT `ac_informations_ibfk_1`"
+ " FOREIGN KEY (`player_id`) "
+ " REFERENCES `ac_players` (`id`)"
+ " ON DELETE CASCADE ON UPDATE CASCADE;");
db.createTable("ALTER TABLE `ac_kit_uses`"
+ " ADD CONSTRAINT `ac_kit_uses_ibfk_1`"
+ " FOREIGN KEY (`player_id`)"
+ " REFERENCES `ac_players` (`id`)"
+ " ON DELETE CASCADE ON UPDATE CASCADE;");
db.createTable("ALTER TABLE `ac_powers`"
+ " ADD CONSTRAINT `ac_powers_ibfk_1`"
+ " FOREIGN KEY (`player_id`)"
+ " REFERENCES `ac_players` (`id`)"
+ " ON DELETE CASCADE ON UPDATE CASCADE;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_warps` ("
+ " `name` varchar(64) NOT NULL,"
+ " `world_id` int(10) unsigned NOT NULL,"
+ " `x` double NOT NULL,"
+ " `y` double NOT NULL,"
+ " `z` double NOT NULL,"
+ " `pitch` double NOT NULL,"
+ " `yaw` double NOT NULL,"
+ " PRIMARY KEY (`name`,`world_id`),"
+ " KEY `world_id` (`world_id`)"
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_worlds` ("
+ " `id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
+ " `name` varchar(64) NOT NULL,"
+ " PRIMARY KEY (`id`),"
+ " UNIQUE KEY `name` (`name`)"
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_w_infos` ("
+ " `key` varchar(64) NOT NULL,"
+ " `world_id` int(10) unsigned NOT NULL,"
+ " `info` text NOT NULL,"
+ " PRIMARY KEY (`key`,`world_id`),"
+ " KEY `world_id` (`world_id`)"
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_spawns` ("
+ " `name` varchar(64) NOT NULL,"
+ " `world_id` int(10) unsigned NOT NULL,"
+ " `x` double NOT NULL,"
+ " `y` double NOT NULL,"
+ " `z` double NOT NULL,"
+ " `pitch` double NOT NULL,"
+ " `yaw` double NOT NULL,"
+ " PRIMARY KEY (`name`,`world_id`),"
+ " KEY `world_id` (`world_id`)"
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
db.createTable("ALTER TABLE `ac_warps`"
+ " ADD CONSTRAINT `ac_warps_ibfk_1` "
+ " FOREIGN KEY (`world_id`) "
+ " REFERENCES `ac_worlds` (`id`) "
+ " ON DELETE CASCADE ON UPDATE CASCADE;");
db.createTable("ALTER TABLE `ac_w_infos`"
+ " ADD CONSTRAINT `ac_w_infos_ibfk_1`"
+ " FOREIGN KEY (`world_id`)"
+ " REFERENCES `ac_worlds` (`id`) "
+ " ON DELETE CASCADE ON UPDATE CASCADE;");
db.createTable("ALTER TABLE `ac_spawns`"
+ " ADD CONSTRAINT `ac_spawns_ibfk_1`"
+ " FOREIGN KEY (`world_id`)"
+ " REFERENCES `ac_worlds` (`id`) "
+ " ON DELETE CASCADE ON UPDATE CASCADE;");
} else if (db.getType() == DatabaseType.SQLITE) {
db.createTable("CREATE TABLE IF NOT EXISTS `ac_homes` ("
+ " `name` varchar(64) NOT NULL,"
+ " `player_id` INTEGER NOT NULL,"
+ " `world` varchar(64) NOT NULL,"
+ " `x` double NOT NULL,"
+ " `y` double NOT NULL,"
+ " `z` double NOT NULL,"
+ " `yaw` double NOT NULL,"
+ " `pitch` double NOT NULL,"
+ " PRIMARY KEY (`name`,`player_id`)" + ");");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_informations` ("
+ " `key` varchar(128) NOT NULL,"
+ " `player_id` INTEGER NOT NULL,"
+ " `info` text NOT NULL,"
+ " PRIMARY KEY (`key`,`player_id`)" + " ) ;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_kit_uses` ("
+ " `kit` varchar(64) NOT NULL,"
+ " `player_id` INTEGER NOT NULL,"
+ " `use` INTEGER NOT NULL,"
+ " PRIMARY KEY (`kit`,`player_id`)" + " );");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_powers` ("
+ " `key` varchar(128) NOT NULL,"
+ " `player_id` INTEGER NOT NULL,"
+ " `info` text NOT NULL,"
+ " `category` varchar(64) NOT NULL,"
+ " PRIMARY KEY (`key`,`player_id`)" + ");");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_players` ("
+ " `id` INTEGER PRIMARY KEY AUTOINCREMENT ,"
+ " `name` varchar(64) NOT NULL,"
+ " `world` varchar(64) DEFAULT NULL,"
+ " `x` double DEFAULT NULL,"
+ " `y` double DEFAULT NULL,"
+ " `z` double DEFAULT NULL,"
+ " `yaw` double DEFAULT NULL,"
+ " `pitch` double DEFAULT NULL,"
+ " UNIQUE (`name`)" + ") ;");
db.createTable("CREATE INDEX home_pid ON ac_homes (player_id);");
db.createTable("CREATE INDEX info_pid ON ac_informations (player_id);");
db.createTable("CREATE INDEX kit_pid ON ac_kit_uses (player_id);");
db.createTable("CREATE INDEX power_pid ON ac_powers (player_id);");
db.createTable("CREATE INDEX power_cat ON ac_powers (category);");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_warps` ("
+ " `name` varchar(64) NOT NULL,"
+ " `world_id` INTEGER NOT NULL,"
+ " `x` double NOT NULL,"
+ " `y` double NOT NULL,"
+ " `z` double NOT NULL,"
+ " `pitch` double NOT NULL,"
+ " `yaw` double NOT NULL,"
+ " PRIMARY KEY (`name`,`world_id`)" + ") ;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_worlds` ("
+ " `id` INTEGER PRIMARY KEY AUTOINCREMENT,"
+ " `name` varchar(64) NOT NULL,"
+ " UNIQUE (`name`)" + ") ;");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_w_infos` ("
+ " `key` varchar(64) NOT NULL,"
+ " `world_id` INTEGER NOT NULL,"
+ " `info` text NOT NULL,"
+ " PRIMARY KEY (`key`,`world_id`)" + ");");
db.createTable("CREATE TABLE IF NOT EXISTS `ac_spawns` ("
+ " `name` varchar(64) NOT NULL,"
+ " `world_id` INTEGER NOT NULL,"
+ " `x` double NOT NULL,"
+ " `y` double NOT NULL,"
+ " `z` double NOT NULL,"
+ " `pitch` double NOT NULL,"
+ " `yaw` double NOT NULL,"
+ " PRIMARY KEY (`name`,`world_id`)" + ") ");
db.createTable("CREATE INDEX warp_wid ON ac_warps (world_id);");
db.createTable("CREATE INDEX info_wid ON ac_w_infos (world_id);");
db.createTable("CREATE INDEX spawn_wid ON ac_spawns (world_id);");
}
}
} catch (final SQLException e) {
ACLogger.severe("There is a problem in your SQL configuration : ",
e);
ACLogger.warning("The plugin is falling back to YML data managment");
throw e;
}
}
final String currentWrapper = ConfigEnum.DATA_WRAPPER.getString();
final String convertTo = ConfigEnum.CONVERT_INTO.getString();
if (convertTo.equalsIgnoreCase(currentWrapper)) {
return;
}
if (currentWrapper.equalsIgnoreCase("yml")
&& (convertTo.equalsIgnoreCase("sqlite") || convertTo
.equalsIgnoreCase("mysql"))) {
ConfigEnum.DATA_WRAPPER.setValue(convertTo);
try {
ConfigEnum.save();
} catch (final IOException e) {
}
try {
createTable();
} catch (final SQLException e) {
ACLogger.severe(
"Can't Convert to the Database. There is a problem in your configuration",
e);
return;
}
WorldManager.getInstance().convertFactory(new SQLWorldFactory());
PlayerManager.getInstance().convertFactory(new SQLPlayerFactory());
FilePlayer.stopSavingTask();
} else if (isSqlWrapper() && (convertTo.equalsIgnoreCase("yml"))) {
ConfigEnum.DATA_WRAPPER.setValue(convertTo);
try {
ConfigEnum.save();
} catch (final IOException e) {
}
WorldManager.getInstance().convertFactory(
new FileWorldFactory(coreInstance.getDataFolder().getPath()
+ File.separator + "worldData"));
PlayerManager.getInstance().convertFactory(
new FilePlayerFactory(coreInstance.getDataFolder()
.getPath() + File.separator + "userData"));
FilePlayer.scheduleAsyncSave();
} else if (isSqlWrapper()
&& (convertTo.equalsIgnoreCase("sqlite") || convertTo
.equalsIgnoreCase("mysql"))) {
WorldManager.getInstance().convertFactory(
new FileWorldFactory(coreInstance.getDataFolder().getPath()
+ File.separator + "worldData"));
PlayerManager.getInstance().convertFactory(
new FilePlayerFactory(coreInstance.getDataFolder()
.getPath() + File.separator + "userData"));
ConfigEnum.DATA_WRAPPER.setValue(convertTo);
try {
ConfigEnum.save();
} catch (final IOException e) {
}
Database.initDb();
try {
createTable();
} catch (final SQLException e) {
ACLogger.severe(
"Can't Convert to the Database. There is a problem in your configuration",
e);
return;
}
SQLPlayer.initPrepStmt();
SQLWorld.initPrepStmt();
WorldManager.getInstance().convertFactory(new SQLWorldFactory());
PlayerManager.getInstance().convertFactory(new SQLPlayerFactory());
}
}
}