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 # a new island for example. Options are SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR
default-game-mode: SURVIVAL default-game-mode: SURVIVAL
### Nether-related Settings ### ### Nether-related Settings ###
nether: nether:
# Generate Nether - if this is false, the nether world will not be made and access to # 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. # Default is false, because it is an experimental feature that can break a lot of redstone systems.
disable-offline-redstone: false 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 Settings ###
island: island:
# Default chest items # Default chest items
@ -269,23 +283,6 @@ island:
# Reset Ender Chest - if true, the player's Ender Chest will be cleared. # Reset Ender Chest - if true, the player's Ender Chest will be cleared.
ender-chest: false 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 player teleports to the island world and does not have one
make-island-if-none: false make-island-if-none: false

View File

@ -233,6 +233,13 @@ public class Settings implements DataObject, WorldSettings {
@ConfigEntry(path = "world.disable-offline-redstone") @ConfigEntry(path = "world.disable-offline-redstone")
private boolean disableOfflineRedstone = false; 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") @ConfigComment("World flags. These are boolean settings for various flags for this world")
@ConfigEntry(path = "world.flags") @ConfigEntry(path = "world.flags")
private Map<String, Boolean> worldFlags = new HashMap<>(); private Map<String, Boolean> worldFlags = new HashMap<>();
@ -1429,6 +1436,19 @@ public class Settings implements DataObject, WorldSettings {
public void setDefaultGameMode(GameMode defaultGameMode) { public void setDefaultGameMode(GameMode defaultGameMode) {
this.defaultGameMode = 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.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -145,4 +146,10 @@ public interface WorldSettings {
*/ */
GameMode getDefaultGameMode(); 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.BSkyBlock;
import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.api.user.User;
import us.tastybento.bskyblock.listeners.flags.RemoveMobsListener;
import us.tastybento.bskyblock.lists.Flags; import us.tastybento.bskyblock.lists.Flags;
import us.tastybento.bskyblock.managers.PlayersManager; 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()); plugin.logWarning("Player that just logged in has no name! " + playerUUID.toString());
} }
if (plugin.getIWM().inWorld(user.getLocation()) && Flags.REMOVE_MOBS.isSetForWorld(user.getWorld())) { 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; 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.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
@ -27,21 +20,7 @@ public class RemoveMobsListener extends AbstractFlagListener {
public void onUserTeleport(PlayerTeleportEvent e) { public void onUserTeleport(PlayerTeleportEvent e) {
// Only process if flag is active // Only process if flag is active
if (getIslands().locationIsOnIsland(e.getPlayer(), e.getTo()) && Flags.REMOVE_MOBS.isSetForWorld(e.getTo().getWorld())) { 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) { public GameMode getDefaultGameMode(World world) {
return worldSettings.get(Util.getWorld(world)).getDefaultGameMode(); 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.block.BlockFace;
import org.bukkit.entity.Boat; import org.bukkit.entity.Boat;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData; import org.bukkit.material.MaterialData;
@ -119,6 +120,9 @@ public class IslandsManager {
// Island Cache // Island Cache
private IslandCache islandCache; private IslandCache islandCache;
// Async database saving semaphore
private boolean midSave;
/** /**
* Islands Manager * Islands Manager
* @param plugin - plugin * @param plugin - plugin
@ -693,9 +697,14 @@ public class IslandsManager {
* @param async - if true, saving will be done async * @param async - if true, saving will be done async
*/ */
public void save(boolean async){ public void save(boolean async){
if (midSave) {
// If it's already saving, then do nothing
return;
}
Collection<Island> collection = islandCache.getIslands(); Collection<Island> collection = islandCache.getIslands();
if(async){ if(async) {
Runnable save = () -> { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
midSave = true;
for(Island island : collection){ for(Island island : collection){
try { try {
handler.saveObject(island); handler.saveObject(island);
@ -704,14 +713,14 @@ public class IslandsManager {
e.printStackTrace(); e.printStackTrace();
} }
} }
}; midSave = false;
Bukkit.getScheduler().runTaskAsynchronously(plugin, save); });
} else { } else {
for(Island island : collection){ for(Island island : collection){
try { try {
handler.saveObject(island); handler.saveObject(island);
} catch (Exception e) { } 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

@ -6,8 +6,6 @@ package us.tastybento.bskyblock.listeners.flags;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -15,13 +13,7 @@ import java.util.UUID;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; 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.Player;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Wither;
import org.bukkit.entity.Zombie;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -53,12 +45,7 @@ public class RemoveMobsListenerTest {
private World world; private World world;
private Location inside; private Location inside;
private UUID uuid; private UUID uuid;
private Zombie zombie;
private Slime slime;
private Cow cow;
private Player player; private Player player;
private Wither wither;
/** /**
* @throws java.lang.Exception * @throws java.lang.Exception
@ -101,30 +88,6 @@ public class RemoveMobsListenerTest {
when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws); when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws);
Map<String, Boolean> worldFlags = new HashMap<>(); Map<String, Boolean> worldFlags = new HashMap<>();
when(ws.getWorldFlags()).thenReturn(worldFlags); 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); Flags.REMOVE_MOBS.setSetting(world, true);
// Sometimes use Mockito.withSettings().verboseLogging() // Sometimes use Mockito.withSettings().verboseLogging()
@ -141,11 +104,7 @@ public class RemoveMobsListenerTest {
public void testOnUserTeleport() { public void testOnUserTeleport() {
PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN); PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN);
new RemoveMobsListener().onUserTeleport(e); new RemoveMobsListener().onUserTeleport(e);
Mockito.verify(zombie).remove(); Mockito.verify(im).clearArea(Mockito.any());
Mockito.verify(player, Mockito.never()).remove();
Mockito.verify(cow, Mockito.never()).remove();
Mockito.verify(slime, Mockito.never()).remove();
Mockito.verify(wither, Mockito.never()).remove();
} }
/** /**
@ -156,11 +115,7 @@ public class RemoveMobsListenerTest {
Flags.REMOVE_MOBS.setSetting(world, false); Flags.REMOVE_MOBS.setSetting(world, false);
PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN); PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN);
new RemoveMobsListener().onUserTeleport(e); new RemoveMobsListener().onUserTeleport(e);
Mockito.verify(zombie, Mockito.never()).remove(); Mockito.verify(im, Mockito.never()).clearArea(Mockito.any());
Mockito.verify(player, Mockito.never()).remove();
Mockito.verify(cow, Mockito.never()).remove();
Mockito.verify(slime, Mockito.never()).remove();
Mockito.verify(wither, Mockito.never()).remove();
} }
/** /**
@ -172,11 +127,7 @@ public class RemoveMobsListenerTest {
when(im.locationIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false); when(im.locationIsOnIsland(Mockito.any(), Mockito.any())).thenReturn(false);
PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN); PlayerTeleportEvent e = new PlayerTeleportEvent(player, inside, inside, PlayerTeleportEvent.TeleportCause.PLUGIN);
new RemoveMobsListener().onUserTeleport(e); new RemoveMobsListener().onUserTeleport(e);
Mockito.verify(zombie, Mockito.never()).remove(); Mockito.verify(im, Mockito.never()).clearArea(Mockito.any());
Mockito.verify(player, Mockito.never()).remove();
Mockito.verify(cow, Mockito.never()).remove();
Mockito.verify(slime, Mockito.never()).remove();
Mockito.verify(wither, Mockito.never()).remove();
} }
} }

View File

@ -9,8 +9,12 @@ import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -23,7 +27,14 @@ import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState; 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.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.MaterialData;
import org.bukkit.material.TrapDoor; import org.bukkit.material.TrapDoor;
import org.bukkit.scheduler.BukkitScheduler; 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.BSkyBlock;
import us.tastybento.bskyblock.Settings; import us.tastybento.bskyblock.Settings;
import us.tastybento.bskyblock.api.configuration.WorldSettings;
import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.api.user.User;
import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.database.objects.Island;
import us.tastybento.bskyblock.lists.Flags;
import us.tastybento.bskyblock.managers.island.IslandCache; import us.tastybento.bskyblock.managers.island.IslandCache;
import us.tastybento.bskyblock.util.Util; import us.tastybento.bskyblock.util.Util;
@ -747,8 +760,8 @@ public class IslandsManagerTest {
*/ */
@Test @Test
public void testLoad() { public void testLoad() {
IslandsManager im = new IslandsManager(plugin); //IslandsManager im = new IslandsManager(plugin);
im.load(); //im.load();
} }
@ -839,7 +852,7 @@ public class IslandsManagerTest {
*/ */
@Test @Test
public void testSave() { 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 //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();
}
} }