Adds white list for remove mobs to settings.

This commit is contained in:
tastybento 2018-06-24 17:57:31 -07:00
parent 8125ec52af
commit eb855edfeb
9 changed files with 164 additions and 111 deletions

View File

@ -135,7 +135,6 @@ world:
# a new island for example. Options are SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR
default-game-mode: SURVIVAL
### Nether-related Settings ###
nether:
# Generate Nether - if this is false, the nether world will not be made and access to
@ -172,6 +171,21 @@ world:
# Default is false, because it is an experimental feature that can break a lot of redstone systems.
disable-offline-redstone: false
# Removing mobs - this kills all monsters in the vicinity. Benefit is that it helps
# players return to their island if the island has been overrun by monsters.
# This setting is toggled in world flags and set by the settings GUI
# Mob white list - these mobs will NOT be removed when logging in or doing /island
remove-mobs-whitelist:
- WITHER
- ENDERMAN
- PIG_ZOMBIE
- ZOMBIE_VILLAGER
# World flags. These are boolean settings for various flags for this world
flags:
ENTER_EXIT_MESSAGES: true
REMOVE_MOBS: true
### Island Settings ###
island:
# Default chest items
@ -269,23 +283,6 @@ island:
# Reset Ender Chest - if true, the player's Ender Chest will be cleared.
ender-chest: false
# Removing mobs - this kills all monsters in the vicinity. Benefit is that it helps
# players return to their island if the island has been overrun by monsters.
# Con is that it kills any mob grinders.
remove-mobs:
# Remove mobs on island when logging in.
on-login: false
# Remove mobs when /island.
on-island: false
# Mob white list - these mobs will NOT be removed when logging in or doing /island
whitelist:
- WITHER
- ENDERMAN
- PIG_ZOMBIE
#- ZOMBIE_VILLAGER (1.10+)
# Make island if player teleports to the island world and does not have one
make-island-if-none: false

View File

@ -233,6 +233,13 @@ public class Settings implements DataObject, WorldSettings {
@ConfigEntry(path = "world.disable-offline-redstone")
private boolean disableOfflineRedstone = false;
@ConfigComment("Removing mobs - this kills all monsters in the vicinity. Benefit is that it helps")
@ConfigComment("players return to their island if the island has been overrun by monsters.")
@ConfigComment("This setting is toggled in world flags and set by the settings GUI.")
@ConfigComment("Mob white list - these mobs will NOT be removed when logging in or doing /island")
@ConfigEntry(path = "world.remove-mobs-whitelist")
private Set<EntityType> removeMobsWhitelist = new HashSet<>();
@ConfigComment("World flags. These are boolean settings for various flags for this world")
@ConfigEntry(path = "world.flags")
private Map<String, Boolean> worldFlags = new HashMap<>();
@ -1429,6 +1436,19 @@ public class Settings implements DataObject, WorldSettings {
public void setDefaultGameMode(GameMode defaultGameMode) {
this.defaultGameMode = defaultGameMode;
}
/**
* @return the removeMobsWhitelist
*/
@Override
public Set<EntityType> getRemoveMobsWhitelist() {
return removeMobsWhitelist;
}
/**
* @param removeMobsWhitelist the removeMobsWhitelist to set
*/
public void setRemoveMobsWhitelist(Set<EntityType> removeMobsWhitelist) {
this.removeMobsWhitelist = removeMobsWhitelist;
}
}

View File

@ -2,6 +2,7 @@ package us.tastybento.bskyblock.api.configuration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.GameMode;
import org.bukkit.entity.EntityType;
@ -145,4 +146,10 @@ public interface WorldSettings {
*/
GameMode getDefaultGameMode();
/**
* Get the set of entity types that should not be removed in this world when a player teleports to their island
* @return set of entity types
*/
Set<EntityType> getRemoveMobsWhitelist();
}

View File

@ -10,7 +10,6 @@ import org.bukkit.event.player.PlayerQuitEvent;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.api.user.User;
import us.tastybento.bskyblock.listeners.flags.RemoveMobsListener;
import us.tastybento.bskyblock.lists.Flags;
import us.tastybento.bskyblock.managers.PlayersManager;
@ -53,7 +52,7 @@ public class JoinLeaveListener implements Listener {
plugin.logWarning("Player that just logged in has no name! " + playerUUID.toString());
}
if (plugin.getIWM().inWorld(user.getLocation()) && Flags.REMOVE_MOBS.isSetForWorld(user.getWorld())) {
RemoveMobsListener.clearArea(user.getLocation());
plugin.getIslands().clearArea(user.getLocation());
}
}
}

View File

@ -3,13 +3,6 @@
*/
package us.tastybento.bskyblock.listeners.flags;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Monster;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerTeleportEvent;
@ -27,21 +20,7 @@ public class RemoveMobsListener extends AbstractFlagListener {
public void onUserTeleport(PlayerTeleportEvent e) {
// Only process if flag is active
if (getIslands().locationIsOnIsland(e.getPlayer(), e.getTo()) && Flags.REMOVE_MOBS.isSetForWorld(e.getTo().getWorld())) {
clearArea(e.getTo());
getIslands().clearArea(e.getTo());
}
}
public static void clearArea(Location loc) {
Set<EntityType> keepers = new HashSet<>();
keepers.add(EntityType.ZOMBIE_VILLAGER);
keepers.add(EntityType.PIG_ZOMBIE);
keepers.add(EntityType.WITHER);
keepers.add(EntityType.ENDERMAN);
keepers.add(EntityType.GHAST);
loc.getWorld().getNearbyEntities(loc, 5D, 5D, 5D).stream()
.filter(en -> (en instanceof Monster))
.filter(en -> !keepers.contains(en.getType()))
.forEach(Entity::remove);
}
}

View File

@ -486,4 +486,13 @@ public class IslandWorldManager {
public GameMode getDefaultGameMode(World world) {
return worldSettings.get(Util.getWorld(world)).getDefaultGameMode();
}
/**
* Get the set of entity types not to remove when player teleports to island
* @param world - world
* @return - set of entity types
*/
public Set<EntityType> getRemoveMobsWhitelist(World world) {
return worldSettings.get(Util.getWorld(world)).getRemoveMobsWhitelist();
}
}

View File

@ -16,6 +16,7 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
@ -119,6 +120,9 @@ public class IslandsManager {
// Island Cache
private IslandCache islandCache;
// Async database saving semaphore
private boolean midSave;
/**
* Islands Manager
* @param plugin - plugin
@ -693,9 +697,14 @@ public class IslandsManager {
* @param async - if true, saving will be done async
*/
public void save(boolean async){
if (midSave) {
// If it's already saving, then do nothing
return;
}
Collection<Island> collection = islandCache.getIslands();
if(async){
Runnable save = () -> {
if(async) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
midSave = true;
for(Island island : collection){
try {
handler.saveObject(island);
@ -704,14 +713,14 @@ public class IslandsManager {
e.printStackTrace();
}
}
};
Bukkit.getScheduler().runTaskAsynchronously(plugin, save);
midSave = false;
});
} else {
for(Island island : collection){
try {
handler.saveObject(island);
} catch (Exception e) {
plugin.logError("Could not save island to datavase when running sync! " + e.getMessage());
plugin.logError("Could not save island to database when running sync! " + e.getMessage());
}
}
}
@ -802,4 +811,15 @@ public class IslandsManager {
}
/**
* Clear an area of mobs as per world rules. Radius is 5 blocks in every direction.
* @param loc - location to clear
*/
public void clearArea(Location loc) {
loc.getWorld().getNearbyEntities(loc, 5D, 5D, 5D).stream()
.filter(en -> (en instanceof Monster))
.filter(en -> !plugin.getIWM().getRemoveMobsWhitelist(loc.getWorld()).contains(en.getType()))
.forEach(Entity::remove);
}
}

View File

@ -1,13 +1,11 @@
/**
*
*
*/
package us.tastybento.bskyblock.listeners.flags;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@ -15,13 +13,7 @@ import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Wither;
import org.bukkit.entity.Zombie;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.junit.Before;
import org.junit.Test;
@ -47,18 +39,13 @@ import us.tastybento.bskyblock.util.Util;
@RunWith(PowerMockRunner.class)
@PrepareForTest({BSkyBlock.class, Util.class })
public class RemoveMobsListenerTest {
private Island island;
private IslandsManager im;
private World world;
private Location inside;
private UUID uuid;
private Zombie zombie;
private Slime slime;
private Cow cow;
private Player player;
private Wither wither;
/**
* @throws java.lang.Exception
@ -68,13 +55,13 @@ public class RemoveMobsListenerTest {
// Set up plugin
BSkyBlock plugin = mock(BSkyBlock.class);
Whitebox.setInternalState(BSkyBlock.class, "instance", plugin);
// World
world = mock(World.class);
// Owner
uuid = UUID.randomUUID();
// Island initialization
island = mock(Island.class);
when(island.getOwner()).thenReturn(uuid);
@ -93,7 +80,7 @@ public class RemoveMobsListenerTest {
PowerMockito.mockStatic(Util.class);
when(Util.getWorld(Mockito.any())).thenReturn(world);
// World Settings
IslandWorldManager iwm = mock(IslandWorldManager.class);
when(plugin.getIWM()).thenReturn(iwm);
@ -101,32 +88,8 @@ public class RemoveMobsListenerTest {
when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws);
Map<String, Boolean> worldFlags = new HashMap<>();
when(ws.getWorldFlags()).thenReturn(worldFlags);
// Monsters and animals
zombie = mock(Zombie.class);
when(zombie.getLocation()).thenReturn(inside);
when(zombie.getType()).thenReturn(EntityType.ZOMBIE);
slime = mock(Slime.class);
when(slime.getLocation()).thenReturn(inside);
when(slime.getType()).thenReturn(EntityType.SLIME);
cow = mock(Cow.class);
when(cow.getLocation()).thenReturn(inside);
when(cow.getType()).thenReturn(EntityType.COW);
wither = mock(Wither.class);
when(wither.getType()).thenReturn(EntityType.WITHER);
Collection<Entity> collection = new ArrayList<>();
collection.add(player);
collection.add(zombie);
collection.add(cow);
collection.add(slime);
collection.add(wither);
when(world
.getNearbyEntities(Mockito.any(Location.class), Mockito.anyDouble(), Mockito.anyDouble(), Mockito.anyDouble()))
.thenReturn(collection);
Flags.REMOVE_MOBS.setSetting(world, true);
// Sometimes use Mockito.withSettings().verboseLogging()
player = mock(Player.class);
UUID uuid = UUID.randomUUID();
@ -141,13 +104,9 @@ public class RemoveMobsListenerTest {
public void testOnUserTeleport() {
PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN);
new RemoveMobsListener().onUserTeleport(e);
Mockito.verify(zombie).remove();
Mockito.verify(player, Mockito.never()).remove();
Mockito.verify(cow, Mockito.never()).remove();
Mockito.verify(slime, Mockito.never()).remove();
Mockito.verify(wither, Mockito.never()).remove();
Mockito.verify(im).clearArea(Mockito.any());
}
/**
* Test method for {@link us.tastybento.bskyblock.listeners.flags.RemoveMobsListener#onUserTeleport(org.bukkit.event.player.PlayerTeleportEvent)}.
*/
@ -156,13 +115,9 @@ public class RemoveMobsListenerTest {
Flags.REMOVE_MOBS.setSetting(world, false);
PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN);
new RemoveMobsListener().onUserTeleport(e);
Mockito.verify(zombie, Mockito.never()).remove();
Mockito.verify(player, Mockito.never()).remove();
Mockito.verify(cow, Mockito.never()).remove();
Mockito.verify(slime, Mockito.never()).remove();
Mockito.verify(wither, Mockito.never()).remove();
Mockito.verify(im, Mockito.never()).clearArea(Mockito.any());
}
/**
* Test method for {@link us.tastybento.bskyblock.listeners.flags.RemoveMobsListener#onUserTeleport(org.bukkit.event.player.PlayerTeleportEvent)}.
*/
@ -172,11 +127,7 @@ public class RemoveMobsListenerTest {
when(im.locationIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false);
PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN);
new RemoveMobsListener().onUserTeleport(e);
Mockito.verify(zombie, Mockito.never()).remove();
Mockito.verify(player, Mockito.never()).remove();
Mockito.verify(cow, Mockito.never()).remove();
Mockito.verify(slime, Mockito.never()).remove();
Mockito.verify(wither, Mockito.never()).remove();
Mockito.verify(im, Mockito.never()).clearArea(Mockito.any());
}
}

View File

@ -9,8 +9,12 @@ import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@ -23,7 +27,14 @@ import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Wither;
import org.bukkit.entity.Zombie;
import org.bukkit.material.MaterialData;
import org.bukkit.material.TrapDoor;
import org.bukkit.scheduler.BukkitScheduler;
@ -43,8 +54,10 @@ import com.google.common.collect.ImmutableSet.Builder;
import us.tastybento.bskyblock.BSkyBlock;
import us.tastybento.bskyblock.Settings;
import us.tastybento.bskyblock.api.configuration.WorldSettings;
import us.tastybento.bskyblock.api.user.User;
import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.lists.Flags;
import us.tastybento.bskyblock.managers.island.IslandCache;
import us.tastybento.bskyblock.util.Util;
@ -747,8 +760,8 @@ public class IslandsManagerTest {
*/
@Test
public void testLoad() {
IslandsManager im = new IslandsManager(plugin);
im.load();
//IslandsManager im = new IslandsManager(plugin);
//im.load();
}
@ -839,7 +852,7 @@ public class IslandsManagerTest {
*/
@Test
public void testSave() {
//fail("Not yet implemented"); // TODO
//fail("Not yet implemented"); // TODO - warning saving stuff will go on the file system
}
/**
@ -882,4 +895,62 @@ public class IslandsManagerTest {
//fail("Not yet implemented"); // TODO
}
/**
* Test method for {@link us.tastybento.bskyblock.managers.IslandsManager#clearArea(Location)}.
*/
@Test
public void testClearArea() {
WorldSettings ws = mock(WorldSettings.class);
when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws);
Map<String, Boolean> worldFlags = new HashMap<>();
when(ws.getWorldFlags()).thenReturn(worldFlags);
Flags.REMOVE_MOBS.setSetting(world, true);
// Default whitelist
Set<EntityType> whitelist = new HashSet<>();
whitelist.add(EntityType.ENDERMAN);
whitelist.add(EntityType.WITHER);
whitelist.add(EntityType.ZOMBIE_VILLAGER);
whitelist.add(EntityType.PIG_ZOMBIE);
when(iwm.getRemoveMobsWhitelist(Mockito.any())).thenReturn(whitelist);
// Monsters and animals
Zombie zombie = mock(Zombie.class);
when(zombie.getLocation()).thenReturn(location);
when(zombie.getType()).thenReturn(EntityType.ZOMBIE);
Slime slime = mock(Slime.class);
when(slime.getLocation()).thenReturn(location);
when(slime.getType()).thenReturn(EntityType.SLIME);
Cow cow = mock(Cow.class);
when(cow.getLocation()).thenReturn(location);
when(cow.getType()).thenReturn(EntityType.COW);
Wither wither = mock(Wither.class);
when(wither.getType()).thenReturn(EntityType.WITHER);
Creeper creeper = mock(Creeper.class);
when(creeper.getType()).thenReturn(EntityType.CREEPER);
Collection<Entity> collection = new ArrayList<>();
collection.add(player);
collection.add(zombie);
collection.add(cow);
collection.add(slime);
collection.add(wither);
collection.add(creeper);
when(world
.getNearbyEntities(Mockito.any(Location.class), Mockito.anyDouble(), Mockito.anyDouble(), Mockito.anyDouble()))
.thenReturn(collection);
IslandsManager im = new IslandsManager(plugin);
im.clearArea(location);
Mockito.verify(zombie).remove();
Mockito.verify(player, Mockito.never()).remove();
Mockito.verify(cow, Mockito.never()).remove();
Mockito.verify(slime, Mockito.never()).remove();
Mockito.verify(wither, Mockito.never()).remove();
Mockito.verify(creeper).remove();
}
}