bentobox/src/main/java/us/tastybento/bskyblock/listeners/protection/IslandGuard1_9.java

498 lines
20 KiB
Java

package us.tastybento.bskyblock.listeners.protection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Animals;
import org.bukkit.entity.EnderCrystal;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Snowman;
import org.bukkit.entity.Squid;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.LingeringPotionSplashEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.projectiles.ProjectileSource;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.database.objects.Island.SettingsFlag;
import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.util.Util;
import us.tastybento.bskyblock.util.VaultHelper;
/**
* @author tastybento
* Provides protection to islands - handles newer events that may not
* exist in older servers
*/
public class IslandGuard1_9 implements Listener {
private final BSkyBlock plugin;
private final static boolean DEBUG = false;
private HashMap<Integer, UUID> thrownPotions;
public IslandGuard1_9(final BSkyBlock plugin) {
this.plugin = plugin;
this.thrownPotions = new HashMap<Integer, UUID>();
}
/**
* Handles Frost Walking on visitor's islands
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onBlockForm(EntityBlockFormEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +e.getEventName());
}
if (e.getEntity() instanceof Player && e.getNewState().getType().equals(Material.FROSTED_ICE)) {
Player player= (Player) e.getEntity();
if (!IslandGuard.inWorld(player)) {
return;
}
if (player.isOp()) {
return;
}
// This permission bypasses protection
if (VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect")) {
return;
}
// Check island
Island island = plugin.getIslands().getIslandAt(player.getLocation());
if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) {
return;
}
if (island !=null) {
if (island.getMembers().contains(player.getUniqueId()) || island.getFlag(SettingsFlag.PLACE_BLOCKS)) {
return;
}
}
// Silently cancel the event
e.setCancelled(true);
}
}
/**
* Handle interaction with end crystals 1.9
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onHitEndCrystal(final PlayerInteractAtEntityEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +e.getEventName());
}
if (!IslandGuard.inWorld(e.getPlayer())) {
return;
}
if (e.getPlayer().isOp()) {
return;
}
// This permission bypasses protection
if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")) {
return;
}
if (e.getRightClicked() != null && e.getRightClicked().getType().equals(EntityType.ENDER_CRYSTAL)) {
// Check island
Island island = plugin.getIslands().getIslandAt(e.getRightClicked().getLocation());
if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) {
return;
}
if (island !=null) {
if (island.getMembers().contains(e.getPlayer().getUniqueId()) || island.getFlag(SettingsFlag.BREAK_BLOCKS)) {
return;
}
}
e.setCancelled(true);
Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected"));
}
}
// End crystal
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true)
void placeEndCrystalEvent(PlayerInteractEvent e) {
Player p = e.getPlayer();
if (DEBUG) {
plugin.getLogger().info("1.9 " +"End crystal place " + e.getEventName());
}
if (!IslandGuard.inWorld(p)) {
return;
}
if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) {
// You can do anything if you are Op
return;
}
// Check if they are holding armor stand
for (ItemStack inHand : Util.getPlayerInHandItems(e.getPlayer())) {
if (inHand.getType().equals(Material.END_CRYSTAL)) {
// Check island
Island island = plugin.getIslands().getIslandAt(e.getPlayer().getLocation());
if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.PLACE_BLOCKS)) {
return;
}
if (island !=null && (island.getMembers().contains(p.getUniqueId()) || island.getFlag(SettingsFlag.PLACE_BLOCKS))) {
//plugin.getLogger().info("1.9 " +"DEBUG: armor stand place check");
if (Settings.limitedBlocks.containsKey("END_CRYSTAL") && Settings.limitedBlocks.get("END_CRYSTAL") > -1) {
//plugin.getLogger().info("1.9 " +"DEBUG: count armor stands");
int count = island.getTileEntityCount(Material.END_CRYSTAL,e.getPlayer().getWorld());
//plugin.getLogger().info("1.9 " +"DEBUG: count is " + count + " limit is " + Settings.limitedBlocks.get("ARMOR_STAND"));
if (Settings.limitedBlocks.get("END_CRYSTAL") <= count) {
Util.sendMessage(e.getPlayer(), ChatColor.RED + (plugin.getLocale(e.getPlayer().getUniqueId()).get("moblimits.entity").replace("[entity]",
Util.prettifyText(Material.END_CRYSTAL.toString()))).replace("[number]", String.valueOf(Settings.limitedBlocks.get("END_CRYSTAL"))));
e.setCancelled(true);
return;
}
}
return;
}
// plugin.getLogger().info("1.9 " +"DEBUG: stand place cancelled");
e.setCancelled(true);
Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected"));
e.getPlayer().updateInventory();
}
}
}
/**
* Handle end crystal damage by visitors
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void EndCrystalDamage(EntityDamageByEntityEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +"IslandGuard 1_9 " + e.getEventName());
plugin.getLogger().info("1.9 " +"Entity is " + e.getEntityType());
}
if (e.getEntity() == null || !IslandGuard.inWorld(e.getEntity())) {
return;
}
if (!(e.getEntity() instanceof EnderCrystal)) {
if (DEBUG) {
plugin.getLogger().info("1.9 Entity is not End crystal it is " + e.getEntityType());
}
return;
}
if (DEBUG) {
plugin.getLogger().info("1.9 Damager is " + e.getDamager());
}
Player p = null;
if (e.getDamager() instanceof Player) {
p = (Player) e.getDamager();
if (DEBUG) {
plugin.getLogger().info("1.9 Damager is a player");
}
} else if (e.getDamager() instanceof Projectile) {
// Get the shooter
Projectile projectile = (Projectile)e.getDamager();
ProjectileSource shooter = projectile.getShooter();
if (shooter instanceof Player) {
p = (Player)shooter;
}
if (DEBUG) {
plugin.getLogger().info("1.9 " +"Damager is a projectile shot by " + p.getName());
}
}
if (p != null) {
if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +"Bypassing protection");
}
return;
}
// Check if on island
if (plugin.getIslands().playerIsOnIsland(p)) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +"Player is on their own island");
}
return;
}
// Check island
Island island = plugin.getIslands().getIslandAt(e.getEntity().getLocation());
if (island == null && Settings.defaultWorldSettings.get(SettingsFlag.BREAK_BLOCKS)) {
return;
}
if (island != null && island.getFlag(SettingsFlag.BREAK_BLOCKS)) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +"Visitor is allowed to break blocks");
}
return;
}
Util.sendMessage(p, ChatColor.RED + plugin.getLocale(p.getUniqueId()).get("island.protected"));
e.setCancelled(true);
}
}
/**
* Handles end crystal explosions
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onExplosion(final EntityExplodeEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +e.getEventName());
plugin.getLogger().info("1.9 " +"Entity exploding is " + e.getEntity());
}
if (e.getEntity() == null || !e.getEntityType().equals(EntityType.ENDER_CRYSTAL)) {
if (DEBUG) {
plugin.getLogger().info("1.9 " +"Entity is not an END CRYSTAL");
}
return;
}
if (!IslandGuard.inWorld(e.getLocation())) {
return;
}
// General settings irrespective of whether this is allowed or not
if (!Settings.allowTNTDamage) {
plugin.getLogger().info("1.9 " +"TNT block damage prevented");
e.blockList().clear();
} else {
if (!Settings.allowChestDamage) {
List<Block> toberemoved = new ArrayList<Block>();
// Save the chest blocks in a list
for (Block b : e.blockList()) {
switch (b.getType()) {
case CHEST:
case ENDER_CHEST:
case STORAGE_MINECART:
case TRAPPED_CHEST:
toberemoved.add(b);
break;
default:
break;
}
}
// Now delete them
for (Block b : toberemoved) {
e.blockList().remove(b);
}
}
}
// prevent at spawn
if (plugin.getIslands().isAtSpawn(e.getLocation())) {
e.blockList().clear();
e.setCancelled(true);
}
}
/**
* Handle blocks that need special treatment
* Tilling of coarse dirt into dirt using off-hand (regular hand is in 1.8)
* Usually prevented because it could lead to an endless supply of dirt with gravel
*
* @param e
*/
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onPlayerInteract(final PlayerInteractEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.9 " + e.getEventName());
}
if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
return;
}
if (!IslandGuard.inWorld(e.getPlayer())) {
return;
}
if (e.getPlayer().isOp()) {
return;
}
// This permission bypasses protection
if (VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "mod.bypassprotect")
|| VaultHelper.hasPerm(e.getPlayer(), Settings.PERMPREFIX + "craft.dirt")) {
return;
}
// Prevents tilling of coarse dirt into dirt
ItemStack inHand = e.getPlayer().getInventory().getItemInOffHand();
if (inHand.getType() == Material.WOOD_HOE || inHand.getType() == Material.IRON_HOE || inHand.getType() == Material.GOLD_HOE
|| inHand.getType() == Material.DIAMOND_HOE || inHand.getType() == Material.STONE_HOE) {
// plugin.getLogger().info("1.8 " + "DEBUG: hoe in hand");
Block block = e.getClickedBlock();
// plugin.getLogger().info("1.8 " + "DEBUG: block is " + block.getType() +
// ":" + block.getData());
// Check if coarse dirt
if (block.getType() == Material.DIRT && block.getData() == (byte) 1) {
// plugin.getLogger().info("1.8 " + "DEBUG: hitting coarse dirt!");
e.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onLingeringPotionSplash(final LingeringPotionSplashEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.9 " + e.getEventName());
plugin.getLogger().info("1.9 entity = " + e.getEntity());
plugin.getLogger().info("1.9 entity type = " + e.getEntityType());
plugin.getLogger().info("1.9 radius = " + e.getAreaEffectCloud().getRadius());
plugin.getLogger().info("1.9 id = " + e.getAreaEffectCloud().getEntityId());
plugin.getLogger().info("1.9 hit entity = " + e.getHitEntity());
}
if (!IslandGuard.inWorld(e.getEntity().getLocation())) {
return;
}
// Try to get the shooter
Projectile projectile = (Projectile) e.getEntity();
plugin.getLogger().info("shooter = " + projectile.getShooter());
if (projectile.getShooter() != null && projectile.getShooter() instanceof Player) {
UUID uuid = ((Player)projectile.getShooter()).getUniqueId();
// Store it and remove it when the effect is gone
thrownPotions.put(e.getAreaEffectCloud().getEntityId(), uuid);
plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
if (DEBUG)
plugin.getLogger().info("DEBUG: Effect finished");
thrownPotions.remove(e.getAreaEffectCloud().getEntityId());
}}, e.getAreaEffectCloud().getDuration());
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onLingeringPotionDamage(final EntityDamageByEntityEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.9 lingering potion damage " + e.getEventName());
plugin.getLogger().info("1.9 lingering potion entity = " + e.getEntity());
plugin.getLogger().info("1.9 lingering potion entity type = " + e.getEntityType());
plugin.getLogger().info("1.9 lingering potion cause = " + e.getCause());
plugin.getLogger().info("1.9 lingering potion damager = " + e.getDamager());
}
if (!IslandGuard.inWorld(e.getEntity().getLocation())) {
return;
}
if (e.getEntity() == null || e.getEntity().getUniqueId() == null) {
return;
}
if (e.getCause().equals(DamageCause.ENTITY_ATTACK) && thrownPotions.containsKey(e.getDamager().getEntityId())) {
UUID attacker = thrownPotions.get(e.getDamager().getEntityId());
// Self damage
if (attacker.equals(e.getEntity().getUniqueId())) {
if (DEBUG)
plugin.getLogger().info("DEBUG: Self damage from lingering potion!");
return;
}
Island island = plugin.getIslands().getIslandAt(e.getEntity().getLocation());
boolean inNether = false;
if (e.getEntity().getWorld().equals(IslandWorld.getNetherWorld())) {
inNether = true;
}
// Monsters being hurt
if (e.getEntity() instanceof Monster || e.getEntity() instanceof Slime || e.getEntity() instanceof Squid) {
// Normal island check
if (island != null && island.getMembers().contains(attacker)) {
// Members always allowed
return;
}
if (actionAllowed(attacker, e.getEntity().getLocation(), SettingsFlag.HURT_MONSTERS)) {
return;
}
// Not allowed
e.setCancelled(true);
return;
}
// Mobs being hurt
if (e.getEntity() instanceof Animals || e.getEntity() instanceof IronGolem || e.getEntity() instanceof Snowman
|| e.getEntity() instanceof Villager) {
if (island != null && (island.getFlag(SettingsFlag.HURT_ANIMALS) || island.getMembers().contains(attacker))) {
return;
}
if (DEBUG)
plugin.getLogger().info("DEBUG: Mobs not allowed to be hurt. Blocking");
e.setCancelled(true);
return;
}
// Establish whether PVP is allowed or not.
boolean pvp = false;
if ((inNether && island != null && island.getFlag(SettingsFlag.PVP_NETHER) || (!inNether && island != null && island.getFlag(SettingsFlag.PVP_OVERWORLD)))) {
if (DEBUG) plugin.getLogger().info("DEBUG: PVP allowed");
pvp = true;
}
// Players being hurt PvP
if (e.getEntity() instanceof Player) {
if (pvp) {
if (DEBUG) plugin.getLogger().info("DEBUG: PVP allowed");
return;
} else {
if (DEBUG) plugin.getLogger().info("DEBUG: PVP not allowed");
e.setCancelled(true);
return;
}
}
}
}
/**
* Checks if action is allowed for player in location for flag
* @param uuid
* @param location
* @param flag
* @return true if allowed
*/
private boolean actionAllowed(UUID uuid, Location location, SettingsFlag flag) {
Player player = plugin.getServer().getPlayer(uuid);
if (player == null) {
return actionAllowed(location, flag);
}
// This permission bypasses protection
if (player.isOp() || VaultHelper.hasPerm(player, Settings.PERMPREFIX + "mod.bypassprotect")) {
return true;
}
Island island = plugin.getIslands().getProtectedIslandAt(location);
if (island != null && (island.getFlag(flag) || island.getMembers().contains(player.getUniqueId()))){
return true;
}
if (island == null && Settings.defaultWorldSettings.get(flag)) {
return true;
}
return false;
}
/**
* Action allowed in this location
* @param location
* @param flag
* @return true if allowed
*/
private boolean actionAllowed(Location location, SettingsFlag flag) {
Island island = plugin.getIslands().getProtectedIslandAt(location);
if (island != null && island.getFlag(flag)){
return true;
}
if (island == null && Settings.defaultWorldSettings.get(flag)) {
return true;
}
return false;
}
}