diff --git a/config/checkstyle/suppression.xml b/config/checkstyle/suppression.xml index c460957..5d0bdaa 100644 --- a/config/checkstyle/suppression.xml +++ b/config/checkstyle/suppression.xml @@ -8,7 +8,10 @@ + + + \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/EcoArmorPlugin.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/EcoArmorPlugin.java index 3d8006b..c0596c1 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/EcoArmorPlugin.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/EcoArmorPlugin.java @@ -11,6 +11,7 @@ import com.willfp.ecoarmor.commands.TabcompleterEagive; import com.willfp.ecoarmor.display.ArmorDisplay; import com.willfp.ecoarmor.effects.Effect; import com.willfp.ecoarmor.effects.Effects; +import com.willfp.ecoarmor.effects.util.EffectWatcher; import com.willfp.ecoarmor.sets.ArmorSets; import com.willfp.ecoarmor.sets.util.EffectiveDurabilityListener; import com.willfp.ecoarmor.sets.util.PotionEffectListener; @@ -139,7 +140,8 @@ public class EcoArmorPlugin extends AbstractEcoPlugin { new AdvancementShardListener(this), new PotionEffectListener(this), new EffectiveDurabilityListener(this), - new DiscoverRecipeListener(this) + new DiscoverRecipeListener(this), + new EffectWatcher(this) ); } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/Condition.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/Condition.java new file mode 100644 index 0000000..936fe1c --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/Condition.java @@ -0,0 +1,57 @@ +package com.willfp.ecoarmor.conditions; + +import com.willfp.ecoarmor.EcoArmorPlugin; +import lombok.AccessLevel; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; + +public abstract class Condition implements Listener { + /** + * Instance of EcoArmor. + */ + @Getter(AccessLevel.PROTECTED) + private final EcoArmorPlugin plugin = EcoArmorPlugin.getInstance(); + + /** + * The name of the effect. + */ + @Getter + private final String name; + + /** + * The class of the config getter type. + */ + @Getter + private final Class typeClass; + + /** + * Create a new condition. + * + * @param name The condition name. + * @param typeClass The class of the config type. + */ + protected Condition(@NotNull final String name, + @NotNull final Class typeClass) { + this.name = name; + this.typeClass = typeClass; + + Conditions.addNewCondition(this); + } + + /** + * Get if condition is met for a player. + * + * @param player The player. + * @param value The value of the condition. + * @return If met. + */ + public final boolean isMet(@NotNull final Player player, + @NotNull final Object value) { + return isConditionMet(player, typeClass.cast(value)); + } + + protected abstract boolean isConditionMet(@NotNull Player player, + @NotNull T value); +} diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/Conditions.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/Conditions.java new file mode 100644 index 0000000..0d22f0d --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/Conditions.java @@ -0,0 +1,50 @@ +package com.willfp.ecoarmor.conditions; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableList; +import com.willfp.ecoarmor.conditions.conditions.ConditionBelowY; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@UtilityClass +@SuppressWarnings("unused") +public class Conditions { + /** + * All registered effects. + */ + private static final BiMap> BY_NAME = HashBiMap.create(); + + public static final Condition BELOW_Y = new ConditionBelowY(); + + /** + * Get condition matching name. + * + * @param name The name to query. + * @return The matching condition, or null if not found. + */ + public static Condition getByName(@NotNull final String name) { + return BY_NAME.get(name); + } + + /** + * List of all registered conditions. + * + * @return The conditions. + */ + public static List> values() { + return ImmutableList.copyOf(BY_NAME.values()); + } + + /** + * Add new condition to EcoArmor. + * + * @param condition The condition to add. + */ + public static void addNewCondition(@NotNull final Condition condition) { + BY_NAME.remove(condition.getName()); + BY_NAME.put(condition.getName(), condition); + } +} diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/conditions/ConditionBelowY.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/conditions/ConditionBelowY.java new file mode 100644 index 0000000..cd8f8f1 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/conditions/conditions/ConditionBelowY.java @@ -0,0 +1,44 @@ +package com.willfp.ecoarmor.conditions.conditions; + +import com.willfp.ecoarmor.conditions.Condition; +import com.willfp.ecoarmor.sets.ArmorSet; +import com.willfp.ecoarmor.sets.util.ArmorUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerMoveEvent; +import org.jetbrains.annotations.NotNull; + +public class ConditionBelowY extends Condition { + public ConditionBelowY() { + super("below-y", Double.class); + } + + @EventHandler + public void listener(@NotNull final PlayerMoveEvent event) { + Player player = event.getPlayer(); + + ArmorSet set = ArmorUtils.getSetOnPlayer(player); + + if (set == null) { + return; + } + + Double value = set.getConditionValue(this); + + if (value == null) { + return; + } + + if (isMet(player, value)) { + set.getEffects().keySet().forEach(effect -> effect.enable(player)); + } else { + set.getEffects().keySet().forEach(effect -> effect.disable(player)); + } + } + + @Override + public boolean isConditionMet(@NotNull final Player player, + @NotNull final Double value) { + return player.getLocation().getY() < value; + } +} diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/Effect.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/Effect.java index ff88a3c..2ee6abc 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/Effect.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/Effect.java @@ -3,9 +3,12 @@ package com.willfp.ecoarmor.effects; import com.willfp.ecoarmor.EcoArmorPlugin; import lombok.AccessLevel; import lombok.Getter; +import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.jetbrains.annotations.NotNull; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; public abstract class Effect implements Listener { @@ -39,6 +42,11 @@ public abstract class Effect implements Listener { @Getter private final Class typeClass; + /** + * Players that the effect is currently enabled for. + */ + private final Set enabledPlayers = new HashSet<>(); + /** * Create a new effect. * @@ -54,6 +62,53 @@ public abstract class Effect implements Listener { update(); Effects.addNewEffect(this); } + /** + * Get if effect is enabled for player. + * + * @param player The player. + * @return If enabled. + */ + public final boolean isEnabledForPlayer(@NotNull final Player player) { + return enabledPlayers.contains(player.getUniqueId()); + } + + /** + * Enable the effect for a player. + * + * @param player The player. + */ + public final void enable(@NotNull final Player player) { + if (enabledPlayers.contains(player.getUniqueId())) { + return; + } + + enabledPlayers.add(player.getUniqueId()); + + this.onEnable(player); + } + + /** + * Disable the effect for a player. + * + * @param player The player. + */ + public final void disable(@NotNull final Player player) { + if (!enabledPlayers.contains(player.getUniqueId())) { + return; + } + + enabledPlayers.remove(player.getUniqueId()); + + this.onDisable(player); + } + + protected void onEnable(@NotNull final Player player) { + // Empty by default + } + + protected void onDisable(@NotNull final Player player) { + // Empty by default + } /** * Update if the effect is enabled. diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/effects/SpeedMultiplier.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/effects/SpeedMultiplier.java index 127a872..acdc6e5 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/effects/SpeedMultiplier.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/effects/SpeedMultiplier.java @@ -1,13 +1,11 @@ package com.willfp.ecoarmor.effects.effects; -import com.willfp.eco.util.events.armorequip.ArmorEquipEvent; import com.willfp.ecoarmor.effects.Effect; import com.willfp.ecoarmor.sets.util.ArmorUtils; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; import org.jetbrains.annotations.NotNull; public class SpeedMultiplier extends Effect { @@ -15,23 +13,28 @@ public class SpeedMultiplier extends Effect { super("speed-multiplier", Double.class); } - @EventHandler - public void listener(@NotNull final ArmorEquipEvent event) { - Player player = event.getPlayer(); - + @Override + protected void onEnable(@NotNull final Player player) { AttributeInstance movementSpeed = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED); assert movementSpeed != null; - this.getPlugin().getScheduler().runLater(() -> { - Double multiplier = ArmorUtils.getEffectStrength(player, this); - if (multiplier == null) { - movementSpeed.removeModifier(new AttributeModifier(this.getUuid(), "speed-multiplier", 0, AttributeModifier.Operation.MULTIPLY_SCALAR_1)); - } else { - AttributeModifier modifier = new AttributeModifier(this.getUuid(), "speed-multiplier", multiplier - 1, AttributeModifier.Operation.MULTIPLY_SCALAR_1); - if (!movementSpeed.getModifiers().contains(modifier)) { - movementSpeed.addModifier(modifier); - } - } - }, 1); + Double strength = ArmorUtils.getEffectStrength(player, this); + + if (strength == null) { + return; + } + + AttributeModifier modifier = new AttributeModifier(this.getUuid(), "speed-multiplier", strength - 1, AttributeModifier.Operation.MULTIPLY_SCALAR_1); + if (!movementSpeed.getModifiers().contains(modifier)) { + movementSpeed.addModifier(modifier); + } + } + + @Override + protected void onDisable(@NotNull final Player player) { + AttributeInstance movementSpeed = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED); + assert movementSpeed != null; + + movementSpeed.removeModifier(new AttributeModifier(this.getUuid(), "speed-multiplier", 0, AttributeModifier.Operation.MULTIPLY_SCALAR_1)); } } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/util/EffectWatcher.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/util/EffectWatcher.java new file mode 100644 index 0000000..97e3795 --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/effects/util/EffectWatcher.java @@ -0,0 +1,60 @@ +package com.willfp.ecoarmor.effects.util; + +import com.willfp.eco.util.events.armorequip.ArmorEquipEvent; +import com.willfp.eco.util.internal.PluginDependent; +import com.willfp.eco.util.plugin.AbstractEcoPlugin; +import com.willfp.ecoarmor.effects.Effect; +import com.willfp.ecoarmor.effects.Effects; +import com.willfp.ecoarmor.sets.ArmorSet; +import com.willfp.ecoarmor.sets.util.ArmorUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; + +public class EffectWatcher extends PluginDependent implements Listener { + /** + * Pass an {@link AbstractEcoPlugin} in order to interface with it. + * + * @param plugin The plugin to manage. + */ + public EffectWatcher(@NotNull final AbstractEcoPlugin plugin) { + super(plugin); + } + + /** + * Listener for armor equipping. + * + * @param event The event to listen for. + */ + @EventHandler + public void armorEquipListener(@NotNull final ArmorEquipEvent event) { + Player player = event.getPlayer(); + + this.getPlugin().getScheduler().runLater(() -> { + ArmorSet set = ArmorUtils.getSetOnPlayer(player); + + for (Effect effect : Effects.values()) { + boolean enabled = true; + + if (set == null) { + enabled = false; + } else { + if (set.getEffectStrength(effect) == null) { + enabled = false; + } + + if (ArmorUtils.areConditionsMet(player)) { + enabled = false; + } + } + + if (enabled) { + effect.enable(player); + } else { + effect.disable(player); + } + } + }, 1); + } +} diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/ArmorSet.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/ArmorSet.java index 652d717..ffc0519 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/ArmorSet.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/ArmorSet.java @@ -8,6 +8,8 @@ import com.willfp.eco.util.recipe.RecipeParts; import com.willfp.eco.util.recipe.parts.ComplexRecipePart; import com.willfp.eco.util.recipe.recipes.EcoShapedRecipe; import com.willfp.ecoarmor.EcoArmorPlugin; +import com.willfp.ecoarmor.conditions.Condition; +import com.willfp.ecoarmor.conditions.Conditions; import com.willfp.ecoarmor.effects.Effect; import com.willfp.ecoarmor.effects.Effects; import com.willfp.ecoarmor.sets.meta.ArmorSlot; @@ -55,6 +57,12 @@ public class ArmorSet { @Getter(AccessLevel.PRIVATE) private final AbstractUndefinedConfig config; + /** + * Conditions and their values. + */ + @Getter + private final Map, Object> conditions = new HashMap<>(); + /** * Effects and their strengths. */ @@ -115,6 +123,14 @@ public class ArmorSet { this.config = config; this.name = name; + for (String definedKey : this.getConfig().getStrings("conditions")) { + String[] split = definedKey.split(":"); + String key = split[0].trim(); + String value = split[1].trim(); + Condition condition = Conditions.getByName(key); + conditions.put(condition, ArmorUtils.getConditionValue(value, condition)); + } + for (String definedKey : this.getConfig().getStrings("set-bonus")) { String[] split = definedKey.split(":"); String key = split[0].trim(); @@ -324,6 +340,18 @@ public class ArmorSet { return advancedItems.get(slot); } + /** + * Get condition value of effect. + * + * @param condition The condition to query. + * @param The type of the condition value. + * @return The value. + */ + @Nullable + public T getConditionValue(@NotNull final Condition condition) { + return (T) conditions.get(condition); + } + /** * Get effect strength of effect. * diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/util/ArmorUtils.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/util/ArmorUtils.java index a802f56..8c6dc21 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/util/ArmorUtils.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoarmor/sets/util/ArmorUtils.java @@ -1,6 +1,7 @@ package com.willfp.ecoarmor.sets.util; import com.willfp.ecoarmor.EcoArmorPlugin; +import com.willfp.ecoarmor.conditions.Condition; import com.willfp.ecoarmor.effects.Effect; import com.willfp.ecoarmor.sets.ArmorSet; import com.willfp.ecoarmor.sets.ArmorSets; @@ -20,6 +21,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.UUID; @UtilityClass @@ -133,6 +135,46 @@ public class ArmorUtils { return getEffectStrength(player, effect) != null; } + /** + * Get the value of a condition on a player's set. + * + * @param player The player to test. + * @param condition The condition to test. + * @param Condition type. + * @return The value or null if not found. + */ + @Nullable + public T getConditionValue(@NotNull final Player player, + @NotNull final Condition condition) { + ArmorSet set = getSetOnPlayer(player); + if (set == null) { + return null; + } + + return set.getConditionValue(condition); + } + + /** + * Get if all conditions are met for a player. + * + * @param player The player. + * @return If conditions are men. + */ + public boolean areConditionsMet(@NotNull final Player player) { + ArmorSet set = getSetOnPlayer(player); + if (set == null) { + return true; + } + + for (Map.Entry, Object> entry : set.getConditions().entrySet()) { + if (!entry.getKey().isMet(player, entry.getValue())) { + return false; + } + } + + return true; + } + /** * Get tier on upgrade crystal. * @@ -184,7 +226,7 @@ public class ArmorUtils { * Set tier on item. * * @param itemStack The item to check. - * @param tier The tier to set. + * @param tier The tier to set. */ public static void setTier(@NotNull final ItemStack itemStack, @NotNull final Tier tier) { @@ -382,4 +424,30 @@ public class ArmorUtils { return string; } + + /** + * Get value of condition. + * + * @param string Value as string. + * @param condition Condition. + * @param The type of the condition. + * @return Value. + */ + @NotNull + public static Object getConditionValue(@NotNull final String string, + @NotNull final Condition condition) { + if (condition.getTypeClass().equals(Boolean.class)) { + return Boolean.parseBoolean(string); + } + + if (condition.getTypeClass().equals(Integer.class)) { + return Integer.parseInt(string); + } + + if (condition.getTypeClass().equals(Double.class)) { + return Double.parseDouble(string); + } + + return string; + } } diff --git a/eco-core/core-plugin/src/main/resources/sets/young.yml b/eco-core/core-plugin/src/main/resources/sets/young.yml index 16d7c26..fe99704 100644 --- a/eco-core/core-plugin/src/main/resources/sets/young.yml +++ b/eco-core/core-plugin/src/main/resources/sets/young.yml @@ -1,4 +1,6 @@ enabled: true +conditions: + - "below-y: 40" set-bonus: - "speed-multiplier: 1.25" advanced-set-bonus: