Added LIMIT_MOBS flag (WORLD_SETTING) (#1155)

It provides a way to prevent selected EntityTypes from spawning at all.
Partially implements https://github.com/BentoBoxWorld/BentoBox/issues/1133
This commit is contained in:
tastybento 2020-02-16 04:12:32 -08:00 committed by GitHub
parent ada1909973
commit 06b5aac36f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 165 additions and 0 deletions

View File

@ -1,5 +1,6 @@
package world.bentobox.bentobox.api.configuration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -313,6 +314,15 @@ public interface WorldSettings extends ConfigObject {
*/
List<String> getGeoLimitSettings();
/**
* Get list of entities that should not spawn in this game mode
* @return list of entities that should NOT spawn
* @since 1.12.0
*/
default List<String> getMobLimitSettings() {
return new ArrayList<>();
}
/**
* @return reset limit for world
*/
@ -440,4 +450,5 @@ public interface WorldSettings extends ConfigObject {
default boolean isTeleportPlayerToIslandUponIslandCreation() {
return true;
}
}

View File

@ -0,0 +1,102 @@
package world.bentobox.bentobox.listeners.flags.clicklisteners;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.EntityType;
import org.bukkit.event.inventory.ClickType;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.util.Util;
/**
* Provide limiting of mob types globally
* @author tastybento
*
*/
public class MobLimitClickListener implements ClickHandler {
/**
* A list of all living entity types, minus some
*/
private final List<EntityType> livingEntityTypes = Arrays.stream(EntityType.values())
.filter(EntityType::isAlive)
.filter(t -> !(t.equals(EntityType.PLAYER) || t.equals(EntityType.GIANT) || t.equals(EntityType.ARMOR_STAND)))
.sorted(Comparator.comparing(EntityType::name))
.collect(Collectors.toList());
@Override
public boolean onClick(Panel panel, User user, ClickType clickType, int slot) {
// Get the world
if (!user.inWorld()) {
user.sendMessage("general.errors.wrong-world");
return true;
}
IslandWorldManager iwm = BentoBox.getInstance().getIWM();
String reqPerm = iwm.getPermissionPrefix(Util.getWorld(user.getWorld())) + "admin.settings.LIMIT_MOBS";
if (!user.hasPermission(reqPerm)) {
user.sendMessage("general.errors.no-permission", "[permission]", reqPerm);
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
return true;
}
String panelName = user.getTranslation("protection.flags.LIMIT_MOBS.name");
if (panel.getName().equals(panelName)) {
// This is a click on the mob limit panel
// Slot relates to the enum
EntityType c = livingEntityTypes.get(slot);
if (iwm.getMobLimitSettings(user.getWorld()).contains(c.name())) {
iwm.getMobLimitSettings(user.getWorld()).remove(c.name());
} else {
iwm.getMobLimitSettings(user.getWorld()).add(c.name());
}
// Apply change to panel
panel.getInventory().setItem(slot, getPanelItem(c, user).getItem());
// Save settings
iwm.getAddon(Util.getWorld(user.getWorld())).ifPresent(GameModeAddon::saveWorldSettings);
} else {
// Open the Sub Settings panel
openPanel(user, panelName);
}
return true;
}
private void openPanel(User user, String panelName) {
// Close the current panel
user.closeInventory();
// Open a new panel
PanelBuilder pb = new PanelBuilder();
pb.user(user).name(panelName);
// Make panel items
livingEntityTypes.forEach(c -> pb.item(getPanelItem(c, user)));
pb.build();
}
private PanelItem getPanelItem(EntityType c, User user) {
PanelItemBuilder pib = new PanelItemBuilder();
pib.name(Util.prettifyText(c.toString()));
pib.clickHandler(this);
if (!BentoBox.getInstance().getIWM().getMobLimitSettings(user.getWorld()).contains(c.name())) {
pib.icon(Material.GREEN_SHULKER_BOX);
pib.description(user.getTranslation("protection.flags.LIMIT_MOBS.can"));
} else {
pib.icon(Material.RED_SHULKER_BOX);
pib.description(user.getTranslation("protection.flags.LIMIT_MOBS.cannot"));
}
return pib.build();
}
}

View File

@ -0,0 +1,26 @@
package world.bentobox.bentobox.listeners.flags.worldsettings;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.CreatureSpawnEvent;
import world.bentobox.bentobox.api.flags.FlagListener;
/**
* Limit what mob types can spawn globally
* @author tastybento
*
*/
public class LimitMobsListener extends FlagListener {
/**
* Limit mob types if they are not allowed
* @param e - event
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onMobSpawn(CreatureSpawnEvent e) {
if (getIWM().inWorld(e.getLocation()) && getIWM().getMobLimitSettings(e.getLocation().getWorld()).contains(e.getEntityType().name())) {
e.setCancelled(true);
}
}
}

View File

@ -12,6 +12,7 @@ import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.api.flags.clicklisteners.CycleClick;
import world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener;
import world.bentobox.bentobox.listeners.flags.clicklisteners.GeoLimitClickListener;
import world.bentobox.bentobox.listeners.flags.clicklisteners.MobLimitClickListener;
import world.bentobox.bentobox.listeners.flags.protection.BlockInteractionListener;
import world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener;
import world.bentobox.bentobox.listeners.flags.protection.BreedingListener;
@ -49,6 +50,7 @@ import world.bentobox.bentobox.listeners.flags.worldsettings.GeoLimitMobsListene
import world.bentobox.bentobox.listeners.flags.worldsettings.InvincibleVisitorsListener;
import world.bentobox.bentobox.listeners.flags.worldsettings.IslandRespawnListener;
import world.bentobox.bentobox.listeners.flags.worldsettings.ItemFrameListener;
import world.bentobox.bentobox.listeners.flags.worldsettings.LimitMobsListener;
import world.bentobox.bentobox.listeners.flags.worldsettings.LiquidsFlowingOutListener;
import world.bentobox.bentobox.listeners.flags.worldsettings.NaturalSpawningOutsideRangeListener;
import world.bentobox.bentobox.listeners.flags.worldsettings.ObsidianScoopingListener;
@ -353,6 +355,12 @@ public final class Flags {
public static final Flag GEO_LIMIT_MOBS = new Flag.Builder("GEO_LIMIT_MOBS", Material.CHAINMAIL_CHESTPLATE).type(Type.WORLD_SETTING)
.listener(new GeoLimitMobsListener()).clickHandler(new GeoLimitClickListener()).usePanel(true).build();
/**
* @since 1.12.0
*/
public static final Flag LIMIT_MOBS = new Flag.Builder("LIMIT_MOBS", Material.CHAINMAIL_BOOTS).type(Type.WORLD_SETTING)
.listener(new LimitMobsListener()).clickHandler(new MobLimitClickListener()).usePanel(true).build();
public static final Flag REMOVE_MOBS = new Flag.Builder("REMOVE_MOBS", Material.GLOWSTONE_DUST).type(Type.WORLD_SETTING)
.listener(new RemoveMobsListener()).defaultSetting(true).build();

View File

@ -720,6 +720,16 @@ public class IslandWorldManager {
public List<String> getGeoLimitSettings(@NonNull World world) {
return gameModes.containsKey(world) ? gameModes.get(world).getWorldSettings().getGeoLimitSettings() : Collections.emptyList();
}
/**
* Check if a mob type should not spawn in this world
* @param world - world
* @return list of limited mobs
* @since 1.12.0
*/
public List<String> getMobLimitSettings(@NonNull World world) {
return gameModes.containsKey(world) ? gameModes.get(world).getWorldSettings().getMobLimitSettings() : Collections.emptyList();
}
/**
* Get the reset limit for this world

View File

@ -952,6 +952,14 @@ protection:
description: "Toggle use"
name: "Lever use"
hint: "Lever use disabled"
LIMIT_MOBS:
description: |-
&a Limit entities from
&a spawning in this game
&a mode.
name: "&e Limit entity type spawning"
can: "&a Can spawn"
cannot: "&c Cannot spawn"
LIQUIDS_FLOWING_OUT:
name: "Liquids flowing outside islands"
description: |-