diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java index 1bde79d..b0d73b2 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java @@ -21,6 +21,8 @@ import com.willfp.ecobosses.bosses.util.obj.ImmunityOptions; import com.willfp.ecobosses.bosses.util.obj.OptionedSound; import com.willfp.ecobosses.bosses.util.obj.SpawnTotem; import com.willfp.ecobosses.bosses.util.obj.TargetMode; +import com.willfp.ecobosses.bosses.util.requirement.SpawnRequirement; +import com.willfp.ecobosses.bosses.util.requirement.SpawnRequirements; import lombok.AccessLevel; import lombok.Getter; import org.bukkit.Bukkit; @@ -34,6 +36,7 @@ import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -48,6 +51,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.UUID; import java.util.stream.Collectors; public class EcoBoss extends PluginDependent { @@ -277,6 +281,16 @@ public class EcoBoss extends PluginDependent { @Getter private final ItemStack spawnEgg; + /** + * All the requirements needed in order to use the enchantment. + */ + private final Map> requirements = new HashMap<>(); + + /** + * Cached players to see if they meet requirements. + */ + private final Map cachedRequirements = new HashMap<>(); + /** * Create a new Boss. * @@ -494,6 +508,24 @@ public class EcoBoss extends PluginDependent { autoSpawnLocations.add(new Location(world, x, y, z)); } + + for (String req : config.getStrings("spawn-requirements", false)) { + List split = Arrays.asList(req.split(":")); + if (split.size() < 2) { + continue; + } + + SpawnRequirement requirement = SpawnRequirements.getByID(split.get(0).toLowerCase()); + + if (requirement == null) { + continue; + } + + this.requirements.put(requirement, split.subList(1, split.size())); + } + + this.clearCachedRequirements(); + // Spawn egg if (this.getConfig().getBool("spawn-egg.enabled")) { Material material = Material.getMaterial(this.getConfig().getString("spawn-egg.material").toUpperCase()); @@ -527,6 +559,35 @@ public class EcoBoss extends PluginDependent { } } + /** + * Clear requirements cache. + */ + public void clearCachedRequirements() { + this.cachedRequirements.clear(); + } + + /** + * Does the player meet the requirements to use this enchantment. + * + * @param player The player. + * @return If the requirements are met. + */ + public boolean areRequirementsMet(@NotNull final Player player) { + if (cachedRequirements.containsKey(player.getUniqueId())) { + return cachedRequirements.get(player.getUniqueId()); + } + + for (Map.Entry> entry : requirements.entrySet()) { + if (!entry.getKey().doesPlayerMeet(player, entry.getValue())) { + cachedRequirements.put(player.getUniqueId(), false); + return false; + } + } + + cachedRequirements.put(player.getUniqueId(), true); + return true; + } + /** * Create effect tickers for Living Boss. * diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/SpawnListeners.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/SpawnListeners.java index 75052a4..13d9325 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/SpawnListeners.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/listeners/SpawnListeners.java @@ -62,6 +62,11 @@ public class SpawnListeners extends PluginDependent implements Listen if (boss.isSpawnTotemEnabled()) { if (!boss.getSpawnTotemDisabledWorldNames().contains(event.getBlock().getWorld().getName().toLowerCase())) { if (boss.getSpawnTotem().equals(placedTotem)) { + if (!boss.areRequirementsMet(event.getPlayer())) { + event.getPlayer().sendMessage(this.getPlugin().getLangYml().getMessage("requirements-not-met")); + return; + } + block1.setType(Material.AIR); block2.setType(Material.AIR); block3.setType(Material.AIR); @@ -100,8 +105,17 @@ public class SpawnListeners extends PluginDependent implements Listen return; } - event.setCancelled(true); EcoBoss boss = EcoBosses.getByName(id); + if (boss == null) { + return; + } + + if (!boss.areRequirementsMet(event.getPlayer())) { + event.getPlayer().sendMessage(this.getPlugin().getLangYml().getMessage("requirements-not-met")); + return; + } + + event.setCancelled(true); item.setAmount(item.getAmount() - 1); event.setUseItemInHand(Event.Result.DENY); diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/SpawnRequirement.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/SpawnRequirement.java new file mode 100644 index 0000000..e4c65a5 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/SpawnRequirement.java @@ -0,0 +1,31 @@ +package com.willfp.ecobosses.bosses.util.requirement; + +import lombok.Getter; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public abstract class SpawnRequirement { + /** + * The ID of the requirement. + */ + @Getter + private final String id; + + protected SpawnRequirement(@NotNull final String id) { + this.id = id; + + SpawnRequirements.addNewRequirement(this); + } + + /** + * Test if the player meets the requirement. + * + * @param player The player. + * @param args The arguments. + * @return The requirement. + */ + public abstract boolean doesPlayerMeet(@NotNull Player player, + @NotNull List args); +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/SpawnRequirements.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/SpawnRequirements.java new file mode 100644 index 0000000..ef7d12b --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/SpawnRequirements.java @@ -0,0 +1,67 @@ +package com.willfp.ecobosses.bosses.util.requirement; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableList; +import com.willfp.ecobosses.bosses.util.requirement.requirements.RequirementHasPermission; +import com.willfp.ecobosses.bosses.util.requirement.requirements.RequirementPlaceholderEquals; +import com.willfp.ecobosses.bosses.util.requirement.requirements.RequirementPlaceholderGreaterThan; +import com.willfp.ecobosses.bosses.util.requirement.requirements.RequirementPlaceholderLessThan; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@UtilityClass +@SuppressWarnings({"unused", "checkstyle:JavadocVariable"}) +public class SpawnRequirements { + /** + * All registered requirements. + */ + private static final BiMap BY_ID = HashBiMap.create(); + + public static final SpawnRequirement HAS_PERMISSION = new RequirementHasPermission(); + public static final SpawnRequirement PLACEHOLDER_EQUALS = new RequirementPlaceholderEquals(); + public static final SpawnRequirement PLACEHOLDER_GREATER_THAN = new RequirementPlaceholderGreaterThan(); + public static final SpawnRequirement PLACEHOLDER_LESS_THAN = new RequirementPlaceholderLessThan(); + + /** + * Get all registered requirements. + * + * @return A list of all requirements. + */ + public static List values() { + return ImmutableList.copyOf(BY_ID.values()); + } + + /** + * Get {@link SpawnRequirement} matching ID. + * + * @param name The ID to search for. + * @return The matching {@link SpawnRequirement}, or null if not found. + */ + public static SpawnRequirement getByID(@NotNull final String name) { + return BY_ID.get(name); + } + + /** + * Add new {@link SpawnRequirement}. + *

+ * Only for internal use, requirements are automatically added in the constructor. + * + * @param req The {@link SpawnRequirement} to add. + */ + public static void addNewRequirement(@NotNull final SpawnRequirement req) { + BY_ID.inverse().remove(req); + BY_ID.put(req.getId(), req); + } + + /** + * Remove {@link SpawnRequirement}. + * + * @param req The {@link SpawnRequirement} to remove. + */ + public static void removeRequirement(@NotNull final SpawnRequirement req) { + BY_ID.inverse().remove(req); + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementHasPermission.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementHasPermission.java new file mode 100644 index 0000000..a88b607 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementHasPermission.java @@ -0,0 +1,23 @@ +package com.willfp.ecobosses.bosses.util.requirement.requirements; + +import com.willfp.ecobosses.bosses.util.requirement.SpawnRequirement; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class RequirementHasPermission extends SpawnRequirement { + /** + * Create new requirement. + */ + public RequirementHasPermission() { + super("has-permission"); + } + + @Override + public boolean doesPlayerMeet(@NotNull final Player player, + @NotNull final List args) { + String permission = args.get(0); + return player.hasPermission(permission); + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderEquals.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderEquals.java new file mode 100644 index 0000000..7304f13 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderEquals.java @@ -0,0 +1,26 @@ +package com.willfp.ecobosses.bosses.util.requirement.requirements; + +import com.willfp.eco.core.integrations.placeholder.PlaceholderManager; +import com.willfp.ecobosses.bosses.util.requirement.SpawnRequirement; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class RequirementPlaceholderEquals extends SpawnRequirement { + /** + * Create new requirement. + */ + public RequirementPlaceholderEquals() { + super("placeholder-equals"); + } + + @Override + public boolean doesPlayerMeet(@NotNull final Player player, + @NotNull final List args) { + String placeholder = args.get(0); + String equals = args.get(1); + + return PlaceholderManager.translatePlaceholders(placeholder, player).equalsIgnoreCase(equals); + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderGreaterThan.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderGreaterThan.java new file mode 100644 index 0000000..1851e80 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderGreaterThan.java @@ -0,0 +1,30 @@ +package com.willfp.ecobosses.bosses.util.requirement.requirements; + +import com.willfp.eco.core.integrations.placeholder.PlaceholderManager; +import com.willfp.ecobosses.bosses.util.requirement.SpawnRequirement; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class RequirementPlaceholderGreaterThan extends SpawnRequirement { + /** + * Create new requirement. + */ + public RequirementPlaceholderGreaterThan() { + super("placeholder-greater-than"); + } + + @Override + public boolean doesPlayerMeet(@NotNull final Player player, + @NotNull final List args) { + String placeholder = args.get(0); + double equals = Double.parseDouble(args.get(1)); + + try { + return Double.parseDouble(PlaceholderManager.translatePlaceholders(placeholder, player)) >= equals; + } catch (NumberFormatException e) { + return false; + } + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderLessThan.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderLessThan.java new file mode 100644 index 0000000..a8c4605 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/requirement/requirements/RequirementPlaceholderLessThan.java @@ -0,0 +1,30 @@ +package com.willfp.ecobosses.bosses.util.requirement.requirements; + +import com.willfp.eco.core.integrations.placeholder.PlaceholderManager; +import com.willfp.ecobosses.bosses.util.requirement.SpawnRequirement; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class RequirementPlaceholderLessThan extends SpawnRequirement { + /** + * Create new requirement. + */ + public RequirementPlaceholderLessThan() { + super("placeholder-less-than"); + } + + @Override + public boolean doesPlayerMeet(@NotNull final Player player, + @NotNull final List args) { + String placeholder = args.get(0); + double equals = Double.parseDouble(args.get(1)); + + try { + return Double.parseDouble(PlaceholderManager.translatePlaceholders(placeholder, player)) < equals; + } catch (NumberFormatException e) { + return false; + } + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml b/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml index 5542e0f..519da88 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml @@ -17,6 +17,8 @@ time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to d auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable. auto-spawn-locations: [ ] # Formatted as world:x:y:z - for example world_nether:100:10:100 +spawn-requirements: [] + spawn-egg: enabled: true material: wolf_spawn_egg diff --git a/eco-core/core-plugin/src/main/resources/bosses/dark_guardian.yml b/eco-core/core-plugin/src/main/resources/bosses/dark_guardian.yml index a3f6c32..4fe016c 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/dark_guardian.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/dark_guardian.yml @@ -17,6 +17,8 @@ time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to d auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable. auto-spawn-locations: [ ] # Formatted as world:x:y:z - for example world_nether:100:10:100 +spawn-requirements: [] + spawn-egg: enabled: true material: ravager_spawn_egg diff --git a/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml b/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml index 0e38d3c..6da8b25 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml @@ -17,6 +17,8 @@ time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to d auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable. auto-spawn-locations: [] # Formatted as world:x:y:z - for example world_nether:100:10:100 +spawn-requirements: [] + spawn-egg: enabled: true material: evoker_spawn_egg diff --git a/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml b/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml index 0704e32..59d3250 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml @@ -17,6 +17,8 @@ time-to-live: 120 # Time to live before auto despawn, in seconds. Set to -1 to d auto-spawn-interval: -1 # Time between auto spawns in ticks (20 ticks in a second) - Set to -1 to disable. auto-spawn-locations: [ ] # Formatted as world:x:y:z - for example world_nether:100:10:100 +spawn-requirements: [] + spawn-egg: enabled: true material: cave_spider_spawn_egg diff --git a/eco-core/core-plugin/src/main/resources/lang.yml b/eco-core/core-plugin/src/main/resources/lang.yml index a1d3fd5..8a0c9ce 100644 --- a/eco-core/core-plugin/src/main/resources/lang.yml +++ b/eco-core/core-plugin/src/main/resources/lang.yml @@ -14,5 +14,6 @@ messages: needs-stone: "&cYou must specify a boss" invalid-stone: "&cInvalid boss!" give-success: "Gave &a%boss%&r spawn egg to &a%recipient%" + requirements-not-met: "&cYou can't spawn this boss!" na: "N/A" \ No newline at end of file