Added code to support protection flag listeners.

Made getIslandsAt() Optional to enable better code structures in the
listeners.

Created an abstract class to simplify flag protection listeners.

Added default setting for flags that will be able to be set by config.
This default is used for any space in the worlds not occupied by an
island.
This commit is contained in:
tastybento 2018-01-30 16:59:10 -08:00
parent 085db6cb21
commit 177023f314
14 changed files with 282 additions and 94 deletions

View File

@ -70,7 +70,9 @@ general:
mute-death-messages: false
# Allow FTB Autonomous Activator to work (will allow a pseudo player [CoFH] to place and break blocks and hang items)
allow-FTB-auto-activator: false
# Add other fake player names here if required
fakeplayers:
- "[CoFH]"
# Allow obsidian to be scooped up with an empty bucket back into lava
# This only works if there is a single block of obsidian (no obsidian within 10 blocks)

View File

@ -142,6 +142,7 @@ ranks:
banned: "Banned"
protection:
protected: "&cIsland protected!"
flags:
ACID_DAMAGE: "Acid damage"
ANVIL: "Use anvil"

View File

@ -3,7 +3,9 @@ package us.tastybento.bskyblock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
@ -66,9 +68,8 @@ public class Settings implements ISettings<Settings> {
@ConfigEntry(path = "general.database.backup-period")
private int databaseBackupPeriod = 5;
//TODO change allowAutoActivator to the fakePlayers introduced in ASB 3.0.8
@ConfigEntry(path = "general.allow-FTB-auto-activators")
private boolean allowAutoActivator = false;
@ConfigEntry(path = "general.fakeplayers")
private Set<String> fakePlayers = new HashSet<>();
@ConfigEntry(path = "general.allow-obsidian-scooping")
private boolean allowObsidianScooping = true;
@ -537,12 +538,6 @@ public class Settings implements ISettings<Settings> {
public boolean isAcidDamageOp() {
return acidDamageOp;
}
/**
* @return the allowAutoActivator
*/
public boolean isAllowAutoActivator() {
return allowAutoActivator;
}
/**
* @return the allowChestDamage
*/
@ -771,12 +766,6 @@ public class Settings implements ISettings<Settings> {
public void setAcidRainDamage(int acidRainDamage) {
this.acidRainDamage = acidRainDamage;
}
/**
* @param allowAutoActivator the allowAutoActivator to set
*/
public void setAllowAutoActivator(boolean allowAutoActivator) {
this.allowAutoActivator = allowAutoActivator;
}
/**
* @param allowChestDamage the allowChestDamage to set
*/
@ -1216,6 +1205,18 @@ public class Settings implements ISettings<Settings> {
public void setWorldName(String worldName) {
this.worldName = worldName;
}
/**
* @return the fakePlayers
*/
public Set<String> getFakePlayers() {
return fakePlayers;
}
/**
* @param fakePlayers the fakePlayers to set
*/
public void setFakePlayers(Set<String> fakePlayers) {
this.fakePlayers = fakePlayers;
}
}

View File

@ -6,15 +6,15 @@ import org.bukkit.event.Listener;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.panels.PanelItem;
import us.tastybento.bskyblock.managers.FlagsManager;
public class Flag {
private String id;
private PanelItem icon;
private Listener listener;
private boolean defaultSetting;
public Flag(String id, PanelItem icon, Listener listener) {
public Flag(String id, PanelItem icon, Listener listener, boolean defaultSetting) {
this.id = id;
this.icon = icon;
this.listener = listener;
@ -32,4 +32,12 @@ public class Flag {
public Optional<Listener> getListener() {
return Optional.of(listener);
}
public boolean isAllowed() {
return defaultSetting;
}
public void setDefaultSetting(boolean defaultSetting) {
this.defaultSetting = defaultSetting;
}
}

View File

@ -12,6 +12,7 @@ public class FlagBuilder {
private String id = "";
private PanelItem icon;
private Listener listener;
private boolean defaultSetting;
public FlagBuilder id(String id) {
this.id = id;
@ -37,6 +38,16 @@ public class FlagBuilder {
}
public Flag build() {
return new Flag(id, icon, listener);
return new Flag(id, icon, listener, defaultSetting);
}
/**
* Sets the default setting for this flag in the world
* @param setting
* @return
*/
public FlagBuilder allowedByDefault(boolean setting) {
this.defaultSetting = setting;
return this;
}
}

View File

@ -7,6 +7,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@ -376,11 +377,8 @@ public class PlayersManager{
if (loc == null)
return null;
// Look in the grid
Island island = plugin.getIslands().getIslandAt(loc);
if (island != null) {
return island.getOwner();
}
return null;
Optional<Island> island = plugin.getIslands().getIslandAt(loc);
return island.map(x->x.getOwner()).orElse(null);
}
/**

View File

@ -2,6 +2,7 @@ package us.tastybento.bskyblock.database.managers.island;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@ -160,11 +161,12 @@ public class IslandsManager {
height = i;
depth = i;
} else {
Island island = getIslandAt(l);
if (island == null) {
Optional<Island> island = getIslandAt(l);
if (!island.isPresent()) {
return null;
}
i = island.getProtectionRange();
i = island.get().getProtectionRange();
height = l.getWorld().getMaxHeight() - l.getBlockY();
depth = l.getBlockY();
}
@ -344,28 +346,28 @@ public class IslandsManager {
}
/**
* Returns the island at the location or null if there is none.
* Returns the island at the location or Optional empty if there is none.
* This includes the full island space, not just the protected area
*
* @param location
* @return Island object
*/
public Island getIslandAt(Location location) {
public Optional<Island> getIslandAt(Location location) {
if (location == null) {
//plugin.getLogger().info("DEBUG: location is null");
return null;
return Optional.empty();
}
// World check
if (!Util.inWorld(location)) {
//plugin.getLogger().info("DEBUG: not in right world");
return null;
return Optional.empty();
}
// Check if it is spawn
if (spawn != null && spawn.onIsland(location)) {
//plugin.getLogger().info("DEBUG: spawn");
return spawn;
return Optional.of(spawn);
}
return getIslandAt(location.getBlockX(), location.getBlockZ());
return Optional.ofNullable(getIslandAt(location.getBlockX(), location.getBlockZ()));
}
/**
@ -405,31 +407,20 @@ public class IslandsManager {
}
/**
* Returns the island being public at the location or null if there is none
* Returns the island being public at the location or Optional Empty if there is none
*
* @param location
* @return Island object
* @return Optional Island object
*/
public Island getProtectedIslandAt(Location location) {
public Optional<Island> getProtectedIslandAt(Location location) {
//plugin.getLogger().info("DEBUG: getProtectedIslandAt " + location);
// Try spawn
if (spawn != null && spawn.onIsland(location)) {
return spawn;
return Optional.of(spawn);
}
Island island = getIslandAt(location);
if (island == null) {
if (DEBUG2)
plugin.getLogger().info("DEBUG: no island at this location");
return null;
}
if (island.onIsland(location)) {
if (DEBUG2)
plugin.getLogger().info("DEBUG: on island");
return island;
}
if (DEBUG2)
plugin.getLogger().info("DEBUG: not in island protection zone");
return null;
Optional<Island> island = getIslandAt(location);
return island.map(x->x.onIsland(location) ? island.get() : null);
}
/**
@ -760,15 +751,8 @@ public class IslandsManager {
// 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 = plugin.getSettings().getIslandProtectionRange();
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();
}
}
int protectionRange = getIslandAt(islandTestLocation).map(x->x.getProtectionRange())
.orElse(plugin.getSettings().getIslandProtectionRange());
if (loc.getX() > islandTestLocation.getX() - protectionRange
&& loc.getX() < islandTestLocation.getX() + protectionRange
&& loc.getZ() > islandTestLocation.getZ() - protectionRange
@ -793,15 +777,15 @@ public class IslandsManager {
return false;
}
// Get the player's island from the grid if it exists
Island island = getIslandAt(loc);
if (island != null) {
Optional<Island> island = getIslandAt(loc);
if (island.isPresent()) {
//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())) {
if (island.get().onIsland(loc) && island.get().getMembers().contains(player.getUniqueId())) {
//plugin.getLogger().info("DEBUG: allowed");
// In a protected zone but is on the list of acceptable players
return true;

View File

@ -0,0 +1,112 @@
/**
*
*/
package us.tastybento.bskyblock.listeners;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.PlayerLeashEntityEvent;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryPickupItemEvent;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.commands.User;
/**
* Abstract class for flag listeners to inherit. Provides some common code.
* @author ben
*
*/
public abstract class FlagListener implements Listener {
private static final boolean DEBUG = false;
protected BSkyBlock plugin;
protected User user;
public FlagListener(BSkyBlock plugin) {
super();
this.plugin = plugin;
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEvent(Event e) {
if (DEBUG) {
plugin.getLogger().info(e.getEventName());
}
}
/*
* The following methods cover the cancellable events and enable a simple noGo(e) to be used to cancel and send the error message
*/
/**
* Sends the island protected message to user
* @param e
*/
protected void noGo(BlockBreakEvent e) {
e.setCancelled(true);
user.sendMessage("protection.protected");
}
/**
* Sends the island protected message to user
* @param e
*/
protected void noGo(BlockPlaceEvent e) {
e.setCancelled(true);
user.sendMessage("protection.protected");
}
/**
* Sends the island protected message to user
* @param e
*/
protected void noGo(InventoryPickupItemEvent e) {
e.setCancelled(true);
user.sendMessage("protection.protected");
}
/**
* Sends the island protected message to user
* @param e
*/
protected void noGo(PlayerLeashEntityEvent e) {
e.setCancelled(true);
user.sendMessage("protection.protected");
}
/**
* Sends the island protected message to user
* @param e
*/
protected void noGo(InventoryMoveItemEvent e) {
e.setCancelled(true);
user.sendMessage("protection.protected");
}
/**
* Check if loc is in the island worlds
* @param loc
* @return true if the location is in the island worlds
*/
protected 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;
}
/**
* Check if the entity is in the island worlds
* @param entity - the entity
* @return true if in world
*/
protected boolean inWorld(Entity entity) {
return inWorld(entity.getLocation());
}
}

View File

@ -1,5 +1,6 @@
package us.tastybento.bskyblock.listeners;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.event.EventHandler;
@ -67,7 +68,7 @@ public class JoinLeaveListener implements Listener {
}
// Check if they logged in to a locked island and expel them or if they are banned
Island currentIsland = plugin.getIslands().getIslandAt(user.getLocation());
Island currentIsland = plugin.getIslands().getIslandAt(user.getLocation()).orElse(null);
if (currentIsland != null && (currentIsland.isLocked() || plugin.getPlayers().isBanned(currentIsland.getOwner(),user.getUniqueId()))) {
if (DEBUG)
plugin.getLogger().info("DEBUG: Current island is locked, or player is banned");

View File

@ -1,6 +1,44 @@
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
public class BreakBlocksListener implements Listener {
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());
}
/**
* Prevents blocks from being broken
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockBreak(final BlockBreakEvent e) {
// If this is not an Island World, skip
if (!inWorld(e.getPlayer())) return;
// Handle fake players
if (plugin.getSettings().getFakePlayers().contains(e.getPlayer().getName())) return;
// Real players
// Get the island and if present, check the flag, react if required and return
plugin.getIslands().getIslandAt(e.getBlock().getLocation()).ifPresent(x -> {
if (!x.isAllowed(User.getInstance(e.getPlayer()), Flags.BREAK_BLOCKS)) noGo(e);
return;
});
// The player is in the world, but not on an island, so general world settings apply
if (!Flags.BREAK_BLOCKS.isAllowed()) noGo(e);
}
}

View File

@ -1,6 +1,43 @@
package us.tastybento.bskyblock.listeners.flags;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
public class PlaceBlocksListener implements Listener {
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 PlaceBlocksListener extends FlagListener {
public PlaceBlocksListener() {
super(BSkyBlock.getInstance());
}
/**
* Prevents blocks from being broken
*
* @param e
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onBlockPlace(final BlockPlaceEvent e) {
// If this is not an Island World, skip
if (!inWorld(e.getPlayer())) return;
// Handle fake players
if (plugin.getSettings().getFakePlayers().contains(e.getPlayer().getName())) return;
// Real players
// Get the island and if present, check the flag, react if required and return
plugin.getIslands().getIslandAt(e.getBlock().getLocation()).ifPresent(x -> {
if (!x.isAllowed(User.getInstance(e.getPlayer()), Flags.PLACE_BLOCKS)) noGo(e);
return;
});
// The player is in the world, but not on an island, so general world settings apply
if (!Flags.PLACE_BLOCKS.isAllowed()) noGo(e);
}
}

View File

@ -86,13 +86,7 @@ public class FlyingMobEvents implements Listener {
plugin.getLogger().info("Flying mobs " + e.getEventName());
}
// Store where this mob originated
Island island = plugin.getIslands().getIslandAt(e.getLocation());
if (island != null) {
if (DEBUG) {
plugin.getLogger().info("DEBUG: Mob spawned on known island - id = " + e.getEntity().getUniqueId());
}
mobSpawnInfo.put(e.getEntity(),island);
} // Else do nothing - maybe an Op spawned it? If so, on their head be it!
plugin.getIslands().getIslandAt(e.getLocation()).map(island->mobSpawnInfo.put(e.getEntity(),island));
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)

View File

@ -67,7 +67,7 @@ public class SafeSpotTeleport {
//this.plugin = plugin;
//plugin.getLogger().info("DEBUG: running safe spot");
// Get island
Island island = plugin.getIslands().getIslandAt(islandLoc);
Island island = plugin.getIslands().getIslandAt(islandLoc).orElse(null);
if (island != null) {
final World world = islandLoc.getWorld();
// Get the chunks

View File

@ -1,22 +1,33 @@
package bskyblock;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.ItemFactory;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.Constants;
import us.tastybento.bskyblock.api.commands.CompositeCommand;
@ -24,20 +35,10 @@ import us.tastybento.bskyblock.api.commands.User;
import us.tastybento.bskyblock.api.events.IslandBaseEvent;
import us.tastybento.bskyblock.api.events.team.TeamEvent;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.lists.Flags;
import us.tastybento.bskyblock.managers.FlagsManager;
import us.tastybento.bskyblock.managers.RanksManager;
import us.tastybento.bskyblock.util.Util;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Logger;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
//@RunWith(PowerMockRunner.class)
//@SuppressStaticInitializationFor("us.tastybento.BSkyBlock")
//@PrepareForTest( { BSkyBlock.class })