diff --git a/pom.xml b/pom.xml
index 7746d1ad..1da291fb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,7 +67,7 @@
-LOCAL
- 1.15.0
+ 1.16.0
BentoBoxWorld_AOneBlock
bentobox-world
diff --git a/src/main/java/world/bentobox/aoneblock/AOneBlock.java b/src/main/java/world/bentobox/aoneblock/AOneBlock.java
index 2a63c99e..5a9c27ea 100644
--- a/src/main/java/world/bentobox/aoneblock/AOneBlock.java
+++ b/src/main/java/world/bentobox/aoneblock/AOneBlock.java
@@ -4,6 +4,7 @@
import java.util.Objects;
import org.bukkit.Bukkit;
+import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
@@ -24,6 +25,7 @@
import world.bentobox.aoneblock.listeners.ItemsAdderListener;
import world.bentobox.aoneblock.listeners.JoinLeaveListener;
import world.bentobox.aoneblock.listeners.NoBlockHandler;
+import world.bentobox.aoneblock.listeners.StartSafetyListener;
import world.bentobox.aoneblock.oneblocks.OneBlockCustomBlockCreator;
import world.bentobox.aoneblock.oneblocks.OneBlocksManager;
import world.bentobox.aoneblock.oneblocks.customblock.ItemsAdderCustomBlock;
@@ -32,6 +34,9 @@
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.configuration.WorldSettings;
+import world.bentobox.bentobox.api.flags.Flag;
+import world.bentobox.bentobox.api.flags.Flag.Mode;
+import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.database.objects.Island;
/**
@@ -51,8 +56,16 @@ public class AOneBlock extends GameModeAddon {
private final Config configObject = new Config<>(this, Settings.class);
private BlockListener blockListener;
private OneBlocksManager oneBlockManager;
- private PlaceholdersManager phManager;
+ private AOneBlockPlaceholders phManager;
private HoloListener holoListener;
+
+ // Flag
+ public final Flag START_SAFETY = new Flag.Builder("START_SAFETY", Material.BAMBOO_BLOCK)
+ .mode(Mode.BASIC)
+ .type(Type.WORLD_SETTING)
+ .listener(new StartSafetyListener(this))
+ .defaultSetting(false)
+ .build();
@Override
public void onLoad() {
@@ -73,10 +86,13 @@ public void onLoad() {
// Register commands
playerCommand = new PlayerCommand(this);
adminCommand = new AdminCommand(this);
+ // Register flag with BentoBox
+ // Register protection flag with BentoBox
+ getPlugin().getFlagsManager().registerFlag(this, START_SAFETY);
}
}
- private boolean loadSettings() {
+ private boolean loadSettings() {
// Load settings again to get worlds
settings = configObject.loadConfigObject();
if (settings == null) {
@@ -105,7 +121,7 @@ public void onEnable() {
registerListener(new JoinLeaveListener(this));
registerListener(new InfoListener(this));
// Register placeholders
- registerPlaceholders();
+ phManager = new AOneBlockPlaceholders(this, getPlugin().getPlaceholdersManager());
// Register request handlers
registerRequestHandler(new IslandStatsHandler(this));
@@ -130,37 +146,6 @@ public boolean loadData() {
return false;
}
- private void registerPlaceholders() {
- phManager = new PlaceholdersManager(this);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "visited_island_phase",
- phManager::getPhaseByLocation);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "visited_island_count",
- phManager::getCountByLocation);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_phase", phManager::getPhase);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_count", phManager::getCount);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "visited_island_next_phase",
- phManager::getNextPhaseByLocation);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_next_phase", phManager::getNextPhase);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_blocks_for_phase",
- phManager::getPhaseBlocks);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_blocks_to_next_phase",
- phManager::getNextPhaseBlocks);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "visited_island_blocks_to_next_phase",
- phManager::getNextPhaseBlocksByLocation);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_percent_done",
- phManager::getPercentDone);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "visited_island_percent_done",
- phManager::getPercentDoneByLocation);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_done_scale", phManager::getDoneScale);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "visited_island_done_scale",
- phManager::getDoneScaleByLocation);
- // Since 1.10
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "visited_island_lifetime_count",
- phManager::getLifetimeByLocation);
- getPlugin().getPlaceholdersManager().registerPlaceholder(this, "my_island_lifetime_count",
- phManager::getLifetime);
- }
-
@Override
public void onDisable() {
// save cache
@@ -319,7 +304,7 @@ public BlockListener getBlockListener() {
*
* @return the phManager
*/
- public PlaceholdersManager getPlaceholdersManager() {
+ public AOneBlockPlaceholders getPlaceholdersManager() {
return phManager;
}
@@ -336,4 +321,18 @@ public HoloListener getHoloListener() {
public boolean hasItemsAdder() {
return hasItemsAdder;
}
+
+ /**
+ * Set the addon's world. Used only for testing.
+ * @param world world
+ */
+ public void setIslandWorld(World world) {
+ this.islandWorld = world;
+
+ }
+
+ public void setSettings(Settings settings) {
+ this.settings = settings;
+ }
+
}
diff --git a/src/main/java/world/bentobox/aoneblock/PlaceholdersManager.java b/src/main/java/world/bentobox/aoneblock/AOneBlockPlaceholders.java
similarity index 81%
rename from src/main/java/world/bentobox/aoneblock/PlaceholdersManager.java
rename to src/main/java/world/bentobox/aoneblock/AOneBlockPlaceholders.java
index 05750d79..784c847e 100644
--- a/src/main/java/world/bentobox/aoneblock/PlaceholdersManager.java
+++ b/src/main/java/world/bentobox/aoneblock/AOneBlockPlaceholders.java
@@ -7,7 +7,7 @@
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
-public class PlaceholdersManager {
+public class AOneBlockPlaceholders {
private static final TreeMap SCALE;
private static final String INFINITE = "aoneblock.placeholders.infinite";
@@ -26,8 +26,26 @@ public class PlaceholdersManager {
private final AOneBlock addon;
- public PlaceholdersManager(AOneBlock addon) {
+ public AOneBlockPlaceholders(AOneBlock addon,
+ world.bentobox.bentobox.managers.PlaceholdersManager placeholdersManager) {
this.addon = addon;
+ placeholdersManager.registerPlaceholder(addon, "visited_island_phase", this::getPhaseByLocation);
+ placeholdersManager.registerPlaceholder(addon, "visited_island_count", this::getCountByLocation);
+ placeholdersManager.registerPlaceholder(addon, "my_island_phase", this::getPhase);
+ placeholdersManager.registerPlaceholder(addon, "my_island_count", this::getCount);
+ placeholdersManager.registerPlaceholder(addon, "visited_island_next_phase", this::getNextPhaseByLocation);
+ placeholdersManager.registerPlaceholder(addon, "my_island_next_phase", this::getNextPhase);
+ placeholdersManager.registerPlaceholder(addon, "my_island_blocks_for_phase", this::getPhaseBlocks);
+ placeholdersManager.registerPlaceholder(addon, "my_island_blocks_to_next_phase", this::getNextPhaseBlocks);
+ placeholdersManager.registerPlaceholder(addon, "visited_island_blocks_to_next_phase",
+ this::getNextPhaseBlocksByLocation);
+ placeholdersManager.registerPlaceholder(addon, "my_island_percent_done", this::getPercentDone);
+ placeholdersManager.registerPlaceholder(addon, "visited_island_percent_done", this::getPercentDoneByLocation);
+ placeholdersManager.registerPlaceholder(addon, "my_island_done_scale", this::getDoneScale);
+ placeholdersManager.registerPlaceholder(addon, "visited_island_done_scale", this::getDoneScaleByLocation);
+ // Since 1.10
+ placeholdersManager.registerPlaceholder(addon, "visited_island_lifetime_count", this::getLifetimeByLocation);
+ placeholdersManager.registerPlaceholder(addon, "my_island_lifetime_count", this::getLifetime);
}
/**
diff --git a/src/main/java/world/bentobox/aoneblock/Settings.java b/src/main/java/world/bentobox/aoneblock/Settings.java
index 24a6ba3b..709f26b8 100644
--- a/src/main/java/world/bentobox/aoneblock/Settings.java
+++ b/src/main/java/world/bentobox/aoneblock/Settings.java
@@ -8,6 +8,7 @@
import java.util.Map;
import java.util.Set;
+import org.bukkit.Color;
import org.bukkit.Difficulty;
import org.bukkit.GameMode;
import org.bukkit.block.Biome;
@@ -111,6 +112,28 @@ public class Settings implements WorldSettings {
@ConfigEntry(path = "world.hologram-duration")
private int hologramDuration = 10;
+ @ConfigComment("Duration in seconds that players cannot move when they start a new one block.")
+ @ConfigComment("Used only if the Starting Safety world setting is active.")
+ @ConfigEntry(path = "world.starting-safety-duration")
+ private int startingSafetyDuration = 10;
+
+ @ConfigComment("Block identification appearance.")
+ @ConfigComment("Click type that will make particles appear. Options are:")
+ @ConfigComment("LEFT (default), RIGHT, or NONE")
+ @ConfigEntry(path = "world.block-id.click-type")
+ private String clickType = "LEFT";
+
+ @ConfigComment("Size of particles. Default is 0.5. Must be greater than 0.")
+ @ConfigEntry(path = "world.block-id.particle-size")
+ private Double particleSize = 0.5;
+ @ConfigComment("Density of particles - Value from 0.1 to 1. Default is 0.65. Smaller values are more dense, higher are less.")
+ @ConfigEntry(path = "world.block-id.particle-density")
+ private Double particleDensity = 0.65D;
+ @ConfigComment("Color of particles")
+ @ConfigEntry(path = "world.block-id.particle-color")
+ private Color particleColor = Color.GREEN;
+
+
@ConfigComment("Clear blocks when spawning mobs.")
@ConfigComment("Mobs break blocks when they spawn is to prevent players from building a box around the magic block,")
@ConfigComment("having the mob spawn, and then die by suffocation, i.e., it's a cheat prevention.")
@@ -2061,4 +2084,96 @@ public boolean isClearBlocks() {
public void setClearBlocks(boolean clearBlocks) {
this.clearBlocks = clearBlocks;
}
+
+ /**
+ * @return the startingSafetyDuration
+ */
+ public int getStartingSafetyDuration() {
+ return startingSafetyDuration;
+ }
+
+ /**
+ * @param startingSafetyDuration the startingSafetyDuration to set
+ */
+ public void setStartingSafetyDuration(int startingSafetyDuration) {
+ this.startingSafetyDuration = startingSafetyDuration;
+ }
+
+ /**
+ * @return the particleSize
+ */
+ public Double getParticleSize() {
+ if (particleSize == null) {
+ particleSize = 0.8;
+ }
+ if (particleSize < 0.0) {
+ particleSize = 0.0;
+ }
+ return particleSize;
+ }
+
+
+ /**
+ * @param particleSize the particleSize to set
+ */
+ public void setParticleSize(Double particleSize) {
+ this.particleSize = particleSize;
+ }
+
+ /**
+ * @return the particleColor
+ */
+ public Color getParticleColor() {
+ if (particleColor == null) {
+ particleColor = Color.GREEN;
+ }
+ return particleColor;
+ }
+
+ /**
+ * @param particleColor the particleColor to set
+ */
+ public void setParticleColor(Color particleColor) {
+ this.particleColor = particleColor;
+ }
+
+ /**
+ * @return the particleDensity
+ */
+ public Double getParticleDensity() {
+ if (particleDensity == null) {
+ particleDensity = 0.5;
+ }
+ if (particleDensity < 0.1D) {
+ particleDensity = 0.1D;
+ }
+ if (particleDensity > 1D) {
+ particleDensity = 1D;
+ }
+ return particleDensity;
+ }
+
+ /**
+ * @param particleDensity the particleDensity to set
+ */
+ public void setParticleDensity(Double particleDensity) {
+ this.particleDensity = particleDensity;
+ }
+
+ /**
+ * @return the clickType
+ */
+ public String getClickType() {
+ if (clickType == null || (!clickType.equalsIgnoreCase("LEFT") && !clickType.equalsIgnoreCase("RIGHT")
+ && !clickType.equalsIgnoreCase("NONE"))) {
+ clickType = "LEFT";
+ }
+ return clickType;
+ }
+ /**
+ * @param clickType the clickType to set
+ */
+ public void setClickType(String clickType) {
+ this.clickType = clickType;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/aoneblock/commands/island/IslandRespawnBlockCommand.java b/src/main/java/world/bentobox/aoneblock/commands/island/IslandRespawnBlockCommand.java
index 57b778d5..27ae4ae6 100644
--- a/src/main/java/world/bentobox/aoneblock/commands/island/IslandRespawnBlockCommand.java
+++ b/src/main/java/world/bentobox/aoneblock/commands/island/IslandRespawnBlockCommand.java
@@ -3,12 +3,12 @@
import java.util.List;
import org.bukkit.Bukkit;
-import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.util.Vector;
+import world.bentobox.aoneblock.listeners.BlockProtect;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
@@ -20,6 +20,7 @@
*/
public class IslandRespawnBlockCommand extends CompositeCommand
{
+
/**
* Instantiates a new Island respawn block command.
*
@@ -83,32 +84,14 @@ else if (Material.BEDROCK.equals(island.getCenter().getBlock().getType()) ||
}
else
{
- // Spawn 6 particles where block is located.
- island.getWorld().spawnParticle(Particle.REDSTONE,
- island.getCenter().add(new Vector(0.5, 1.0, 0.5)),
- 5, 0.1, 0, 0.1, 1,
- new Particle.DustOptions(Color.fromBGR(0, 100, 0), 1));
- island.getWorld().spawnParticle(Particle.REDSTONE,
- island.getCenter().add(new Vector(1.0, 0.5, 0.5)),
- 5, 0.1, 0, 0.1, 1,
- new Particle.DustOptions(Color.fromBGR(0, 100, 0), 1));
- island.getWorld().spawnParticle(Particle.REDSTONE,
- island.getCenter().add(new Vector(0.5, 0.5, 1.0)),
- 5, 0.1, 0, 0.1, 1,
- new Particle.DustOptions(Color.fromBGR(0, 100, 0), 1));
- island.getWorld().spawnParticle(Particle.REDSTONE,
- island.getCenter().add(new Vector(0.5, 0.0, 0.5)),
- 5, 0.1, 0, 0.1, 1,
- new Particle.DustOptions(Color.fromBGR(0, 100, 0), 1));
- island.getWorld().spawnParticle(Particle.REDSTONE,
- island.getCenter().add(new Vector(0.0, 0.5, 0.5)),
- 5, 0.1, 0, 0.1, 1,
- new Particle.DustOptions(Color.fromBGR(0, 100, 0), 1));
- island.getWorld().spawnParticle(Particle.REDSTONE,
- island.getCenter().add(new Vector(0.5, 0.5, 0.0)),
- 5, 0.1, 0, 0.1, 1,
- new Particle.DustOptions(Color.fromBGR(0, 100, 0), 1));
-
+ for (double x = 0.0; x <= 1.0; x += 0.5) {
+ for (double y = 0.0; y <= 1.0; y += 0.5) {
+ for (double z = 0.0; z < 1.0; z += 0.5) {
+ island.getWorld().spawnParticle(Particle.REDSTONE, island.getCenter().add(new Vector(x, y, z)),
+ 5, 0.1, 0, 0.1, 1, new Particle.DustOptions(BlockProtect.GREEN, 1));
+ }
+ }
+ }
user.sendMessage("aoneblock.commands.respawn-block.block-exist");
}
diff --git a/src/main/java/world/bentobox/aoneblock/listeners/BlockProtect.java b/src/main/java/world/bentobox/aoneblock/listeners/BlockProtect.java
index 08486d44..e0d994e2 100644
--- a/src/main/java/world/bentobox/aoneblock/listeners/BlockProtect.java
+++ b/src/main/java/world/bentobox/aoneblock/listeners/BlockProtect.java
@@ -1,5 +1,8 @@
package world.bentobox.aoneblock.listeners;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import org.bukkit.Color;
@@ -11,12 +14,13 @@
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
-import org.bukkit.event.block.BlockDamageEvent;
+import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.util.Vector;
import world.bentobox.aoneblock.AOneBlock;
@@ -24,6 +28,10 @@
public class BlockProtect implements Listener {
+ public static final Color GREEN = Color.fromBGR(0, 100, 0);
+ private static final List PARTICLES = new ArrayList<>(List.of(Particle.REDSTONE));
+ private Iterator particleIterator = Collections.emptyIterator();
+
private final AOneBlock addon;
/**
@@ -38,14 +46,40 @@ public BlockProtect(AOneBlock addon) {
* @param e - event
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
- public void onBlockDamage(BlockDamageEvent e) {
- if (!addon.inWorld(e.getBlock().getWorld())) {
+ public void onBlockDamage(PlayerInteractEvent e) {
+ Action action = e.getAction();
+ String clickType = addon.getSettings().getClickType();
+
+ if (clickType.equalsIgnoreCase("NONE") || !addon.inWorld(e.getPlayer().getWorld())
+ || e.getClickedBlock() == null) {
return;
}
- Block block = e.getBlock();
- Location l = block.getLocation();
- addon.getIslands().getIslandAt(l).filter(i -> l.equals(i.getCenter())).ifPresent(i ->
- block.getWorld().spawnParticle(Particle.REDSTONE, l.add(new Vector(0.5, 1.0, 0.5)), 5, 0.1, 0, 0.1, 1, new Particle.DustOptions(Color.fromBGR(0,100,0), 1)));
+
+ if ((action == Action.LEFT_CLICK_BLOCK && clickType.equalsIgnoreCase("LEFT"))
+ || (action == Action.RIGHT_CLICK_BLOCK && clickType.equalsIgnoreCase("RIGHT"))) {
+
+ Location l = e.getClickedBlock().getLocation();
+ addon.getIslands().getIslandAt(l).map(Island::getCenter).filter(center -> center.equals(l))
+ .ifPresent(this::showSparkles);
+ }
+ }
+
+ public void showSparkles(Location location) {
+ if (!particleIterator.hasNext()) {
+ Collections.shuffle(PARTICLES);
+ particleIterator = PARTICLES.iterator();
+ }
+ Particle p = particleIterator.next();
+ for (double x = -0.5; x <= 1.5; x += addon.getSettings().getParticleDensity()) {
+ for (double y = 0.0; y <= 1.5; y += addon.getSettings().getParticleDensity()) {
+ for (double z = -0.5; z < 1.5; z += addon.getSettings().getParticleDensity()) {
+ location.getWorld().spawnParticle(p, location.clone().add(new Vector(x, y, z)), 5,
+ 0.1, 0, 0.1, 1, new Particle.DustOptions(addon.getSettings().getParticleColor(),
+ addon.getSettings().getParticleSize().floatValue()));
+
+ }
+ }
+ }
}
/**
diff --git a/src/main/java/world/bentobox/aoneblock/listeners/StartSafetyListener.java b/src/main/java/world/bentobox/aoneblock/listeners/StartSafetyListener.java
new file mode 100644
index 00000000..fa752a68
--- /dev/null
+++ b/src/main/java/world/bentobox/aoneblock/listeners/StartSafetyListener.java
@@ -0,0 +1,74 @@
+package world.bentobox.aoneblock.listeners;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerMoveEvent;
+
+import world.bentobox.aoneblock.AOneBlock;
+import world.bentobox.bentobox.api.events.island.IslandCreatedEvent;
+import world.bentobox.bentobox.api.events.island.IslandResetEvent;
+import world.bentobox.bentobox.api.localization.TextVariables;
+import world.bentobox.bentobox.api.user.User;
+
+/**
+ * Listener to provide protection for players in the first minute of their island. Prevents movement.
+ */
+public class StartSafetyListener implements Listener {
+
+ private final AOneBlock addon;
+ private final Map newIslands = new HashMap<>();
+
+ public StartSafetyListener(AOneBlock addon) {
+ super();
+ this.addon = addon;
+ }
+
+ @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
+ public void onNewIsland(IslandCreatedEvent e) {
+ store(e.getIsland().getWorld(), e.getPlayerUUID());
+ }
+
+ private void store(World world, UUID playerUUID) {
+ if (addon.inWorld(world) && addon.START_SAFETY.isSetForWorld(world) && !newIslands.containsKey(playerUUID)) {
+ long time = addon.getSettings().getStartingSafetyDuration();
+ if (time < 0) {
+ time = 10; // 10 seconds
+ }
+ newIslands.put(playerUUID, System.currentTimeMillis() + (time * 1000));
+ Bukkit.getScheduler().runTaskLater(addon.getPlugin(), () -> {
+ newIslands.remove(playerUUID);
+ User.getInstance(playerUUID).sendMessage("protection.flags.START_SAFETY.free-to-move");
+ }, time);
+ }
+
+ }
+
+ @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
+ public void onResetIsland(IslandResetEvent e) {
+ store(e.getIsland().getWorld(), e.getPlayerUUID());
+ }
+
+ @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
+ public void onPlayerMove(PlayerMoveEvent e) {
+ if (addon.inWorld(e.getPlayer().getWorld()) && newIslands.containsKey(e.getPlayer().getUniqueId())
+ && e.getTo() != null && !e.getPlayer().isSneaking()
+ && (e.getFrom().getX() != e.getTo().getX() || e.getFrom().getZ() != e.getTo().getZ())) {
+ // Do not allow x or z movement
+ e.setTo(new Location(e.getFrom().getWorld(), e.getFrom().getX(), e.getTo().getY(), e.getFrom().getZ(),
+ e.getTo().getYaw(), e.getTo().getPitch()));
+ String waitTime = String
+ .valueOf((int) ((newIslands.get(e.getPlayer().getUniqueId()) - System.currentTimeMillis()) / 1000));
+ User.getInstance(e.getPlayer()).notify(addon.START_SAFETY.getHintReference(), TextVariables.NUMBER,
+ waitTime);
+ }
+ }
+
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 39ef256d..2db2ff43 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -33,7 +33,7 @@ aoneblock:
set-count-command: setCount
# How long a player must wait until they can use the setCount command again. In minutes.
# This is the command that is run from the phases panel.
- # Added since 1.13.0
+ # Added since 1.13.0.
set-count-cooldown: 5
# The command label that allows to check if magic block is present and respawns it if not.
# By default it is 'respawnBlock check'.
@@ -58,11 +58,29 @@ world:
# Duration in seconds that phase holograms will exist after being displayed, if used.
# If set to 0, then holograms will persist until cleared some other way.
hologram-duration: 10
+ # Duration in seconds that players cannot move when they start a new one block.
+ # Used only if the Starting Safety world setting is active.
+ starting-safety-duration: 10
+ block-id:
+ # Block identification appearance.
+ # Click type that will make particles appear. Options are:
+ # LEFT (default), RIGHT, or NONE
+ click-type: RIGHT
+ # Size of particles. Default is 0.7. Must be greater than 0.
+ particle-size: 0.5
+ # Density of particles - Value from 0.1 to 1. Default is 0.5. Smaller values are more dense, higher are less.
+ particle-density: 0.65
+ # Color of particles
+ particle-color:
+ ==: Color
+ ALPHA: 255
+ RED: 0
+ BLUE: 0
+ GREEN: 128
# Clear blocks when spawning mobs.
# Mobs break blocks when they spawn is to prevent players from building a box around the magic block,
# having the mob spawn, and then die by suffocation, i.e., it's a cheat prevention.
- clear-blocks: true
-
+ mobs-clear-blocks: true
spawn-limits:
# Spawn limits. These override the limits set in bukkit.yml
# If set to a negative number, the server defaults will be used
@@ -174,34 +192,37 @@ world:
# Mob white list - these mobs will NOT be removed when logging in or doing /island
remove-mobs-whitelist:
- ENDERMAN
- - WITHER
- ZOMBIE_VILLAGER
+ - WITHER
# World flags. These are boolean settings for various flags for this world
flags:
CREEPER_DAMAGE: true
OBSIDIAN_SCOOPING: true
- PISTON_PUSH: false
ISLAND_RESPAWN: true
CREEPER_GRIEFING: false
VISITOR_KEEP_INVENTORY: false
+ PETS_STAY_AT_HOME: true
+ NATURAL_SPAWNING_OUTSIDE_RANGE: true
+ LIQUIDS_FLOWING_OUT: false
+ REMOVE_MOBS: true
+ ENDER_CHEST: false
+ TREES_GROWING_OUTSIDE_RANGE: false
+ WITHER_DAMAGE: false
+ PISTON_PUSH: false
COARSE_DIRT_TILLING: true
ENDERMAN_GRIEFING: true
CLEAN_SUPER_FLAT: false
CHEST_DAMAGE: false
PREVENT_TELEPORT_WHEN_FALLING: false
- NATURAL_SPAWNING_OUTSIDE_RANGE: true
+ START_SAFETY: false
ENTER_EXIT_MESSAGES: true
+ ALLOW_MOVE_BOX: true
ENDERMAN_DEATH_DROP: true
- LIQUIDS_FLOWING_OUT: false
OFFLINE_REDSTONE: true
REMOVE_END_EXIT_ISLAND: true
OFFLINE_GROWTH: true
- REMOVE_MOBS: true
- ENDER_CHEST: false
ITEM_FRAME_DAMAGE: false
- TREES_GROWING_OUTSIDE_RANGE: false
SPAWNER_SPAWN_EGGS: true
- WITHER_DAMAGE: false
# These are the default protection settings for new islands.
# The value is the minimum island rank required allowed to do the action
# Ranks are the following:
@@ -213,6 +234,7 @@ world:
# OWNER = 1000
default-island-flags:
HURT_ANIMALS: 500
+ LOOM: 500
DRAGON_EGG: 500
REDSTONE: 500
BUCKET: 500
@@ -228,6 +250,8 @@ world:
END_PORTAL: 500
BREEDING: 500
HURT_VILLAGERS: 500
+ BOOKSHELF: 500
+ HARVEST: 500
FROST_WALKER: 500
TURTLE_EGGS: 500
COLLECT_LAVA: 500
@@ -240,6 +264,7 @@ world:
NAME_TAG: 500
ARMOR_STAND: 500
CHANGE_SETTINGS: 1000
+ SIGN_EDITING: 500
TRADING: 0
EGGS: 500
ITEM_DROP: 0
@@ -250,15 +275,19 @@ world:
SCULK_SENSOR: 500
LECTERN: 500
SHULKER_BOX: 500
+ GRINDSTONE: 500
ITEM_PICKUP: 0
CROP_TRAMPLE: 500
DROPPER: 500
BREWING: 500
+ MOVE_BOX: 1000
TNT_PRIMING: 500
+ PARKOUR_CREATIVE: 500
COLLECT_WATER: 500
AXOLOTL_SCOOPING: 500
BUTTON: 500
COMPOSTER: 500
+ STONECUTTING: 500
FIRE_EXTINGUISH: 500
COMMAND_RANKS: 500
BEACON: 500
@@ -270,6 +299,7 @@ world:
HIVE: 500
ITEM_FRAME: 500
PLACE_BLOCKS: 500
+ CROP_PLANTING: 500
CRAFTING: 0
SHEARING: 500
ENCHANTING: 0
@@ -281,6 +311,7 @@ world:
DISPENSER: 500
SCULK_SHRIEKER: 500
GATE: 0
+ SMITHING: 500
EXPERIENCE_PICKUP: 500
HOPPER: 500
LEASH: 500
@@ -292,13 +323,16 @@ world:
POTION_THROWING: 500
BARREL: 500
COLLECT_POWDERED_SNOW: 500
+ CARTOGRAPHY: 500
# These are the default settings for new islands
default-island-settings:
PVP_END: false
PVP_NETHER: false
LEAF_DECAY: true
+ ENDERMAN_TELEPORT: true
ANIMAL_NATURAL_SPAWN: true
MONSTER_NATURAL_SPAWN: true
+ SHULKER_TELEPORT: true
FIRE_SPREAD: true
FIRE_BURNING: true
PVP_OVERWORLD: false
@@ -548,4 +582,3 @@ protection:
do-not-edit-these-settings:
# These settings should not be edited
reset-epoch: 0
-
diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml
index 1d59b20e..285b4f06 100755
--- a/src/main/resources/locales/en-US.yml
+++ b/src/main/resources/locales/en-US.yml
@@ -3,6 +3,17 @@
# the one at http://yaml-online-parser.appspot.com #
###########################################################################################
+protection:
+ flags:
+ START_SAFETY:
+ name: Starting Safety
+ description: |
+ &b Prevents new players
+ &b from moving for 1 minute
+ &b so they don't fall off.
+ hint: "&c Movement blocked for safety for [number] more seconds!"
+ free-to-move: "&a You are free to move. Be careful!"
+
aoneblock:
commands:
admin:
@@ -29,7 +40,7 @@ aoneblock:
description: show the block count and phase
info: "&a You are on block &b [number] in the &a [name] phase"
info:
- count: "&a Island is on block &b [number]&a in the &b [name] &a phase. Lifetime count &b [lifetime] &a."
+ count: "&a Island is on block &b [number] &a in the &b [name] &a phase. Lifetime count &b [lifetime] &a."
phases:
description: show a list of all the phases
title: "&2 OneBlock Phases"
diff --git a/src/main/resources/panels/phases_panel.yml b/src/main/resources/panels/phases_panel.yml
index fabdab41..1255c678 100644
--- a/src/main/resources/panels/phases_panel.yml
+++ b/src/main/resources/panels/phases_panel.yml
@@ -19,7 +19,7 @@ phases_panel:
8: phase_button
3:
1:
- icon: TIPPED_ARROW:INSTANT_HEAL::::1
+ icon: tipped_arrow{CustomPotionColor:11546150}
title: aoneblock.gui.buttons.previous.name
description: aoneblock.gui.buttons.previous.description
data:
@@ -37,7 +37,7 @@ phases_panel:
7: phase_button
8: phase_button
9:
- icon: TIPPED_ARROW:JUMP::::1
+ icon: tipped_arrow{CustomPotionColor:8439583}
title: aoneblock.gui.buttons.next.name
description: aoneblock.gui.buttons.next.description
data:
diff --git a/src/test/java/world/bentobox/aoneblock/PlaceholdersManagerTest.java b/src/test/java/world/bentobox/aoneblock/PlaceholdersManagerTest.java
index 8548175a..d6116b24 100644
--- a/src/test/java/world/bentobox/aoneblock/PlaceholdersManagerTest.java
+++ b/src/test/java/world/bentobox/aoneblock/PlaceholdersManagerTest.java
@@ -22,6 +22,7 @@
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.IslandsManager;
+import world.bentobox.bentobox.managers.PlaceholdersManager;
/**
* @author tastybento
@@ -36,7 +37,7 @@ public class PlaceholdersManagerTest {
private UUID uuid = UUID.randomUUID();
- private PlaceholdersManager pm;
+ private AOneBlockPlaceholders pm;
@Mock
private IslandsManager im;
@Mock
@@ -49,6 +50,8 @@ public class PlaceholdersManagerTest {
@Mock
private OneBlocksManager obm;
private Settings settings;
+ @Mock
+ private PlaceholdersManager phm;
/**
* @throws java.lang.Exception
@@ -76,11 +79,11 @@ public void setUp() throws Exception {
settings = new Settings();
when(addon.getSettings()).thenReturn(settings);
- pm = new PlaceholdersManager(addon);
+ pm = new AOneBlockPlaceholders(addon, phm);
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getPhaseByLocation(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getPhaseByLocation(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetPhaseByLocation() {
@@ -93,7 +96,7 @@ public void testGetPhaseByLocation() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getCountByLocation(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getCountByLocation(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetCountByLocation() {
@@ -106,7 +109,7 @@ public void testGetCountByLocation() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getPhase(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getPhase(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetPhase() {
@@ -119,7 +122,7 @@ public void testGetPhase() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getCount(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getCount(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetCount() {
@@ -132,7 +135,7 @@ public void testGetCount() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getNextPhaseByLocation(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getNextPhaseByLocation(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetNextPhaseByLocation() {
@@ -145,7 +148,7 @@ public void testGetNextPhaseByLocation() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getNextPhase(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getNextPhase(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetNextPhase() {
@@ -158,7 +161,7 @@ public void testGetNextPhase() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getNextPhaseBlocksByLocation(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getNextPhaseBlocksByLocation(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetNextPhaseBlocksByLocation() {
@@ -173,7 +176,7 @@ public void testGetNextPhaseBlocksByLocation() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getNextPhaseBlocks(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getNextPhaseBlocks(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetNextPhaseBlocks() {
@@ -188,7 +191,7 @@ public void testGetNextPhaseBlocks() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getPercentDoneByLocation(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getPercentDoneByLocation(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetPercentDoneByLocation() {
@@ -201,7 +204,7 @@ public void testGetPercentDoneByLocation() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getPercentDone(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getPercentDone(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetPercentDone() {
@@ -214,7 +217,7 @@ public void testGetPercentDone() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getDoneScaleByLocation(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getDoneScaleByLocation(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetDoneScaleByLocation() {
@@ -227,7 +230,7 @@ public void testGetDoneScaleByLocation() {
}
/**
- * Test method for {@link world.bentobox.aoneblock.PlaceholdersManager#getDoneScale(world.bentobox.bentobox.api.user.User)}.
+ * Test method for {@link world.bentobox.aoneblock.AOneBlockPlaceholders#getDoneScale(world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testGetDoneScale() {
diff --git a/src/test/java/world/bentobox/aoneblock/listeners/BlockProtectTest.java b/src/test/java/world/bentobox/aoneblock/listeners/BlockProtectTest.java
index 4b4c2e1b..dc8b0082 100644
--- a/src/test/java/world/bentobox/aoneblock/listeners/BlockProtectTest.java
+++ b/src/test/java/world/bentobox/aoneblock/listeners/BlockProtectTest.java
@@ -9,6 +9,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -26,12 +27,13 @@
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
-import org.bukkit.event.block.BlockDamageEvent;
+import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.junit.After;
import org.junit.Before;
@@ -41,6 +43,7 @@
import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.aoneblock.AOneBlock;
+import world.bentobox.aoneblock.Settings;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.IslandsManager;
@@ -72,11 +75,14 @@ public class BlockProtectTest {
*/
@Before
public void setUp() throws Exception {
+
+ when(p.getWorld()).thenReturn(world);
// In World
when(addon.inWorld(world)).thenReturn(true);
// Location
when(location.getWorld()).thenReturn(world);
+ when(location.clone()).thenReturn(location);
// Block
when(block.getWorld()).thenReturn(world);
@@ -87,6 +93,9 @@ public void setUp() throws Exception {
when(island.getCenter()).thenReturn(location);
when(im.getIslandAt(any())).thenReturn(Optional.of(island));
+ // Settings
+ Settings settings = new Settings();
+ when(addon.getSettings()).thenReturn(settings);
// Class under test
bp = new BlockProtect(addon);
}
@@ -112,11 +121,12 @@ public void testBlockProtect() {
@Test
public void testOnBlockDamage() {
ItemStack item = new ItemStack(Material.DIAMOND_PICKAXE);
- BlockDamageEvent blockDamageEvent = new BlockDamageEvent(p, block, item, false);
+ PlayerInteractEvent blockDamageEvent = new PlayerInteractEvent(p, Action.LEFT_CLICK_BLOCK, item, block,
+ BlockFace.UP);
bp.onBlockDamage(blockDamageEvent);
verify(addon).inWorld(world);
verify(im).getIslandAt(location);
- verify(world).spawnParticle(eq(Particle.REDSTONE), eq(null), eq(5),
+ verify(world, times(48)).spawnParticle(eq(Particle.REDSTONE), eq(null), eq(5),
eq(0.1D), eq(0D), eq(0.1D), eq(1D), any(Particle.DustOptions.class));
}
@@ -125,9 +135,10 @@ public void testOnBlockDamage() {
*/
@Test
public void testOnBlockDamageWrongWorld() {
- when(block.getWorld()).thenReturn(mock(World.class));
+ when(p.getWorld()).thenReturn(mock(World.class));
ItemStack item = new ItemStack(Material.DIAMOND_PICKAXE);
- BlockDamageEvent blockDamageEvent = new BlockDamageEvent(p, block, item, false);
+ PlayerInteractEvent blockDamageEvent = new PlayerInteractEvent(p, Action.LEFT_CLICK_BLOCK, item, block,
+ BlockFace.UP);
bp.onBlockDamage(blockDamageEvent);
verify(im, never()).getIslandAt(location);
verify(world, never()).spawnParticle(any(Particle.class), any(Location.class),anyInt(),
@@ -141,7 +152,8 @@ public void testOnBlockDamageWrongWorld() {
public void testOnBlockDamageNotCenterMagicBlock() {
when(block.getLocation()).thenReturn(mock(Location.class));
ItemStack item = new ItemStack(Material.DIAMOND_PICKAXE);
- BlockDamageEvent blockDamageEvent = new BlockDamageEvent(p, block, item, false);
+ PlayerInteractEvent blockDamageEvent = new PlayerInteractEvent(p, Action.LEFT_CLICK_BLOCK, item, block,
+ BlockFace.UP);
bp.onBlockDamage(blockDamageEvent);
verify(addon).inWorld(world);
verify(im).getIslandAt(any(Location.class));
diff --git a/src/test/java/world/bentobox/aoneblock/listeners/StartSafetyListenerTest.java b/src/test/java/world/bentobox/aoneblock/listeners/StartSafetyListenerTest.java
new file mode 100644
index 00000000..c3d351d8
--- /dev/null
+++ b/src/test/java/world/bentobox/aoneblock/listeners/StartSafetyListenerTest.java
@@ -0,0 +1,581 @@
+package world.bentobox.aoneblock.listeners;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Difficulty;
+import org.bukkit.GameMode;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.scheduler.BukkitScheduler;
+import org.eclipse.jdt.annotation.NonNull;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import world.bentobox.aoneblock.AOneBlock;
+import world.bentobox.aoneblock.Settings;
+import world.bentobox.bentobox.BentoBox;
+import world.bentobox.bentobox.api.configuration.WorldSettings;
+import world.bentobox.bentobox.api.events.island.IslandCreatedEvent;
+import world.bentobox.bentobox.api.events.island.IslandResetEvent;
+import world.bentobox.bentobox.api.flags.Flag;
+import world.bentobox.bentobox.api.user.Notifier;
+import world.bentobox.bentobox.api.user.User;
+import world.bentobox.bentobox.database.objects.Island;
+import world.bentobox.bentobox.managers.IslandWorldManager;
+import world.bentobox.bentobox.managers.LocalesManager;
+import world.bentobox.bentobox.managers.PlaceholdersManager;
+
+/**
+ * @author tastybento
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ Bukkit.class, BentoBox.class })
+public class StartSafetyListenerTest {
+
+ private AOneBlock addon;
+ private StartSafetyListener ssl;
+ @Mock
+ private Island island;
+ private UUID uuid = UUID.randomUUID();
+ @Mock
+ private Location location;
+ @Mock
+ private Location location2;
+ @Mock
+ private World world;
+ @Mock
+ private BentoBox plugin;
+ @Mock
+ private IslandWorldManager iwm;
+ @Mock
+ private Flag flag;
+
+ private @NonNull WSettings ws = new WSettings();
+ @Mock
+ private BukkitScheduler scheduler;
+ @Mock
+ private Player player;
+ @Mock
+ private LocalesManager lm;
+ @Mock
+ private PlaceholdersManager phm;
+ @Mock
+ private Notifier notifier;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+
+ PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
+ when(Bukkit.getScheduler()).thenReturn(scheduler);
+
+ // Set up plugin
+ Whitebox.setInternalState(BentoBox.class, "instance", plugin);
+
+ addon = new AOneBlock();
+ addon.setIslandWorld(world);
+ addon.setSettings(new Settings());
+
+ // Player
+ when(player.getUniqueId()).thenReturn(uuid);
+ when(player.getWorld()).thenReturn(world);
+ User.getInstance(player);
+
+ when(world.getName()).thenReturn("world");
+
+ when(flag.isSetForWorld(world)).thenReturn(true);
+
+ when(iwm.inWorld(world)).thenReturn(true);
+ when(iwm.getWorldSettings(world)).thenReturn(ws);
+ when(plugin.getIWM()).thenReturn(iwm);
+
+ when(location.getWorld()).thenReturn(world);
+ when(location2.getWorld()).thenReturn(world);
+ when(island.getWorld()).thenReturn(world);
+ when(island.getCenter()).thenReturn(location);
+
+ when(plugin.getNotifier()).thenReturn(notifier);
+
+ // Placeholders
+ when(phm.replacePlaceholders(any(), anyString()))
+ .thenAnswer((Answer) invocation -> invocation.getArgument(1, String.class));
+
+ // BentoBox
+ when(plugin.getLocalesManager()).thenReturn(lm);
+ when(plugin.getPlaceholdersManager()).thenReturn(phm);
+
+ when(location2.getX()).thenReturn(0.5D);
+
+ addon.START_SAFETY.setSetting(world, true);
+
+ ssl = new StartSafetyListener(addon);
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ User.clearUsers();
+ }
+
+ /**
+ * Test method for {@link world.bentobox.aoneblock.listeners.StartSafetyListener#StartSafetyListener(world.bentobox.aoneblock.AOneBlock)}.
+ */
+ @Test
+ public void testStartSafetyListener() {
+ assertNotNull(ssl);
+ }
+
+ /**
+ * Test method for {@link world.bentobox.aoneblock.listeners.StartSafetyListener#onNewIsland(world.bentobox.bentobox.api.events.island.IslandCreatedEvent)}.
+ */
+ @Test
+ public void testOnNewIsland() {
+ IslandCreatedEvent e = new IslandCreatedEvent(island, uuid, false, location);
+ ssl.onNewIsland(e);
+ verify(scheduler).runTaskLater(eq(plugin), any(Runnable.class), anyLong());
+ }
+
+ /**
+ * Test method for {@link world.bentobox.aoneblock.listeners.StartSafetyListener#onResetIsland(world.bentobox.bentobox.api.events.island.IslandResetEvent)}.
+ */
+ @Test
+ public void testOnResetIsland() {
+ IslandResetEvent e = new IslandResetEvent(island, uuid, false, location, null, island);
+ ssl.onResetIsland(e);
+ verify(scheduler).runTaskLater(eq(plugin), any(Runnable.class), anyLong());
+
+ }
+
+ /**
+ * Test method for {@link world.bentobox.aoneblock.listeners.StartSafetyListener#onPlayerMove(org.bukkit.event.player.PlayerMoveEvent)}.
+ */
+ @Test
+ public void testOnPlayerMove() {
+ testOnResetIsland();
+ PlayerMoveEvent e = new PlayerMoveEvent(player, location, location2);
+ ssl.onPlayerMove(e);
+ // No movement
+ assertEquals(0D, e.getTo().getX(), 0D);
+ assertEquals(0D, e.getTo().getZ(), 0D);
+ verify(player).isSneaking();
+
+ }
+
+ class WSettings implements WorldSettings {
+
+ private Map flags = new HashMap<>();
+
+ @Override
+ public GameMode getDefaultGameMode() {
+
+ return null;
+ }
+
+ @Override
+ public Map getDefaultIslandFlags() {
+
+ return null;
+ }
+
+ @Override
+ public Map getDefaultIslandSettings() {
+
+ return null;
+ }
+
+ @Override
+ public Difficulty getDifficulty() {
+
+ return null;
+ }
+
+ @Override
+ public void setDifficulty(Difficulty difficulty) {
+
+ }
+
+ @Override
+ public String getFriendlyName() {
+
+ return null;
+ }
+
+ @Override
+ public int getIslandDistance() {
+
+ return 0;
+ }
+
+ @Override
+ public int getIslandHeight() {
+
+ return 0;
+ }
+
+ @Override
+ public int getIslandProtectionRange() {
+
+ return 0;
+ }
+
+ @Override
+ public int getIslandStartX() {
+
+ return 0;
+ }
+
+ @Override
+ public int getIslandStartZ() {
+
+ return 0;
+ }
+
+ @Override
+ public int getIslandXOffset() {
+
+ return 0;
+ }
+
+ @Override
+ public int getIslandZOffset() {
+
+ return 0;
+ }
+
+ @Override
+ public List getIvSettings() {
+
+ return null;
+ }
+
+ @Override
+ public int getMaxHomes() {
+
+ return 0;
+ }
+
+ @Override
+ public int getMaxIslands() {
+
+ return 0;
+ }
+
+ @Override
+ public int getMaxTeamSize() {
+
+ return 0;
+ }
+
+ @Override
+ public int getNetherSpawnRadius() {
+
+ return 0;
+ }
+
+ @Override
+ public String getPermissionPrefix() {
+
+ return null;
+ }
+
+ @Override
+ public Set getRemoveMobsWhitelist() {
+
+ return null;
+ }
+
+ @Override
+ public int getSeaHeight() {
+
+ return 0;
+ }
+
+ @Override
+ public List getHiddenFlags() {
+
+ return null;
+ }
+
+ @Override
+ public List getVisitorBannedCommands() {
+
+ return null;
+ }
+
+ @Override
+ public Map getWorldFlags() {
+ return flags;
+ }
+
+ @Override
+ public String getWorldName() {
+
+ return null;
+ }
+
+ @Override
+ public boolean isDragonSpawn() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isEndGenerate() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isEndIslands() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isNetherGenerate() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isNetherIslands() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnJoinResetEnderChest() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnJoinResetInventory() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnJoinResetMoney() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnJoinResetHealth() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnJoinResetHunger() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnJoinResetXP() {
+
+ return false;
+ }
+
+ @Override
+ public @NonNull List getOnJoinCommands() {
+
+ return null;
+ }
+
+ @Override
+ public boolean isOnLeaveResetEnderChest() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnLeaveResetInventory() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnLeaveResetMoney() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnLeaveResetHealth() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnLeaveResetHunger() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isOnLeaveResetXP() {
+
+ return false;
+ }
+
+ @Override
+ public @NonNull List getOnLeaveCommands() {
+
+ return null;
+ }
+
+ @Override
+ public boolean isUseOwnGenerator() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isWaterUnsafe() {
+
+ return false;
+ }
+
+ @Override
+ public List getGeoLimitSettings() {
+
+ return null;
+ }
+
+ @Override
+ public int getResetLimit() {
+
+ return 0;
+ }
+
+ @Override
+ public long getResetEpoch() {
+
+ return 0;
+ }
+
+ @Override
+ public void setResetEpoch(long timestamp) {
+
+ }
+
+ @Override
+ public boolean isTeamJoinDeathReset() {
+
+ return false;
+ }
+
+ @Override
+ public int getDeathsMax() {
+
+ return 0;
+ }
+
+ @Override
+ public boolean isDeathsCounted() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isDeathsResetOnNewIsland() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isAllowSetHomeInNether() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isAllowSetHomeInTheEnd() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isRequireConfirmationToSetHomeInNether() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isRequireConfirmationToSetHomeInTheEnd() {
+
+ return false;
+ }
+
+ @Override
+ public int getBanLimit() {
+
+ return 0;
+ }
+
+ @Override
+ public boolean isLeaversLoseReset() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isKickedKeepInventory() {
+
+ return false;
+ }
+
+ @Override
+ public boolean isCreateIslandOnFirstLoginEnabled() {
+
+ return false;
+ }
+
+ @Override
+ public int getCreateIslandOnFirstLoginDelay() {
+
+ return 0;
+ }
+
+ @Override
+ public boolean isCreateIslandOnFirstLoginAbortOnLogout() {
+
+ return false;
+ }
+
+ }
+
+}