Added protection for islands.

This commit is contained in:
tastybento 2017-07-06 22:00:21 -07:00
parent f31dcb5ce1
commit cce5828ac0
9 changed files with 3887 additions and 19 deletions

View File

@ -22,10 +22,14 @@ import us.tastybento.bskyblock.database.BSBDatabase;
import us.tastybento.bskyblock.database.managers.IslandsManager;
import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages;
import us.tastybento.bskyblock.database.managers.PlayersManager;
import us.tastybento.bskyblock.database.objects.Island.SettingsFlag;
import us.tastybento.bskyblock.generators.IslandWorld;
import us.tastybento.bskyblock.listeners.JoinLeaveListener;
import us.tastybento.bskyblock.listeners.NetherEvents;
import us.tastybento.bskyblock.listeners.NetherPortals;
import us.tastybento.bskyblock.listeners.protection.IslandGuard;
import us.tastybento.bskyblock.listeners.protection.IslandGuard1_8;
import us.tastybento.bskyblock.listeners.protection.IslandGuard1_9;
import us.tastybento.bskyblock.listeners.protection.NetherEvents;
import us.tastybento.bskyblock.schematics.SchematicsMgr;
import us.tastybento.bskyblock.util.FileLister;
import us.tastybento.bskyblock.util.VaultHelper;
@ -68,7 +72,7 @@ public class BSkyBlock extends JavaPlugin{
Settings.dbName = "ASkyBlock";
Settings.dbUsername = "username";
Settings.dbPassword = "password";
*/
*/
playersManager = new PlayersManager(this);
islandsManager = new IslandsManager(this);
// Only load metrics if set to true in config
@ -97,12 +101,19 @@ public class BSkyBlock extends JavaPlugin{
@Override
public void run() {
// Create the world if it does not exist
// TODO: get world name from config.yml
// TODO: All these settings are placeholders and need to come from config.yml
Settings.worldName = "BSkyBlock_world";
Settings.createNether = true;
Settings.createEnd = true;
Settings.islandNether = true;
Settings.islandEnd = false;
Settings.limitedBlocks = new HashMap<String, Integer>();
Settings.defaultWorldSettings = new HashMap<SettingsFlag, Boolean>();
for (SettingsFlag flag: SettingsFlag.values()) {
Settings.defaultWorldSettings.put(flag, false);
}
Settings.defaultWorldSettings.put(SettingsFlag.ANIMAL_SPAWN, true);
Settings.defaultWorldSettings.put(SettingsFlag.MONSTER_SPAWN, true);
new IslandWorld(plugin);
// Test: Create a random island and save it
@ -155,11 +166,7 @@ public class BSkyBlock extends JavaPlugin{
loadLocales();
// Register Listeners
PluginManager manager = getServer().getPluginManager();
// Player join events
manager.registerEvents(new JoinLeaveListener(plugin), plugin);
manager.registerEvents(new NetherEvents(plugin), plugin);
manager.registerEvents(new NetherPortals(plugin), plugin);
registerListeners();
/*
*DEBUG CODE
Island loadedIsland = islandsManager.getIsland(owner);
@ -189,6 +196,17 @@ public class BSkyBlock extends JavaPlugin{
}
}
protected void registerListeners() {
PluginManager manager = getServer().getPluginManager();
// Player join events
manager.registerEvents(new JoinLeaveListener(this), this);
manager.registerEvents(new NetherEvents(this), this);
manager.registerEvents(new NetherPortals(this), this);
manager.registerEvents(new IslandGuard(this), this);
manager.registerEvents(new IslandGuard1_8(this), this);
manager.registerEvents(new IslandGuard1_9(this), this);
}
@Override
public void onDisable(){
// Save data

View File

@ -11,6 +11,7 @@ import org.bukkit.potion.PotionEffectType;
import us.tastybento.bskyblock.database.BSBDatabase.DatabaseType;
import us.tastybento.bskyblock.database.managers.OfflineHistoryMessages.HistoryMessageType;
import us.tastybento.bskyblock.database.objects.Island.SettingsFlag;
/**
* All the plugin settings are here
@ -215,5 +216,17 @@ public class Settings {
public static int islandStartZ;
public static boolean logInRemoveMobs;
public static HashMap<SettingsFlag, Boolean> defaultWorldSettings;
public static boolean allowEndermanGriefing;
public static boolean endermanDeathDrop;
public static boolean allowTNTDamage;
public static boolean allowChestDamage;
public static boolean allowCreeperDamage;
public static boolean allowCreeperGriefing;
public static boolean allowAutoActivator;
public static boolean allowMobDamageToItemFrames;
public static HashMap<String,Integer> limitedBlocks;
public static boolean allowTNTPushing;
public static boolean showInActionBar;
}

View File

@ -43,6 +43,7 @@ import us.tastybento.bskyblock.util.Util;
*/
public class IslandsManager {
private static final boolean DEBUG = false;
private BSkyBlock plugin;
private BSBDatabase database;
@ -407,17 +408,17 @@ public class IslandsManager {
*/
public Island getIslandAt(Location location) {
if (location == null) {
plugin.getLogger().info("DEBUG: location is null");
//plugin.getLogger().info("DEBUG: location is null");
return null;
}
// World check
if (!inWorld(location)) {
plugin.getLogger().info("DEBUG: not in right world");
//plugin.getLogger().info("DEBUG: not in right world");
return null;
}
// Check if it is spawn
if (spawn != null && spawn.onIsland(location)) {
plugin.getLogger().info("DEBUG: spawn");
//plugin.getLogger().info("DEBUG: spawn");
return spawn;
}
return getIslandAt(location.getBlockX(), location.getBlockZ());
@ -432,8 +433,10 @@ public class IslandsManager {
* @return PlayerIsland or null
*/
public Island getIslandAt(int x, int z) {
plugin.getLogger().info("DEBUG: getting island at " + x + "," + z);
plugin.getLogger().info("DEBUG: island grid is " + islandGrid.size());
if (DEBUG) {
plugin.getLogger().info("DEBUG: getting island at " + x + "," + z);
plugin.getLogger().info("DEBUG: island grid is " + islandGrid.size());
}
Entry<Integer, TreeMap<Integer, Island>> en = islandGrid.floorEntry(x);
if (en != null) {
Entry<Integer, Island> ent = en.getValue().floorEntry(z);
@ -441,10 +444,12 @@ public class IslandsManager {
// Check if in the island range
Island island = ent.getValue();
if (island.inIslandSpace(x, z)) {
plugin.getLogger().info("DEBUG: In island space");
if (DEBUG)
plugin.getLogger().info("DEBUG: In island space");
return island;
}
plugin.getLogger().info("DEBUG: not in island space");
if (DEBUG)
plugin.getLogger().info("DEBUG: not in island space");
}
}
return null;
@ -458,7 +463,17 @@ public class IslandsManager {
* @return true if in the island world
*/
protected boolean inWorld(Location loc) {
// TODO: determine if the world is correct
if (loc != null) {
if (loc.getWorld().equals(IslandWorld.getIslandWorld())) {
return true;
}
if (Settings.islandNether && loc.getWorld().equals(IslandWorld.getNetherWorld())) {
return true;
}
if (Settings.islandEnd && loc.getWorld().equals(IslandWorld.getEndWorld())) {
return true;
}
}
return true;
}
@ -1077,4 +1092,214 @@ public class IslandsManager {
}
/**
* Returns the island being public at the location or null if there is none
*
* @param location
* @return PlayerIsland object
*/
public Island getProtectedIslandAt(Location location) {
//plugin.getLogger().info("DEBUG: getProtectedIslandAt " + location);
// Try spawn
if (spawn != null && spawn.onIsland(location)) {
return spawn;
}
Island island = getIslandAt(location);
if (island == null) {
if (DEBUG)
plugin.getLogger().info("DEBUG: no island at this location");
return null;
}
if (island.onIsland(location)) {
if (DEBUG)
plugin.getLogger().info("DEBUG: on island");
return island;
}
if (DEBUG)
plugin.getLogger().info("DEBUG: not in island protection zone");
return null;
}
/**
* Indicates whether a player is at the island spawn or not
*
* @param playerLoc
* @return true if they are, false if they are not, or spawn does not exist
*/
public boolean isAtSpawn(Location playerLoc) {
if (spawn == null) {
return false;
}
return spawn.onIsland(playerLoc);
}
/**
* Checks if a specific location is within the protected range of an island
* owned by the player
*
* @param player
* @param loc
* @return true if location is on island of player
*/
public boolean locationIsOnIsland(final Player player, final Location loc) {
if (player == null) {
return false;
}
// Get the player's island from the grid if it exists
Island island = getIslandAt(loc);
if (island != null) {
//plugin.getLogger().info("DEBUG: island here is " + island.getCenter());
// On an island in the grid
//plugin.getLogger().info("DEBUG: onIsland = " + island.onIsland(loc));
//plugin.getLogger().info("DEBUG: members = " + island.getMembers());
//plugin.getLogger().info("DEBUG: player UUID = " + player.getUniqueId());
if (island.onIsland(loc) && island.getMembers().contains(player.getUniqueId())) {
//plugin.getLogger().info("DEBUG: allowed");
// In a protected zone but is on the list of acceptable players
return true;
} else {
// Not allowed
//plugin.getLogger().info("DEBUG: not allowed");
return false;
}
} else {
//plugin.getLogger().info("DEBUG: no island at this location");
}
// Not in the grid, so do it the old way
// Make a list of test locations and test them
Set<Location> islandTestLocations = new HashSet<Location>();
if (plugin.getPlayers().hasIsland(player.getUniqueId()) || plugin.getPlayers().inTeam(player.getUniqueId())) {
islandTestLocations.add(getIslandLocation(player.getUniqueId()));
}
// TODO: Check any coop locations
/*
islandTestLocations.addAll(CoopPlay.getInstance().getCoopIslands(player));
if (islandTestLocations.isEmpty()) {
return false;
}*/
// Run through all the locations
for (Location islandTestLocation : islandTestLocations) {
if (loc.getWorld().equals(islandTestLocation.getWorld())) {
if (loc.getX() >= islandTestLocation.getX() - Settings.islandProtectionRange / 2
&& loc.getX() < islandTestLocation.getX() + Settings.islandProtectionRange / 2
&& loc.getZ() >= islandTestLocation.getZ() - Settings.islandProtectionRange / 2
&& loc.getZ() < islandTestLocation.getZ() + Settings.islandProtectionRange / 2) {
return true;
}
}
}
return false;
}
/**
* Checks if an online player is in the protected area of their island, a team island or a
* coop island
*
* @param player
* @return true if on valid island, false if not
*/
public boolean playerIsOnIsland(final Player player) {
return playerIsOnIsland(player, true);
}
/**
* Checks if an online player is in the protected area of their island, a team island or a
* coop island
* @param player
* @param coop - if true, coop islands are included
* @return true if on valid island, false if not
*/
public boolean playerIsOnIsland(final Player player, boolean coop) {
return locationIsAtHome(player, coop, player.getLocation());
}
/**
* Checks if a location is within the home boundaries of a player. If coop is true, this check includes coop players.
* @param player
* @param coop
* @param loc
* @return true if the location is within home boundaries
*/
public boolean locationIsAtHome(final Player player, boolean coop, Location loc) {
// Make a list of test locations and test them
Set<Location> islandTestLocations = new HashSet<Location>();
if (plugin.getPlayers().hasIsland(player.getUniqueId()) || plugin.getPlayers().inTeam(player.getUniqueId())) {
islandTestLocations.add(plugin.getIslands().getIslandLocation(player.getUniqueId()));
// If new Nether
if (Settings.createNether && Settings.islandNether && IslandWorld.getNetherWorld() != null) {
islandTestLocations.add(netherIsland(plugin.getIslands().getIslandLocation(player.getUniqueId())));
}
}
// TODO: Check coop locations
/*
if (coop) {
islandTestLocations.addAll(CoopPlay.getInstance().getCoopIslands(player));
}*/
if (islandTestLocations.isEmpty()) {
return false;
}
// Run through all the locations
for (Location islandTestLocation : islandTestLocations) {
// Must be in the same world as the locations being checked
// Note that getWorld can return null if a world has been deleted on the server
if (islandTestLocation != null && islandTestLocation.getWorld() != null && islandTestLocation.getWorld().equals(loc.getWorld())) {
int protectionRange = Settings.islandProtectionRange;
if (getIslandAt(islandTestLocation) != null) {
// Get the protection range for this location if possible
Island island = getProtectedIslandAt(islandTestLocation);
if (island != null) {
// We are in a protected island area.
protectionRange = island.getProtectionRange();
}
}
if (loc.getX() > islandTestLocation.getX() - protectionRange / 2
&& loc.getX() < islandTestLocation.getX() + protectionRange / 2
&& loc.getZ() > islandTestLocation.getZ() - protectionRange / 2
&& loc.getZ() < islandTestLocation.getZ() + protectionRange / 2) {
return true;
}
}
}
return false;
}
/**
* Generates a Nether version of the locations
* @param islandLocation
* @return
*/
private Location netherIsland(Location islandLocation) {
//plugin.getLogger().info("DEBUG: netherworld = " + ASkyBlock.getNetherWorld());
return islandLocation.toVector().toLocation(IslandWorld.getNetherWorld());
}
/**
* Get name of the island owned by owner
* @param owner
* @return Returns the name of owner's island, or the owner's name if there is none.
*/
public String getIslandName(UUID owner) {
String result = plugin.getPlayers().getName(owner);
if (islandsByUUID.containsKey(owner)) {
Island island = islandsByUUID.get(owner);
if (!island.getName().isEmpty()) {
result = island.getName();
}
}
return ChatColor.translateAlternateColorCodes('&', result) + ChatColor.RESET;
}
/**
* Set the island name
* @param owner
* @param name
*/
public void setIslandName(UUID owner, String name) {
if (islandsByUUID.containsKey(owner)) {
Island island = islandsByUUID.get(owner);
island.setName(name);
}
}
}

View File

@ -7,8 +7,11 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import us.tastybento.bskyblock.api.events.island.IslandLockEvent;
import us.tastybento.bskyblock.api.events.island.IslandUnlockEvent;
@ -425,6 +428,7 @@ public class Island extends DataObject {
public long getCreatedDate(){
return createdDate;
}
/**
* Get the Island Guard flag status
* @param flag
@ -434,6 +438,11 @@ public class Island extends DataObject {
if(flags.containsKey(flag)) {
return flags.get(flag);
} else {
if (flag.equals(SettingsFlag.ANIMAL_SPAWN) || flag.equals(SettingsFlag.MONSTER_SPAWN)) {
flags.put(flag, true);
return true;
}
flags.put(flag, false);
return false;
}
}
@ -612,8 +621,8 @@ public class Island extends DataObject {
*/
public boolean onIsland(Location target) {
if (center.getWorld() != null) {
if (target.getBlockX() >= minProtectedX && target.getBlockX() < (minProtectedX + protectionRange)
&& target.getBlockZ() >= minProtectedZ && target.getBlockZ() < (minProtectedZ + protectionRange)) {
if (target.getBlockX() >= minProtectedX && target.getBlockX() < (minProtectedX + protectionRange*2)
&& target.getBlockZ() >= minProtectedZ && target.getBlockZ() < (minProtectedZ + protectionRange*2)) {
return true;
}
}
@ -852,4 +861,55 @@ public class Island extends DataObject {
return locked;
}
/**
* @return spawn
*/
public boolean isSpawn() {
return spawn;
}
/**
* @param material
* @return count of how many tile entities of type mat are on the island at last count. Counts are done when a player places
* a tile entity.
*/
public int getTileEntityCount(Material material, World world) {
int result = 0;
for (int x = getMinProtectedX() /16; x <= (getMinProtectedX() + getProtectionRange() - 1)/16; x++) {
for (int z = getMinProtectedZ() /16; z <= (getMinProtectedZ() + getProtectionRange() - 1)/16; z++) {
for (BlockState holder : world.getChunkAt(x, z).getTileEntities()) {
//plugin.getLogger().info("DEBUG: tile entity: " + holder.getType());
if (onIsland(holder.getLocation())) {
if (holder.getType() == material) {
result++;
} else if (material.equals(Material.REDSTONE_COMPARATOR_OFF)) {
if (holder.getType().equals(Material.REDSTONE_COMPARATOR_ON)) {
result++;
}
} else if (material.equals(Material.FURNACE)) {
if (holder.getType().equals(Material.BURNING_FURNACE)) {
result++;
}
} else if (material.toString().endsWith("BANNER")) {
if (holder.getType().toString().endsWith("BANNER")) {
result++;
}
} else if (material.equals(Material.WALL_SIGN) || material.equals(Material.SIGN_POST)) {
if (holder.getType().equals(Material.WALL_SIGN) || holder.getType().equals(Material.SIGN_POST)) {
result++;
}
}
}
}
for (Entity holder : world.getChunkAt(x, z).getEntities()) {
//plugin.getLogger().info("DEBUG: entity: " + holder.getType());
if (holder.getType().toString().equals(material.toString()) && onIsland(holder.getLocation())) {
result++;
}
}
}
}
return result;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,229 @@
/*******************************************************************************
* This file is part of BSkyBlock.
*
* BSkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* BSkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with BSkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.listeners.protection;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
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.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
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.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_8 implements Listener {
private final BSkyBlock plugin;
private final static boolean DEBUG = false;
public IslandGuard1_8(final BSkyBlock plugin) {
this.plugin = plugin;
}
/**
* Checks if action is allowed for player in location for flag
* @param player
* @param location
* @param flag
* @return true if allowed
*/
private boolean actionAllowed(Player player, Location location, SettingsFlag 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;
}
/**
* Handle interaction with armor stands V1.8
* Note - some armor stand protection is done in IslandGuard.java, e.g. against projectiles.
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onPlayerInteract(final PlayerInteractAtEntityEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.8 " + e.getEventName());
}
if (!IslandGuard.inWorld(e.getPlayer())) {
return;
}
if (e.getRightClicked() != null && e.getRightClicked().getType().equals(EntityType.ARMOR_STAND)) {
if (actionAllowed(e.getPlayer(), e.getRightClicked().getLocation(), SettingsFlag.ARMOR_STAND)) {
return;
}
e.setCancelled(true);
Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected"));
}
}
/**
* Handle V1.8 blocks that need special treatment
* Tilling of coarse dirt into dirt
* 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.8 " + 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().getItemInHand();
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);
}
}
}
// Armor stand events
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled=true)
void placeArmorStandEvent(PlayerInteractEvent e) {
Player p = e.getPlayer();
if (DEBUG) {
plugin.getLogger().info("1.8 " + "Armor stand 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.ARMOR_STAND)) {
// 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.8 " + "DEBUG: armor stand place check");
if (Settings.limitedBlocks.containsKey("ARMOR_STAND") && Settings.limitedBlocks.get("ARMOR_STAND") > -1) {
//plugin.getLogger().info("1.8 " + "DEBUG: count armor stands");
int count = island.getTileEntityCount(Material.ARMOR_STAND,e.getPlayer().getWorld());
//plugin.getLogger().info("1.8 " + "DEBUG: count is " + count + " limit is " + Settings.limitedBlocks.get("ARMOR_STAND"));
if (Settings.limitedBlocks.get("ARMOR_STAND") <= count) {
Util.sendMessage(e.getPlayer(), ChatColor.RED + (plugin.getLocale(e.getPlayer().getUniqueId()).get("moblimits.entity").replace("[entity]",
Util.prettifyText(Material.ARMOR_STAND.toString()))).replace("[number]", String.valueOf(Settings.limitedBlocks.get("ARMOR_STAND"))));
e.setCancelled(true);
return;
}
}
return;
}
// plugin.getLogger().info("1.8 " + "DEBUG: stand place cancelled");
e.setCancelled(true);
Util.sendMessage(e.getPlayer(), ChatColor.RED + plugin.getLocale(e.getPlayer().getUniqueId()).get("island.protected"));
e.getPlayer().updateInventory();
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void ArmorStandDestroy(EntityDamageByEntityEvent e) {
if (DEBUG) {
plugin.getLogger().info("1.8 " + "IslandGuard New " + e.getEventName());
}
if (!(e.getEntity() instanceof LivingEntity)) {
return;
}
if (!IslandGuard.inWorld(e.getEntity())) {
return;
}
final LivingEntity livingEntity = (LivingEntity) e.getEntity();
if (!livingEntity.getType().equals(EntityType.ARMOR_STAND)) {
return;
}
if (e.getDamager() instanceof Player) {
Player p = (Player) e.getDamager();
if (p.isOp() || VaultHelper.hasPerm(p, Settings.PERMPREFIX + "mod.bypassprotect")) {
return;
}
// Check if on island
if (plugin.getIslands().playerIsOnIsland(p)) {
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)) {
return;
}
Util.sendMessage(p, ChatColor.RED + plugin.getLocale(p.getUniqueId()).get("island.protected"));
e.setCancelled(true);
}
}
}

View File

@ -0,0 +1,514 @@
/*******************************************************************************
* This file is part of BSkyBlock.
*
* BSkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* BSkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with BSkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
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;
}
}

View File

@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with BSkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package us.tastybento.bskyblock.listeners;
package us.tastybento.bskyblock.listeners.protection;
import org.bukkit.Location;
import org.bukkit.Material;

View File

@ -11,10 +11,14 @@ import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.config.Settings;
import us.tastybento.bskyblock.util.nms.NMSAbstraction;
import us.tastybento.bskyblock.util.placeholders.PlaceholderHandler;
@ -147,4 +151,96 @@ public class Util {
// TODO Auto-generated method stub
return false;
}
/**
* Results a list of items in a player's hands. Works for older versions of servers
* @param player
* @return list of itemstacks
*/
@SuppressWarnings("deprecation")
public static List<ItemStack> getPlayerInHandItems(Player player) {
List<ItemStack> result = new ArrayList<ItemStack>(2);
if (plugin.getServer().getVersion().contains("(MC: 1.7")
|| plugin.getServer().getVersion().contains("(MC: 1.8")) {
if (player.getItemInHand() != null)
result.add(player.getItemInHand());
return result;
}
if (player.getInventory().getItemInMainHand() != null)
result.add(player.getInventory().getItemInMainHand());
if (player.getInventory().getItemInOffHand() != null)
result.add(player.getInventory().getItemInOffHand());
return result;
}
/**
* Converts a name like IRON_INGOT into Iron Ingot to improve readability
*
* @param ugly
* The string such as IRON_INGOT
* @return A nicer version, such as Iron Ingot
*
* Credits to mikenon on GitHub!
*/
public static String prettifyText(String ugly) {
if (!ugly.contains("_") && (!ugly.equals(ugly.toUpperCase())))
return ugly;
String fin = "";
ugly = ugly.toLowerCase();
if (ugly.contains("_")) {
String[] splt = ugly.split("_");
int i = 0;
for (String s : splt) {
i += 1;
fin += Character.toUpperCase(s.charAt(0)) + s.substring(1);
if (i < splt.length)
fin += " ";
}
} else {
fin += Character.toUpperCase(ugly.charAt(0)) + ugly.substring(1);
}
return fin;
}
/**
* Checks if player has this type of item in either hand
* @param player
* @param type
* @return true if they are holding an item of type type
*/
@SuppressWarnings("deprecation")
public static boolean playerIsHolding(Player player, Material type) {
if (plugin.getServer().getVersion().contains("(MC: 1.7")
|| plugin.getServer().getVersion().contains("(MC: 1.8")) {
if (player.getItemInHand() != null && player.getItemInHand().getType().equals(type)) {
return true;
}
return false;
}
if (player.getInventory().getItemInMainHand() != null && player.getInventory().getItemInMainHand().getType().equals(type)) {
return true;
}
if (player.getInventory().getItemInMainHand() != null && player.getInventory().getItemInOffHand().getType().equals(type)) {
return true;
}
return false;
}
/**
* Display message to player in action bar (1.11+ or chat)
* @param player
* @param message
*/
public static void sendEnterExit(Player player, String message) {
if (!Settings.showInActionBar
|| plugin.getServer().getVersion().contains("(MC: 1.7")
|| plugin.getServer().getVersion().contains("(MC: 1.8")
|| plugin.getServer().getVersion().contains("(MC: 1.9")
|| plugin.getServer().getVersion().contains("(MC: 1.10")) {
sendMessage(player, message);
return;
}
plugin.getServer().dispatchCommand(plugin.getServer().getConsoleSender(),
"minecraft:title " + player.getName() + " actionbar {\"text\":\"" + ChatColor.stripColor(message) + "\"}");
}
}