Added the protection listeners. Took all day!

Generally these are very easy to understand. They use an abstract class
for common code.

I have not tested these in-game. I would like to see if I can create
some test classes but it may not be possible because of the static
BSkyBlock calls.
This commit is contained in:
Tastybento 2018-02-01 20:30:57 -08:00
parent 4fe94bee3b
commit 72c99656cc
29 changed files with 1541 additions and 376 deletions

View File

@ -19,7 +19,7 @@ import us.tastybento.bskyblock.managers.RanksManager;
/**
* Main BSkyBlock class - provides an island minigame in the sky
* @author Tastybento
* @author tastybento
* @author Poslovitch
*/
public class BSkyBlock extends JavaPlugin {
@ -83,57 +83,34 @@ public class BSkyBlock extends JavaPlugin {
// These items have to be loaded when the server has done 1 tick.
// Note Worlds are not loaded this early, so any Locations or World reference will be null
// at this point. Therefore, the 1 tick scheduler is required.
getServer().getScheduler().runTask(this, new Runnable() {
getServer().getScheduler().runTask(this, () -> {
// Create the world if it does not exist
islandWorldManager = new IslandWorld(plugin);
@Override
public void run() {
// Create the world if it does not exist
islandWorldManager = new IslandWorld(plugin);
getServer().getScheduler().runTask(plugin, () -> {
// Load islands from database
islandsManager.load();
getServer().getScheduler().runTask(plugin, new Runnable() {
localesManager = new LocalesManager(plugin);
//TODO localesManager.registerLocales(plugin);
@Override
public void run() {
// Load islands from database
islandsManager.load();
// Register Listeners
registerListeners();
localesManager = new LocalesManager(plugin);
//TODO localesManager.registerLocales(plugin);
// Load Flags
flagsManager = new FlagsManager(plugin);
// Register Listeners
registerListeners();
// Load addons
addonsManager = new AddonsManager(plugin);
addonsManager.enableAddons();
// Load Flags
flagsManager = new FlagsManager(plugin);
// Load addons
addonsManager = new AddonsManager(plugin);
addonsManager.enableAddons();
/*
*DEBUG CODE
Island loadedIsland = islandsManager.getIsland(owner);
getLogger().info("Island name = " + loadedIsland.getName());
getLogger().info("Island locked = " + loadedIsland.getLocked());
//getLogger().info("Random set = " + randomSet);
getLogger().info("Island coops = " + loadedIsland.getCoops());
for (Entry<SettingsFlag, Boolean> flag: loadedIsland.getFlags().entrySet()) {
getLogger().info("Flag " + flag.getKey().name() + " = " + flag.getValue());
}
*/
// Save islands & players data asynchronously every X minutes
getSettings().setDatabaseBackupPeriod(10 * 60 * 20);
plugin.getServer().getScheduler().runTaskTimer(plugin, new Runnable() {
@Override
public void run() {
playersManager.save(true);
islandsManager.save(true);
}
}, getSettings().getDatabaseBackupPeriod(), getSettings().getDatabaseBackupPeriod());
}
});
}
// Save islands & players data asynchronously every X minutes
getSettings().setDatabaseBackupPeriod(10 * 60 * 20);
plugin.getServer().getScheduler().runTaskTimer(plugin, () -> {
playersManager.save(true);
islandsManager.save(true);
}, getSettings().getDatabaseBackupPeriod(), getSettings().getDatabaseBackupPeriod());
});
});
}

View File

@ -2,7 +2,6 @@ package us.tastybento.bskyblock.api.events.island;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import us.tastybento.bskyblock.BSkyBlock;

View File

@ -3,7 +3,6 @@ package us.tastybento.bskyblock.api.panels;
import java.util.List;
import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;

View File

@ -3,7 +3,6 @@ package us.tastybento.bskyblock.api.panels.builders;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.bukkit.Bukkit;
import org.bukkit.Material;

View File

@ -377,7 +377,7 @@ public class Island implements DataObject {
/**
* Set the Island Guard flag rank
* @param flag
* @param value
* @param value - rank value. If the flag applies to the island, a positive number = true, negative = false
*/
public void setFlag(Flag flag, int value){
flags.put(flag, value);
@ -655,4 +655,14 @@ public class Island implements DataObject {
public boolean isAllowed(User user, Flag flag) {
return (this.getRank(user) >= this.getFlag(flag)) ? true : false;
}
/**
* Check if the flag is allowed or not
* For flags that are for the island in general and not related to rank
* @param flag
* @return true if allowed, false if not
*/
public boolean isAllowed(Flag flag) {
return this.getFlag(flag) >= 0 ? true : false;
}
}

View File

@ -1,6 +1,5 @@
package us.tastybento.bskyblock.listeners;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.event.EventHandler;

View File

@ -1,7 +1,7 @@
/**
*
*/
package us.tastybento.bskyblock.listeners;
package us.tastybento.bskyblock.listeners.flags;
import java.util.Optional;
@ -18,18 +18,18 @@ import us.tastybento.bskyblock.api.flags.Flag;
import us.tastybento.bskyblock.database.objects.Island;
/**
* Abstract class for flag listeners to inherit. Provides some common code.
* @author ben
* Abstract class for flag listeners. Provides common code.
* @author tastybento
*
*/
public abstract class FlagListener implements Listener {
public abstract class AbstractFlagListener implements Listener {
protected BSkyBlock plugin;
public BSkyBlock plugin;
private User user = null;
public FlagListener(BSkyBlock plugin) {
public AbstractFlagListener() {
super();
this.plugin = plugin;
this.plugin = BSkyBlock.getInstance();
}
/**
@ -38,7 +38,7 @@ public abstract class FlagListener implements Listener {
* @param e - the event
* @return user or empty
*/
protected Optional<User> getEventUser(Event e) {
private Optional<User> createEventUser(Event e) {
// Set the user
if (e instanceof PlayerEvent) {
user = User.getInstance(((PlayerEvent)e).getPlayer());
@ -52,41 +52,33 @@ public abstract class FlagListener implements Listener {
* Explicitly set the user
* @param user
*/
protected void setUser(User user) {
public void setUser(User user) {
this.user = user;
}
/**
* Get the user associated with this event
* @return User or null
*/
protected User getUser() {
return user;
}
/*
* The following methods cover the cancellable events and enable a simple noGo(e) to be used to cancel and send the error message
*/
/**
* Cancels the event and sends the island protected message to user
* Cancels the event and sends the island public message to user
* @param e Event
*/
protected void noGo(Event e) {
public void noGo(Event e) {
noGo(e, false);
}
/**
* Cancels the event and sends the island protected message to user unless silent is true
* Cancels the event and sends the island public message to user unless silent is true
* @param e Event
* @param silent - if true, message is not sent
*/
protected void noGo(Event e, boolean silent) {
public void noGo(Event e, boolean silent) {
if (e instanceof Cancellable)
((Cancellable)e).setCancelled(true);
if (user != null) {
if (!silent)
user.sendMessage("protection.protected");
user.sendMessage("protection.public");
user.updateInventory();
}
}
@ -96,7 +88,7 @@ public abstract class FlagListener implements Listener {
* @param loc
* @return true if the location is in the island worlds
*/
protected boolean inWorld(Location loc) {
public boolean inWorld(Location loc) {
return (loc.getWorld().equals(plugin.getIslandWorldManager().getIslandWorld())
|| loc.getWorld().equals(plugin.getIslandWorldManager().getNetherWorld())
|| loc.getWorld().equals(plugin.getIslandWorldManager().getEndWorld())) ? true : false;
@ -107,7 +99,7 @@ public abstract class FlagListener implements Listener {
* @param entity - the entity
* @return true if in world
*/
protected boolean inWorld(Entity entity) {
public boolean inWorld(Entity entity) {
return inWorld(entity.getLocation());
}
@ -116,7 +108,7 @@ public abstract class FlagListener implements Listener {
* @param user - a user
* @return true if in world
*/
protected boolean inWorld(User user) {
public boolean inWorld(User user) {
return inWorld(user.getLocation());
}
@ -126,7 +118,7 @@ public abstract class FlagListener implements Listener {
* @param loc
* @return true if the check is okay, false if it was disallowed
*/
protected boolean checkIsland(Event e, Location loc, Flag flag) {
public boolean checkIsland(Event e, Location loc, Flag flag) {
return checkIsland(e, loc, flag, false);
}
@ -139,20 +131,20 @@ public abstract class FlagListener implements Listener {
* @param silent - if true, no attempt is made to tell the user
* @return true if the check is okay, false if it was disallowed
*/
protected boolean checkIsland(Event e, Location loc, Flag flag, boolean silent) {
public boolean checkIsland(Event e, Location loc, Flag flag, boolean silent) {
// If the user is not set, try to get it from the event
if (getUser() == null) {
if (user == null) {
// Set the user associated with this event
if (!getEventUser(e).isPresent()) return true;
if (!createEventUser(e).isPresent()) return true;
}
// If this is not an Island World, skip
if (!inWorld(getUser())) return true;
if (!inWorld(user)) return true;
// Get the island and if present, check the flag, react if required and return
Optional<Island> island = plugin.getIslands().getIslandAt(loc);
if (island.isPresent()) {
if (!island.get().isAllowed(getUser(), flag)) {
if (!island.get().isAllowed(user, flag)) {
noGo(e, silent);
return false;
} else {

View File

@ -1,39 +0,0 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.listeners.FlagListener;
import us.tastybento.bskyblock.lists.Flags;
/**
* @author ben
*
*/
public class AnvilListener extends FlagListener {
public AnvilListener() {
super(BSkyBlock.getInstance());
}
/**
* Handle placing of Anvils
* @param e
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerInteract(final PlayerInteractEvent e) {
if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
return;
}
if (e.getClickedBlock().getType().equals(Material.ANVIL)) {
checkIsland(e, getUser().getLocation(), Flags.ANVIL);
}
}
}

View File

@ -0,0 +1,138 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* @author ben
*
*/
public class BlockInteractionListener extends AbstractFlagListener {
/**
* Handle interaction with blocks
* @param e
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerInteract(final PlayerInteractEvent e) {
if (!e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
return;
}
switch (e.getClickedBlock().getType()) {
case ANVIL:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.ANVIL);
break;
case BEACON:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.BEACON);
break;
case BED_BLOCK:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.BED);
break;
case BREWING_STAND:
case CAULDRON:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.BREWING);
break;
case CHEST:
case STORAGE_MINECART:
case TRAPPED_CHEST:
case BLACK_SHULKER_BOX:
case BLUE_SHULKER_BOX:
case BROWN_SHULKER_BOX:
case CYAN_SHULKER_BOX:
case GRAY_SHULKER_BOX:
case GREEN_SHULKER_BOX:
case LIGHT_BLUE_SHULKER_BOX:
case LIME_SHULKER_BOX:
case PINK_SHULKER_BOX:
case MAGENTA_SHULKER_BOX:
case ORANGE_SHULKER_BOX:
case PURPLE_SHULKER_BOX:
case RED_SHULKER_BOX:
case SILVER_SHULKER_BOX:
case WHITE_SHULKER_BOX:
case YELLOW_SHULKER_BOX:
case DISPENSER:
case DROPPER:
case HOPPER:
case HOPPER_MINECART:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.CHEST);
break;
case ACACIA_DOOR:
case BIRCH_DOOR:
case DARK_OAK_DOOR:
case IRON_DOOR:
case IRON_DOOR_BLOCK:
case IRON_TRAPDOOR:
case JUNGLE_DOOR:
case SPRUCE_DOOR:
case TRAP_DOOR:
case WOODEN_DOOR:
case WOOD_DOOR:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.DOOR);
break;
case ACACIA_FENCE_GATE:
case BIRCH_FENCE_GATE:
case DARK_OAK_FENCE_GATE:
case FENCE_GATE:
case JUNGLE_FENCE_GATE:
case SPRUCE_FENCE_GATE:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.GATE);
break;
case BURNING_FURNACE:
case FURNACE:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.FURNACE);
break;
case ENCHANTMENT_TABLE:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.ENCHANTING);
break;
case ENDER_CHEST:
break;
case JUKEBOX:
case NOTE_BLOCK:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.MUSIC);
break;
case WORKBENCH:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.CRAFTING);
break;
case STONE_BUTTON:
case WOOD_BUTTON:
case LEVER:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.LEVER_BUTTON);
break;
case DIODE:
case DIODE_BLOCK_OFF:
case DIODE_BLOCK_ON:
case REDSTONE_COMPARATOR_ON:
case REDSTONE_COMPARATOR_OFF:
case DAYLIGHT_DETECTOR:
case DAYLIGHT_DETECTOR_INVERTED:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.REDSTONE);
break;
default:
break;
}
// Now check for in-hand items
if (e.getItem() != null) {
switch (e.getItem().getType()) {
case ENDER_PEARL:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.ENDER_PEARL);
break;
case MONSTER_EGG:
checkIsland(e, e.getClickedBlock().getLocation(), Flags.SPAWN_EGGS);
default:
break;
}
}
}
}

View File

@ -3,6 +3,7 @@ package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.Material;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
@ -16,16 +17,10 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.util.BlockIterator;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.listeners.FlagListener;
import us.tastybento.bskyblock.lists.Flags;
public class BreakBlocksListener extends FlagListener {
public BreakBlocksListener() {
super(BSkyBlock.getInstance());
}
public class BreakBlocksListener extends AbstractFlagListener {
/**
* Prevents blocks from being broken
@ -36,7 +31,7 @@ public class BreakBlocksListener extends FlagListener {
public void onBlockBreak(final BlockBreakEvent e) {
checkIsland(e, e.getBlock().getLocation(), Flags.BREAK_BLOCKS);
}
/**
* Prevents the breakage of hanging items
*
@ -59,7 +54,7 @@ public class BreakBlocksListener extends FlagListener {
public void onPlayerInteract(final PlayerInteractEvent e) {
// Only handle hitting things
if (!e.getAction().equals(Action.LEFT_CLICK_BLOCK)) return;
// Look along player's sight line to see if any blocks are skulls
try {
BlockIterator iter = new BlockIterator(e.getPlayer(), 10);
@ -72,7 +67,7 @@ public class BreakBlocksListener extends FlagListener {
}
}
} catch (Exception ex) {}
switch (e.getClickedBlock().getType()) {
case CAKE_BLOCK:
case DRAGON_EGG:
@ -100,7 +95,7 @@ public class BreakBlocksListener extends FlagListener {
User user = User.getInstance((Player) e.getAttacker());
// Get the island and if present, check the flag, react if required and return
plugin.getIslands().getIslandAt(e.getVehicle().getLocation()).ifPresent(x -> {
if (!x.isAllowed(getUser(), Flags.BREAK_BLOCKS)) {
if (!x.isAllowed(user, Flags.BREAK_BLOCKS)) {
e.setCancelled(true);
user.sendMessage("protection.protected");
}
@ -121,8 +116,8 @@ public class BreakBlocksListener extends FlagListener {
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onEntityDamage(EntityDamageByEntityEvent e) {
// Only handle item frames
if (!(e.getEntity() instanceof ItemFrame) && !e.getEntityType().toString().endsWith("STAND")) return;
// Only handle item frames and armor stands
if (!(e.getEntity() instanceof ItemFrame) && !(e.getEntity() instanceof ArmorStand)) return;
// Get the attacker
if (e.getDamager() instanceof Player) {
@ -141,5 +136,4 @@ public class BreakBlocksListener extends FlagListener {
}
}
}

View File

@ -0,0 +1,51 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import java.util.Arrays;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Animals;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles breeding protection
* Note - animal protection is done elsewhere.
* @author tastybento
*
*/
public class BreedingListener extends AbstractFlagListener {
/**
* A list of items that cause breeding if a player has them in their hand and they click an animal
* This list may need to be extended with future versions of Minecraft.
*/
private final static List<Material> BREEDING_ITEMS = Arrays.asList(
Material.EGG,
Material.WHEAT,
Material.CARROT_ITEM,
Material.SEEDS);
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onPlayerInteract(final PlayerInteractAtEntityEvent e) {
if (e.getRightClicked() != null && e.getRightClicked() instanceof Animals) {
ItemStack inHand = e.getPlayer().getInventory().getItemInMainHand();
if (e.getHand().equals(EquipmentSlot.OFF_HAND)) {
inHand = e.getPlayer().getInventory().getItemInOffHand();
}
if (inHand != null && BREEDING_ITEMS.contains(inHand.getType())) {
checkIsland(e, e.getRightClicked().getLocation(), Flags.BREEDING);
}
}
}
}

View File

@ -0,0 +1,56 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles interaction with beds
* Note - bed protection from breaking or placing is done elsewhere.
* @author tastybento
*
*/
public class BucketListener extends AbstractFlagListener {
/**
* Prevents emptying of buckets
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBucketEmpty(final PlayerBucketEmptyEvent e) {
if (e.getBlockClicked() != null) {
// This is where the water or lava actually will be dumped
Block dumpBlock = e.getBlockClicked().getRelative(e.getBlockFace());
checkIsland(e, dumpBlock.getLocation(), Flags.BUCKET);
}
}
/**
* Prevents collecting of lava, water, milk. If bucket use is denied in general, it is blocked.
* @param e
*/
@EventHandler(priority = EventPriority.LOW)
public void onBucketFill(final PlayerBucketFillEvent e) {
// Check filling of various liquids
if (e.getItemStack().getType().equals(Material.LAVA_BUCKET)) {
if (!checkIsland(e, e.getBlockClicked().getLocation(), Flags.COLLECT_LAVA)) return;
}
if (e.getItemStack().getType().equals(Material.WATER_BUCKET)) {
if (!checkIsland(e, e.getBlockClicked().getLocation(), Flags.COLLECT_WATER)) return;
}
if (e.getItemStack().getType().equals(Material.MILK_BUCKET)) {
if (!checkIsland(e, e.getBlockClicked().getLocation(), Flags.MILKING)) return;
}
// Check general bucket use
checkIsland(e, e.getBlockClicked().getLocation(), Flags.BUCKET);
}
}

View File

@ -0,0 +1,30 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerEggThrowEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles throwing regular eggs (not spawn eggs)
* @author tastybento
*
*/
public class EggListener extends AbstractFlagListener {
/**
* Handle visitor chicken egg throwing
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onEggThrow(PlayerEggThrowEvent e) {
if (!checkIsland(e, e.getEgg().getLocation(), Flags.EGGS)) {
e.setHatching(false);
}
}
}

View File

@ -0,0 +1,43 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.entity.Animals;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles interaction with entities like armor stands
* Note - armor stand protection from breaking or placing is done elsewhere.
* @author tastybento
*
*/
public class EntityInteractListener extends AbstractFlagListener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onPlayerInteract(final PlayerInteractAtEntityEvent e) {
if (e.getRightClicked() instanceof ArmorStand) {
checkIsland(e, e.getRightClicked().getLocation(), Flags.ARMOR_STAND);
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerHitEntity(PlayerInteractEntityEvent e) {
// Animal riding
if (e.getRightClicked() instanceof Vehicle && e.getRightClicked() instanceof Animals) {
checkIsland(e, e.getRightClicked().getLocation(), Flags.RIDING);
}
// Villager trading
if (e.getRightClicked().getType().equals(EntityType.VILLAGER)) {
checkIsland(e, e.getRightClicked().getLocation(), Flags.TRADING);
}
}
}

View File

@ -0,0 +1,165 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.util.BlockIterator;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles fire
* @author tastybento
*
*/
public class FireListener extends AbstractFlagListener {
/**
* Prevents fire spread
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockBurn(BlockBurnEvent e) {
if (!inWorld(e.getBlock().getLocation())) {
return;
}
// Check if the island exists and if fire is allowed
Optional<Island> island = plugin.getIslands().getIslandAt(e.getBlock().getLocation());
island.ifPresent(x -> {
if (!x.isAllowed(Flags.FIRE_SPREAD)) e.setCancelled(true);
});
// If not on an island, check the default setting
if (!island.isPresent() && !Flags.FIRE_SPREAD.isAllowed()) e.setCancelled(true);
}
/**
* Prevent fire spread
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockSpread(BlockSpreadEvent e) {
if (e.getSource().getType().equals(Material.FIRE)) {
if (!inWorld(e.getBlock().getLocation())) {
return;
}
// Check if the island exists and if fire is allowed
Optional<Island> island = plugin.getIslands().getIslandAt(e.getBlock().getLocation());
island.ifPresent(x -> {
if (!x.isAllowed(Flags.FIRE_SPREAD)) e.setCancelled(true);
});
// If not on an island, check the default setting
if (!island.isPresent() && !Flags.FIRE_SPREAD.isAllowed()) e.setCancelled(true);
}
}
/**
* Igniting fires
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockIgnite(BlockIgniteEvent e) {
if (!inWorld(e.getBlock().getLocation())) {
return;
}
// Check if this is a portal lighting - that is allowed any time
if (e.getBlock().getType().equals(Material.OBSIDIAN)) {
return;
}
// Check if the island exists and if fire is allowed
Optional<Island> island = plugin.getIslands().getIslandAt(e.getBlock().getLocation());
island.ifPresent(x -> {
if (!x.isAllowed(Flags.FIRE)) e.setCancelled(true);
});
// If not on an island, check the default setting
if (!island.isPresent() && !Flags.FIRE.isAllowed()) e.setCancelled(true);
}
/**
* Flint & Steel and Extinguishing fire
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent e) {
if (e.getAction().equals(Action.RIGHT_CLICK_BLOCK) && e.getMaterial() != null && e.getMaterial().equals(Material.FLINT_AND_STEEL)) {
checkIsland(e, e.getClickedBlock().getLocation(), Flags.FIRE);
}
// Look along player's sight line to see if any blocks are fire. Players can hit fire out quite a long way away.
try {
BlockIterator iter = new BlockIterator(e.getPlayer(), 10);
Block lastBlock = iter.next();
while (iter.hasNext()) {
lastBlock = iter.next();
if (lastBlock.equals(e.getClickedBlock())) {
break;
}
if (lastBlock.getType().equals(Material.FIRE)) {
checkIsland(e, lastBlock.getLocation(), Flags.FIRE_EXTINGUISH);
}
}
} catch (Exception ex) {
// To catch at block iterator exceptions that can happen in the void or at the very top of blocks
}
}
/**
* Protect TNT.
* Note that allowing TNT to explode is governed by the Break Blocks flag.
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onTNTPrimed(EntityChangeBlockEvent e) {
// Check world
if (!inWorld(e.getBlock().getLocation())) {
return;
}
// Check for TNT
if (!e.getBlock().getType().equals(Material.TNT)) {
//plugin.getLogger().info("DEBUG: not tnt");
return;
}
// Check if the island exists and if fire is allowed
Optional<Island> island = plugin.getIslands().getIslandAt(e.getBlock().getLocation());
island.ifPresent(x -> {
if (!x.isAllowed(Flags.FIRE)) e.setCancelled(true);
});
// If not on an island, check the default setting
if (!island.isPresent() && !Flags.FIRE.isAllowed()) e.setCancelled(true);
// If either of these canceled the event, return
if (e.isCancelled()) return;
// Stop TNT from being damaged if it is being caused by a visitor with a flaming arrow
if (e.getEntity() instanceof Projectile) {
Projectile projectile = (Projectile) e.getEntity();
// Find out who fired it
if (projectile.getShooter() instanceof Player) {
if (projectile.getFireTicks() > 0) {
Player shooter = (Player)projectile.getShooter();
setUser(User.getInstance(shooter));
if (checkIsland(e, e.getBlock().getLocation(), Flags.BREAK_BLOCKS)) {
// Remove the arrow
projectile.remove();
}
}
}
}
}
}

View File

@ -0,0 +1,207 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Entity;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.LivingEntity;
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.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.LingeringPotionSplashEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.potion.PotionEffect;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.api.flags.Flag;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles hurting of monsters and animals directly and indirectly
* @author tastybento
*
*/
public class HurtingListener extends AbstractFlagListener {
private HashMap<Integer, UUID> thrownPotions = new HashMap<>();
/**
* Handles mob and monster protection
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onEntityDamage(final EntityDamageByEntityEvent e) {
// Mobs being hurt
if (e.getEntity() instanceof Animals || e.getEntity() instanceof IronGolem || e.getEntity() instanceof Snowman
|| e.getEntity() instanceof Villager) {
respond(e, e.getDamager(), Flags.HURT_MOBS);
} else if (e.getEntity() instanceof Monster || e.getEntity() instanceof Squid || e.getEntity() instanceof Slime) {
respond(e, e.getDamager(), Flags.HURT_MONSTERS);
}
}
/**
* Finds the true attacker, even if the attack was via a projectile
* @param event
* @param damager
* @param flag
*/
private void respond(Event event, Entity damager, Flag flag) {
// Get the attacker
if (damager instanceof Player) {
setUser(User.getInstance(damager));
checkIsland(event, damager.getLocation(), flag);
} else if (damager instanceof Projectile) {
// Find out who fired the projectile
Projectile p = (Projectile) damager;
if (p.getShooter() instanceof Player) {
setUser(User.getInstance((Player)p.getShooter()));
if (!checkIsland(event, damager.getLocation(), flag)) {
damager.setFireTicks(0);
damager.remove();
}
}
}
}
/**
* Handle attacks with a fishing rod
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onFishing(PlayerFishEvent e) {
if (e.getCaught() == null)
return;
if (e.getCaught() instanceof Animals || e.getCaught() instanceof IronGolem || e.getCaught() instanceof Snowman
|| e.getCaught() instanceof Villager) {
if (checkIsland(e, e.getCaught().getLocation(), Flags.HURT_MONSTERS)) {
e.getHook().remove();
return;
}
} else if (e.getCaught() instanceof Monster || e.getCaught() instanceof Squid || e.getCaught() instanceof Slime) {
if (checkIsland(e, e.getCaught().getLocation(), Flags.HURT_MONSTERS)) {
e.getHook().remove();
return;
}
}
}
/**
* Handles feeding cookies to animals, which may hurt them
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerHitEntity(PlayerInteractEntityEvent e) {
if (e.getRightClicked() instanceof Animals) {
if ((e.getHand().equals(EquipmentSlot.HAND) && e.getPlayer().getInventory().getItemInMainHand().getType().equals(Material.COOKIE))
|| (e.getHand().equals(EquipmentSlot.OFF_HAND) && e.getPlayer().getInventory().getItemInOffHand().getType().equals(Material.COOKIE))) {
checkIsland(e, e.getRightClicked().getLocation(), Flags.HURT_MOBS);
}
}
}
/**
* Checks for splash damage. Remove damage if it should not affect.
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onSplashPotionSplash(final PotionSplashEvent e) {
// Try to get the shooter
Projectile projectile = (Projectile) e.getEntity();
if (projectile.getShooter() != null && projectile.getShooter() instanceof Player) {
Player attacker = (Player)projectile.getShooter();
setUser(User.getInstance(attacker));
// Run through all the affected entities
for (LivingEntity entity: e.getAffectedEntities()) {
// Self damage
if (attacker.equals(entity)) {
continue;
}
// Monsters being hurt
if (entity instanceof Monster || entity instanceof Slime || entity instanceof Squid) {
if (!checkIsland(e, entity.getLocation(), Flags.HURT_MONSTERS)) {
for (PotionEffect effect : e.getPotion().getEffects()) {
entity.removePotionEffect(effect.getType());
}
}
}
// Mobs being hurt
if (entity instanceof Animals || entity instanceof IronGolem || entity instanceof Snowman
|| entity instanceof Villager) {
if (!checkIsland(e, entity.getLocation(), Flags.HURT_MONSTERS)) {
for (PotionEffect effect : e.getPotion().getEffects()) {
entity.removePotionEffect(effect.getType());
}
}
}
}
}
}
/**
* Handle lingering potions. This tracks when a potion has been initially splashed.
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onLingeringPotionSplash(final LingeringPotionSplashEvent e) {
// Try to get the shooter
Projectile projectile = (Projectile) e.getEntity();
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, () -> {
thrownPotions.remove(e.getAreaEffectCloud().getEntityId());
}, e.getAreaEffectCloud().getDuration());
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onLingeringPotionDamage(final EntityDamageByEntityEvent e) {
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())) {
return;
}
Entity entity = e.getEntity();
// Monsters being hurt
if (entity instanceof Monster || entity instanceof Slime || entity instanceof Squid) {
checkIsland(e, entity.getLocation(), Flags.HURT_MONSTERS);
}
// Mobs being hurt
else if (entity instanceof Animals || entity instanceof IronGolem || entity instanceof Snowman
|| entity instanceof Villager) {
checkIsland(e, entity.getLocation(), Flags.HURT_MONSTERS);
}
}
}
}

View File

@ -0,0 +1,59 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.block.Beacon;
import org.bukkit.block.BrewingStand;
import org.bukkit.block.Chest;
import org.bukkit.block.Dispenser;
import org.bukkit.block.Dropper;
import org.bukkit.block.Furnace;
import org.bukkit.block.Hopper;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Animals;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.InventoryClickEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles inventory protection
* @author tastybento
*
*/
public class InventoryListener extends AbstractFlagListener {
/**
* Prevents visitors picking items from inventories
* @param event
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onMountInventoryClick(InventoryClickEvent event) {
if (event.getInventory().getHolder() == null) {
return;
}
if (event.getInventory().getHolder() instanceof Animals) {
checkIsland(event, event.getInventory().getLocation(), Flags.MOUNT_INVENTORY);
}
else if (event.getInventory().getHolder() instanceof Chest
|| event.getInventory().getHolder() instanceof Dispenser
|| event.getInventory().getHolder() instanceof Hopper
|| event.getInventory().getHolder() instanceof Dropper
|| event.getInventory().getHolder() instanceof ShulkerBox) {
checkIsland(event, event.getInventory().getLocation(), Flags.CHEST);
}
else if (event.getInventory().getHolder() instanceof Furnace) {
checkIsland(event, event.getInventory().getLocation(), Flags.FURNACE);
}
else if (event.getInventory().getHolder() instanceof BrewingStand) {
checkIsland(event, event.getInventory().getLocation(), Flags.BREWING);
}
else if (event.getInventory().getHolder() instanceof Beacon) {
checkIsland(event, event.getInventory().getLocation(), Flags.BEACON);
}
}
}

View File

@ -0,0 +1,39 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.lists.Flags;
/**
* @author tastybento
*
*/
public class ItemDropPickUpListener extends AbstractFlagListener {
/*
* Handle item drop by visitors
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onVisitorDrop(PlayerDropItemEvent e) {
checkIsland(e, e.getItemDrop().getLocation(), Flags.VISITOR_ITEM_DROP);
}
/*
* Handle item pickup by visitors
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onVisitorDrop(EntityPickupItemEvent e) {
if (e.getEntity() instanceof Player) {
setUser(User.getInstance(e.getEntity()));
checkIsland(e, e.getItem().getLocation(), Flags.VISITOR_ITEM_PICKUP);
}
}
}

View File

@ -0,0 +1,53 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.PlayerLeashEntityEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerUnleashEntityEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* @author tastybento
*
*/
public class LeashListener extends AbstractFlagListener {
/**
* Prevents leashing
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onLeashUse(PlayerLeashEntityEvent e) {
checkIsland(e, e.getEntity().getLocation(),Flags.LEASH);
}
/**
* Prevents unleashing
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onLeashUse(PlayerUnleashEntityEvent e) {
checkIsland(e, e.getEntity().getLocation(),Flags.LEASH);
}
/**
* Prevents hitching
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerLeashHitch(final HangingPlaceEvent e) {
if (e.getEntity() != null && e.getEntity().getType().equals(EntityType.LEASH_HITCH)) {
checkIsland(e, e.getEntity().getLocation(),Flags.LEASH);
}
}
}

View File

@ -0,0 +1,79 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import java.util.Optional;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Slime;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles natural mob spawning.
* @author tastybento
*
*/
public class MobSpawnListener extends AbstractFlagListener {
/**
* Prevents mobs spawning naturally
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onNaturalMobSpawn(final CreatureSpawnEvent e) {
// If not in the right world, return
if (!inWorld(e.getEntity())) {
return;
}
// Deal with natural spawning
if (e.getSpawnReason().equals(SpawnReason.NATURAL)
|| e.getSpawnReason().equals(SpawnReason.JOCKEY)
|| e.getSpawnReason().equals(SpawnReason.CHUNK_GEN)
|| e.getSpawnReason().equals(SpawnReason.DEFAULT)
|| e.getSpawnReason().equals(SpawnReason.MOUNT)
|| e.getSpawnReason().equals(SpawnReason.JOCKEY)
|| e.getSpawnReason().equals(SpawnReason.NETHER_PORTAL)) {
Optional<Island> island = plugin.getIslands().getIslandAt(e.getLocation());
if (island.isPresent()) {
if (e.getEntity() instanceof Monster || e.getEntity() instanceof Slime) {
if (!island.get().isAllowed(Flags.MOB_SPAWN)) {
// Mobs not allowed to spawn
e.setCancelled(true);
return;
}
} else if (e.getEntity() instanceof Animals) {
if (!island.get().isAllowed(Flags.MONSTER_SPAWN)) {
// Mobs not allowed to spawn
e.setCancelled(true);
return;
}
}
} else {
// Outside of the island
if (e.getEntity() instanceof Monster || e.getEntity() instanceof Slime) {
if (!Flags.MOB_SPAWN.isAllowed()) {
// Mobs not allowed to spawn
e.setCancelled(true);
return;
}
} else if (e.getEntity() instanceof Animals) {
if (!Flags.MONSTER_SPAWN.isAllowed()) {
// Mobs not allowed to spawn
e.setCancelled(true);
return;
}
}
}
}
}
}

View File

@ -0,0 +1,157 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import java.util.HashMap;
import java.util.UUID;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.LingeringPotionSplashEvent;
import org.bukkit.event.entity.PotionSplashEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.potion.PotionEffect;
import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.api.flags.Flag;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles PVP
* @author tastybento
*
*/
public class PVPListener extends AbstractFlagListener {
private HashMap<Integer, UUID> thrownPotions = new HashMap<>();
/**
* This method protects players from PVP if it is not allowed and from
* arrows fired by other players
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onEntityDamage(final EntityDamageByEntityEvent e) {
if (e.getEntity() instanceof Player) {
Flag flag = Flags.PVP;
if (e.getEntity().getWorld().equals(plugin.getIslandWorldManager().getNetherWorld())) flag = Flags.NETHER_PVP;
else if (e.getEntity().getWorld().equals(plugin.getIslandWorldManager().getEndWorld())) flag = Flags.END_PVP;
respond(e, e.getDamager(), flag);
}
}
private void respond(Event event, Entity damager, Flag flag) {
// Get the attacker
if (damager instanceof Player) {
setUser(User.getInstance(damager));
checkIsland(event, damager.getLocation(), flag);
} else if (damager instanceof Projectile) {
// Find out who fired the arrow
Projectile p = (Projectile) damager;
if (p.getShooter() instanceof Player) {
setUser(User.getInstance((Player)p.getShooter()));
if (!checkIsland(event, damager.getLocation(), flag)) {
damager.setFireTicks(0);
damager.remove();
}
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onFishing(PlayerFishEvent e) {
if (e.getCaught() != null && e.getCaught() instanceof Player) {
Flag flag = Flags.PVP;
if (e.getCaught().getWorld().equals(plugin.getIslandWorldManager().getNetherWorld())) flag = Flags.NETHER_PVP;
else if (e.getCaught().getWorld().equals(plugin.getIslandWorldManager().getEndWorld())) flag = Flags.END_PVP;
if (checkIsland(e, e.getCaught().getLocation(), flag)) {
e.getHook().remove();
return;
}
}
}
/**
* Checks for splash damage. Remove damage if it should not affect.
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onSplashPotionSplash(final PotionSplashEvent e) {
// Deduce the world
Flag flag = Flags.PVP;
if (e.getPotion().getWorld().equals(plugin.getIslandWorldManager().getNetherWorld())) flag = Flags.NETHER_PVP;
else if (e.getPotion().getWorld().equals(plugin.getIslandWorldManager().getEndWorld())) flag = Flags.END_PVP;
// Try to get the thrower
Projectile projectile = (Projectile) e.getEntity();
if (projectile.getShooter() != null && projectile.getShooter() instanceof Player) {
Player attacker = (Player)projectile.getShooter();
setUser(User.getInstance(attacker));
// Run through all the affected entities
for (LivingEntity entity: e.getAffectedEntities()) {
// Self damage
if (attacker.equals(entity)) {
continue;
}
// PVP?
if (entity instanceof Player) {
if (!checkIsland(e, entity.getLocation(), flag)) {
for (PotionEffect effect : e.getPotion().getEffects()) {
entity.removePotionEffect(effect.getType());
}
}
}
}
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onLingeringPotionSplash(final LingeringPotionSplashEvent e) {
// Try to get the shooter
Projectile projectile = (Projectile) e.getEntity();
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, () -> {
thrownPotions.remove(e.getAreaEffectCloud().getEntityId());
}, e.getAreaEffectCloud().getDuration());
}
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
public void onLingeringPotionDamage(final EntityDamageByEntityEvent e) {
if (e.getEntity() == null || e.getEntity().getUniqueId() == null) {
return;
}
if (e.getCause().equals(DamageCause.ENTITY_ATTACK) && thrownPotions.containsKey(e.getDamager().getEntityId())) {
// Deduce the world
Flag flag = Flags.PVP;
if (e.getEntity().getWorld().equals(plugin.getIslandWorldManager().getNetherWorld())) flag = Flags.NETHER_PVP;
else if (e.getEntity().getWorld().equals(plugin.getIslandWorldManager().getEndWorld())) flag = Flags.END_PVP;
UUID attacker = thrownPotions.get(e.getDamager().getEntityId());
// Self damage
if (attacker.equals(e.getEntity().getUniqueId())) {
return;
}
Entity entity = e.getEntity();
// PVP?
if (entity instanceof Player) {
checkIsland(e, entity.getLocation(), flag);
}
}
}
}

View File

@ -0,0 +1,46 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* @author ben
*
*/
public class PhysicalInteractionListener extends AbstractFlagListener {
/**
* Handle physical interaction with blocks
* Crop trample, pressure plates, triggering redstone, tripwires
* @param e
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onPlayerInteract(final PlayerInteractEvent e) {
if (!e.getAction().equals(Action.PHYSICAL)) {
return;
}
switch (e.getClickedBlock().getType()) {
case SOIL:
// Crop trample
checkIsland(e, e.getPlayer().getLocation(), Flags.CROP_TRAMPLE);
break;
case WOOD_PLATE:
case STONE_PLATE:
case GOLD_PLATE:
case IRON_PLATE:
// Pressure plates
checkIsland(e, e.getPlayer().getLocation(), Flags.PRESSURE_PLATE);
break;
default:
break;
}
}
}

View File

@ -10,16 +10,9 @@ import org.bukkit.event.block.EntityBlockFormEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.listeners.FlagListener;
import us.tastybento.bskyblock.lists.Flags;
public class PlaceBlocksListener extends FlagListener {
public PlaceBlocksListener() {
super(BSkyBlock.getInstance());
}
public class PlaceBlocksListener extends AbstractFlagListener {
/**
* Check blocks being placed in general
@ -73,7 +66,7 @@ public class PlaceBlocksListener extends FlagListener {
if (e.getMaterial().equals(Material.END_CRYSTAL) || e.getMaterial() == Material.WOOD_DOOR || e.getMaterial() == Material.CHEST
|| e.getMaterial() == Material.TRAPPED_CHEST || e.getMaterial() == Material.IRON_DOOR
|| (e.getMaterial().name().contains("BOAT") && !e.getClickedBlock().isLiquid())) {
checkIsland(e, getUser().getLocation(), Flags.PLACE_BLOCKS);
checkIsland(e, e.getPlayer().getLocation(), Flags.PLACE_BLOCKS);
}
}
}
@ -87,7 +80,7 @@ public class PlaceBlocksListener extends FlagListener {
public void onBlockForm(EntityBlockFormEvent e) {
if (e.getNewState().getType().equals(Material.FROSTED_ICE)) {
// Silently check
checkIsland(e, getUser().getLocation(), Flags.PLACE_BLOCKS, true);
checkIsland(e, e.getBlock().getLocation(), Flags.PLACE_BLOCKS, true);
}
}

View File

@ -0,0 +1,23 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerPortalEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles portal protection
* @author tastybento
*
*/
public class PortalListener extends AbstractFlagListener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerPortal(PlayerPortalEvent e) {
checkIsland(e, e.getFrom(), Flags.PORTAL);
}
}

View File

@ -0,0 +1,25 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerShearEntityEvent;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles shearing
* @author tastybento
*
*/
public class ShearingListener extends AbstractFlagListener {
// Protect sheep
@EventHandler(priority = EventPriority.LOW)
public void onShear(final PlayerShearEntityEvent e) {
checkIsland(e, e.getEntity().getLocation(), Flags.SHEARING);
}
}

View File

@ -0,0 +1,37 @@
/**
*
*/
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import us.tastybento.bskyblock.lists.Flags;
/**
* Handles interaction with entities like armor stands
* Note - armor stand protection from breaking or placing is done elsewhere.
* @author tastybento
*
*/
public class TeleportationListener extends AbstractFlagListener {
/**
* Ender pearl and chorus fruit teleport checks
*
* @param e
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerTeleport(final PlayerTeleportEvent e) {
if (e.getCause() != null) {
if (e.getCause().equals(TeleportCause.ENDER_PEARL)) {
checkIsland(e, e.getTo(), Flags.ENDER_PEARL);
} else if (e.getCause().equals(TeleportCause.CHORUS_FRUIT)) {
checkIsland(e, e.getTo(), Flags.CHORUS_FRUIT);
}
}
}
}

View File

@ -1,56 +1,121 @@
package us.tastybento.bskyblock.lists;
import org.bukkit.Material;
import us.tastybento.bskyblock.api.flags.Flag;
import us.tastybento.bskyblock.api.flags.FlagBuilder;
import us.tastybento.bskyblock.listeners.flags.*;
import us.tastybento.bskyblock.listeners.flags.BlockInteractionListener;
import us.tastybento.bskyblock.listeners.flags.BreakBlocksListener;
import us.tastybento.bskyblock.listeners.flags.BreedingListener;
import us.tastybento.bskyblock.listeners.flags.BucketListener;
import us.tastybento.bskyblock.listeners.flags.EggListener;
import us.tastybento.bskyblock.listeners.flags.EntityInteractListener;
import us.tastybento.bskyblock.listeners.flags.FireListener;
import us.tastybento.bskyblock.listeners.flags.HurtingListener;
import us.tastybento.bskyblock.listeners.flags.InventoryListener;
import us.tastybento.bskyblock.listeners.flags.LeashListener;
import us.tastybento.bskyblock.listeners.flags.PVPListener;
import us.tastybento.bskyblock.listeners.flags.PhysicalInteractionListener;
import us.tastybento.bskyblock.listeners.flags.PlaceBlocksListener;
import us.tastybento.bskyblock.listeners.flags.PortalListener;
import us.tastybento.bskyblock.listeners.flags.ShearingListener;
import us.tastybento.bskyblock.listeners.flags.TeleportationListener;
public class Flags {
/*
* Protection Flags
*/
// Break and place blocks
public static final Flag BREAK_BLOCKS = new FlagBuilder().id("BREAK_BLOCKS").icon(Material.STONE).listener(new BreakBlocksListener()).build();
public static final Flag PLACE_BLOCKS = new FlagBuilder().id("PLACE_BLOCKS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag ANVIL = new FlagBuilder().id("ANVIL").icon(Material.DIRT).listener(new AnvilListener()).build();
public static final Flag ARMOR_STAND = new FlagBuilder().id("ARMOR_STAND").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag BEACON = new FlagBuilder().id("BEACON").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag BED = new FlagBuilder().id("BED").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag BREEDING = new FlagBuilder().id("BREEDING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag BREWING = new FlagBuilder().id("BREWING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag BUCKET = new FlagBuilder().id("BUCKET").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag COLLECT_LAVA = new FlagBuilder().id("COLLECT_LAVA").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag COLLECT_WATER = new FlagBuilder().id("COLLECT_WATER").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag CHEST = new FlagBuilder().id("CHEST").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag CHORUS_FRUIT = new FlagBuilder().id("CHORUS_FRUIT").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag CRAFTING = new FlagBuilder().id("CRAFTING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag CROP_TRAMPLE = new FlagBuilder().id("CROP_TRAMPLE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag DOOR = new FlagBuilder().id("DOOR").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag EGGS = new FlagBuilder().id("EGGS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag ENCHANTING = new FlagBuilder().id("ENCHANTING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag ENDER_PEARL = new FlagBuilder().id("ENDER_PEARL").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag FIRE = new FlagBuilder().id("FIRE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag FIRE_EXTINGUISH = new FlagBuilder().id("FIRE_EXTINGUISH").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag FIRE_SPREAD = new FlagBuilder().id("FIRE_SPREAD").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag FURNACE = new FlagBuilder().id("FURNACE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag GATE = new FlagBuilder().id("GATE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag MOUNT_INVENTORY = new FlagBuilder().id("MOUNT_INVENTORY").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag RIDING = new FlagBuilder().id("RIDING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag HURT_MOBS = new FlagBuilder().id("HURT_MOBS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag LEASH = new FlagBuilder().id("LEASH").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag LEVER_BUTTON = new FlagBuilder().id("LEVER_BUTTON").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag MOB_SPAWN = new FlagBuilder().id("MOB_SPAWN").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag MUSIC = new FlagBuilder().id("MUSIC").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag PORTAL = new FlagBuilder().id("PORTAL").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag PRESSURE_PLATE = new FlagBuilder().id("PRESSURE_PLATE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag PVP = new FlagBuilder().id("PVP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag MILKING = new FlagBuilder().id("MILKING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag NETHER_PVP = new FlagBuilder().id("NETHER_PVP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag END_PVP = new FlagBuilder().id("END_PVP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag REDSTONE = new FlagBuilder().id("REDSTONE").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag SPAWN_EGGS = new FlagBuilder().id("SPAWN_EGGS").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag SHEARING = new FlagBuilder().id("SHEARING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag TRADING = new FlagBuilder().id("TRADING").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
// Block interactions - all use BlockInteractionListener()
public static final Flag ANVIL = new FlagBuilder().id("ANVIL").icon(Material.ANVIL).listener(new BlockInteractionListener()).build();
public static final Flag BEACON = new FlagBuilder().id("BEACON").icon(Material.BEACON).build();
public static final Flag BED = new FlagBuilder().id("BED").icon(Material.BED).build();
public static final Flag BREWING = new FlagBuilder().id("BREWING").icon(Material.BREWING_STAND_ITEM).build();
public static final Flag CHEST = new FlagBuilder().id("CHEST").icon(Material.CHEST).build();
public static final Flag DOOR = new FlagBuilder().id("DOOR").allowedByDefault(true).icon(Material.WOODEN_DOOR).build();
public static final Flag CRAFTING = new FlagBuilder().id("CRAFTING").allowedByDefault(true).icon(Material.WORKBENCH).build();
public static final Flag ENCHANTING = new FlagBuilder().id("ENCHANTING").allowedByDefault(true).icon(Material.ENCHANTMENT_TABLE).build();
public static final Flag FURNACE = new FlagBuilder().id("FURNACE").icon(Material.FURNACE).build();
public static final Flag GATE = new FlagBuilder().id("GATE").allowedByDefault(true).icon(Material.FENCE_GATE).build();
public static final Flag MUSIC = new FlagBuilder().id("MUSIC").icon(Material.JUKEBOX).build();
public static final Flag LEVER_BUTTON = new FlagBuilder().id("LEVER_BUTTON").icon(Material.LEVER).build();
public static final Flag REDSTONE = new FlagBuilder().id("REDSTONE").icon(Material.REDSTONE).listener(new PlaceBlocksListener()).build();
public static final Flag SPAWN_EGGS = new FlagBuilder().id("SPAWN_EGGS").icon(Material.MONSTER_EGG).listener(new PlaceBlocksListener()).build();
// Entity interactions
public static final Flag ARMOR_STAND = new FlagBuilder().id("ARMOR_STAND").icon(Material.ARMOR_STAND).listener(new EntityInteractListener()).build();
public static final Flag RIDING = new FlagBuilder().id("RIDING").icon(Material.GOLD_BARDING).build();
public static final Flag TRADING = new FlagBuilder().id("TRADING").allowedByDefault(true).icon(Material.EMERALD).build();
// Breeding
public static final Flag BREEDING = new FlagBuilder().id("BREEDING").icon(Material.CARROT).listener(new BreedingListener()).build();
// Buckets. All bucket use is covered by one listener
public static final Flag BUCKET = new FlagBuilder().id("BUCKET").icon(Material.BUCKET).listener(new BucketListener()).build();
public static final Flag COLLECT_LAVA = new FlagBuilder().id("COLLECT_LAVA").icon(Material.LAVA_BUCKET).build();
public static final Flag COLLECT_WATER = new FlagBuilder().id("COLLECT_WATER").icon(Material.WATER_BUCKET).build();
public static final Flag MILKING = new FlagBuilder().id("MILKING").icon(Material.MILK_BUCKET).build();
// Chorus Fruit and Enderpearls
public static final Flag CHORUS_FRUIT = new FlagBuilder().id("CHORUS_FRUIT").icon(Material.CHORUS_FRUIT).listener(new TeleportationListener()).build();
public static final Flag ENDER_PEARL = new FlagBuilder().id("ENDER_PEARL").icon(Material.ENDER_PEARL).build();
// Physical interactions
public static final Flag CROP_TRAMPLE = new FlagBuilder().id("CROP_TRAMPLE").icon(Material.WHEAT).listener(new PhysicalInteractionListener()).build();
public static final Flag PRESSURE_PLATE = new FlagBuilder().id("PRESSURE_PLATE").icon(Material.GOLD_PLATE).build();
// Egg throwing
public static final Flag EGGS = new FlagBuilder().id("EGGS").icon(Material.EGG).listener(new EggListener()).build();
/*
* Fire
* I'll take you to burn.
* Fire
* I'll take you to learn.
* You gonna burn, burn, burn
* Fire
* I'll take you to burn
* - The Crazy World of Arthur Brown
*/
public static final Flag FIRE = new FlagBuilder().id("FIRE").icon(Material.FLINT_AND_STEEL).listener(new FireListener()).build();
public static final Flag FIRE_EXTINGUISH = new FlagBuilder().id("FIRE_EXTINGUISH").icon(Material.POTION).build();
public static final Flag FIRE_SPREAD = new FlagBuilder().id("FIRE_SPREAD").icon(Material.FIREWORK_CHARGE).build();
// Inventories
public static final Flag MOUNT_INVENTORY = new FlagBuilder().id("MOUNT_INVENTORY").icon(Material.IRON_BARDING).listener(new InventoryListener()).build();
// Hurting things
public static final Flag HURT_MOBS = new FlagBuilder().id("HURT_MOBS").icon(Material.STONE_SWORD).listener(new HurtingListener()).build();
public static final Flag HURT_MONSTERS = new FlagBuilder().id("HURT_MONSTERS").icon(Material.WOOD_SWORD).build();
// Leashes
public static final Flag LEASH = new FlagBuilder().id("LEASH").icon(Material.LEASH).listener(new LeashListener()).build();
// Portal use protection
public static final Flag PORTAL = new FlagBuilder().id("PORTAL").icon(Material.OBSIDIAN).listener(new PortalListener()).build();
// PVP
public static final Flag PVP = new FlagBuilder().id("PVP").icon(Material.ARROW).listener(new PVPListener()).build();
public static final Flag NETHER_PVP = new FlagBuilder().id("NETHER_PVP").icon(Material.IRON_AXE).build();
public static final Flag END_PVP = new FlagBuilder().id("END_PVP").icon(Material.END_CRYSTAL).build();
// Shearing
public static final Flag SHEARING = new FlagBuilder().id("SHEARING").icon(Material.SHEARS).listener(new ShearingListener()).build();
// Visitor item pickup or drop
public static final Flag VISITOR_ITEM_DROP = new FlagBuilder().id("VISITOR_ITEM_DROP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
public static final Flag VISITOR_ITEM_PICKUP = new FlagBuilder().id("VISITOR_ITEM_PICKUP").icon(Material.DIRT).listener(new PlaceBlocksListener()).build();
/*
* Non-protection flags
*/
public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).allowedByDefault(true).listener(new PlaceBlocksListener()).build();
public static final Flag MOB_SPAWN = new FlagBuilder().id("MOB_SPAWN").icon(Material.APPLE).allowedByDefault(true).listener(new PlaceBlocksListener()).build();
public static final Flag MONSTER_SPAWN = new FlagBuilder().id("MONSTER_SPAWN").icon(Material.MOB_SPAWNER).allowedByDefault(true).listener(new PlaceBlocksListener()).build();
}

View File

@ -3,8 +3,6 @@ package us.tastybento.bskyblock.managers;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.flags.Flag;
import us.tastybento.bskyblock.api.panels.PanelItem;

View File

@ -98,203 +98,174 @@ public class SafeSpotTeleport {
}
final int worldHeight = maxHeight;
//plugin.getLogger().info("DEBUG:world height = " + worldHeight);
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
// Find a safe spot, defined as a solid block, with 2 air spaces above it
//long time = System.nanoTime();
int x = 0;
int y = 0;
int z = 0;
ChunkSnapshot safeChunk = null;
ChunkSnapshot portalChunk = null;
boolean safeSpotFound = false;
Vector safeSpotInChunk = null;
Vector portalPart = null;
double distance = 0D;
double safeDistance = 0D;
for (ChunkSnapshot chunk: finalChunk) {
for (x = 0; x< 16; x++) {
for (z = 0; z < 16; z++) {
// Work down from the entry point up
for (y = Math.min(chunk.getHighestBlockYAt(x, z), worldHeight); y >= 0; y--) {
//System.out.println("Trying " + (16 * chunk.getX() + x) + " " + y + " " + (16 * chunk.getZ() + z));
// Check for portal - only if this is not a safe home search
if (!setHome && chunk.getBlockType(x, y, z).equals(Material.PORTAL)) {
if (portalPart == null || (distance > islandLoc.toVector().distanceSquared(new Vector(x,y,z)))) {
// First one found or a closer one, save the chunk the position and the distance
portalChunk = chunk;
portalPart = new Vector(x,y,z);
distance = portalPart.distanceSquared(islandLoc.toVector());
}
}
// Check for safe spot, but only if it is closer than one we have found already
if (!safeSpotFound || (safeDistance > islandLoc.toVector().distanceSquared(new Vector(x,y,z)))) {
// No safe spot yet, or closer distance
if (checkBlock(chunk,x,y,z, worldHeight)) {
safeChunk = chunk;
safeSpotFound = true;
safeSpotInChunk = new Vector(x,y,z);
safeDistance = islandLoc.toVector().distanceSquared(safeSpotInChunk);
}
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
// Find a safe spot, defined as a solid block, with 2 air spaces above it
//long time = System.nanoTime();
int x = 0;
int y = 0;
int z = 0;
ChunkSnapshot safeChunk = null;
ChunkSnapshot portalChunk = null;
boolean safeSpotFound = false;
Vector safeSpotInChunk = null;
Vector portalPart = null;
double distance = 0D;
double safeDistance = 0D;
for (ChunkSnapshot chunk: finalChunk) {
for (x = 0; x< 16; x++) {
for (z = 0; z < 16; z++) {
// Work down from the entry point up
for (y = Math.min(chunk.getHighestBlockYAt(x, z), worldHeight); y >= 0; y--) {
//System.out.println("Trying " + (16 * chunk.getX() + x) + " " + y + " " + (16 * chunk.getZ() + z));
// Check for portal - only if this is not a safe home search
if (!setHome && chunk.getBlockType(x, y, z).equals(Material.PORTAL)) {
if (portalPart == null || (distance > islandLoc.toVector().distanceSquared(new Vector(x,y,z)))) {
// First one found or a closer one, save the chunk the position and the distance
portalChunk = chunk;
portalPart = new Vector(x,y,z);
distance = portalPart.distanceSquared(islandLoc.toVector());
}
}
} //end z
} // end x
//if (safeSpotFound) {
//System.out.print("DEBUG: safe spot found " + safeSpotInChunk.toString());
//break search;
//}
}
// End search
// Check if the portal is safe (it should be)
if (portalPart != null) {
//System.out.print("DEBUG: Portal found");
// There is a portal available, but is it safe?
// Get the lowest portal spot
x = portalPart.getBlockX();
y = portalPart.getBlockY();
z = portalPart.getBlockZ();
while (portalChunk.getBlockType(x,y,z).equals(Material.PORTAL)) {
y--;
}
//System.out.print("DEBUG: Portal teleport loc = " + (16 * portalChunk.getX() + x) + "," + (y) + "," + (16 * portalChunk.getZ() + z));
// Now check if this is a safe location
if (checkBlock(portalChunk,x,y,z, worldHeight)) {
// Yes, so use this instead of the highest location
//System.out.print("DEBUG: Portal is safe");
safeSpotFound = true;
safeSpotInChunk = new Vector(x,y,z);
safeChunk = portalChunk;
// TODO: Add safe portal spot to island
}
}
//System.out.print("Seconds = " + ((System.nanoTime() - time) * 0.000000001));
if (safeChunk != null && safeSpotFound) {
//final Vector spot = new Vector((16 *currentChunk.getX()) + x + 0.5D, y +1, (16 * currentChunk.getZ()) + z + 0.5D)
final Vector spot = new Vector((16 *safeChunk.getX()) + 0.5D, 1, (16 * safeChunk.getZ()) + 0.5D).add(safeSpotInChunk);
// Return to main thread and teleport the player
plugin.getServer().getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
Location destination = spot.toLocation(islandLoc.getWorld());
//plugin.getLogger().info("DEBUG: safe spot found = " + destination);
// Create a portal
// TODO Add if statement here
//Block b = player.getLocation().getBlock();
//if (b.getType() != Material.PORTAL) {
/*
if (world.equals(BSkyBlock.getNetherWorld())) {
for (int x = -1; x < 3; x++) {
for (int y = -1; y< 4; y++) {
Location l = new Location(islandLoc.getWorld(), destination.getBlockX() + x, destination.getBlockY() + y, destination.getBlockZ() -1);
if (x == -1 || x == 2 || y == -1 || y == 3) {
//nms.setBlockSuperFast(l.getBlock(), Material.OBSIDIAN.getId(), (byte)0, false);
//l.getBlock().setType(Material.OBSIDIAN);
//plugin.getLogger().info("DEBUG: obsidian at "+ l);
} else {
//plugin.getLogger().info("DEBUG: Portal at "+ l);
nms.setBlockSuperFast(l.getBlock(), Material.PORTAL.getId(), (byte)0, false);
//l.getBlock().setType(Material.PORTAL);
}
}
}
}*/
if (setHome && entity instanceof Player) {
plugin.getPlayers().setHomeLocation(entity.getUniqueId(), destination, homeNumber);
}
Vector velocity = entity.getVelocity();
entity.teleport(destination);
entity.setVelocity(velocity);
// Exit spectator mode if in it
if (entity instanceof Player) {
Player player = (Player)entity;
if (player.getGameMode().equals(GameMode.SPECTATOR)) {
player.setGameMode(GameMode.SURVIVAL);
// Check for safe spot, but only if it is closer than one we have found already
if (!safeSpotFound || (safeDistance > islandLoc.toVector().distanceSquared(new Vector(x,y,z)))) {
// No safe spot yet, or closer distance
if (checkBlock(chunk,x,y,z, worldHeight)) {
safeChunk = chunk;
safeSpotFound = true;
safeSpotInChunk = new Vector(x,y,z);
safeDistance = islandLoc.toVector().distanceSquared(safeSpotInChunk);
}
}
}});
} else {
// We did not find a spot
plugin.getServer().getScheduler().runTask(plugin, () -> {
//plugin.getLogger().info("DEBUG: safe spot not found");
if (entity instanceof Player) {
if (!failureMessage.isEmpty()) {
entity.sendMessage(failureMessage);
} else {
entity.sendMessage("Warp not safe");
}
}
});
} //end z
} // end x
//if (safeSpotFound) {
//System.out.print("DEBUG: safe spot found " + safeSpotInChunk.toString());
//break search;
//}
}
// End search
// Check if the portal is safe (it should be)
if (portalPart != null) {
//System.out.print("DEBUG: Portal found");
// There is a portal available, but is it safe?
// Get the lowest portal spot
x = portalPart.getBlockX();
y = portalPart.getBlockY();
z = portalPart.getBlockZ();
while (portalChunk.getBlockType(x,y,z).equals(Material.PORTAL)) {
y--;
}
//System.out.print("DEBUG: Portal teleport loc = " + (16 * portalChunk.getX() + x) + "," + (y) + "," + (16 * portalChunk.getZ() + z));
// Now check if this is a safe location
if (checkBlock(portalChunk,x,y,z, worldHeight)) {
// Yes, so use this instead of the highest location
//System.out.print("DEBUG: Portal is safe");
safeSpotFound = true;
safeSpotInChunk = new Vector(x,y,z);
safeChunk = portalChunk;
// TODO: Add safe portal spot to island
}
}
/**
* Returns true if the location is a safe one.
* @param chunk
* @param x
* @param y
* @param z
* @param worldHeight
* @return
*/
@SuppressWarnings("deprecation")
private boolean checkBlock(ChunkSnapshot chunk, int x, int y, int z, int worldHeight) {
int type = chunk.getBlockTypeId(x, y, z);
if (type != 0) { // AIR
int space1 = chunk.getBlockTypeId(x, Math.min(y + 1, worldHeight), z);
int space2 = chunk.getBlockTypeId(x, Math.min(y + 2, worldHeight), z);
if ((space1 == 0 && space2 == 0) || (space1 == Material.PORTAL.getId() || space2 == Material.PORTAL.getId())) {
// Now there is a chance that this is a safe spot
// Check for safe ground
Material mat = Material.getMaterial(type);
if (!mat.toString().contains("FENCE")
&& !mat.toString().contains("DOOR")
&& !mat.toString().contains("GATE")
&& !mat.toString().contains("PLATE")) {
switch (mat) {
// Unsafe
case ANVIL:
case BARRIER:
case BOAT:
case CACTUS:
case DOUBLE_PLANT:
case ENDER_PORTAL:
case FIRE:
case FLOWER_POT:
case LADDER:
case LAVA:
case LEVER:
case LONG_GRASS:
case PISTON_EXTENSION:
case PISTON_MOVING_PIECE:
case PORTAL:
case SIGN_POST:
case SKULL:
case STANDING_BANNER:
case STATIONARY_LAVA:
case STATIONARY_WATER:
case STONE_BUTTON:
case TORCH:
case TRIPWIRE:
case WATER:
case WEB:
case WOOD_BUTTON:
//System.out.println("Block is dangerous " + mat.toString());
break;
default:
// Safe
// System.out.println("Block is safe " + mat.toString());
return true;
}
//System.out.print("Seconds = " + ((System.nanoTime() - time) * 0.000000001));
if (safeChunk != null && safeSpotFound) {
//final Vector spot = new Vector((16 *currentChunk.getX()) + x + 0.5D, y +1, (16 * currentChunk.getZ()) + z + 0.5D)
final Vector spot = new Vector((16 *safeChunk.getX()) + 0.5D, 1, (16 * safeChunk.getZ()) + 0.5D).add(safeSpotInChunk);
// Return to main thread and teleport the player
plugin.getServer().getScheduler().runTask(plugin, () -> {
Location destination = spot.toLocation(islandLoc.getWorld());
if (setHome && entity instanceof Player) {
plugin.getPlayers().setHomeLocation(entity.getUniqueId(), destination, homeNumber);
}
Vector velocity = entity.getVelocity();
entity.teleport(destination);
entity.setVelocity(velocity);
// Exit spectator mode if in it
if (entity instanceof Player) {
Player player = (Player)entity;
if (player.getGameMode().equals(GameMode.SPECTATOR)) {
player.setGameMode(GameMode.SURVIVAL);
}
}
}
return false;
}});
});
} else {
// We did not find a spot
plugin.getServer().getScheduler().runTask(plugin, () -> {
//plugin.getLogger().info("DEBUG: safe spot not found");
if (entity instanceof Player) {
if (!failureMessage.isEmpty()) {
entity.sendMessage(failureMessage);
} else {
entity.sendMessage("Warp not safe");
}
}
});
}
});
}
}
/**
* Returns true if the location is a safe one.
* @param chunk
* @param x
* @param y
* @param z
* @param worldHeight
* @return
*/
@SuppressWarnings("deprecation")
private boolean checkBlock(ChunkSnapshot chunk, int x, int y, int z, int worldHeight) {
int type = chunk.getBlockTypeId(x, y, z);
if (type != 0) { // AIR
int space1 = chunk.getBlockTypeId(x, Math.min(y + 1, worldHeight), z);
int space2 = chunk.getBlockTypeId(x, Math.min(y + 2, worldHeight), z);
if ((space1 == 0 && space2 == 0) || (space1 == Material.PORTAL.getId() || space2 == Material.PORTAL.getId())) {
// Now there is a chance that this is a safe spot
// Check for safe ground
Material mat = Material.getMaterial(type);
if (!mat.toString().contains("FENCE")
&& !mat.toString().contains("DOOR")
&& !mat.toString().contains("GATE")
&& !mat.toString().contains("PLATE")) {
switch (mat) {
// Unsafe
case ANVIL:
case BARRIER:
case BOAT:
case CACTUS:
case DOUBLE_PLANT:
case ENDER_PORTAL:
case FIRE:
case FLOWER_POT:
case LADDER:
case LAVA:
case LEVER:
case LONG_GRASS:
case PISTON_EXTENSION:
case PISTON_MOVING_PIECE:
case PORTAL:
case SIGN_POST:
case SKULL:
case STANDING_BANNER:
case STATIONARY_LAVA:
case STATIONARY_WATER:
case STONE_BUTTON:
case TORCH:
case TRIPWIRE:
case WATER:
case WEB:
case WOOD_BUTTON:
//System.out.println("Block is dangerous " + mat.toString());
break;
default:
// Safe
// System.out.println("Block is safe " + mat.toString());
return true;
}
}
}
}
return false;
}
}