Fixes a number of issues with spawn island setting

https://github.com/BentoBoxWorld/BentoBox/issues/523

Uses safe-spot teleport to teleport players.
The spawn point of an island was not being set by the setspawn command.
The spawn point on the spawn island can now be reset using the setspawn
command.
If the spawn point does not exist, a safe spot will be found.

Added AdminSetspawnCommand test class.
This commit is contained in:
tastybento 2019-02-21 10:46:29 -08:00
parent 8dd1ce10a9
commit 83827da448
4 changed files with 193 additions and 14 deletions

View File

@ -5,6 +5,7 @@ import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.World;
import com.google.common.collect.ImmutableSet;
@ -17,7 +18,7 @@ import world.bentobox.bentobox.database.objects.Island;
/**
* Admin command (only player) to set an island as the world's spawn.
* @author Poslovitch
* @author Poslovitch, tastybento
* @since 1.1
*/
public class AdminSetspawnCommand extends ConfirmableCommand {
@ -40,8 +41,8 @@ public class AdminSetspawnCommand extends ConfirmableCommand {
if (island.isPresent()) {
// Check if the island is already a spawn
if (island.map(Island::isSpawn).orElse(false)) {
// Show warning, but allow it because the position may change
user.sendMessage("commands.admin.setspawn.already-spawn");
return false;
}
// Everything's fine, we can set the island as spawn :)
@ -73,6 +74,7 @@ public class AdminSetspawnCommand extends ConfirmableCommand {
});
}
getIslands().setSpawn(i);
i.setSpawnPoint(World.Environment.NORMAL, user.getLocation());
user.sendMessage("general.success");
}

View File

@ -800,6 +800,7 @@ public class Island implements DataObject {
* @param islandType - island type
* @return - location or null if one does not exist
*/
@Nullable
public Location getSpawnPoint(Environment islandType) {
return spawnPoint.get(islandType);
}
@ -830,7 +831,7 @@ public class Island implements DataObject {
/**
* Sets the history of the island.
* @param history the list of {@link LogEntry} to se for this island.
* @param history the list of {@link LogEntry} to set for this island.
*/
public void setHistory(List<LogEntry> history) {
this.history = history;

View File

@ -629,14 +629,14 @@ public class IslandsManager {
*/
public void spawnTeleport(@NonNull World world, @NonNull Player player) {
User user = User.getInstance(player);
Optional<Island> spawnIsland = getSpawn(world);
if (!spawnIsland.isPresent()) {
// If there's no spawn island or the spawn location is null for some reason, then error
Location spawnTo = getSpawn(world).map(i -> i.getSpawnPoint(World.Environment.NORMAL) == null ? i.getCenter() : i.getSpawnPoint(World.Environment.NORMAL))
.orElse(null);
if (spawnTo == null) {
// There is no spawn here.
user.sendMessage("commands.island.spawn.no-spawn");
} else {
// Teleport the player to the spawn
// Stop any gliding
player.setGliding(false);
// Check if the player is a passenger in a boat
@ -652,12 +652,8 @@ public class IslandsManager {
}
user.sendMessage("commands.island.spawn.teleporting");
player.teleport(spawnIsland.get().getSpawnPoint(World.Environment.NORMAL));
// If the player is in SPECTATOR gamemode, reset it to default
if (player.getGameMode().equals(GameMode.SPECTATOR)) {
player.setGameMode(plugin.getIWM().getDefaultGameMode(world));
}
// Safe teleport
new SafeSpotTeleport.Builder(plugin).entity(player).location(spawnTo).build();
}
}

View File

@ -0,0 +1,180 @@
/**
*
*/
package world.bentobox.bentobox.api.commands.admin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.HashMap;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.plugin.PluginManager;
import org.bukkit.scheduler.BukkitScheduler;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
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.bentobox.BentoBox;
import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.LocalesManager;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, BentoBox.class, User.class })
public class AdminSetspawnCommandTest {
private CompositeCommand ac;
private UUID uuid;
private User user;
private IslandsManager im;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
// Set up plugin
BentoBox plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// Command manager
CommandsManager cm = mock(CommandsManager.class);
when(plugin.getCommandsManager()).thenReturn(cm);
// Player
Player p = mock(Player.class);
// Sometimes use Mockito.withSettings().verboseLogging()
user = mock(User.class);
when(user.isOp()).thenReturn(false);
uuid = UUID.randomUUID();
when(user.getUniqueId()).thenReturn(uuid);
when(user.getPlayer()).thenReturn(p);
when(user.getName()).thenReturn("tastybento");
User.setPlugin(plugin);
// Parent command has no aliases
ac = mock(CompositeCommand.class);
when(ac.getSubCommandAliases()).thenReturn(new HashMap<>());
when(ac.getPermissionPrefix()).thenReturn("bskyblock.");
// Island World Manager
IslandWorldManager iwm = mock(IslandWorldManager.class);
when(plugin.getIWM()).thenReturn(iwm);
// Player has island to begin with
im = mock(IslandsManager.class);
when(im.hasIsland(Mockito.any(), Mockito.any(UUID.class))).thenReturn(true);
when(im.hasIsland(Mockito.any(), Mockito.any(User.class))).thenReturn(true);
when(im.isOwner(Mockito.any(),Mockito.any())).thenReturn(true);
when(im.getOwner(Mockito.any(),Mockito.any())).thenReturn(uuid);
when(plugin.getIslands()).thenReturn(im);
// Server & Scheduler
BukkitScheduler sch = mock(BukkitScheduler.class);
PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getScheduler()).thenReturn(sch);
// Locales
LocalesManager lm = mock(LocalesManager.class);
when(lm.get(Mockito.any(), Mockito.any())).thenReturn("mock translation");
when(plugin.getLocalesManager()).thenReturn(lm);
// Return the reference (USE THIS IN THE FUTURE)
when(user.getTranslation(Mockito.anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgumentAt(0, String.class));
// Plugin Manager
Server server = mock(Server.class);
PluginManager pim = mock(PluginManager.class);
when(server.getPluginManager()).thenReturn(pim);
when(Bukkit.getServer()).thenReturn(server);
// Confirmable command settings
Settings settings = mock(Settings.class);
when(settings.getConfirmationTime()).thenReturn(10);
when(plugin.getSettings()).thenReturn(settings);
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSetspawnCommand#AdminSetspawnCommand(world.bentobox.bentobox.api.commands.CompositeCommand)}.
*/
@Test
public void testAdminSetspawnCommand() {
AdminSetspawnCommand c = new AdminSetspawnCommand(ac);
assertEquals("setspawn", c.getLabel());
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSetspawnCommand#setup()}.
*/
@Test
public void testSetup() {
AdminSetspawnCommand c = new AdminSetspawnCommand(ac);
assertEquals("bskyblock.admin.setspawn", c.getPermission());
assertTrue(c.isOnlyPlayer());
assertEquals("commands.admin.setspawn.description", c.getDescription());
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSetspawnCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testExecuteUserStringListOfString() {
Island island = mock(Island.class);
Optional<Island> oi = Optional.of(island);
when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi);
AdminSetspawnCommand c = new AdminSetspawnCommand(ac);
assertTrue(c.execute(user, "setspawn", Collections.emptyList()));
Mockito.verify(user).getTranslation("commands.admin.setspawn.confirmation");
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSetspawnCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testExecuteUserStringListOfStringNoIsland() {
when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(Optional.empty());
AdminSetspawnCommand c = new AdminSetspawnCommand(ac);
assertFalse(c.execute(user, "setspawn", Collections.emptyList()));
Mockito.verify(user).sendMessage("commands.admin.setspawn.no-island-here");
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSetspawnCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testExecuteUserStringListOfStringAlreadySpawn() {
Island island = mock(Island.class);
when(island.isSpawn()).thenReturn(true);
Optional<Island> oi = Optional.of(island);
when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oi);
AdminSetspawnCommand c = new AdminSetspawnCommand(ac);
assertFalse(c.execute(user, "setspawn", Collections.emptyList()));
Mockito.verify(user).sendMessage("commands.admin.setspawn.already-spawn");
}
}