/*
* Copyright 2011 Tyler Blair. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and contributors and should not be interpreted as representing official policies,
* either expressed or implied, of anybody else.
*/
package com.griefcraft.lwc;
import com.griefcraft.cache.ProtectionCache;
import com.griefcraft.integration.ICurrency;
import com.griefcraft.integration.IPermissions;
import com.griefcraft.integration.currency.BOSECurrency;
import com.griefcraft.integration.currency.EssentialsCurrency;
import com.griefcraft.integration.currency.NoCurrency;
import com.griefcraft.integration.currency.VaultCurrency;
import com.griefcraft.integration.currency.iConomy5Currency;
import com.griefcraft.integration.currency.iConomy6Currency;
import com.griefcraft.integration.permissions.BukkitPermissions;
import com.griefcraft.integration.permissions.PEXPermissions;
import com.griefcraft.integration.permissions.SuperPermsPermissions;
import com.griefcraft.integration.permissions.VaultPermissions;
import com.griefcraft.integration.permissions.bPermissions;
import com.griefcraft.io.BackupManager;
import com.griefcraft.listeners.LWCMCPCSupport;
import com.griefcraft.migration.ConfigPost300;
import com.griefcraft.migration.MySQLPost200;
import com.griefcraft.model.Flag;
import com.griefcraft.model.History;
import com.griefcraft.model.LWCPlayer;
import com.griefcraft.model.Permission;
import com.griefcraft.model.Protection;
import com.griefcraft.modules.admin.AdminBackup;
import com.griefcraft.modules.admin.AdminCache;
import com.griefcraft.modules.admin.AdminCleanup;
import com.griefcraft.modules.admin.AdminClear;
import com.griefcraft.modules.admin.AdminDump;
import com.griefcraft.modules.admin.AdminExpire;
import com.griefcraft.modules.admin.AdminFind;
import com.griefcraft.modules.admin.AdminFlush;
import com.griefcraft.modules.admin.AdminForceOwner;
import com.griefcraft.modules.admin.AdminLocale;
import com.griefcraft.modules.admin.AdminPurge;
import com.griefcraft.modules.admin.AdminPurgeBanned;
import com.griefcraft.modules.admin.AdminQuery;
import com.griefcraft.modules.admin.AdminRebuild;
import com.griefcraft.modules.admin.AdminReload;
import com.griefcraft.modules.admin.AdminRemove;
import com.griefcraft.modules.admin.AdminReport;
import com.griefcraft.modules.admin.AdminVersion;
import com.griefcraft.modules.admin.AdminView;
import com.griefcraft.modules.admin.BaseAdminModule;
import com.griefcraft.modules.confirm.ConfirmModule;
import com.griefcraft.modules.create.CreateModule;
import com.griefcraft.modules.credits.CreditsModule;
import com.griefcraft.modules.debug.DebugModule;
import com.griefcraft.modules.destroy.DestroyModule;
import com.griefcraft.modules.doors.DoorsModule;
import com.griefcraft.modules.fix.FixModule;
import com.griefcraft.modules.flag.BaseFlagModule;
import com.griefcraft.modules.flag.MagnetModule;
import com.griefcraft.modules.free.FreeModule;
import com.griefcraft.modules.history.HistoryModule;
import com.griefcraft.modules.info.InfoModule;
import com.griefcraft.modules.limits.LimitsModule;
import com.griefcraft.modules.limits.LimitsV2;
import com.griefcraft.modules.modes.BaseModeModule;
import com.griefcraft.modules.modes.DropTransferModule;
import com.griefcraft.modules.modes.NoSpamModule;
import com.griefcraft.modules.modes.PersistModule;
import com.griefcraft.modules.modify.ModifyModule;
import com.griefcraft.modules.owners.OwnersModule;
import com.griefcraft.modules.pluginsupport.Towny;
import com.griefcraft.modules.pluginsupport.WorldGuard;
import com.griefcraft.modules.redstone.RedstoneModule;
import com.griefcraft.modules.setup.BaseSetupModule;
import com.griefcraft.modules.setup.DatabaseSetupModule;
import com.griefcraft.modules.setup.LimitsSetup;
import com.griefcraft.modules.unlock.UnlockModule;
import com.griefcraft.scripting.Module;
import com.griefcraft.scripting.ModuleLoader;
import com.griefcraft.scripting.event.LWCAccessEvent;
import com.griefcraft.scripting.event.LWCReloadEvent;
import com.griefcraft.scripting.event.LWCSendLocaleEvent;
import com.griefcraft.sql.Database;
import com.griefcraft.sql.PhysDB;
import com.griefcraft.util.Colors;
import com.griefcraft.util.DatabaseThread;
import com.griefcraft.util.ProtectionFinder;
import com.griefcraft.util.Statistics;
import com.griefcraft.util.StringUtil;
import com.griefcraft.util.UUIDRegistry;
import com.griefcraft.util.config.Configuration;
import com.griefcraft.util.locale.LocaleUtil;
import com.griefcraft.util.matchers.DoubleChestMatcher;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.mcstats.Metrics;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class LWC {
/**
* If LWC is currently enabled
*/
public static boolean ENABLED = false;
/**
* The current instance of LWC
*/
private static LWC instance;
/**
* Core LWC configuration
*/
private Configuration configuration;
/**
* The module loader
*/
private final ModuleLoader moduleLoader;
/**
* The manager of backups
*/
private final BackupManager backupManager;
/**
* The protection cache
*/
private final ProtectionCache protectionCache;
/**
* Physical database instance
*/
private PhysDB physicalDatabase;
/**
* Plugin instance
*/
private LWCPlugin plugin;
/**
* Updates to the database that can be ran on a seperate thread
*/
private DatabaseThread databaseThread;
/**
* The permissions handler
*/
private IPermissions permissions;
/**
* The currency handler
*/
private ICurrency currency;
/**
* Protection configuration cache
*/
private final Map<String, String> protectionConfigurationCache = new HashMap<String, String>();
public LWC(LWCPlugin plugin) {
this.plugin = plugin;
LWC.instance = this;
configuration = Configuration.load("core.yml");
protectionCache = new ProtectionCache(this);
backupManager = new BackupManager();
moduleLoader = new ModuleLoader(this);
}
/**
* Get the currently loaded LWC instance
*
* @return
*/
public static LWC getInstance() {
return instance;
}
/**
* Get a string representation of a block type
*
* @param id
* @return
*/
public static String materialToString(int id) {
return materialToString(Material.getMaterial(id));
}
/**
* Get a string representation of a block material
*
* @param material
* @return
*/
public static String materialToString(Material material) {
if (material != null) {
String materialName = normalizeMaterialName(material);
// attempt to match the locale
String locale = LWC.getInstance().getPlugin().getMessageParser().parseMessage(materialName.toLowerCase());
// if it starts with UNKNOWN_LOCALE, use the default material name
if (locale == null) {
locale = materialName;
}
return StringUtil.capitalizeFirstLetter(locale);
}
return "";
}
/**
* Normalize a name to a more readable & usable form.
* <p/>
* E.g sign_post/wall_sign = Sign, furnace/burning_furnace = Furnace,
* iron_door_block = iron_door
*
* @param material
* @return
*/
public static String normalizeMaterialName(Material material) {
String name = StringUtils.replace(material.toString().toLowerCase(), "block", "");
// some name normalizations
if (name.contains("sign")) {
name = "Sign";
}
if (name.contains("furnace")) {
name = "furnace";
}
if (name.endsWith("_")) {
name = name.substring(0, name.length() - 1);
}
return name.toLowerCase();
}
/**
* Restore the direction the block is facing for when 1.8 broke it
*
* @param block
*/
public void adjustChestDirection(Block block, BlockFace face) {
if (block.getType() != Material.CHEST) {
return;
}
// Is there a double chest?
Block doubleChest = findAdjacentDoubleChest(block);
// Calculate the data byte to set
byte data = 0;
switch (face) {
case NORTH:
data = 4;
break;
case SOUTH:
data = 5;
break;
case EAST:
data = 2;
break;
case WEST:
data = 3;
break;
}
// set the data for both sides of the chest
block.setData(data);
if (doubleChest != null) {
doubleChest.setData(data);
}
}
/**
* Look for a double chest adjacent to a chest
*
* @param block
* @return
*/
public Block findAdjacentDoubleChest(Block block) {
if (!DoubleChestMatcher.PROTECTABLES_CHESTS.contains(block.getType())) {
throw new UnsupportedOperationException("findAdjacentDoubleChest() cannot be called on a: " + block.getType());
}
return findAdjacentBlock(block, block.getType());
}
/**
* Check if a player has the ability to access a protection
*
* @param player
* @param block
* @return
*/
public boolean canAccessProtection(Player player, Block block) {
Protection protection = findProtection(block.getLocation());
return protection != null && canAccessProtection(player, protection);
}
/**
* Check if a player has the ability to access a protection
*
* @param player
* @param x
* @param y
* @param z
* @return
*/
public boolean canAccessProtection(Player player, int x, int y, int z) {
return canAccessProtection(player, physicalDatabase.loadProtection(player.getWorld().getName(), x, y, z));
}
/**
* Check if a player has the ability to administrate a protection
*
* @param player
* @param block
* @return
*/
public boolean canAdminProtection(Player player, Block block) {
Protection protection = findProtection(block.getLocation());
return protection != null && canAdminProtection(player, protection);
}
/**
* Check if a player has the ability to administrate a protection
*
* @param player
* @param protection
* @return
*/
public boolean canAdminProtection(Player player, Protection protection) {
if (protection == null || player == null) {
return true;
}
if (isAdmin(player)) {
return true;
}
// Their access level
Permission.Access access = Permission.Access.NONE;
switch (protection.getType()) {
case PUBLIC:
if (protection.isOwner(player)) {
return true;
}
break;
case PASSWORD:
if (protection.isOwner(player) && wrapPlayer(player).getAccessibleProtections().contains(protection)) {
return true;
}
break;
case PRIVATE:
case DONATION:
if (protection.isOwner(player)) {
return true;
}
if (protection.getAccess(player.getUniqueId().toString(), Permission.Type.PLAYER) == Permission.Access.ADMIN) {
return true;
}
if (protection.getAccess(player.getName(), Permission.Type.PLAYER) == Permission.Access.ADMIN) {
return true;
}
for (String groupName : permissions.getGroups(player)) {
if (protection.getAccess(groupName, Permission.Type.GROUP) == Permission.Access.ADMIN) {
return true;
}
}
break;
}
// call the canAccessProtection hook
LWCAccessEvent event = new LWCAccessEvent(player, protection, access);
moduleLoader.dispatchEvent(event);
return event.getAccess() == Permission.Access.ADMIN;
}
/**
* Deposit items into an inventory chest
* Works with double chests.
*
* @param block
* @param itemStack
* @return remaining items (if any)
*/
public Map<Integer, ItemStack> depositItems(Block block, ItemStack itemStack) {
BlockState blockState;
if ((blockState = block.getState()) != null && (blockState instanceof InventoryHolder)) {
Block doubleChestBlock = null;
InventoryHolder holder = (InventoryHolder) blockState;
if (DoubleChestMatcher.PROTECTABLES_CHESTS.contains(block.getType())) {
doubleChestBlock = findAdjacentDoubleChest(block);
} else if (block.getType() == Material.FURNACE || block.getType() == Material.BURNING_FURNACE) {
Inventory inventory = holder.getInventory();
if (inventory.getItem(0) != null && inventory.getItem(1) != null) {
if (inventory.getItem(0).getType() == itemStack.getType()
&& inventory.getItem(0).getData().getData() == itemStack.getData().getData()
&& inventory.getItem(0).getMaxStackSize() >= (inventory.getItem(0).getAmount() + itemStack.getAmount())) {
// ItemStack fits on Slot 0
} else if (inventory.getItem(1).getType() == itemStack.getType()
&& inventory.getItem(1).getData().getData() == itemStack.getData().getData()
&& inventory.getItem(1).getMaxStackSize() >= (inventory.getItem(1).getAmount() + itemStack.getAmount())) {
// ItemStack fits on Slot 1
} else {
return null;
}
}
}
if (itemStack.getAmount() <= 0) {
return new HashMap<Integer, ItemStack>();
}
Map<Integer, ItemStack> remaining = holder.getInventory().addItem(itemStack);
// we have remainders, deal with it
if (remaining.size() > 0) {
int key = remaining.keySet().iterator().next();
ItemStack remainingItemStack = remaining.get(key);
// is it a double chest ?????
if (doubleChestBlock != null) {
InventoryHolder holder2 = (InventoryHolder) doubleChestBlock.getState();
remaining = holder2.getInventory().addItem(remainingItemStack);
}
// recheck remaining in the event of double chest being used
if (remaining.size() > 0) {
return remaining;
}
}
}
return new HashMap<Integer, ItemStack>();
}
/**
* Find a block that is adjacent to another block given a Material
*
* @param block
* @param material
* @param ignore
* @return
*/
public Block findAdjacentBlock(Block block, Material material, Block... ignore) {
BlockFace[] faces = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST};
List<Block> ignoreList = Arrays.asList(ignore);
for (BlockFace face : faces) {
Block adjacentBlock = block.getRelative(face);
if (adjacentBlock.getType() == material && !ignoreList.contains(adjacentBlock)) {
return adjacentBlock;
}
}
return null;
}
/**
* Find a block that is adjacent to another block on any of the block's 6 sides given a Material
*
* @param block
* @param material
* @param ignore
* @return
*/
public Block findAdjacentBlockOnAllSides(Block block, Material material, Block... ignore) {
BlockFace[] faces = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN};
List<Block> ignoreList = Arrays.asList(ignore);
for (BlockFace face : faces) {
Block adjacentBlock = block.getRelative(face);
if (adjacentBlock.getType() == material && !ignoreList.contains(adjacentBlock)) {
return adjacentBlock;
}
}
return null;
}
/**
* Find a protection that is adjacent to another block on any of the block's 6 sides
*
* @param block
* @param ignore
* @return
*/
public List<Protection> findAdjacentProtectionsOnAllSides(Block block, Block... ignore) {
BlockFace[] faces = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN};
List<Block> ignoreList = Arrays.asList(ignore);
List<Protection> found = new ArrayList<Protection>();
for (BlockFace face : faces) {
Protection protection;
Block adjacentBlock = block.getRelative(face);
if (!ignoreList.contains(adjacentBlock.getLocation()) && (protection = findProtection(adjacentBlock.getLocation())) != null) {
found.add(protection);
}
}
return found;
}
/**
* Free some memory (LWC was disabled)
*/
public void destruct() {
// destroy the modules
moduleLoader.shutdown();
log("Flushing protection updates (" + databaseThread.size() + ")");
if (databaseThread != null) {
databaseThread.stop();
databaseThread = null;
}
if (physicalDatabase != null) {
physicalDatabase.dispose();
}
physicalDatabase = null;
}
/**
* Log a string
*
* @param str
*/
public void log(String str) {
plugin.getLogger().info(str);
}
/**
* Encrypt a string using SHA1
*
* @param text
* @return
*/
public String encrypt(String text) {
return StringUtil.encrypt(text);
}
/**
* Enforce access to a protected block
*
* @param player
* @param protection
* @param block
* @return true if the player was granted access
*/
public boolean enforceAccess(Player player, Protection protection, Block block, boolean hasAccess) {
MessageParser parser = plugin.getMessageParser();
if (block == null || protection == null) {
return true;
}
// support for old protection dbs that do not contain the block id
if (block != null && (protection.getBlockId() <= 0 && block.getTypeId() != protection.getBlockId())) {
protection.setBlockId(block.getTypeId());
protection.save();
}
// multi-world, update old protections
if (block != null && (protection.getWorld() == null || !block.getWorld().getName().equals(protection.getWorld()))) {
protection.setWorld(block.getWorld().getName());
protection.save();
}
// update timestamp
if (hasAccess) {
long timestamp = System.currentTimeMillis() / 1000L;
// check that they aren't an admin and if they are, they need to be the owner of the protection or have access through /cmodify
if (protection.isOwner(player) || protection.getAccess(player.getName(), Permission.Type.PLAYER) != Permission.Access.NONE) {
protection.setLastAccessed(timestamp);
protection.save();
}
}
boolean permShowNotices = hasPermission(player, "lwc.shownotices");
if ((permShowNotices && configuration.getBoolean("core.showNotices", true))
&& !Boolean.parseBoolean(resolveProtectionConfiguration(block, "quiet"))) {
boolean isOwner = protection.isOwner(player);
boolean showMyNotices = configuration.getBoolean("core.showMyNotices", true);
if (!isOwner || (isOwner && (showMyNotices || permShowNotices))) {
String owner;
// replace your username with "you" if you own the protection
if (protection.isRealOwner(player)) {
owner = parser.parseMessage("you");
} else {
owner = protection.getFormattedOwnerPlayerName();
}
String blockName = materialToString(block);
String protectionTypeToString = parser.parseMessage(protection.typeToString().toLowerCase());
if (protectionTypeToString == null) {
protectionTypeToString = "Unknown";
}
if (parser.parseMessage("protection." + blockName.toLowerCase() + ".notice.protected") != null) {
sendLocale(player, "protection." + blockName.toLowerCase() + ".notice.protected", "type", protectionTypeToString, "block", blockName, "owner", owner);
} else {
sendLocale(player, "protection.general.notice.protected", "type", protectionTypeToString, "block", blockName, "owner", owner);
}
}
}
if (!hasAccess) {
Protection.Type type = protection.getType();
if (type == Protection.Type.PASSWORD) {
sendLocale(player, "protection.general.locked.password", "block", materialToString(block), "owner", protection.getOwner());
} else if (type == Protection.Type.PRIVATE || type == Protection.Type.DONATION) {
sendLocale(player, "protection.general.locked.private", "block", materialToString(block), "owner", protection.getOwner());
}
}
return hasAccess;
}
/**
* Check if a player has the ability to access a protection
*
* @param player
* @param protection
* @return
*/
public boolean canAccessProtection(Player player, Protection protection) {
if (protection == null || player == null) {
return true;
}
if (isAdmin(player)) {
return true;
}
if (isMod(player)) {
Player protectionOwner = protection.getBukkitOwner();
if (protectionOwner == null) {
return true;
}
if (!isAdmin(protectionOwner)) {
return true;
}
}
// Their access level
Permission.Access access = Permission.Access.NONE;
switch (protection.getType()) {
case PUBLIC:
case DONATION:
return true;
case PASSWORD:
if (wrapPlayer(player).getAccessibleProtections().contains(protection)) {
return true;
}
break;
case PRIVATE:
if (protection.isOwner(player)) {
return true;
}
if (protection.getAccess(player.getUniqueId().toString(), Permission.Type.PLAYER).ordinal() >= Permission.Access.PLAYER.ordinal()) {
return true;
}
if (protection.getAccess(player.getName(), Permission.Type.PLAYER).ordinal() >= Permission.Access.PLAYER.ordinal()) {
return true;
}
// Check for item keys
for (Permission permission : protection.getPermissions()) {
if (permission.getType() != Permission.Type.ITEM) {
continue;
}
// Get the item they need to have
int item = Integer.parseInt(permission.getName());
// Are they wielding it?
if (player.getItemInHand().getTypeId() == item) {
return true;
}
}
for (String groupName : permissions.getGroups(player)) {
if (protection.getAccess(groupName, Permission.Type.GROUP).ordinal() >= Permission.Access.PLAYER.ordinal()) {
return true;
}
}
break;
}
// call the canAccessProtection hook
LWCAccessEvent event = new LWCAccessEvent(player, protection, access);
moduleLoader.dispatchEvent(event);
return event.getAccess() == Permission.Access.PLAYER || event.getAccess() == Permission.Access.ADMIN;
}
/**
* Check if a player can do mod functions on LWC
*
* @param player the player to check
* @return true if the player is an LWC mod
*/
public boolean isMod(Player player) {
return hasPermission(player, "lwc.mod");
}
/**
* Check if a player can do admin functions on LWC
*
* @param player the player to check
* @return true if the player is an LWC admin
*/
public boolean isAdmin(Player player) {
if (player.isOp()) {
if (configuration.getBoolean("core.opIsLWCAdmin", true)) {
return true;
}
}
return hasPermission(player, "lwc.admin");
}
/**
* Check if a player has a permissions node
*
* @param player
* @param node
* @return
*/
public boolean hasPermission(Player player, String node) {
try {
return player.hasPermission(node);
} catch (NoSuchMethodError e) {
// their server does not support Superperms..
return !node.contains("admin") && !node.contains("mod");
}
}
/**
* Create an LWCPlayer object for a player
*
* @param sender
* @return
*/
public LWCPlayer wrapPlayer(CommandSender sender) {
if (sender instanceof LWCPlayer) {
return (LWCPlayer) sender;
}
if (!(sender instanceof Player)) {
return null;
}
return LWCPlayer.getPlayer((Player) sender);
}
/**
* Find a player in the given ranges
*
* @param minX
* @param maxX
* @param minY
* @param maxY
* @param minZ
* @param maxZ
* @return
*/
public Player findPlayer(int minX, int maxX, int minY, int maxY, int minZ, int maxZ) {
for (Player player : plugin.getServer().getOnlinePlayers()) {
Location location = player.getLocation();
int plrX = location.getBlockX();
int plrY = location.getBlockY();
int plrZ = location.getBlockZ();
// simple check of the ranges
if (plrX >= minX && plrX <= maxX && plrY >= plrY && plrY <= maxY && plrZ >= minZ && plrZ <= maxZ) {
return player;
}
}
return null;
}
/**
* Send a locale to a player or console
*
* @param sender
* @param key
* @param args
*/
public void sendLocale(CommandSender sender, String key, Object... args) {
String[] message; // The message to send to the player
MessageParser parser = plugin.getMessageParser();
String parsed = parser.parseMessage(key, args);
if (parsed == null) {
return; // Nothing to send
}
// message = parsed.split("\\n");
message = StringUtils.split(parsed, '\n');
// broadcast an event if they are a player
if (sender instanceof Player) {
LWCSendLocaleEvent evt = new LWCSendLocaleEvent((Player) sender, key);
moduleLoader.dispatchEvent(evt);
// did they cancel it?
if (evt.isCancelled()) {
return;
}
}
if (message == null) {
sender.sendMessage(Colors.Red + "LWC: " + Colors.White + "Undefined locale: \"" + Colors.Gray + key + Colors.White + "\"");
return;
}
if (message.length > 0 && message[0].equalsIgnoreCase("null")) {
return;
}
// Send the message!
// sender.sendMessage(message);
for (String line : message) {
sender.sendMessage(line);
}
}
/**
* Get a string representation of a block's material
*
* @param block
* @return
*/
public static String materialToString(Block block) {
return materialToString(block.getType());
}
/**
* Fast remove all protections for a player. ~100k protections / second.
*
* @param sender
* @param player
* @param shouldRemoveBlocks
* @return
*/
public int fastRemoveProtectionsByPlayer(CommandSender sender, String player, boolean shouldRemoveBlocks) {
// remove their protections first
int ret = fastRemoveProtections(sender, "Lower(owner) = Lower('" + player + "')", shouldRemoveBlocks);
// invalid any history objects associated with the player
physicalDatabase.invalidateHistory(player);
return ret;
}
/**
* Remove protections very quickly with raw SQL calls
*
* @param sender
* @param where
* @param shouldRemoveBlocks
* @return
*/
public int fastRemoveProtections(CommandSender sender, String where, boolean shouldRemoveBlocks) {
List<Integer> exemptedBlocks = configuration.getIntList("optional.exemptBlocks", new ArrayList<Integer>());
List<Integer> toRemove = new LinkedList<Integer>();
List<Block> removeBlocks = null;
int totalProtections = physicalDatabase.getProtectionCount();
int completed = 0;
int count = 0;
// flush all changes to the database before working on the live database
databaseThread.flush();
if (shouldRemoveBlocks) {
removeBlocks = new LinkedList<Block>();
}
if (where != null && !where.trim().isEmpty()) {
where = " WHERE " + where.trim();
}
sender.sendMessage("Loading protections via STREAM mode");
try {
Statement resultStatement = physicalDatabase.getConnection().createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
if (physicalDatabase.getType() == Database.Type.MySQL) {
resultStatement.setFetchSize(Integer.MIN_VALUE);
}
String prefix = physicalDatabase.getPrefix();
ResultSet result = resultStatement.executeQuery("SELECT id, owner, type, x, y, z, data, blockId, world, password, date, last_accessed FROM " + prefix + "protections" + where);
while (result.next()) {
Protection protection = physicalDatabase.resolveProtection(result);
World world = protection.getBukkitWorld();
// check if the protection is exempt from being removed
if (protection.hasFlag(Flag.Type.EXEMPTION) || exemptedBlocks.contains(protection.getBlockId())) {
continue;
}
count++;
if (count % 100000 == 0 || count == totalProtections || count == 1) {
sender.sendMessage(Colors.Red + count + " / " + totalProtections);
}
if (world == null) {
continue;
}
// remove the protection
toRemove.add(protection.getId());
// remove the block ?
if (shouldRemoveBlocks) {
removeBlocks.add(protection.getBlock());
}
// Remove it from the cache if it's in there
Protection cached = protectionCache.getProtection(protection.getCacheKey());
if (cached != null) {
cached.removeCache();
}
completed++;
}
// Close the streaming statement
result.close();
resultStatement.close();
// flush all of the queries
fullRemoveProtections(sender, toRemove);
if (shouldRemoveBlocks) {
removeBlocks(sender, removeBlocks);
}
} catch (SQLException e) {
e.printStackTrace();
}
return completed;
}
/**
* Push removal changes to the database
*
* @param sender
* @param toRemove
*/
private void fullRemoveProtections(CommandSender sender, List<Integer> toRemove) throws SQLException {
StringBuilder deleteProtectionsQuery = new StringBuilder();
StringBuilder deleteHistoryQuery = new StringBuilder();
int total = toRemove.size();
int count = 0;
// iterate over the items to remove
Iterator<Integer> iter = toRemove.iterator();
// the database prefix
String prefix = getPhysicalDatabase().getPrefix();
// create the statement to use
Statement statement = getPhysicalDatabase().getConnection().createStatement();
while (iter.hasNext()) {
int protectionId = iter.next();
if (count % 10000 == 0) {
deleteProtectionsQuery.append("DELETE FROM ").append(prefix).append("protections WHERE id IN (").append(protectionId);
deleteHistoryQuery.append("UPDATE ").append(prefix).append("history SET status = " + History.Status.INACTIVE.ordinal() + " WHERE protectionId IN(").append(protectionId);
} else {
deleteProtectionsQuery.append(",").append(protectionId);
deleteHistoryQuery.append(",").append(protectionId);
}
if (count % 10000 == 9999 || count == (total - 1)) {
deleteProtectionsQuery.append(")");
deleteHistoryQuery.append(")");
statement.executeUpdate(deleteProtectionsQuery.toString());
statement.executeUpdate(deleteHistoryQuery.toString());
deleteProtectionsQuery.setLength(0);
deleteHistoryQuery.setLength(0);
sender.sendMessage(Colors.Green + "REMOVED " + (count + 1) + " / " + total);
}
count++;
physicalDatabase.decrementProtectionCount();
}
statement.close();
}
/**
* Remove a list of blocks from the world
*
* @param sender
* @param blocks
*/
private void removeBlocks(CommandSender sender, List<Block> blocks) {
int count = 0;
for (Block block : blocks) {
if (block == null || !isProtectable(block)) {
continue;
}
// possibility of a double chest
if (DoubleChestMatcher.PROTECTABLES_CHESTS.contains(block.getType())) {
Block doubleChest = findAdjacentDoubleChest(block);
if (doubleChest != null) {
removeInventory(doubleChest);
doubleChest.setType(Material.AIR);
}
}
// remove the inventory from the block if it has one
removeInventory(block);
// and now remove the block
block.setType(Material.AIR);
count++;
}
sender.sendMessage("Removed " + count + " blocks from the world");
}
/**
* Remove the inventory from a block
*
* @param block
*/
private void removeInventory(Block block) {
if (block == null) {
return;
}
if (!(block.getState() instanceof InventoryHolder)) {
return;
}
InventoryHolder holder = (InventoryHolder) block.getState();
holder.getInventory().clear();
}
/**
* Compares two blocks if they are equal
*
* @param block
* @param block2
* @return
*/
public boolean blockEquals(Block block, Block block2) {
return block.getType() == block2.getType() && block.getX() == block2.getX() && block.getY() == block2.getY()
&& block.getZ() == block2.getZ() && block.getData() == block2.getData();
}
/**
* Compares two blocks if they are equal
*
* @param block
* @param block2
* @return
*/
public boolean blockEquals(BlockState block, BlockState block2) {
return block.getType() == block2.getType() && block.getX() == block2.getX() && block.getY() == block2.getY()
&& block.getZ() == block2.getZ() && block.getRawData() == block2.getRawData();
}
/**
* Find a protection linked to the location
*
* @param location
* @return
*/
public Protection findProtection(Location location) {
String cacheKey = protectionCache.cacheKey(location);
if (protectionCache.isKnownNull(cacheKey)) {
return null;
}
Protection protection = protectionCache.getProtection(cacheKey);
return protection != null ? protection : findProtection(location.getBlock());
}
/**
* Find a protection linked to the block
*
* @param block
* @return
*/
public Protection findProtection(Block block) {
return findProtection(block.getState());
}
/**
* Find a protection linked to the block
*
* @param state
* @return
*/
public Protection findProtection(BlockState state) {
// If the block type is AIR, then we have a problem .. but attempt to load a protection anyway
// Note: this call stems from a very old bug in Bukkit that likely does not exist anymore at all
// but is kept just incase. At one point getBlock() in Bukkit would sometimes say a block
// is an eir block even though the client and server sees it differently (ie a chest).
// This was of course very problematic!
if (state.getType() == Material.AIR) {
// We won't be able to match any other blocks anyway, so the least we can do is attempt to load a protection
return physicalDatabase.loadProtection(state.getWorld().getName(), state.getX(), state.getY(), state.getZ());
}
// Create a protection finder
ProtectionFinder finder = new ProtectionFinder(this);
// Search for a protection
boolean result = finder.matchBlocks(state);
Protection found = null;
// We're done, load the possibly loaded protection
if (result) {
found = finder.loadProtection();
}
if (found == null) {
protectionCache.addKnownNull(protectionCache.cacheKey(state.getLocation()));
}
return found;
}
/**
* Find a protection linked to the block at [x, y, z]
*
* @param world
* @param x
* @param y
* @param z
* @return
*/
public Protection findProtection(World world, int x, int y, int z) {
if (world == null) {
return null;
}
return findProtection(new Location(world, x, y, z));
}
/**
* Check if a player has either access to lwc.admin or the specified node
*
* @param sender
* @param node
* @return
*/
public boolean hasAdminPermission(CommandSender sender, String node) {
return isAdmin(sender) || hasPermission(sender, node, "lwc.admin");
}
/**
* Check if a player is an LWC admin -- Console defaults to *YES*
*
* @param sender
* @return
*/
public boolean isAdmin(CommandSender sender) {
return !(sender instanceof Player) || isAdmin((Player) sender);
}
/**
* Check a player for a node, using a fallback as a default (e.g lwc.protect)
*
* @param sender
* @param node
* @param fallback
* @return
*/
public boolean hasPermission(CommandSender sender, String node, String... fallback) {
if (!(sender instanceof Player)) {
return true;
}
Player player = (Player) sender;
boolean hasNode = hasPermission(player, node);
if (!hasNode) {
for (String temp : fallback) {
if (hasPermission(player, temp)) {
return true;
}
}
}
return hasNode;
}
/**
* Check if a player has either access to lwc.protect or the specified node
*
* @param sender
* @param node
* @return
*/
public boolean hasPlayerPermission(CommandSender sender, String node) {
return hasPermission(sender, node, "lwc.protect");
}
/**
* Check if a mode is enabled
*
* @param mode
* @return
*/
public boolean isModeEnabled(String mode) {
return configuration.getBoolean("modes." + mode + ".enabled", true);
}
/**
* Check if a mode is whitelisted for a player
*
* @param mode
* @return
*/
public boolean isModeWhitelisted(Player player, String mode) {
return hasPermission(player, "lwc.mode." + mode, "lwc.allmodes");
}
/**
* Check a block to see if it is protectable
*
* @param block
* @return
*/
public boolean isProtectable(Block block) {
Material material = block.getType();
if (material == null) {
return false;
}
return Boolean.parseBoolean(resolveProtectionConfiguration(block, "enabled"));
}
/**
* Check a block to see if it is protectable
*
* @param state
* @return
*/
public boolean isProtectable(BlockState state) {
Material material = state.getType();
if (material == null) {
return false;
}
return Boolean.parseBoolean(resolveProtectionConfiguration(state, "enabled"));
}
/**
* Get the appropriate config value for the block (protections.block.node)
*
* @param block
* @param node
* @return
*/
public String resolveProtectionConfiguration(Block block, String node) {
Material material = block.getType();
String cacheKey = block.getData() + "-" + material.toString() + "-" + node;
if (protectionConfigurationCache.containsKey(cacheKey)) {
return protectionConfigurationCache.get(cacheKey);
}
List<String> names = new ArrayList<String>();
String materialName = normalizeMaterialName(material);
// add the name & the block id
names.add(materialName);
names.add(material.getId() + "");
names.add(material.getId() + ":" + block.getData());
names.add(materialName + ":" + block.getData());
if (!materialName.equals(material.toString().toLowerCase())) {
names.add(material.toString().toLowerCase());
}
// Add the wildcards last so it can be overriden
names.add("*");
names.add(material.getId() + ":*");
String value = configuration.getString("protections." + node);
for (String name : names) {
String temp = configuration.getString("protections.blocks." + name + "." + node);
if (temp != null && !temp.isEmpty()) {
value = temp;
}
}
protectionConfigurationCache.put(cacheKey, value);
return value;
}
/**
* Get the appropriate config value for the block (protections.block.node)
*
* @param state
* @param node
* @return
*/
public String resolveProtectionConfiguration(BlockState state, String node) {
Material material = state.getType();
String cacheKey = state.getRawData() + "-" + material.toString() + "-" + node;
if (protectionConfigurationCache.containsKey(cacheKey)) {
return protectionConfigurationCache.get(cacheKey);
}
List<String> names = new ArrayList<String>();
String materialName = normalizeMaterialName(material);
// add the name & the block id
names.add(materialName);
names.add(material.getId() + "");
names.add(material.getId() + ":" + state.getRawData());
names.add(materialName + ":" + state.getRawData());
if (!materialName.equals(material.toString().toLowerCase())) {
names.add(material.toString().toLowerCase());
}
// Add the wildcards last so it can be overriden
names.add("*");
names.add(material.getId() + ":*");
String value = configuration.getString("protections." + node);
for (String name : names) {
String temp = configuration.getString("protections.blocks." + name + "." + node);
if (temp != null && !temp.isEmpty()) {
value = temp;
}
}
protectionConfigurationCache.put(cacheKey, value);
return value;
}
/**
* Get the appropriate config value for the block (protections.block.node)
*
* @param material
* @param node
* @return
*/
public String resolveProtectionConfiguration(Material material, String node) {
String cacheKey = "00-" + material.toString() + "-" + node;
if (protectionConfigurationCache.containsKey(cacheKey)) {
return protectionConfigurationCache.get(cacheKey);
}
List<String> names = new ArrayList<String>();
String materialName = normalizeMaterialName(material);
// add the name & the block id
names.add(materialName);
names.add(material.getId() + "");
if (!materialName.equals(material.toString().toLowerCase())) {
names.add(material.toString().toLowerCase());
}
// Add the wildcards last so it can be overriden
names.add("*");
names.add(material.getId() + ":*");
String value = configuration.getString("protections." + node);
for (String name : names) {
String temp = configuration.getString("protections.blocks." + name + "." + node);
if (temp != null && !temp.isEmpty()) {
value = temp;
}
}
protectionConfigurationCache.put(cacheKey, value);
return value;
}
/**
* Load sqlite (done only when LWC is loaded so memory isn't used unnecessarily)
*/
public void load() {
configuration = Configuration.load("core.yml");
registerCoreModules();
// check for upgrade before everything else
new ConfigPost300().run();
plugin.loadDatabase();
Statistics.init();
physicalDatabase = new PhysDB();
databaseThread = new DatabaseThread(this);
// Permissions init
permissions = new SuperPermsPermissions();
if (resolvePlugin("Vault") != null) {
permissions = new VaultPermissions();
} else if (resolvePlugin("PermissionsBukkit") != null) {
permissions = new BukkitPermissions();
} else if (resolvePlugin("PermissionsEx") != null) {
permissions = new PEXPermissions();
} else if (resolvePlugin("bPermissions") != null) {
permissions = new bPermissions();
}
// Currency init
currency = new NoCurrency();
if (resolvePlugin("Vault") != null) {
currency = new VaultCurrency();
} else if (resolvePlugin("iConomy") != null) {
// We need to figure out which iConomy plugin we have...
Plugin plugin = resolvePlugin("iConomy");
// get the class name
String className = plugin.getClass().getName();
// check for the iConomy5 package
try {
if (className.startsWith("com.iConomy")) {
currency = new iConomy5Currency();
} else {
// iConomy 6!
currency = new iConomy6Currency();
}
} catch (NoClassDefFoundError e) {
}
} else if (resolvePlugin("BOSEconomy") != null) {
currency = new BOSECurrency();
} else if (resolvePlugin("Essentials") != null) {
currency = new EssentialsCurrency();
}
plugin.getUpdater().init();
log("Connecting to " + Database.DefaultType);
try {
if (!physicalDatabase.connect()) {
Bukkit.getPluginManager().disablePlugin(plugin);
return;
}
physicalDatabase.load();
} catch (Exception e) {
e.printStackTrace();
}
// check any major conversions
new MySQLPost200().run();
// precache protections
physicalDatabase.precache();
// We are now done loading!
moduleLoader.loadAll();
// Should we try metrics?
if (!configuration.getBoolean("optional.optOut", false)) {
try {
Metrics metrics = new Metrics(plugin);
// Create a line graph
Metrics.Graph lineGraph = metrics.createGraph("Protections");
// Add the total protections plotter
lineGraph.addPlotter(new Metrics.Plotter("Total") {
@Override
public int getValue() {
return physicalDatabase.getProtectionCount();
}
});
// Create a pie graph for individual protections
Metrics.Graph pieGraph = metrics.createGraph("Protection percentages");
for (final Protection.Type type : Protection.Type.values()) {
if (type == Protection.Type.RESERVED1 || type == Protection.Type.RESERVED2) {
continue;
}
// Create the plotter
Metrics.Plotter plotter = new Metrics.Plotter(StringUtil.capitalizeFirstLetter(type.toString()) + " Protections") {
@Override
public int getValue() {
return physicalDatabase.getProtectionCount(type);
}
};
// Add it to both graphs
lineGraph.addPlotter(plotter);
pieGraph.addPlotter(plotter);
}
// Locale
Metrics.Graph langGraph = metrics.createGraph("Locale");
langGraph.addPlotter(new Metrics.Plotter(LocaleUtil.iso639ToEnglish(configuration.getString("core.locale", "en"))) {
@Override
public int getValue() {
return 1;
}
});
// Database type
Metrics.Graph databaseGraph = metrics.createGraph("Database Engine");
databaseGraph.addPlotter(new Metrics.Plotter(physicalDatabase.getType().toString()) {
@Override
public int getValue() {
return 1;
}
});
metrics.start();
} catch (IOException e) {
log(e.getMessage());
}
}
}
/**
* Register the core modules for LWC
*/
private void registerCoreModules() {
// MCPC
registerModule(new LWCMCPCSupport(this));
// core
registerModule(new LimitsV2());
registerModule(new LimitsModule());
registerModule(new CreateModule());
registerModule(new ModifyModule());
registerModule(new DestroyModule());
registerModule(new FreeModule());
registerModule(new InfoModule());
registerModule(new UnlockModule());
registerModule(new OwnersModule());
registerModule(new DoorsModule());
registerModule(new DebugModule());
registerModule(new CreditsModule());
registerModule(new FixModule());
registerModule(new HistoryModule());
registerModule(new ConfirmModule());
// admin commands
registerModule(new BaseAdminModule());
registerModule(new AdminCache());
registerModule(new AdminCleanup());
registerModule(new AdminClear());
registerModule(new AdminFind());
registerModule(new AdminFlush());
registerModule(new AdminForceOwner());
registerModule(new AdminLocale());
registerModule(new AdminPurge());
registerModule(new AdminReload());
registerModule(new AdminRemove());
registerModule(new AdminReport());
registerModule(new AdminVersion());
registerModule(new AdminQuery());
registerModule(new AdminPurgeBanned());
registerModule(new AdminExpire());
registerModule(new AdminDump());
registerModule(new AdminRebuild());
registerModule(new AdminBackup());
registerModule(new AdminView());
// /lwc setup
registerModule(new BaseSetupModule());
registerModule(new DatabaseSetupModule());
registerModule(new LimitsSetup());
// flags
registerModule(new BaseFlagModule());
registerModule(new RedstoneModule());
registerModule(new MagnetModule());
// modes
registerModule(new BaseModeModule());
registerModule(new PersistModule());
registerModule(new DropTransferModule());
registerModule(new NoSpamModule());
// non-core modules but are included with LWC anyway
if (resolvePlugin("WorldGuard") != null) {
registerModule(new WorldGuard());
}
if (resolvePlugin("Towny") != null) {
registerModule(new Towny());
}
}
/**
* Register a module
*
* @param module
*/
private void registerModule(Module module) {
moduleLoader.registerModule(plugin, module);
}
/**
* Get a plugin by the name. Does not have to be enabled, and will remain disabled if it is disabled.
*
* @param name
* @return
*/
private Plugin resolvePlugin(String name) {
Plugin temp = plugin.getServer().getPluginManager().getPlugin(name);
if (temp == null) {
return null;
}
return temp;
}
/**
* Merge inventories into one
*
* @param blocks
* @return
*/
public ItemStack[] mergeInventories(List<Block> blocks) {
ItemStack[] stacks = new ItemStack[54];
int index = 0;
try {
for (Block block : blocks) {
if (!(block.getState() instanceof InventoryHolder)) {
continue;
}
InventoryHolder holder = (InventoryHolder) block.getState();
Inventory inventory = holder.getInventory();
// Add all the items from this inventory
for (ItemStack stack : inventory.getContents()) {
stacks[index] = stack;
index++;
}
}
} catch (Exception e) {
return mergeInventories(blocks);
}
return stacks;
}
/**
* Process rights inputted for a protection and add or remove them to the given protection
*
* @param sender
* @param protection
* @param arguments
*/
public void processRightsModifications(CommandSender sender, Protection protection, String... arguments) {
// Does it match a protection type?
try {
Protection.Type protectionType = Protection.Type.matchType(arguments[0]);
if (protectionType != null) {
protection.setType(protectionType);
protection.save();
// If it's being passworded, we need to set the password
if (protectionType == Protection.Type.PASSWORD) {
String password = StringUtil.join(arguments, 1);
protection.setPassword(encrypt(password));
}
sendLocale(sender, "protection.typechanged", "type", plugin.getMessageParser().parseMessage(protectionType.toString().toLowerCase()));
return;
}
} catch (IllegalArgumentException e) {
// It's normal for this to be thrown if nothing was matched
}
for (String value : arguments) {
boolean remove = false;
boolean isAdmin = false;
Permission.Type type = Permission.Type.PLAYER;
// Gracefully ignore id
if (value.startsWith("id:")) {
continue;
}
if (value.startsWith("-")) {
remove = true;
value = value.substring(1);
}
if (value.startsWith("@")) {
isAdmin = true;
value = value.substring(1);
}
if (value.toLowerCase().startsWith("p:")) {
type = Permission.Type.PLAYER;
value = value.substring(2);
}
if (value.toLowerCase().startsWith("g:")) {
type = Permission.Type.GROUP;
value = value.substring(2);
}
if (value.toLowerCase().startsWith("t:")) {
type = Permission.Type.TOWN;
value = value.substring(2);
}
if (value.toLowerCase().startsWith("town:")) {
type = Permission.Type.TOWN;
value = value.substring(5);
}
if (value.toLowerCase().startsWith("item:")) {
type = Permission.Type.ITEM;
value = value.substring(5);
}
if (value.toLowerCase().startsWith("r:")) {
type = Permission.Type.REGION;
value = value.substring(2);
}
if (value.toLowerCase().startsWith("region:")) {
type = Permission.Type.REGION;
value = value.substring(7);
}
if (value.trim().isEmpty()) {
continue;
}
String localeChild = type.toString().toLowerCase();
// If it's a player, convert it to UUID
if (type == Permission.Type.PLAYER) {
UUID uuid = UUIDRegistry.getUUID(value);
if (uuid != null) {
value = uuid.toString();
}
}
if (!remove) {
Permission permission = new Permission(value, type);
permission.setAccess(isAdmin ? Permission.Access.ADMIN : Permission.Access.PLAYER);
// add it to the protection and queue it to be saved
protection.addPermission(permission);
protection.save();
if (type == Permission.Type.PLAYER) {
sendLocale(sender, "protection.interact.rights.register." + localeChild, "name", UUIDRegistry.formatPlayerName(value), "isadmin", isAdmin ? "[" + Colors.Red + "ADMIN" + Colors.Gold + "]" : "");
} else {
sendLocale(sender, "protection.interact.rights.register." + localeChild, "name", value, "isadmin", isAdmin ? "[" + Colors.Red + "ADMIN" + Colors.Gold + "]" : "");
}
} else {
protection.removePermissions(value, type);
protection.save();
if (type == Permission.Type.PLAYER) {
sendLocale(sender, "protection.interact.rights.remove." + localeChild, "name", UUIDRegistry.formatPlayerName(value), "isadmin", isAdmin ? "[" + Colors.Red + "ADMIN" + Colors.Gold + "]" : "");
} else {
sendLocale(sender, "protection.interact.rights.remove." + localeChild, "name", value, "isadmin", isAdmin ? "[" + Colors.Red + "ADMIN" + Colors.Gold + "]" : "");
}
}
}
}
/**
* Reload internal data structures
*/
public void reload() {
plugin.loadLocales();
protectionConfigurationCache.clear();
Configuration.reload();
moduleLoader.dispatchEvent(new LWCReloadEvent());
}
/**
* Reload the database
*/
public void reloadDatabase() {
try {
databaseThread.flush();
databaseThread.stop();
physicalDatabase = new PhysDB();
physicalDatabase.connect();
physicalDatabase.load();
databaseThread = new DatabaseThread(this);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Remove all modes if the player is not in persistent mode
*
* @param sender
*/
public void removeModes(CommandSender sender) {
if (sender instanceof Player) {
Player bPlayer = (Player) sender;
if (notInPersistentMode(bPlayer.getName())) {
wrapPlayer(bPlayer).removeAllActions();
}
} else if (sender instanceof LWCPlayer) {
removeModes(((LWCPlayer) sender).getBukkitPlayer());
}
}
/**
* Return if the player is in persistent mode
*
* @param player the player to check
* @return true if the player is NOT in persistent mode
*/
public boolean notInPersistentMode(String player) {
return !wrapPlayer(Bukkit.getServer().getPlayer(player)).hasMode("persist");
}
/**
* Send the full help to a player
*
* @param sender the player to send to
*/
public void sendFullHelp(CommandSender sender) {
sendLocale(sender, "help.basic");
if (isAdmin(sender)) {
sender.sendMessage("");
sender.sendMessage(Colors.Red + "/lwc admin - Administration");
}
}
/**
* Send the simple usage of a command
*
* @param player
* @param command
*/
public void sendSimpleUsage(CommandSender player, String command) {
sendLocale(player, "help.simpleusage", "command", command);
}
/**
* @return the configuration object
*/
public Configuration getConfiguration() {
return configuration;
}
/**
* @return the Currency handler
*/
public ICurrency getCurrency() {
return currency;
}
/**
* @return the backup manager
*/
public BackupManager getBackupManager() {
return backupManager;
}
/**
* @return the module loader
*/
public ModuleLoader getModuleLoader() {
return moduleLoader;
}
/**
* @return the Permissions handler
*/
public IPermissions getPermissions() {
return permissions;
}
/**
* @return physical database object
*/
public PhysDB getPhysicalDatabase() {
return physicalDatabase;
}
/**
* @return the plugin class
*/
public LWCPlugin getPlugin() {
return plugin;
}
/**
* @return the protection cache
*/
public ProtectionCache getProtectionCache() {
return protectionCache;
}
/**
* @return the update thread
*/
public DatabaseThread getDatabaseThread() {
return databaseThread;
}
/**
* @return the plugin version
*/
public double getVersion() {
return Double.parseDouble(plugin.getDescription().getVersion());
}
/**
* @return true if history logging is enabled
*/
public boolean isHistoryEnabled() {
return !configuration.getBoolean("core.disableHistory", false);
}
}